source: soft/giet_vm/giet_kernel/sys_handler.c @ 709

Last change on this file since 709 was 709, checked in by alain, 9 years ago

Major release: Change the task model to implement the POSIX threads API.

  • The shell "exec" and "kill" commands can be used to activate/de-activate the applications.
  • The "pause", "resume", and "context" commands can be used to stop, restart, a single thtead or to display the thread context.

This version has been tested on the following multi-threaded applications,
that have been modified to use the POSIX threads:

  • classif
  • convol
  • transpose
  • gameoflife
  • raycast
  • Property svn:executable set to *
File size: 110.1 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : sys_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner and joel porquet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <sys_handler.h>
9#include <tty_driver.h>
10#include <tim_driver.h>
11#include <nic_driver.h>
[440]12#include <mmc_driver.h>
[519]13#include <mwr_driver.h>
[440]14#include <cma_driver.h>
[258]15#include <ctx_handler.h>
16#include <fat32.h>
[707]17#include <elf-types.h>
[258]18#include <utils.h>
[478]19#include <kernel_malloc.h>
[459]20#include <tty0.h>
[396]21#include <vmem.h>
[322]22#include <hard_config.h>
[258]23#include <giet_config.h>
24#include <mapping_info.h>
[547]25#include <irq_handler.h>
[519]26#include <io.h>
[258]27
[709]28#if !defined(X_SIZE)
29# error: You must define X_SIZE in the hard_config.h file
30#endif
31
32#if !defined(Y_SIZE)
33# error: You must define Y_SIZE in the hard_config.h file
34#endif
35
36#if !defined(NB_PROCS_MAX)
37# error: You must define NB_PROCS_MAX in the hard_config.h file
38#endif
39
[322]40#if !defined(SEG_BOOT_MAPPING_BASE)
41# error: You must define SEG_BOOT_MAPPING_BASE in the hard_config.h file
42#endif
43
[449]44#if !defined(NB_TTY_CHANNELS)
45# error: You must define NB_TTY_CHANNELS in the hard_config.h file
46#endif
47
[459]48#if (NB_TTY_CHANNELS < 1)
49# error: NB_TTY_CHANNELS cannot be smaller than 1!
50#endif
51
[449]52#if !defined(NB_TIM_CHANNELS)
53# error: You must define NB_TIM_CHANNELS in the hard_config.h file
54#endif
55
56#if !defined(NB_NIC_CHANNELS)
57# error: You must define NB_NIC_CHANNELS in the hard_config.h file
58#endif
59
60#if !defined(NB_CMA_CHANNELS)
61# error: You must define NB_CMA_CHANNELS in the hard_config.h file
62#endif
63
[478]64#if !defined(GIET_NO_HARD_CC)
65# error: You must define GIET_NO_HARD_CC in the giet_config.h file
[449]66#endif
67
[478]68#if !defined ( GIET_NIC_MAC4 )
69# error: You must define GIET_NIC_MAC4 in the giet_config.h file
[449]70#endif
71
[478]72#if !defined ( GIET_NIC_MAC2 )
73# error: You must define GIET_NIC_MAC2 in the giet_config.h file
[449]74#endif
75
[258]76////////////////////////////////////////////////////////////////////////////
[528]77//        Extern variables
[519]78////////////////////////////////////////////////////////////////////////////
79
[528]80// allocated in tty0.c file.
81extern sqt_lock_t _tty0_sqt_lock;
[519]82
[528]83// allocated in mwr_driver.c file.
84extern simple_lock_t  _coproc_lock[X_SIZE*Y_SIZE];
[556]85extern unsigned int   _coproc_type[X_SIZE*Y_SIZE];
86extern unsigned int   _coproc_info[X_SIZE*Y_SIZE];
87extern unsigned int   _coproc_mode[X_SIZE*Y_SIZE];
88extern unsigned int   _coproc_error[X_SIZE*Y_SIZE];
[709]89extern unsigned int   _coproc_trdid[X_SIZE*Y_SIZE];
[519]90
[528]91// allocated in tty_driver.c file.
[709]92extern tty_fifo_t   _tty_rx_fifo[NB_TTY_CHANNELS];
[528]93
[629]94// allocated in kernel_init.c file
95extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
96
[709]97////////////////////////////////////////////////////////////////////////////////
98//     Channel allocators for multi-channels peripherals
99// - The array _***_channel_allocator[channel] defines the number of user
100//   threads for a dynamically allocated channel of peripheral ***.
101// - The array _***_channel_wti[channel] defines the WTI index and the
102//   processor coordinates for the processor receiving the channel WTI.
103////////////////////////////////////////////////////////////////////////////////
[440]104
[709]105#if NB_TTY_CHANNELS
[494]106__attribute__((section(".kdata")))
[709]107unsigned int _tty_channel_alloc[NB_TTY_CHANNELS] = {0};
[494]108
109__attribute__((section(".kdata")))
[709]110unsigned int _tty_channel_wti[NB_TTY_CHANNELS];
111#endif
[494]112
[709]113#if NB_TIM_CHANNELS
[494]114__attribute__((section(".kdata")))
[709]115unsigned int _tim_channel_alloc[NB_TIM_CHANNELS] = {0};
[494]116
117__attribute__((section(".kdata")))
[709]118unsigned int _tim_channel_wti[NB_TIM_CHANNELS];
119#endif
[494]120
[709]121#if NB_CMA_CHANNELS
[494]122__attribute__((section(".kdata")))
[709]123unsigned int _cma_channel_alloc[NB_CMA_CHANNELS] = {0};
[440]124
[709]125__attribute__((section(".kdata")))
126unsigned int _cma_channel_wti[NB_CMA_CHANNELS];
127#endif
128
129#if NB_NIC_CHANNELS
130__attribute__((section(".kdata")))
131unsigned int _nic_rx_channel_alloc[NB_NIC_CHANNELS] = {0};
132
133__attribute__((section(".kdata")))
134unsigned int _nic_rx_channel_wti[NB_NIC_CHANNELS];
135
136__attribute__((section(".kdata")))
137unsigned int _nic_tx_channel_alloc[NB_NIC_CHANNELS] = {0};
138
139__attribute__((section(".kdata")))
140unsigned int _nic_tx_channel_wti[NB_NIC_CHANNELS];
141#endif
142
[440]143////////////////////////////////////////////////////////////////////////////
[614]144//     NIC_RX and NIC_TX kernel chbuf arrays
[449]145////////////////////////////////////////////////////////////////////////////
146
[494]147__attribute__((section(".kdata")))
[614]148ker_chbuf_t  _nic_ker_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
[459]149
[494]150__attribute__((section(".kdata")))
[614]151ker_chbuf_t  _nic_ker_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
[459]152
[478]153////////////////////////////////////////////////////////////////////////////
154// FBF related chbuf descriptors array, indexed by the CMA channel index.
155// Physical addresses of these chbuf descriptors required for L2 cache sync.
[614]156// FBF status
[478]157////////////////////////////////////////////////////////////////////////////
[459]158
[494]159__attribute__((section(".kdata")))
[478]160fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(64)));
[459]161
[494]162__attribute__((section(".kdata")))
[478]163unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
164
[614]165__attribute__((section(".kdata")))
166buffer_status_t _fbf_status[NB_CMA_CHANNELS] __attribute__((aligned(64)));
167
[449]168////////////////////////////////////////////////////////////////////////////
[258]169//    Initialize the syscall vector with syscall handlers
170// Note: This array must be synchronised with the define in file stdio.h
171////////////////////////////////////////////////////////////////////////////
[494]172
173__attribute__((section(".kdata")))
[258]174const void * _syscall_vector[64] = 
175{
[556]176    &_sys_proc_xyp,                  /* 0x00 */
177    &_get_proctime,                  /* 0x01 */
[709]178    &_sys_procs_number,              /* 0x02 */
179    &_sys_xy_from_ptr,               /* 0x03 */
180    &_sys_ukn,                       /* 0x04 */
181    &_sys_ukn,                       /* 0x05 */
[670]182    &_sys_ukn,                       /* 0x06 */
[556]183    &_sys_heap_info,                 /* 0x07 */
[709]184    &_sys_vseg_get_vbase,            /* 0x08 */
185    &_sys_vseg_get_length,           /* 0x09 */ 
[556]186    &_sys_fbf_cma_alloc,             /* 0x0A */
[614]187    &_sys_fbf_cma_init_buf,          /* 0x0B */
188    &_sys_fbf_cma_start,             /* 0x0C */
189    &_sys_fbf_cma_display,           /* 0x0D */
190    &_sys_fbf_cma_stop,              /* 0x0E */
[709]191    &_sys_ukn,                       /* 0x0F */
[258]192
[709]193    &_sys_applications_status,       /* 0x10 */
[614]194    &_sys_fbf_sync_write,            /* 0x11 */
195    &_sys_fbf_sync_read,             /* 0x12 */
[709]196    &_sys_ukn,                       /* 0x13 */
[556]197    &_sys_tim_alloc,                 /* 0x14 */
198    &_sys_tim_start,                 /* 0x15 */ 
199    &_sys_tim_stop,                  /* 0x16 */
[629]200    &_sys_kill_application,          /* 0x17 */
201    &_sys_exec_application,          /* 0x18 */   
[709]202    &_sys_ukn,                       /* 0x19 */
203    &_sys_pthread_control,           /* 0x1A */
204    &_sys_pthread_yield,             /* 0x1B */
205    &_sys_pthread_kill,              /* 0x1C */
206    &_sys_pthread_create,            /* 0x1D */
207    &_sys_pthread_join,              /* 0x1E */
208    &_sys_pthread_exit,              /* 0x1F */
[258]209
[592]210    &_fat_open,                      /* 0x20 */
[709]211    &_fat_read,                      /* 0x21 */
[592]212    &_fat_write,                     /* 0x22 */
213    &_fat_lseek,                     /* 0x23 */
214    &_fat_file_info,                 /* 0x24 */
[556]215    &_fat_close,                     /* 0x25 */
[592]216    &_fat_remove,                    /* 0x26 */
217    &_fat_rename,                    /* 0x27 */
218    &_fat_mkdir,                     /* 0x28 */
[661]219    &_fat_opendir,                   /* 0x29 */
220    &_fat_closedir,                  /* 0x2A */
221    &_fat_readdir,                   /* 0x2B */
222    &_sys_ukn,                       /* 0x2C */
[556]223    &_sys_ukn,                       /* 0x2D */
224    &_sys_ukn,                       /* 0x2E */
225    &_sys_ukn,                       /* 0x2F */
[258]226
[556]227    &_sys_nic_alloc,                 /* 0x30 */
228    &_sys_nic_start,                 /* 0x31 */
229    &_sys_nic_move,                  /* 0x32 */
230    &_sys_nic_stop,                  /* 0x33 */
231    &_sys_nic_stats,                 /* 0x34 */
232    &_sys_nic_clear,                 /* 0x35 */ 
[709]233    &_sys_tty_write,                 /* 0x36 */
234    &_sys_tty_read,                  /* 0x37 */
235    &_sys_tty_alloc,                 /* 0x38 */
[556]236    &_sys_ukn,                       /* 0x39 */
237    &_sys_ukn,                       /* 0x3A */
238    &_sys_coproc_completed,          /* 0x3B */
239    &_sys_coproc_alloc,              /* 0x3C */
240    &_sys_coproc_channel_init,       /* 0x3D */
241    &_sys_coproc_run,                /* 0x3E */
242    &_sys_coproc_release,            /* 0x3F */
[258]243};
244
[709]245
246//////////////////////////////////////////////////////////////////////////////
247//           Applications related syscall handlers
248//////////////////////////////////////////////////////////////////////////////
249
[707]250////////////////////////////////////////////////////////////////////////
[709]251// This function is called by the _sys_exec_application function
252// to reload all data segments contained in an application.elf file.
253////////////////////////////////////////////////////////////////////////
[707]254static unsigned int _load_writable_segments( mapping_vspace_t*  vspace )
255{
[709]256
257#if GIET_DEBUG_EXEC 
[707]258unsigned int gpid       = _get_procid();
259unsigned int cluster_xy = gpid >> P_WIDTH;
260unsigned int p          = gpid & ((1<<P_WIDTH)-1);
261unsigned int x          = cluster_xy >> Y_WIDTH;
262unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[709]263if ( _get_proctime() > GIET_DEBUG_EXEC )
264_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
265        "enters for %s\n", x , y , p , vspace->name );
[707]266#endif
[459]267
[707]268    mapping_header_t*  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
269    mapping_vseg_t*    vseg    = _get_vseg_base(header);
270
[709]271    unsigned int vseg_id;        // vseg index in mapping
272    char         buf[4096];      // buffer to store one cluster
273    unsigned int fd = 0;         // file descriptor
[707]274
[709]275    // first scan on vsegs in vspace to find the .elf pathname
[707]276    for (vseg_id = vspace->vseg_offset;
277         vseg_id < (vspace->vseg_offset + vspace->vsegs);
278         vseg_id++)
279    {
[709]280        if( vseg[vseg_id].type == VSEG_TYPE_ELF )
[707]281        {
[709]282            // open the .elf file associated to vspace
[707]283            fd = _fat_open( vseg[vseg_id].binpath , O_RDONLY );
[709]284            if ( fd < 0 ) return 1;
285            break;
[707]286
[709]287#if GIET_DEBUG_EXEC
288if ( _get_proctime() > GIET_DEBUG_EXEC )
289_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
290        "open %s / fd = %d\n", x , y , p , vseg[vseg_id].binpath , fd );
[707]291#endif
292        }
293    }
[709]294 
[707]295    // load Elf-Header into buffer from .elf file
[709]296    if ( _fat_lseek( fd, 0, SEEK_SET ) < 0 )
297    {
298        _fat_close( fd );
299        return 1;
300    }
301    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
302    {
303        _fat_close( fd );
304        return 1;
305    }
[707]306
[709]307#if GIET_DEBUG_EXEC
308if ( _get_proctime() > GIET_DEBUG_EXEC )
309_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
310        "loaded Elf-Header\n", x , y , p );
[707]311#endif
312
313    // get nsegments and Program-Header-Table offset from Elf-Header
314    Elf32_Ehdr*  elf_header_ptr = (Elf32_Ehdr*)buf;
315    unsigned int offset         = elf_header_ptr->e_phoff;
316    unsigned int nsegments      = elf_header_ptr->e_phnum;
317
318    // load Program-Header-Table from .elf file
[709]319    if ( _fat_lseek( fd, offset, SEEK_SET ) < 0 )
320    {
321        _fat_close( fd );
322        return 1;
323    }
324    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
325    {
326        _fat_close( fd );
327        return 1;
328    }
[707]329
[709]330#if GIET_DEBUG_EXEC
331if ( _get_proctime() > GIET_DEBUG_EXEC )
332_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
333        "loaded Program-Header-Table\n", x , y , p );
[707]334#endif
335
336    // set Program-Header-Table pointer
337    Elf32_Phdr*  elf_pht_ptr = (Elf32_Phdr*)buf;
338
[709]339    // second scan on vsegs in vspace to load the seg_data segments :
340    // - type == VSEG_TYPE_ELF
341    // - non eXecutable
342    for (vseg_id = vspace->vseg_offset;
343         vseg_id < (vspace->vseg_offset + vspace->vsegs);
344         vseg_id++)
[707]345    {
[709]346        if( (vseg[vseg_id].type == VSEG_TYPE_ELF) &&   // type ELF
347            ((vseg[vseg_id].mode & 0x4) == 0) )        // non executable
[707]348        {
[709]349            // get vbase and pbase
350            paddr_t      pbase = vseg[vseg_id].pbase; 
351            unsigned int vbase = vseg[vseg_id].vbase;
[707]352
[709]353            // scan segments in Progam-Header-Table to find match
354            // No match checking as the segment was previously found
355            unsigned int seg;
356            for (seg = 0 ; seg < nsegments ; seg++)
357            {
358                if ( (elf_pht_ptr[seg].p_type == PT_LOAD) &&    // loadable
359                     (elf_pht_ptr[seg].p_flags & PF_W)    &&    // writable
360                     (elf_pht_ptr[seg].p_vaddr == vbase) )      // matching
361                {
362                    // Get segment offset and size in .elf file
363                    unsigned int seg_offset = elf_pht_ptr[seg].p_offset;
364                    unsigned int seg_size   = elf_pht_ptr[seg].p_filesz;
[707]365
[709]366                    // compute destination address and extension for _fat_read()
367                    unsigned int dest   = (unsigned int)pbase;
368                    unsigned int extend = (unsigned int)(pbase>>32) | 0xFFFF0000;
369
370                    // load the segment
371                    if ( _fat_lseek( fd, seg_offset, SEEK_SET ) < 0 ) 
372                    {
373                        _fat_close( fd );
374                        return 1;
375                    }
376                    if ( _fat_read( fd, dest, seg_size, extend ) < 0 )
377                    {
378                        _fat_close( fd );
379                        return 1;
380                    }
381                }
382            }
383
384#if GIET_DEBUG_EXEC
385if ( _get_proctime() > GIET_DEBUG_EXEC )
386_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
387        "loaded segment %x\n", x , y , p , vbase );
[707]388#endif
389        }
390    }  // end loop on writable & loadable segments
391
392    // close .elf file
393    _fat_close( fd );
394
395    return 0;
396}  // end load_writable_segments()
397
[648]398
[709]399
[648]400///////////////////////////////////////
[709]401int _sys_exec_application( char* name )
[648]402{
403    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
404    mapping_vspace_t * vspace  = _get_vspace_base(header);
[709]405    mapping_thread_t * thread  = _get_thread_base(header);
406    mapping_vseg_t   * vseg    = _get_vseg_base(header);
[648]407
408    unsigned int vspace_id;
[709]409    unsigned int thread_id;
[648]410
[709]411#if GIET_DEBUG_EXEC
412unsigned int gpid       = _get_procid();
413unsigned int cluster_xy = gpid >> P_WIDTH;
414unsigned int p          = gpid & ((1<<P_WIDTH)-1);
415unsigned int x          = cluster_xy >> Y_WIDTH;
416unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[648]417if ( _get_proctime() > GIET_DEBUG_EXEC )
[709]418_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
419        "enters for %s at cycle %d\n", x, y, p, name, _get_proctime() );
[648]420#endif
421
[709]422    unsigned int y_size = header->y_size;
423
424    // scan vspaces to find matching vspace name
425    for (vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++) 
[648]426    {
[709]427        if ( _strcmp( vspace[vspace_id].name, name ) == 0 )  // vspace found
[648]428        {
429
[709]430#if GIET_DEBUG_EXEC
431if ( _get_proctime() > GIET_DEBUG_EXEC )
432_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
433        "found vspace %s at cycle  %d\n", x, y, p, name, _get_proctime() );
434#endif
435            // reload writable segments
436            if ( _load_writable_segments( &vspace[vspace_id] ) )
[648]437            {
[709]438                _printf("[GIET ERROR] _sys_exec_application() : "
439                        "can't load data segment for vspace %s\n", name );
440                return GIET_SYSCALL_CANNOT_LOAD_DATA_SEGMENT;
441            }
442 
443#if GIET_DEBUG_EXEC
444if ( _get_proctime() > GIET_DEBUG_EXEC )
445_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
446        "load segments for vspace %s at cycle  %d\n", x, y, p, name, _get_proctime() );
447#endif
448            // scan threads in vspace with three goals :
449            // - check all threads desactivated
450            // - re-initialise all threads contexts
451            // - find main thread
452            unsigned int        main_found  = 0;
453            unsigned int        main_ltid   = 0;
454            static_scheduler_t* main_psched = NULL;
455            unsigned int        min         = vspace[vspace_id].thread_offset; 
456            unsigned int        max         = min + vspace[vspace_id].threads; 
457            for ( thread_id = min ; thread_id < max ; thread_id++ ) 
458            {
459                // get thread identifiers : [x,y,p,ltid]
460                unsigned int cid   = thread[thread_id].clusterid;
[648]461                unsigned int x     = cid / y_size;
462                unsigned int y     = cid % y_size;
[709]463                unsigned int p     = thread[thread_id].proclocid;
464                unsigned int ltid  = thread[thread_id].ltid;
465                unsigned int vsid  = thread[thread_id].stack_vseg_id;
[648]466
[709]467                // get scheduler pointer
468                static_scheduler_t* psched = _schedulers[x][y][p];
[648]469
[709]470                // check thread non active
471                if ( psched->context[ltid].slot[CTX_NORUN_ID] == 0 )  // runnable !!!
472                {
473                    _printf("\n[GIET ERROR] in _sys_exec_application() : "
474                            "thread %s already active in vspace %s\n",
475                            thread[thread_id].name, name );
476                    return GIET_SYSCALL_THREAD_ALREADY_ACTIVE;
477                }
478               
479                // initialise thread context
480                unsigned int ctx_epc = psched->context[ltid].slot[CTX_ENTRY_ID];
481                unsigned int ctx_sp  = vseg[vsid].vbase + vseg[vsid].length;
482                unsigned int ctx_ra  = (unsigned int)&_ctx_eret;
483                unsigned int ctx_sr  = GIET_SR_INIT_VALUE;
[648]484
[709]485                psched->context[ltid].slot[CTX_EPC_ID] = ctx_epc;
486                psched->context[ltid].slot[CTX_RA_ID]  = ctx_ra;
487                psched->context[ltid].slot[CTX_SR_ID]  = ctx_sr;
488                psched->context[ltid].slot[CTX_SP_ID]  = ctx_sp;
489
490                // register information required to activate main thread
491                // actual activation done when threads initialisation is completed
492                if ( thread[thread_id].is_main ) 
493                {
494                    main_psched = psched;
495                    main_ltid   = ltid;
496                    main_found  = 1;
497                }
498 
[648]499#if GIET_DEBUG_EXEC
500if ( _get_proctime() > GIET_DEBUG_EXEC )
[709]501_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
502        "initialise thread %s at cycle  %d\n",
503        x, y, p, thread[thread_id].name, _get_proctime() );
[648]504#endif
[709]505            }  // end loop on vspace threads
[648]506
[709]507            // activate main thread
508            if ( main_found )
509            {
510                main_psched->context[main_ltid].slot[CTX_NORUN_ID] = 0;
511            }
512            else
513            {
514                _printf("\n[GIET ERROR] in _sys_exec_application() : "
515                        "main not found in vspace %s\n", name );
516                return GIET_SYSCALL_MAIN_NOT_FOUND;
517            }
518             
[648]519#if GIET_DEBUG_EXEC
520if ( _get_proctime() > GIET_DEBUG_EXEC )
[709]521_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
522        "lauched %s at cycle %d\n", x, y, p, name, _get_proctime() );
[648]523#endif
[709]524            return GIET_SYSCALL_OK;
525        }
526    }  // end of loop on vspaces
[648]527
[709]528    // vspace not found
529    _printf("\n[GIET ERROR] in _sys_exec_application() : "
530            "vspace %s not found\n", name );
531    return GIET_SYSCALL_VSPACE_NOT_FOUND;
[648]532
[709]533}  // end _sys_exec_application()
[648]534   
[709]535
[648]536///////////////////////////////////////
[709]537int _sys_kill_application( char* name )
[648]538{
539    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
540    mapping_vspace_t * vspace  = _get_vspace_base(header);
[709]541    mapping_thread_t * thread  = _get_thread_base(header);
[648]542
543    unsigned int vspace_id;
[709]544    unsigned int thread_id;
[648]545
[707]546#if GIET_DEBUG_EXEC
[709]547unsigned int gpid       = _get_procid();
548unsigned int cluster_xy = gpid >> P_WIDTH;
549unsigned int p          = gpid & ((1<<P_WIDTH)-1);
550unsigned int x          = cluster_xy >> Y_WIDTH;
551unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[648]552if ( _get_proctime() > GIET_DEBUG_EXEC )
[709]553_printf("\n[DEBUG EXEC] _sys_kill_application() P[%d,%d,%d] "
554        "enters at cycle %d for %s\n", x, y, p, _get_proctime() , name );
[648]555#endif
556
[709]557    // shell cannot be killed
558    if ( _strcmp( name , "shell" ) == 0 )
[648]559    {
[709]560        _printf("\n[GIET ERROR] in _sys_kill_application() : "
561                "%s application cannot be killed\n", name );
562        return GIET_SYSCALL_APPLI_CANNOT_BE_KILLED;
[707]563    }
[648]564
[709]565    // scan vspaces to find matching vspace name
566    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
[707]567    {
[709]568        if ( _strcmp( vspace[vspace_id].name, name ) == 0 ) 
569        {
570            // scan threads to send KILL signal to all threads in vspace
571            unsigned int y_size = header->y_size;
572            unsigned int min    = vspace[vspace_id].thread_offset; 
573            unsigned int max    = min + vspace[vspace_id].threads; 
574            for ( thread_id = min ; thread_id < max ; thread_id++ ) 
575            {
576                unsigned int cid   = thread[thread_id].clusterid;
577                unsigned int x     = cid / y_size;
578                unsigned int y     = cid % y_size;
579                unsigned int p     = thread[thread_id].proclocid;
580                unsigned int ltid  = thread[thread_id].ltid;
[648]581
[709]582                // get scheduler pointer for processor running the thread
583                static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
584
585                // set KILL signal bit
586                _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
587            } 
588
589#if GIET_DEBUG_EXEC
590if ( _get_proctime() > GIET_DEBUG_EXEC )
591_printf("\n[DEBUG EXEC] _sys_kill_application() P[%d,%d,%d] "
592        "kill %s at cycle %d\n", x, y, p, name, _get_proctime() );
593#endif
594
595            return GIET_SYSCALL_OK;
596        }
597    }  // en loop on vspaces
598
599    _printf("\n[GIET ERROR] in _sys_kill_application() : "
600            "application %s not found\n", name );
601    return GIET_SYSCALL_VSPACE_NOT_FOUND;
602
603}  // end _sys_kill_application()
604   
605
606
607//////////////////////////////
608int _sys_applications_status()
609{
610    mapping_header_t *  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
611    mapping_thread_t *  thread  = _get_thread_base(header);
612    mapping_vspace_t *  vspace  = _get_vspace_base(header);
613    mapping_cluster_t * cluster = _get_cluster_base(header);
614
615    unsigned int thread_id;
616    unsigned int vspace_id;
617
618    // scan all vspaces
619    for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
[707]620    {
[709]621        _user_printf("\n*** vspace %s\n", vspace[vspace_id].name );
[648]622
[709]623        // scan all threads in vspace
624        unsigned int min = vspace[vspace_id].thread_offset ;
625        unsigned int max = min + vspace[vspace_id].threads ;
626        for ( thread_id = min ; thread_id < max ; thread_id++ )
627        {
628            unsigned int         clusterid = thread[thread_id].clusterid;
629            unsigned int         p         = thread[thread_id].proclocid;
630            unsigned int         x         = cluster[clusterid].x;
631            unsigned int         y         = cluster[clusterid].y;
632            unsigned int         ltid      = thread[thread_id].ltid;
633            static_scheduler_t*  psched    = (static_scheduler_t*)_schedulers[x][y][p];
634            unsigned int         norun     = psched->context[ltid].slot[CTX_NORUN_ID];
635            unsigned int         tty       = psched->context[ltid].slot[CTX_TTY_ID];
636            unsigned int         current   = psched->current;
[648]637
[709]638            if ( current == ltid )
639            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
640                         "TTY = %d / norun = %x : running\n", 
641                         thread[thread_id].name, x, y, p, ltid, tty, norun );
642            else if ( norun == 0 )
643            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
644                         "TTY = %d / norun = %x : runable\n", 
645                         thread[thread_id].name, x, y, p, ltid, tty, norun);
646            else
647            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
648                         "TTY = %d / norun = %x : blocked\n", 
649                         thread[thread_id].name, x, y, p, ltid, tty, norun);
[648]650        }
651    }
[709]652    _user_printf("\n");
653    return GIET_SYSCALL_OK;
654}  // end _sys_applications_status()
[648]655
[709]656
657
658/////////////////////////////////////////////////////////////////////////////
659//          Threads related syscall handlers
660/////////////////////////////////////////////////////////////////////////////
661
662////////////////////////////////////////////////
663int _sys_pthread_create( unsigned int*  buffer,
664                         void*          attr,
665                         void*          function,
666                         void*          arg )
667{
668    // attr argument not supported
669    if ( attr != NULL )
[707]670    {
[709]671        _printf("\n[GIET ERROR] in _sys_pthread_create() : "
672                "attr argument not supported\n" );
673       
674        return GIET_SYSCALL_PTHREAD_ARGUMENT_NOT_SUPPORTED;
[707]675    }
676
[709]677    // get pointers in mapping
678    mapping_header_t*    header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
679    mapping_thread_t*    thread   = _get_thread_base(header);
680    mapping_vspace_t*    vspace   = _get_vspace_base(header);
681    mapping_cluster_t*   cluster  = _get_cluster_base(header);
682
683    // get scheduler for processor running the calling thread
684    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
685
686    // get calling thread local index in scheduler
687    unsigned int  current = psched->current;
688
689    // get vspace index
690    unsigned int  vspace_id = psched->context[current].slot[CTX_VSID_ID];
691
692#if GIET_DEBUG_EXEC
693if ( _get_proctime() > GIET_DEBUG_EXEC )
694_printf("\n[DEBUG EXEC] _sys_pthread_create() : enters at cycle %d"
695        " for vspace %s / entry = %x\n",
696        _get_proctime() , vspace[vspace_id].name , (unsigned int)function );
697#endif
698
699    unsigned int thread_id;        // searched thread : local index in mapping
700    unsigned int clusterid;        // searched thread : cluster index
701    unsigned int lpid;             // searched thread : processor local index
702    unsigned int ltid;             // searched thread : scheduler thread index
703    unsigned int cx;               // searched thread : X coordinate for searched thread
704    unsigned int cy;               // searched thread : Y coordinate for searched thread
705    unsigned int entry;            // searched thread : entry point
706    unsigned int norun;            // searched thread : norun vector
707    unsigned int trdid;            // searched thread : thread identifier
708
709    // scan threads in vspace to find an inactive thread matching function
710    unsigned int min   = vspace[vspace_id].thread_offset;
711    unsigned int max   = min + vspace[vspace_id].threads;
712    unsigned int found = 0;
713    for ( thread_id = min ; (thread_id < max) && (found == 0) ; thread_id++ )
[707]714    {
[709]715        // get thread coordinates [cx,cy,lpid] and ltid from mapping
716        ltid       = thread[thread_id].ltid;
717        clusterid  = thread[thread_id].clusterid; 
718        lpid       = thread[thread_id].proclocid;
719        cx = cluster[clusterid].x;
720        cy = cluster[clusterid].y;
[707]721
[709]722        // get thread scheduler pointer
723        psched = _schedulers[cx][cy][lpid];
[707]724
[709]725        // get thread entry-point, norun-vector, and trdid from context
726        entry = psched->context[ltid].slot[CTX_ENTRY_ID];
727        norun = psched->context[ltid].slot[CTX_NORUN_ID];
728        trdid = psched->context[ltid].slot[CTX_TRDID_ID];
[707]729
[709]730        // check matching
731        if ( ((unsigned int)function == entry ) && 
732             (norun & NORUN_MASK_THREAD)  ) found = 1;
733
734    }  // end loop on threads
735
736    if ( found )  // one matching inactive thread has been found
737    {
738        // set argument value in thread context
739        if ( arg != NULL ) psched->context[ltid].slot[CTX_A0_ID] = (unsigned int)arg;
740
741        // activate thread
742        psched->context[ltid].slot[CTX_NORUN_ID] = 0;
743
744        // return launched thead global identifier
745        *buffer   = trdid;
746               
747#if GIET_DEBUG_EXEC
748if ( _get_proctime() > GIET_DEBUG_EXEC )
749_printf("\n[DEBUG EXEC] exit _sys_pthread_create() at cycle %d : thread %x launched\n",
750        _get_proctime() , trdid);
751#endif
752        return GIET_SYSCALL_OK;
[707]753    }
[709]754    else         // no matching thread found
755    {
756        _printf("\n[GIET ERROR] in _sys_pthread_create() : "
757                "no matching thread for entry = %x in vspace %s\n",
758                (unsigned int)function , vspace[vspace_id].name );
759       
760        return GIET_SYSCALL_THREAD_NOT_FOUND;
761    }
[707]762
[709]763} // end _sys_pthread_create()
764
765
766///////////////////////////////////////////
767int _sys_pthread_join( unsigned int  trdid,
768                       void*         ptr )
769{
770    // ptr argument not supported
771    if ( ptr != NULL )
772    {
773        _printf("\n[GIET ERROR] in _sys_pthread_join() : "
774                "ptr argument not supported, must be NULL\n" );
775       
776        return GIET_SYSCALL_PTHREAD_ARGUMENT_NOT_SUPPORTED;
777    }
778
779               
780#if GIET_DEBUG_EXEC
[648]781if ( _get_proctime() > GIET_DEBUG_EXEC )
[709]782_printf("\n[DEBUG EXEC] enters _sys_pthread_join() at cycle %d for thread %x\n",
783        _get_proctime() , trdid );
[648]784#endif
785
[709]786    // get calling thread vspace
787    unsigned int  caller_vspace = _get_context_slot( CTX_VSID_ID );
788
789    // get and check target thread indexes from trdid
790    unsigned int cx   = (trdid>>24) & 0xFF;
791    unsigned int cy   = (trdid>>16) & 0xFF;
792    unsigned int lpid = (trdid>>8 ) & 0xFF;
793    unsigned int ltid = (trdid    ) & 0xFF;
794
795    // get target thread scheduler, vspace and registered trdid
796    static_scheduler_t*  psched   = _schedulers[cx][cy][lpid];
797    unsigned int target_vspace    = psched->context[ltid].slot[CTX_VSID_ID];
798    unsigned int registered_trdid = psched->context[ltid].slot[CTX_TRDID_ID];
799
800    // check trdid
801    if ( trdid != registered_trdid )
802    {
803       _printf("\nerror in _sys_pthread_join() : "
804               "trdid = %x / registered_trdid = %x\n",
805               trdid , registered_trdid );
806
807       return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
808    }
809   
810    // check calling thread and target thread in same vspace
811    if ( caller_vspace != target_vspace )
812    {
813       _printf("\n[GIET ERROR] in _sys_pthread_join() : "
814               " calling thread and target thread not in same vspace\n");
815
816       return GIET_SYSCALL_NOT_IN_SAME_VSPACE;
817    }
818
819    // get target thread state
820    unsigned int* pnorun = &psched->context[ltid].slot[CTX_NORUN_ID];
821
822    asm volatile ( "2000:                      \n"                         
823                   "move  $11,  %0             \n"   /* $11 <= ptr           */
824                   "lw    $11,  0($11)         \n"   /* $11 <= M[ptr]        */
825                   "andi  $11,  $11,    1      \n"   /* $11 <= norun & 0x1   */
826                   "beqz  $11,  2000b          \n"   
827                   :
828                   : "r" (pnorun)
829                   : "$11" );
830
831    return GIET_SYSCALL_OK;
832
833}  // end _sys_pthread_join()
834                       
835
836////////////////////////////////////////
837int _sys_pthread_kill( pthread_t  trdid,
838                       int        signal )
839{
840    // get calling thread vspace
841    unsigned int  caller_vspace = _get_context_slot( CTX_VSID_ID );
842
843    // get and check target thread indexes from trdid
844    unsigned int cx   = (trdid>>24) & 0xFF;
845    unsigned int cy   = (trdid>>16) & 0xFF;
846    unsigned int lpid = (trdid>>8 ) & 0xFF;
847    unsigned int ltid = (trdid    ) & 0xFF;
848
849    // get target thread scheduler, vspace and registered trdid
850    static_scheduler_t*  psched       = _schedulers[cx][cy][lpid];
851    unsigned int target_vspace        = psched->context[ltid].slot[CTX_VSID_ID];
852    unsigned int registered_trdid = psched->context[ltid].slot[CTX_TRDID_ID];
853
854    // check trdid
855    if ( trdid != registered_trdid )
856    {
857       _printf("\n[GIET ERROR] in _sys_pthread_kill() : trdid = %x"
858               " / registered_trdid = %x\n", trdid , registered_trdid );
859       return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
860    }
861   
862    // check calling thread and target thread in same vspace
863    if ( caller_vspace != target_vspace )
864    {
865       _printf("\n[GIET ERROR] in _sys_pthread_kill() : not in same vspace\n");
866       return GIET_SYSCALL_NOT_IN_SAME_VSPACE;
867    }
868
869    // register KILL signal in target thread context if required
870    if ( signal )
871    {
872        _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
873    }
874
875    return GIET_SYSCALL_OK;
876
877}  // end _sys_pthread_kill()
878
879
880/////////////////////////////////////
881int _sys_pthread_exit( void* string ) 
882{
883    unsigned int date       = _get_proctime();
884
885    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
886    mapping_vspace_t * vspace  = _get_vspace_base(header);
887
888    unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
889    unsigned int trdid      = _get_context_slot(CTX_TRDID_ID);
890    unsigned int vsid       = _get_context_slot(CTX_VSID_ID);
891
892    // print exit message
893    if ( string == NULL )
894    {
895        _printf("\n[GIET WARNING] Exit thread %x in vspace %s at cycle %d\n",
896                trdid , vspace[vsid].name , date );
897    }
898    else
899    {
900        _printf("\n[GIET WARNING] Exit thread %x in vspace %s at cycle %d\n"
901                "               Cause : %s\n\n",
902                trdid , vspace[vsid].name , date , (char*) string );
903    }
[648]904   
[709]905    // get scheduler pointer for calling thread
906    static_scheduler_t*  psched = (static_scheduler_t*)_get_sched();
[648]907
[709]908    // register KILL signal in calling thread context (suicid request)
909    _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
910
911    // deschedule calling thread
912    unsigned int save_sr; 
913    _it_disable( &save_sr );
914
915    _ctx_switch();
916
917    return GIET_SYSCALL_OK;
918
919}  // end _sys_pthread_exit()
920
921////////////////////////
922int _sys_pthread_yield() 
923{
924    unsigned int save_sr;
925
926    _it_disable( &save_sr );
927    _ctx_switch();
928    _it_restore( &save_sr );
929
930    return GIET_SYSCALL_OK;
931}
932
933//////////////////////////////////////////////////
934int _sys_pthread_control( unsigned  int  command,
935                          char*     vspace_name,
936                          char*     thread_name )
937{
938
939#if GIET_DEBUG_EXEC
940if ( _get_proctime() > GIET_DEBUG_EXEC )
941_printf("\n[DEBUG EXEC] _sys_pthread_control() at cycle %d : "
942        "enter for vspace %s / thread %s / command = %d\n",
943        _get_proctime() , vspace_name, thread_name, command );
944#endif
945
946    // get pointers in mapping
947    mapping_header_t*    header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
948    mapping_thread_t*    thread   = _get_thread_base(header);
949    mapping_vspace_t*    vspace   = _get_vspace_base(header);
950    mapping_cluster_t*   cluster  = _get_cluster_base(header);
951
952    unsigned int found;
953
954    // search vspace name to get vspace index: vsid
955    found = 0;
956    unsigned int   vsid;
957    for( vsid = 0 ; vsid < header->vspaces ; vsid++ )
958    {
959        if ( _strcmp( vspace[vsid].name, vspace_name ) == 0 )
960        {
961            found = 1;
962            break;
963        }
964    }
965
966    if ( found == 0 ) return GIET_SYSCALL_VSPACE_NOT_FOUND;
967
968    // search thread name in vspace to get thread index: tid
969    found = 0;
970    unsigned int   tid;
971    unsigned int   min = vspace[vsid].thread_offset;
972    unsigned int   max = min + vspace[vsid].threads;
973    for( tid = min ; tid < max ; tid++ )
974    {
975        if ( _strcmp( thread[tid].name, thread_name ) == 0 )
976        {
977            found = 1;
978            break;
979        }
980    }
981
982    if ( found == 0 ) return GIET_SYSCALL_THREAD_NOT_FOUND;
983
984    // get thread coordinates
985    unsigned int cid  = thread[tid].clusterid;
986    unsigned int x    = cluster[cid].x;
987    unsigned int y    = cluster[cid].y;
988    unsigned int p    = thread[tid].proclocid;
989    unsigned int ltid = thread[tid].ltid;
990
991    static_scheduler_t* psched = _schedulers[x][y][p];
992
993    // check trdid and vsid
994    unsigned int trdid = x<<24 | y<<16 | p<<8 | ltid;
995    if ( (psched->context[ltid].slot[CTX_TRDID_ID] != trdid) ||
996         (psched->context[ltid].slot[CTX_VSID_ID]  != vsid) )
997        return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
998
999    // execute command
1000    if ( command == THREAD_CMD_PAUSE ) 
1001    {
1002        _atomic_or ( &psched->context[ltid].slot[CTX_NORUN_ID],  NORUN_MASK_THREAD );
1003        return GIET_SYSCALL_OK;
1004    }
1005    else if ( command == THREAD_CMD_RESUME )
1006    {
1007        _atomic_and( &psched->context[ltid].slot[CTX_NORUN_ID], ~NORUN_MASK_THREAD );
1008        return GIET_SYSCALL_OK;
1009    }
1010    else if ( command == THREAD_CMD_CONTEXT )
1011    {
1012        _user_printf( " - CTX_TRDID  = %x\n"
1013                      " - CTX_VSID   = %x\n"
1014                      " - CTX_EPC    = %x\n"
1015                      " - CTX_PTAB   = %x\n"
1016                      " - CTX_PTPR   = %x\n"
1017                      " - CTX_SR     = %x\n"
1018                      " - CTX_RA     = %x\n"
1019                      " - CTX_SP     = %x\n"
1020                      " - CTX_ENTRY  = %x\n"
1021                      " - CTX_NORUN  = %x\n"
1022                      " - CTX_SIGS   = %x\n"
1023                      " - CTX_LOCKS  = %x\n"
1024                      " - CTX_TTY    = %x\n"
1025                      " - CTX_NIC_RX = %x\n"
1026                      " - CTX_NIC_TX = %x\n"
1027                      " - CTX_CMA_RX = %x\n"
1028                      " - CTX_CMA_TX = %x\n"
1029                      " - CTX_CMA_FB = %x\n",
1030                      psched->context[ltid].slot[CTX_TRDID_ID], 
1031                      psched->context[ltid].slot[CTX_VSID_ID], 
1032                      psched->context[ltid].slot[CTX_EPC_ID], 
1033                      psched->context[ltid].slot[CTX_PTAB_ID], 
1034                      psched->context[ltid].slot[CTX_PTPR_ID], 
1035                      psched->context[ltid].slot[CTX_SR_ID], 
1036                      psched->context[ltid].slot[CTX_RA_ID], 
1037                      psched->context[ltid].slot[CTX_SP_ID], 
1038                      psched->context[ltid].slot[CTX_ENTRY_ID], 
1039                      psched->context[ltid].slot[CTX_NORUN_ID],
1040                      psched->context[ltid].slot[CTX_SIGS_ID],
1041                      psched->context[ltid].slot[CTX_LOCKS_ID],
1042                      psched->context[ltid].slot[CTX_TTY_ID],
1043                      psched->context[ltid].slot[CTX_NIC_RX_ID],
1044                      psched->context[ltid].slot[CTX_NIC_TX_ID],
1045                      psched->context[ltid].slot[CTX_CMA_RX_ID],
1046                      psched->context[ltid].slot[CTX_CMA_TX_ID],
1047                      psched->context[ltid].slot[CTX_CMA_FB_ID] );
1048        return GIET_SYSCALL_OK;
1049    }
1050    else
1051    {
1052        return GIET_SYSCALL_ILLEGAL_THREAD_COMMAND_TYPE;
1053    }
1054
1055} // end _sys_pthread_control()
1056
1057
1058
1059
[648]1060//////////////////////////////////////////////////////////////////////////////
[519]1061//           Coprocessors related syscall handlers
1062//////////////////////////////////////////////////////////////////////////////
1063
1064//////////////////////////////////////////////////
1065int _sys_coproc_alloc( unsigned int   coproc_type,
[556]1066                       unsigned int*  coproc_info )
[519]1067{
1068    // In this implementation, the allocation policy is constrained:
[709]1069    // the coprocessor must be in the same cluster as the calling thread,
[556]1070    // and there is at most one coprocessor per cluster
[519]1071
1072    mapping_header_t  * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1073    mapping_cluster_t * cluster = _get_cluster_base(header);
1074    mapping_periph_t  * periph  = _get_periph_base(header);
1075
1076    // get cluster coordinates and cluster global index
1077    unsigned int procid     = _get_procid();
1078    unsigned int x          = procid >> (Y_WIDTH + P_WIDTH);
1079    unsigned int y          = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]1080    unsigned int cluster_id = x * Y_SIZE + y;
[519]1081 
1082    // search coprocessor in cluster
1083    mapping_periph_t*  found = NULL;
1084    unsigned int min   = cluster[cluster_id].periph_offset;
1085    unsigned int max   = min + cluster[cluster_id].periphs;
1086    unsigned int periph_id;
1087    for ( periph_id = min ; periph_id < max ; periph_id++ )
1088    {
1089        if ( (periph[periph_id].type == PERIPH_TYPE_MWR) &&
1090             (periph[periph_id].subtype == coproc_type) )
1091        {
1092            found = &periph[periph_id];
1093            break;
1094        }
1095    } 
1096
1097    if ( found != NULL )
1098    {
1099        // get the lock (at most one coproc per cluster)
1100        _simple_lock_acquire( &_coproc_lock[cluster_id] );
[556]1101
1102        // register coproc characteristics in kernel arrays
1103        _coproc_type[cluster_id] = coproc_type;
1104        _coproc_info[cluster_id] = (found->arg0 & 0xFF)     |
1105                                   (found->arg1 & 0xFF)<<8  |
1106                                   (found->arg2 & 0xFF)<<16 |
1107                                   (found->arg3 & 0xFF)<<24 ;
1108
[519]1109        // returns coprocessor info
[556]1110        *coproc_info = _coproc_info[cluster_id];
[519]1111
[709]1112        // register coprocessor coordinates in thread context
[556]1113        unsigned int cluster_xy = (x<<Y_WIDTH) + y;
1114        _set_context_slot( CTX_COPROC_ID , cluster_xy );
1115
[519]1116#if GIET_DEBUG_COPROC
1117_printf("\n[GIET DEBUG COPROC] _sys_coproc_alloc() in cluster[%d,%d]\n"
1118        "  coproc_info = %x / cluster_xy = %x\n",
[556]1119        x , y , *coproc_info , cluster_xy );
[519]1120#endif
[709]1121        return GIET_SYSCALL_OK;
[519]1122    }
1123    else
1124    {
1125         _printf("\n[GIET_ERROR] in _sys_coproc_alloc(): no coprocessor "
1126                 " with type %d available in cluster[%d,%d]\n",
1127                 coproc_type , x , y );
[709]1128        return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
[519]1129    }
1130}  // end _sys_coproc_alloc()
1131
[556]1132////////////////////////////////////////////////////////
1133int _sys_coproc_release( unsigned int coproc_reg_index )
[519]1134{
[556]1135    // processor coordinates
[519]1136    unsigned int procid = _get_procid();
1137    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1138    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]1139    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1140   
1141    // get coprocessor coordinates
1142    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
1143    if ( cluster_xy > 0xFF )
[519]1144    {
[556]1145         _printf("\n[GIET_ERROR] in _sys_coproc_release(): "
[709]1146                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
[556]1147                 x , y , p ); 
[709]1148         return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
[519]1149    }
1150
[556]1151    unsigned int cx         = cluster_xy >> Y_WIDTH;
1152    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
1153    unsigned int cluster_id = cx * Y_SIZE + cy;
1154    unsigned int info       = _coproc_info[cluster_id];
1155    unsigned int nb_to      = info & 0xFF;
1156    unsigned int nb_from    = (info>>8) & 0xFF;
1157    unsigned int channel;
[519]1158
[556]1159    // stops coprocessor and communication channels
1160    _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 0 );
1161    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
1162    {
1163        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 );
1164    }
[519]1165
[709]1166    // deallocates coprocessor coordinates in thread context
[556]1167    _set_context_slot( CTX_COPROC_ID , 0xFFFFFFFF );
1168
1169    // release coprocessor lock
1170    _simple_lock_release( &_coproc_lock[cluster_id] );
1171
[519]1172#if GIET_DEBUG_COPROC
1173_printf("\n[GIET DEBUG COPROC] _sys_coproc_release() in cluster[%d,%d]\n",
[556]1174        cx, cy );
[519]1175#endif
1176
[709]1177    return GIET_SYSCALL_OK;
[519]1178}  // end _sys_coproc_release()
1179
[556]1180//////////////////////////////////////////////////////////////
1181int _sys_coproc_channel_init( unsigned int            channel,
[519]1182                              giet_coproc_channel_t*  desc )
1183{
[556]1184    // processor coordinates
[519]1185    unsigned int procid = _get_procid();
1186    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1187    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]1188    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1189   
1190    // get coprocessor coordinates
1191    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
1192    if ( cluster_xy > 0xFF )
[519]1193    {
1194         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
[709]1195                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
[556]1196                 x , y , p ); 
[709]1197         return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
[519]1198    }
1199
1200    // check channel mode
1201    unsigned mode = desc->channel_mode;
1202    if ( (mode != MODE_MWMR) && 
1203         (mode != MODE_DMA_IRQ) && 
1204         (mode != MODE_DMA_NO_IRQ) )
1205    {
[556]1206         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
[519]1207                 " illegal mode\n");
[709]1208         return GIET_SYSCALL_COPROCESSOR_ILLEGAL_MODE;
[519]1209    }
1210
1211    // get memory buffer size
1212    unsigned int size = desc->buffer_size;
1213 
[528]1214    // physical addresses
[709]1215    unsigned long long buffer_paddr;
[519]1216    unsigned int       buffer_lsb;
1217    unsigned int       buffer_msb;
[709]1218    unsigned long long mwmr_paddr = 0;
[519]1219    unsigned int       mwmr_lsb;
1220    unsigned int       mwmr_msb;
[709]1221    unsigned long long lock_paddr = 0;
[519]1222    unsigned int       lock_lsb;
1223    unsigned int       lock_msb;
1224
[528]1225    unsigned int       flags;     // unused
1226
[519]1227    // compute memory buffer physical address
[528]1228    buffer_paddr = _v2p_translate( desc->buffer_vaddr , &flags );
1229    buffer_lsb   = (unsigned int)buffer_paddr;
1230    buffer_msb   = (unsigned int)(buffer_paddr>>32); 
[519]1231
1232    // call MWMR_DMA driver
[556]1233    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MODE, mode ); 
1234    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_SIZE, size ); 
1235    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_BUFFER_LSB, buffer_lsb ); 
1236    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_BUFFER_MSB, buffer_msb ); 
[519]1237                       
1238    if ( mode == MODE_MWMR )
1239    {
[528]1240        // compute MWMR descriptor physical address
1241        mwmr_paddr = _v2p_translate( desc->mwmr_vaddr , &flags );
[519]1242        mwmr_lsb = (unsigned int)mwmr_paddr;
1243        mwmr_msb = (unsigned int)(mwmr_paddr>>32); 
1244
[528]1245        // call MWMR_DMA driver
[556]1246        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MWMR_LSB, mwmr_lsb ); 
1247        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MWMR_MSB, mwmr_msb ); 
[528]1248
1249        // compute lock physical address
1250        lock_paddr = _v2p_translate( desc->lock_vaddr , &flags );
[519]1251        lock_lsb = (unsigned int)lock_paddr;
1252        lock_msb = (unsigned int)(lock_paddr>>32); 
1253
1254        // call MWMR_DMA driver
[556]1255        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_LOCK_LSB, lock_lsb ); 
1256        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_LOCK_MSB, lock_msb ); 
[519]1257    }
1258
1259#if GIET_DEBUG_COPROC
[556]1260_printf("\n[GIET DEBUG COPROC] _sys_coproc_channel_init() for coproc[%d,%d]\n"
[519]1261        " channel =  %d / mode = %d / buffer_size = %d\n"
1262        " buffer_paddr = %l / mwmr_paddr = %l / lock_paddr = %l\n",
1263        x , y , channel , mode , size ,
1264        buffer_paddr, mwmr_paddr, lock_paddr );
1265#endif
1266       
[709]1267    return GIET_SYSCALL_OK;
[519]1268} // end _sys_coproc_channel_init()
1269
[556]1270////////////////////////////////////////////////////
1271int _sys_coproc_run( unsigned int coproc_reg_index )
[519]1272{
[556]1273    // processor coordinates
[519]1274    unsigned int procid = _get_procid();
1275    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1276    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]1277    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1278   
1279    // get coprocessor coordinates
1280    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
1281    if ( cluster_xy > 0xFF )
[519]1282    {
[556]1283         _printf("\n[GIET_ERROR] in _sys_coproc_run(): "
[709]1284                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
[556]1285                 x , y , p ); 
[709]1286         return -1111;
[519]1287    }
1288
[556]1289    unsigned int cx         = cluster_xy >> Y_WIDTH;
1290    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
1291    unsigned int cluster_id = cx * Y_SIZE + cy;
1292    unsigned int info       = _coproc_info[cluster_id];
1293    unsigned int nb_to      = info & 0xFF;
1294    unsigned int nb_from    = (info>>8) & 0xFF;
1295    unsigned int mode       = 0xFFFFFFFF;
1296    unsigned int channel;
[519]1297
[556]1298    // register coprocessor running mode
1299    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
1300    {
1301        unsigned int temp;
1302        temp = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_MODE );
[519]1303
[556]1304        if ( mode == 0xFFFFFFFF ) 
1305        {
1306            mode = temp;
1307        }
1308        else if ( temp != mode )
1309        {
1310            _printf("\n[GIET_ERROR] P[%d,%d,%d] in _sys_coproc_run() for coprocessor[%d,%d]\n"
1311                    "  all channels don't have the same mode\n", x , y , p , cx , cy );
[709]1312            return -1111;
[556]1313        }
1314    }
1315    _coproc_mode[cluster_id] = mode;
[519]1316
[556]1317    // start all communication channels
1318    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
1319    {
1320        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 1 );
1321    }
[519]1322
[556]1323    //////////////////////////////////////////////////////////////////////////
1324    if ( (mode == MODE_MWMR) || (mode == MODE_DMA_NO_IRQ) )  // no descheduling
[519]1325    {
[556]1326        // start coprocessor
1327        _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 1 );
1328
1329#if GIET_DEBUG_COPROC
1330if ( mode == MODE_MWMR )
1331_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
1332        "   MODE_MWMR at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
1333else
1334_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
1335        "   MODE_DMA_NO_IRQ at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
1336#endif
1337
[709]1338        return GIET_SYSCALL_OK;
[519]1339    }
[556]1340    ///////////////////////////////////////////////////////////////////////////
1341    else                                // mode == MODE_DMA_IRQ => descheduling
1342    {
[709]1343        // set _coproc_trdid
1344        unsigned int ltid = _get_thread_ltid();
1345        _coproc_trdid[cluster_id] = (x<<24) + (y<<16) + (p<<8) + ltid;
[519]1346
[556]1347        // enters critical section
1348        unsigned int save_sr;
1349        _it_disable( &save_sr ); 
1350
[629]1351        // set NORUN_MASK_COPROC bit
1352        static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
[709]1353        unsigned int*       ptr     = &psched->context[ltid].slot[CTX_NORUN_ID];
[629]1354        _atomic_or( ptr , NORUN_MASK_COPROC );
[556]1355
1356        // start coprocessor
1357        _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 1 );
1358
[519]1359#if GIET_DEBUG_COPROC
[556]1360_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
1361        "   MODE_DMA_IRQ at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
[519]1362#endif
1363
[709]1364        // deschedule thread
[556]1365        _ctx_switch(); 
[519]1366
[556]1367#if GIET_DEBUG_COPROC
1368_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] resume\n"
1369        "  coprocessor[%d,%d] completion at cycle %d\n", 
1370        x , y , p , cx , cy , _get_proctime() );
1371#endif
1372
1373        // restore SR
1374        _it_restore( &save_sr );
1375
1376        // return error computed by mwr_isr()
1377        return _coproc_error[cluster_id];
1378    } 
1379} // end _sys_coproc_run()
1380
1381///////////////////////////
1382int _sys_coproc_completed()
[519]1383{
[556]1384    // processor coordinates
[519]1385    unsigned int procid = _get_procid();
1386    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1387    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]1388    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1389   
1390    // get coprocessor coordinates
1391    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
1392    if ( cluster_xy > 0xFF )
[519]1393    {
1394         _printf("\n[GIET_ERROR] in _sys_coproc_completed(): "
[709]1395                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
[556]1396                 x , y , p ); 
[709]1397         return -1111;
[519]1398    }
1399
[556]1400    unsigned int cx         = cluster_xy >> Y_WIDTH;
1401    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
1402    unsigned int cluster_id = cx * Y_SIZE + cy;
1403    unsigned int mode       = _coproc_mode[cluster_id];
[519]1404
[556]1405    // analyse possible errors
1406    if ( mode == MODE_DMA_NO_IRQ )
1407    {
1408        unsigned int info       = _coproc_info[cluster_id];
1409        unsigned int nb_to      = info & 0xFF;
1410        unsigned int nb_from    = (info>>8) & 0xFF;
1411        unsigned int error      = 0;
1412        unsigned int channel;
1413        unsigned int status;
1414
1415        // get status for all channels, and signal all reported errors
1416        for ( channel = 0 ; channel < (nb_to +nb_from) ; channel++ )
1417        {
1418            do
1419            {
1420                status = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_STATUS );
1421                if ( status == MWR_CHANNEL_ERROR_DATA )
1422                {
1423                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
1424                            " / channel %d / DATA_ERROR\n", channel );
1425                    error = 1;
1426                    break;
1427                }
1428                else if ( status == MWR_CHANNEL_ERROR_LOCK )
1429                {
1430                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
1431                            " / channel %d / LOCK_ERROR\n", channel );
1432                    error = 1;
1433                    break;
1434                }
1435                else if ( status == MWR_CHANNEL_ERROR_DESC )
1436                {
1437                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
1438                            " / channel %d / DESC_ERROR\n", channel );
1439                    error = 1;
1440                    break;
1441                }
1442            } while ( status == MWR_CHANNEL_BUSY );
1443
1444            // reset channel
1445            _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 ); 
1446
1447        }  // end for channels
1448
[519]1449#if GIET_DEBUG_COPROC
[556]1450_printf("\n[GIET DEBUG COPROC] _sys_coproc_completed() for coprocessor[%d,%d] error = %d\n", 
1451        cx , cy , error );
[519]1452#endif
1453
[556]1454        return error;
1455    }
1456    else  // mode == MODE_MWMR or MODE_DMA_IRQ
1457    {
1458        _printf("\n[GIET ERROR] sys_coproc_completed() should not be called for "
1459                "coprocessor[%d,%d] running in MODE_MWMR or MODE_DMA_IRQ\n", cx , cy );
1460        return 1;
1461    }
[519]1462} // end _sys_coproc_completed()
1463
1464
1465//////////////////////////////////////////////////////////////////////////////
[440]1466//             TTY related syscall handlers
[258]1467//////////////////////////////////////////////////////////////////////////////
[440]1468
[670]1469/////////////////////////////////////////
1470int _sys_tty_alloc( unsigned int shared )
[258]1471{
[709]1472    unsigned int channel;    // allocated TTY channel
[440]1473
[709]1474    // get trdid and vsid for the calling thread
1475    unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
1476    unsigned int trdid = _get_thread_trdid();
1477
1478    // check no TTY already allocated to calling thread
[698]1479    if ( _get_context_slot( CTX_TTY_ID ) < NB_TTY_CHANNELS )
1480    {
[709]1481        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : "
1482                "TTY channel already allocated to thread %x\n", trdid );
1483        return -1111;
[698]1484    }
1485
[709]1486    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1487    mapping_vspace_t  *vspace   = _get_vspace_base(header);
1488    mapping_thread_t  *thread   = _get_thread_base(header);
1489   
1490    // compute number of users
1491    unsigned int users;
1492    if ( shared )  users = vspace[vsid].threads;
1493    else           users = 1;
1494
1495    // get a TTY channel
[698]1496    for ( channel = 0 ; channel < NB_TTY_CHANNELS ; channel++ )
1497    {
[709]1498        unsigned int* palloc  = &_tty_channel_alloc[channel];
1499
1500        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
[698]1501    }
[440]1502    if ( channel >= NB_TTY_CHANNELS )
1503    {
[709]1504        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : "
1505                "no TTY channel available for thread %x\n", trdid );
1506        return -1111;
[440]1507    }
[547]1508
[709]1509    // initialise allocated TTY channel
1510    _tty_init( channel );
[648]1511
[547]1512    // allocate a WTI mailbox to the calling proc if external IRQ
[709]1513    unsigned int wti_id;
1514    if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &wti_id ); 
1515
1516    // register wti_id and coordinates for processor receiving WTI
1517    unsigned int procid = _get_procid();
1518    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1519    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1520    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1521    _tty_channel_wti[channel] = x<<24 | y<<16 | p<<8 | wti_id;
[547]1522   
[670]1523    // update CTX_TTY_ID
[709]1524    if ( shared )         // for all threads in vspace
[670]1525    {
[709]1526        // scan threads in vspace
1527        unsigned int tid;
1528        for (tid = vspace[vsid].thread_offset;
1529             tid < (vspace[vsid].thread_offset + vspace[vsid].threads);
1530             tid++)
[670]1531        {
1532            unsigned int y_size        = header->y_size;
[709]1533            unsigned int cid           = thread[tid].clusterid;
[670]1534            unsigned int x             = cid / y_size;
1535            unsigned int y             = cid % y_size;
[709]1536            unsigned int p             = thread[tid].proclocid;
1537            unsigned int ltid          = thread[tid].ltid;
[670]1538            static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
[698]1539
[709]1540            psched->context[ltid].slot[CTX_TTY_ID] = channel;
[670]1541        }
1542    }
[709]1543    else                  // for calling thread only
[670]1544    {
1545        _set_context_slot( CTX_TTY_ID, channel );
1546    }
1547
[709]1548    return GIET_SYSCALL_OK;
1549}  // end _sys_tty_alloc()
[258]1550
[709]1551//////////////////////
1552int _sys_tty_release()     // NOTE: not a syscall
[695]1553{
[698]1554    unsigned int channel = _get_context_slot( CTX_TTY_ID );
1555
1556    if ( channel == -1 )
1557    {
[709]1558        unsigned int trdid = _get_thread_trdid();
1559        _printf("\n[GIET_ERROR] in _sys_tty_release() : "
1560                "TTY channel already released for thread %x\n", trdid );
1561        return -1111;
[698]1562    }
1563
[709]1564    // reset CTX_TTY_ID for the calling thread
1565    _set_context_slot( CTX_TTY_ID , 0xFFFFFFFF );
[697]1566
[709]1567    // atomically decrement the _tty_channel_allocator[] array
1568    _atomic_increment( &_tty_channel_alloc[channel] , -1 );
[695]1569
[709]1570    // release WTI mailbox if TTY channel no more used
1571    if ( USE_PIC  && (_tty_channel_alloc[channel] == 0) ) 
[698]1572    {
[709]1573        _ext_irq_release( ISR_TTY_RX , channel );
[698]1574    }
1575
[709]1576    return GIET_SYSCALL_OK;
1577}  // end sys_tty_release()
[698]1578
[709]1579////////////////////////////////////////
[440]1580int _sys_tty_write( const char*  buffer,   
1581                    unsigned int length,    // number of characters
1582                    unsigned int channel)   // channel index
1583{
1584    unsigned int  nwritten;
1585
1586    // compute and check tty channel
1587    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
[709]1588    if( channel >= NB_TTY_CHANNELS ) return -1111;
[440]1589
1590    // write string to TTY channel
1591    for (nwritten = 0; nwritten < length; nwritten++) 
1592    {
1593        // check tty's status
1594        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
1595
1596        // write one byte
1597        if (buffer[nwritten] == '\n') 
1598        {
1599            _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
1600        }
1601        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
1602    }
1603   
1604    return nwritten;
1605}
1606
[709]1607///////////////////////////////////////
[440]1608int _sys_tty_read( char*        buffer, 
1609                   unsigned int length,    // unused
1610                   unsigned int channel)   // channel index
1611{
1612    // compute and check tty channel
1613    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
[709]1614    if( channel >= NB_TTY_CHANNELS ) return -1111;
[440]1615
[709]1616    unsigned int save_sr;
1617    unsigned int found = 0;
1618
1619    // get pointer on TTY_RX FIFO
1620    tty_fifo_t*  fifo = &_tty_rx_fifo[channel];
1621
1622    // try to read one character from FIFO
1623    // blocked in while loop until success
1624    while ( found == 0 )
[440]1625    {
[709]1626        if ( fifo->sts == 0)   // FIFO empty => deschedule
1627        {
1628            // enters critical section
1629             _it_disable( &save_sr );
[440]1630
[709]1631            // set NORUN_MASK_TTY bit for calling thread
1632            static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
1633            unsigned int ltid = psched->current;
1634            _atomic_or( &psched->context[ltid].slot[CTX_NORUN_ID] , NORUN_MASK_TTY );
[440]1635
[709]1636            // register descheduling thread trdid
1637            fifo->trdid = _get_thread_trdid();
[440]1638
[709]1639             // deschedule calling thread
1640            _ctx_switch();
[440]1641
[709]1642            // exit critical section
1643            _it_restore( &save_sr );
1644        }
1645        else                             // FIFO not empty => get one character
1646        {
1647            *buffer   = fifo->data[fifo->ptr];
1648            fifo->sts = fifo->sts - 1;
1649            fifo->ptr = (fifo->ptr + 1) % TTY_FIFO_DEPTH;
1650            found     = 1;
1651        }
1652    }
1653
1654    return 1;
[440]1655}
1656
[709]1657
1658
[428]1659//////////////////////////////////////////////////////////////////////////////
[709]1660//             TIMER related syscall handlers
[428]1661//////////////////////////////////////////////////////////////////////////////
[440]1662
1663////////////////////
1664int _sys_tim_alloc()
[428]1665{
[440]1666
[709]1667#if NB_TIM_CHANNELS
1668
1669    unsigned int channel;    // allocated TIMER channel
1670
1671    unsigned int trdid = _get_thread_trdid();
1672
1673    // check no TIMER already allocated to calling thread
1674    if ( _get_context_slot( CTX_TIM_ID ) < NB_TIM_CHANNELS )
[440]1675    {
[709]1676        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : "
1677                "TIMER channel already allocated to thread %x\n", trdid );
1678        return -1111;
[440]1679    }
[709]1680
1681    // get a TIMER channel
1682    for ( channel = 0 ; channel < NB_TIM_CHANNELS ; channel++ )
[440]1683    {
[709]1684        unsigned int* palloc  = &_tim_channel_alloc[channel];
1685
1686        if ( _atomic_test_and_set( palloc , 1 ) == 0 ) break;
[440]1687    }
[709]1688    if ( channel >= NB_TIM_CHANNELS )
1689    {
1690        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : "
1691                "no TIMER channel available for thread %x\n", trdid );
1692        return -1111;
1693    }
[440]1694
[709]1695    // allocate a WTI mailbox to the calling proc if external IRQ
1696    unsigned int wti_id;
1697    if ( USE_PIC ) _ext_irq_alloc( ISR_TIMER , channel , &wti_id ); 
1698
1699    // register wti_id and coordinates for processor receiving WTI
1700    unsigned int procid = _get_procid();
1701    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1702    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1703    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1704    _tim_channel_wti[channel] = x<<24 | y<<16 | p<<8 | wti_id;
1705   
1706    // update CTX_TIM_ID in thread context
1707    _set_context_slot( CTX_TIM_ID, channel );
1708
1709    return GIET_SYSCALL_OK;
1710
1711#else
1712
1713    _printf("\n[GIET ERROR] in _sys_tim_alloc() : NB_TIM_CHANNELS = 0\n");
1714    return -1111;
1715
1716#endif
1717}  // end _sys_tim_alloc()
1718
1719
1720//////////////////////
1721int _sys_tim_release()     // NOTE: not a syscall
[695]1722{
1723
[709]1724#if NB_TIM_CHANNELS
[695]1725
[709]1726    unsigned int channel = _get_context_slot( CTX_TIM_ID );
1727
1728    if ( channel == -1 )
1729    {
1730        unsigned int trdid = _get_thread_trdid();
1731        _printf("\n[GIET_ERROR] in _sys_tim_release() : "
1732                "TIMER channel already released for thread %x\n", trdid );
1733        return -1111;
1734    }
1735
1736    // reset CTX_TIM_ID for the calling thread
1737    _set_context_slot( CTX_TIM_ID , 0xFFFFFFFF );
1738
1739    // reset the _tim_channel_alloc[] array
1740    _tim_channel_alloc[channel] = 0;
1741
1742    // release WTI mailbox if TTY channel no more used
1743    if ( USE_PIC ) 
1744    {
1745        _ext_irq_release( PERIPH_TYPE_TIM , channel );
1746    }
1747
1748    return GIET_SYSCALL_OK;
1749
1750#else
1751
1752    _printf("\n[GIET ERROR] in _sys_tim_release() : NB_TIM_CHANNELS = 0\n");
1753    return -1111;
1754
1755#endif
1756}  // end _sys_tim_release()
1757
[440]1758/////////////////////////////////////////
1759int _sys_tim_start( unsigned int period )
1760{
[709]1761
1762#if NB_TIM_CHANNELS
1763
[440]1764    // get timer index
1765    unsigned int channel = _get_context_slot( CTX_TIM_ID );
1766    if ( channel >= NB_TIM_CHANNELS )
1767    {
1768        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
[709]1769        return -1111;
[440]1770    }
1771
1772    // start timer
1773    _timer_start( channel, period );
1774
[709]1775    return GIET_SYSCALL_OK;
1776
1777#else
1778
1779    _printf("\n[GIET ERROR] in _sys_tim_start() : NB_TIM_CHANNELS = 0\n");
1780    return -1111;
1781
1782#endif
[440]1783}
1784
1785///////////////////
1786int _sys_tim_stop()
1787{
[709]1788
1789#if NB_TIM_CHANNELS
1790
[440]1791    // get timer index
1792    unsigned int channel = _get_context_slot( CTX_TIM_ID );
1793    if ( channel >= NB_TIM_CHANNELS )
1794    {
1795        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
[709]1796        return -1111;
[440]1797    }
1798
1799    // stop timer
1800    _timer_stop( channel );
1801
[709]1802    return GIET_SYSCALL_OK;
1803
1804#else
1805
1806    _printf("\n[GIET ERROR] in _sys_tim_stop() : NB_TIM_CHANNELS = 0\n");
1807    return -1111;
1808
1809#endif
[440]1810}
1811
[709]1812
[440]1813//////////////////////////////////////////////////////////////////////////////
1814//             NIC related syscall handlers
1815//////////////////////////////////////////////////////////////////////////////
1816
[478]1817#define NIC_CONTAINER_SIZE 4096
1818
[709]1819#if NB_NIC_CHANNELS
1820
[494]1821////////////////////////////////////////
1822int _sys_nic_alloc( unsigned int is_rx,
1823                    unsigned int xmax,
1824                    unsigned int ymax )
[440]1825{
[709]1826    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1827    mapping_vspace_t  *vspace   = _get_vspace_base(header);
1828    mapping_thread_t  *thread   = _get_thread_base(header);
1829
1830    // get calling thread trdid, vspace index, and number of threads
1831    unsigned int trdid = _get_thread_trdid();
1832    unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
1833    unsigned int users = vspace[vsid].threads;
1834
[494]1835    // check xmax / ymax parameters
[709]1836    if ( (xmax > X_SIZE) || (ymax > Y_SIZE) )
[494]1837    {
[709]1838        _printf("\n[GIET_ERROR] in _sys_nic_alloc() "
1839                "xmax or ymax argument too large for thread %x\n", trdid );
1840        return -1111;
[494]1841    }
[459]1842
[614]1843    ////////////////////////////////////////////////////////
1844    // Step 1: get and register CMA and NIC channel index //
1845    ////////////////////////////////////////////////////////
1846
[709]1847    unsigned int   nic_channel;
1848    unsigned int   cma_channel;
1849    unsigned int*  palloc;
[440]1850
[709]1851    // get a NIC_RX or NIC_TX channel
1852    for ( nic_channel = 0 ; nic_channel < NB_NIC_CHANNELS ; nic_channel++ )
1853    {
1854        if ( is_rx ) palloc = &_nic_rx_channel_alloc[nic_channel];
1855        else         palloc = &_nic_tx_channel_alloc[nic_channel];
[449]1856
[709]1857        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
1858    }
[449]1859    if ( (nic_channel >= NB_NIC_CHANNELS) )
[440]1860    {
[709]1861        _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1862                "no NIC channel available for thread %x\n", trdid );
1863        return -1111;
[440]1864    }
[449]1865
[709]1866    // get a CMA channel
[699]1867    for ( cma_channel = 0 ; cma_channel < NB_CMA_CHANNELS ; cma_channel++ )
1868    {
[709]1869        palloc = &_cma_channel_alloc[cma_channel];
1870
1871        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
[699]1872    }
[449]1873    if ( cma_channel >= NB_CMA_CHANNELS )
1874    {
[709]1875        _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1876                "no CMA channel available for thread %x\n", trdid );
1877        if ( is_rx )  _nic_rx_channel_alloc[nic_channel] = 0;
1878        else          _nic_tx_channel_alloc[nic_channel] = 0;
1879        return -1111;
[449]1880    }
[459]1881
[494]1882#if GIET_DEBUG_NIC
[709]1883_printf("\n[GIET DEBUG NIC] Thread %d enters sys_nic_alloc() at cycle %d\n"
[547]1884        "  nic_channel = %d / cma_channel = %d\n",
[709]1885        trdid , _get_proctime() , nic_channel , cma_channel );
[494]1886#endif
1887
[709]1888    // register nic_index and cma_index in all threads
1889    // contexts that are in the same vspace
1890    unsigned int tid;
1891    for (tid = vspace[vsid].thread_offset;
1892         tid < (vspace[vsid].thread_offset + vspace[vsid].threads);
1893         tid++)
[449]1894    {
[709]1895        unsigned int y_size        = header->y_size;
1896        unsigned int cid           = thread[tid].clusterid;
1897        unsigned int x             = cid / y_size;
1898        unsigned int y             = cid % y_size;
1899        unsigned int p             = thread[tid].proclocid;
1900        unsigned int ltid          = thread[tid].ltid;
1901        static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
[440]1902
[709]1903        if ( is_rx )
1904        {
1905            if ( (psched->context[ltid].slot[CTX_NIC_RX_ID] < NB_NIC_CHANNELS) ||
1906                 (psched->context[ltid].slot[CTX_CMA_RX_ID] < NB_CMA_CHANNELS) )
1907            {
1908                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1909                        "NIC_RX or CMA_RX channel already allocated for thread %x\n", trdid );
1910                _nic_rx_channel_alloc[nic_channel] = 0;
1911                _cma_channel_alloc[cma_channel]    = 0;
1912                return -1111;
1913            }
1914            else
1915            {
1916                psched->context[ltid].slot[CTX_NIC_RX_ID] = nic_channel;
1917                psched->context[ltid].slot[CTX_CMA_RX_ID] = cma_channel;
1918            }
1919        }
1920        else // is_tx
1921        {
1922            if ( (psched->context[ltid].slot[CTX_NIC_TX_ID] < NB_NIC_CHANNELS) ||
1923                 (psched->context[ltid].slot[CTX_CMA_TX_ID] < NB_CMA_CHANNELS) )
1924            {
1925                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1926                        "NIC_TX or CMA_TX channel already allocated for thread %x\n", trdid );
1927                _nic_tx_channel_alloc[nic_channel] = 0;
1928                _cma_channel_alloc[cma_channel]    = 0;
1929                return -1111;
1930            }
1931            else
1932            {
1933                psched->context[ltid].slot[CTX_NIC_TX_ID] = nic_channel;
1934                psched->context[ltid].slot[CTX_CMA_TX_ID] = cma_channel;
1935            }
1936        }
1937    }  // end loop on threads
1938
[614]1939    /////////////////////////////////////////////////////////////////////////////////
1940    // Step 2: loop on all the clusters                                            //
1941    // Allocate the kernel containers and status, compute the container and the    //
1942    // status physical addresses, fill and synchronize the kernel CHBUF descriptor //
1943    /////////////////////////////////////////////////////////////////////////////////
1944
[494]1945    // physical addresses to be registered in the CMA registers
[459]1946    unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
1947    unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
[449]1948
[614]1949    // allocate one kernel container and one status variable per cluster in the
1950    // (xmax / ymax) mesh
[528]1951    unsigned int        cx;                 // cluster X coordinate
1952    unsigned int        cy;                 // cluster Y coordinate
1953    unsigned int        index;              // container index in chbuf
1954    unsigned int        vaddr;              // virtual address
1955    unsigned long long  cont_paddr;         // container physical address
[614]1956    unsigned long long  sts_paddr;          // container status physical address
[494]1957
[528]1958    unsigned int        flags;              // for _v2p_translate()
1959
[494]1960    for ( cx = 0 ; cx < xmax ; cx++ )
[478]1961    {
[494]1962        for ( cy = 0 ; cy < ymax ; cy++ )
[478]1963        {
1964            // compute index in chbuf
[494]1965            index = (cx * ymax) + cy; 
[478]1966
[494]1967            // allocate the kernel container
[478]1968            vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
1969
[494]1970            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
1971            {
[709]1972                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1973                        "not enough kenel heap in cluster[%d,%d]\n", cx, cy );
1974                return -1111;
[494]1975            }
1976
[478]1977            // compute container physical address
[528]1978            cont_paddr = _v2p_translate( vaddr , &flags );
[478]1979
[614]1980            // checking container address alignment
1981            if ( cont_paddr & 0x3F )
1982            {
[709]1983                _printf("\n[GIET ERROR] in _sys_nic_alloc() : "
1984                        "container address of cluster[%d,%d] not aligned\n", cx, cy);
1985                return -1111;
[614]1986            }
1987
1988#if GIET_DEBUG_NIC
1989_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
1990        " allocates in cluster[%d,%d]:\n"
1991        " - container vaddr = %x / paddr = %l\n",
1992        thread , cx , cy , vaddr, cont_paddr );
1993#endif
1994
1995            // allocate the kernel container status
1996            // it occupies 64 bytes but only last bit is useful (1 for full and 0 for empty)
1997            vaddr = (unsigned int)_remote_malloc( 64, cx, cy );
1998
1999            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
2000            {
[709]2001                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
2002                        "not enough kernel heap in cluster[%d,%d]\n", cx, cy );
2003                return -1111;
[614]2004            }
2005
2006            // compute status physical address
2007            sts_paddr = _v2p_translate( vaddr , &flags );
2008
2009            // checking status address alignment
2010            if ( sts_paddr & 0x3F )
2011            {
[709]2012                _printf("\n[GIET ERROR] in _sys_nic_alloc() : "
2013                        "status address of cluster[%d,%d] not aligned\n", cx, cy);
2014                return -1111;
[614]2015            }
2016
[494]2017            // initialize chbuf entry
[614]2018            // The buffer descriptor has the following structure:
2019            // - the 26 LSB bits contain bits[6:31] of the buffer physical address
2020            // - the 26 following bits contain bits[6:31] of the physical address where the
2021            //   buffer status is located
2022            // - the 12 MSB bits contain the common address extension of the buffer and its
2023            //   status
2024            if ( is_rx )
2025                _nic_ker_rx_chbuf[nic_channel].buf_desc[index] =
2026                    (unsigned long long)
2027                    ((sts_paddr & 0xFFFFFFFFULL) >> 6) +
2028                    (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26);
2029            else
2030                _nic_ker_tx_chbuf[nic_channel].buf_desc[index] =
2031                    (unsigned long long)
2032                    ((sts_paddr & 0xFFFFFFC0ULL) >> 6) +
2033                    (((cont_paddr & 0xFFFFFFFFFC0ULL) >> 6) << 26);
[478]2034
2035#if GIET_DEBUG_NIC
[614]2036_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
2037        " - status vaddr = %x / paddr = %l\n"
2038        " Buffer descriptor = %l\n",
2039        thread, vaddr, sts_paddr,
2040        (unsigned long long)((sts_paddr & 0xFFFFFFFFULL) >> 6) + 
2041        (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26) );
[478]2042#endif
2043        }
2044    }
2045
[494]2046    // complete kernel chbuf initialisation
2047    if ( is_rx )
2048    {
[614]2049        _nic_ker_rx_chbuf[nic_channel].xmax = xmax;
2050        _nic_ker_rx_chbuf[nic_channel].ymax = ymax;
[494]2051    }
2052    else
2053    {
[614]2054        _nic_ker_tx_chbuf[nic_channel].xmax = xmax;
2055        _nic_ker_tx_chbuf[nic_channel].ymax = ymax;
[494]2056    }
2057
[449]2058    // compute the kernel chbuf descriptor physical address
[614]2059    if ( is_rx ) vaddr = (unsigned int)( &_nic_ker_rx_chbuf[nic_channel] );
2060    else         vaddr = (unsigned int)( &_nic_ker_tx_chbuf[nic_channel] );
[440]2061
[528]2062    ker_chbuf_pbase = _v2p_translate( vaddr , &flags );
2063
[459]2064#if GIET_DEBUG_NIC
[547]2065_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get kernel chbuf\n"
2066        "  vaddr = %x / paddr = %l\n",
[478]2067        thread , vaddr , ker_chbuf_pbase );
[459]2068#endif
[440]2069
[459]2070    // sync the kernel chbuf in L2 after write in L2
[614]2071    _mmc_sync( ker_chbuf_pbase, sizeof( ker_chbuf_t ) );
[459]2072
[614]2073    ///////////////////////////////////////////////////////////////
2074    // Step 3: compute the NIC chbuf descriptor physical address //
2075    ///////////////////////////////////////////////////////////////
2076
2077    unsigned int offset;
2078    if ( is_rx ) offset = 0x4100;
2079    else         offset = 0x4110;
2080    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
2081                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
2082
2083#if GIET_DEBUG_NIC
2084_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get NIC chbuf : paddr = %l\n",
2085        thread , nic_chbuf_pbase );
2086#endif
2087
2088    ////////////////////////////////////////////////////////////////////////////////
2089    // Step 4: initialize CMA registers defining the source & destination chbufs //
2090    ////////////////////////////////////////////////////////////////////////////////
2091
[459]2092    if ( is_rx )               // NIC to kernel
2093    {
2094        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(nic_chbuf_pbase) );
2095        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
2096        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
2097        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(ker_chbuf_pbase) );
2098        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
[494]2099        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, xmax * ymax );
[459]2100    }
2101    else                      // kernel to NIC
2102    {
2103        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(ker_chbuf_pbase) );
2104        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
[494]2105        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, xmax * ymax );
[459]2106        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(nic_chbuf_pbase) );
2107        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
2108        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
2109    }
2110
[494]2111#if GIET_DEBUG_NIC
2112_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d\n",
2113        thread, _get_proctime() );
2114#endif
2115
[709]2116    return GIET_SYSCALL_OK;
[494]2117} // end _sys_nic_alloc()
2118
2119
[709]2120//////////////////////////////////////////
2121int _sys_nic_release( unsigned int is_rx )     // NOTE: not a syscall
[695]2122{
[709]2123    unsigned int trdid = _get_thread_trdid();
2124
2125    unsigned int nic_channel;
2126    unsigned int cma_channel;
2127   
2128    // update the kernel tables
[695]2129    if ( is_rx )
[709]2130    {
2131        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
2132        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
2133
2134        if ( (nic_channel >= NB_NIC_CHANNELS) )
2135        {
2136            _printf("\n[GIET ERROR] in _sys_nic_release() : "
2137                    "NIC_RX channel already released for thread %x\n", trdid );
2138            return -1111;
2139        }
2140        if ( (cma_channel >= NB_CMA_CHANNELS) )
2141        {
2142            _printf("\n[GIET ERROR] in _sys_nic_release() : "
2143                    "CMA_RX channel already released for thread %x\n", trdid );
2144            return -1111;
2145        }
2146
2147        // atomically decrement the NIC and CMA channel allocators
2148        _atomic_increment( &_nic_rx_channel_alloc[nic_channel] , -1 );
2149        _atomic_increment( &_cma_channel_alloc[cma_channel] , -1 );
2150   
2151        // stop the NIC and CMA peripherals channels if no more users
2152        if ( (_nic_rx_channel_alloc[nic_channel] == 0) &&
2153             (_cma_channel_alloc[cma_channel] == 0) )  _sys_nic_stop( 1 );
2154
2155        // reset the calling thread context slots
2156        _set_context_slot( CTX_NIC_RX_ID , 0xFFFFFFFF );
2157        _set_context_slot( CTX_CMA_RX_ID , 0xFFFFFFFF );
2158    }         
[695]2159    else
[709]2160    {
2161        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
2162        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
[695]2163
[709]2164        if ( (nic_channel >= NB_NIC_CHANNELS) )
2165        {
2166            _printf("\n[GIET ERROR] in _sys_nic_release() : "
2167                    "NIC_TX channel already released for thread %x\n", trdid );
2168            return -1111;
2169        }
2170        if ( (cma_channel >= NB_CMA_CHANNELS) )
2171        {
2172            _printf("\n[GIET ERROR] in _sys_nic_release() : "
2173                    "CMA_TX channel already released for thread %x\n", trdid );
2174            return -1111;
2175        }
[695]2176
[709]2177        // atomically decrement the NIC and CMA channel allocators
2178        _atomic_increment( &_nic_tx_channel_alloc[nic_channel] , -1 );
2179        _atomic_increment( &_cma_channel_alloc[cma_channel] , -1 );
2180   
2181        // stop the NIC and CMA peripherals channels if no more users
2182        if ( (_nic_tx_channel_alloc[nic_channel] == 0) &&
2183             (_cma_channel_alloc[cma_channel] == 0) )  _sys_nic_stop( 0 );
[695]2184
[709]2185        // reset the calling thread context slots
2186        _set_context_slot( CTX_NIC_TX_ID , 0xFFFFFFFF );
2187        _set_context_slot( CTX_CMA_TX_ID , 0xFFFFFFFF );
2188    }
2189
2190    return GIET_SYSCALL_OK;
2191}  // end sys_nic_release()
2192
2193
[695]2194////////////////////////////////////////
[709]2195int _sys_nic_start( unsigned int is_rx )
[494]2196{
[709]2197    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
2198
[494]2199    unsigned int nic_channel;
2200    unsigned int cma_channel;
2201
[709]2202    // get NIC channel index and CMA channel index from thread context
[494]2203    if ( is_rx )
2204    {
2205        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
2206        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
2207    }
2208    else
2209    {
2210        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
2211        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
2212    }
2213
2214#if GIET_DEBUG_NIC
[709]2215_printf("\n[GIET DEBUG NIC] Thread %x in _sys_nic_start() at cycle %d\n"
[547]2216        "  get NIC channel = %d / CMA channel = %d\n",
[709]2217        trdid, _get_proctime(), nic_channel, cma_channel );
[494]2218#endif
2219
2220    // check NIC and CMA channels index
[709]2221    if ( nic_channel >= NB_NIC_CHANNELS )
[494]2222    {
[709]2223        _printf("\n[GIET_ERROR] in _sys_nic_start() : "
2224                "illegal NIC channel for thread %x\n", trdid );
2225        return -1111;
[494]2226    }
2227    if ( cma_channel >= NB_CMA_CHANNELS )
2228    {
[709]2229        _printf("\n[GIET_ERROR] in _sys_nic_start() : "
2230                "illegal CMA channel for thread %x\n", trdid );
2231        return -1111;
[494]2232    }
2233
[449]2234    // start CMA transfer
[478]2235    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , NIC_CONTAINER_SIZE );
[505]2236    _cma_set_register( cma_channel, CHBUF_PERIOD   , 0 );     // OUT_OF_ORDER
[449]2237    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
2238
2239    // activates NIC channel
[614]2240    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 );
[459]2241
2242#if GIET_DEBUG_NIC
[614]2243    _printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
[709]2244            trdid , _get_proctime() );
[459]2245#endif
2246
[709]2247    return GIET_SYSCALL_OK;
[505]2248}  // end _sys_nic_start()
[449]2249
[494]2250
[449]2251//////////////////////////////////////
2252int _sys_nic_move( unsigned int is_rx,
2253                   void*        buffer )
2254{
[709]2255    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
[449]2256
[709]2257    unsigned int channel;
2258
[459]2259#if GIET_DEBUG_NIC
[478]2260_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
[709]2261        trdid , _get_proctime() );
[459]2262#endif
2263
[709]2264    // get NIC channel index from thread context
2265    if ( is_rx )  channel = _get_context_slot( CTX_NIC_RX_ID );
2266    else          channel = _get_context_slot( CTX_NIC_TX_ID );
2267
[494]2268    // check NIC channel index
2269    if ( channel >= NB_NIC_CHANNELS )
2270    {
[709]2271        _printf("\n[GIET_ERROR] in _sys_nic_move() : "
2272                "illegal NIC channel index for thread %x\n", trdid );
2273        return -1111;
[494]2274    }
2275
2276    // get kernel chbuf virtual address
[614]2277    ker_chbuf_t* ker_chbuf;
2278    if ( is_rx )  ker_chbuf = &_nic_ker_rx_chbuf[channel];
2279    else          ker_chbuf = &_nic_ker_tx_chbuf[channel];
[494]2280
2281    // get xmax / ymax parameters
[614]2282    unsigned int xmax = ker_chbuf->xmax;
2283    unsigned int ymax = ker_chbuf->ymax;
[494]2284
[709]2285    // get cluster coordinates for the processor running the calling thread
[478]2286    unsigned int  procid = _get_procid();
2287    unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
2288    unsigned int  cy     = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
2289   
[494]2290    // check processor coordinates / (xmax,ymax)
2291    if ( cx >= xmax )
2292    {
2293        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
2294                " / xmax = %d\n", cx , xmax );
[709]2295        return -1111;
[494]2296    }
2297    if ( cy >= ymax )
2298    {
2299        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
2300                " / ymax = %d\n", cy , ymax );
[709]2301        return -1111;
[494]2302    }
2303   
[614]2304    unsigned long long usr_buf_paddr;       // user buffer physical address
2305    unsigned long long ker_buf_paddr;       // kernel buffer physical address
2306    unsigned long long ker_sts_paddr;       // kernel buffer status physical address
2307    unsigned long long ker_buf_desc;        // kernel buffer descriptor
2308    unsigned int       ker_sts;             // kernel buffer status (full or empty)
2309    unsigned int       index;               // kernel buffer index in chbuf
2310    unsigned int       flags;               // for _v2P_translate
[459]2311
2312    // Compute user buffer physical address and check access rights
[614]2313    usr_buf_paddr = _v2p_translate( (unsigned int)buffer , &flags );
[478]2314
[440]2315    if ( (flags & PTE_U) == 0 )
2316    {
[614]2317        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal user buffer address\n");
[709]2318        return -1111;
[440]2319    }
2320
[459]2321#if GIET_DEBUG_NIC
[478]2322_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
[614]2323        thread, usr_buf_paddr );
[459]2324#endif
[440]2325
[614]2326    // compute buffer index, buffer descriptor paddr and buffer status paddr
2327    index = (ymax * cx) + cy;
2328    ker_buf_desc = ker_chbuf->buf_desc[index];
2329    ker_sts_paddr = ((ker_buf_desc & 0xFFF0000000000000ULL) >> 20) +
2330                    ((ker_buf_desc & 0x3FFFFFFULL) << 6);
[459]2331
[614]2332#if GIET_DEBUG_NIC
2333_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_desc %d at cycle %d\n"
2334        "  kernel buffer descriptor = %l\n",
2335        thread, index, _get_proctime(), ker_buf_desc );
2336#endif
2337
[494]2338    // poll local kernel container status until success
[478]2339    while ( 1 )
[449]2340    {
[478]2341        // inval buffer descriptor in L2 before read in L2
[614]2342        _mmc_inval( ker_sts_paddr, 4 );
2343        ker_sts = _physical_read( ker_sts_paddr );
[459]2344
2345#if GIET_DEBUG_NIC
[614]2346_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_sts %d at cycle %d\n"
2347        "  paddr = %l / kernel buffer status = %x\n",
2348        thread, index, _get_proctime(), ker_sts_paddr, ker_sts );
[459]2349#endif
2350
[478]2351        // test buffer status and break if found
[614]2352        if ( ( is_rx != 0 ) && ( ker_sts == 0x1 ) ) break;
2353        if ( ( is_rx == 0 ) && ( ker_sts == 0 ) ) break;
[449]2354    }
[459]2355
2356    // compute kernel buffer physical address
[614]2357    ker_buf_paddr = (ker_buf_desc & 0xFFFFFFFFFC000000ULL) >> 20;
[449]2358   
[494]2359    // move one container
2360    if ( is_rx )              // RX transfer
[459]2361    {
2362        // inval kernel buffer in L2 before read in L2
[614]2363        _mmc_inval( ker_buf_paddr, NIC_CONTAINER_SIZE );
[449]2364
[459]2365        // transfer data from kernel buffer to user buffer
[614]2366        _physical_memcpy( usr_buf_paddr, 
2367                          ker_buf_paddr, 
[478]2368                          NIC_CONTAINER_SIZE );
2369#if GIET_DEBUG_NIC
[547]2370_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer kernel buffer %l\n"
2371        " to user buffer %l at cycle %d\n",
[614]2372        thread , ker_buf_paddr , usr_buf_paddr , _get_proctime() );
[478]2373#endif
[449]2374
[459]2375    }
[494]2376    else                      // TX transfer
[459]2377    {
2378        // transfer data from user buffer to kernel buffer
[614]2379        _physical_memcpy( ker_buf_paddr, 
2380                          usr_buf_paddr, 
[478]2381                          NIC_CONTAINER_SIZE );
[449]2382
[459]2383        // sync kernel buffer in L2 after write in L2
[614]2384        _mmc_sync( ker_buf_paddr, NIC_CONTAINER_SIZE );
[478]2385
2386#if GIET_DEBUG_NIC
2387_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
2388        "user buffer %l to kernel buffer %l at cycle %d\n",
[614]2389        thread , usr_buf_paddr , ker_buf_paddr , _get_proctime() );
[478]2390#endif
2391
[459]2392    }
2393
[478]2394    // update kernel chbuf status
[614]2395    if ( is_rx ) _physical_write ( ker_sts_paddr, 0 );
2396    else         _physical_write ( ker_sts_paddr, 0x1 );
[459]2397
2398    // sync kernel chbuf in L2 after write in L2
[614]2399    _mmc_sync( ker_sts_paddr, 4 );
[459]2400
2401#if GIET_DEBUG_NIC
[478]2402_printf("\n[GIET DEBUG NIC] Task %d get buffer %d  and exit _sys_nic_move() at cycle %d\n",
2403        thread , index , _get_proctime() );
[459]2404#endif
2405
[709]2406    return GIET_SYSCALL_OK;
[449]2407} // end _sys_nic_move()
[440]2408
[494]2409
[709]2410///////////////////////////////////////
2411int _sys_nic_stop( unsigned int is_rx )
[440]2412{
[709]2413    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
2414
[449]2415    unsigned int nic_channel;
2416    unsigned int cma_channel;
[440]2417
[449]2418    // get NIC channel index and CMA channel index
2419    if ( is_rx )
[440]2420    {
[449]2421        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
2422        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
[440]2423    }
[449]2424    else
2425    {
2426        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
2427        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
2428    }
[440]2429
[494]2430    // check NIC and CMA channels index
[709]2431    if ( nic_channel >= NB_NIC_CHANNELS )
[440]2432    {
[709]2433        _printf("\n[GIET_ERROR] in _sys_nic_stop() : " 
2434                "illegal NIC channel for thread %x\n", trdid );
2435        return -1111;
[440]2436    }
[449]2437    if ( cma_channel >= NB_CMA_CHANNELS )
[440]2438    {
[709]2439        _printf("\n[GIET_ERROR] in _sys_nic_stop() : "
2440                "illegal CMA channel for thread %x\n", trdid );
2441        return -1111;
[440]2442    }
2443
[709]2444    // desactivates the CMA channel
2445    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
2446
2447    // wait until CMA channel IDLE
2448    unsigned int volatile status;
2449    do
2450    {
2451         status = _cma_get_register( cma_channel, CHBUF_STATUS );
2452    } while ( status ); 
2453
[449]2454    // desactivates the NIC channel
2455    _nic_channel_stop( nic_channel, is_rx );
[440]2456
[709]2457    return GIET_SYSCALL_OK;
[494]2458}  // end _sys_nic_stop()
[440]2459
[459]2460////////////////////////////////////////
[709]2461int _sys_nic_clear( unsigned int is_rx )
[459]2462{
[709]2463    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
[459]2464
[709]2465    unsigned int channel;
2466
[459]2467    // get NIC channel
[709]2468    if ( is_rx )  channel = _get_context_slot( CTX_NIC_RX_ID );
2469    else          channel = _get_context_slot( CTX_NIC_TX_ID );
[459]2470
[709]2471    if ( channel >= NB_NIC_CHANNELS )
[459]2472    {
[709]2473        _printf("\n[GIET_ERROR] in _sys_nic_clear() : "
2474                "illegal NIC channel for thread %x\n", trdid );
2475        return -1111;
[459]2476    }
2477
2478    if ( is_rx )
2479    {
2480        _nic_set_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       , 0 );
2481        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      , 0 );
2482        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        , 0 );
2483        _nic_set_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     , 0 );
2484        _nic_set_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       , 0 );
2485        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_RECEIVED  , 0 );
2486        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST , 0 );
2487        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  , 0 );
2488        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   , 0 );
2489    } 
2490    else
2491    {
2492        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  , 0 );
2493        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TRANSMIT  , 0 );
2494        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   , 0 );
2495        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL , 0 );
2496        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  , 0 );
2497        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    , 0 );
2498        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
2499    }
[709]2500    return GIET_SYSCALL_OK;
[494]2501}  // en _sys_nic_clear()
[459]2502
2503////////////////////////////////////////
[709]2504int _sys_nic_stats( unsigned int is_rx )
[459]2505{
[709]2506    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
2507
[459]2508    unsigned int nic_channel;
2509
2510    // get NIC channel
2511    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
2512    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
2513
[709]2514    if ( nic_channel >= NB_NIC_CHANNELS )
[459]2515    {
[709]2516        _printf("\n[GIET_ERROR] in _sys_nic_stats() : "
2517                "illegal NIC channel for thread %x\n", trdid );
2518        return -1111;
[459]2519    }
2520
2521    if ( is_rx )
2522    {
2523        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       );
2524        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      );
2525        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        );
2526        unsigned int fifo_full  = _nic_get_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     );
2527        unsigned int crc_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       );
2528        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST );
2529        unsigned int dst_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  );
2530        unsigned int ch_full    = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   );
2531
2532        _printf("\n### Network Controller RX Statistics ###\n"
2533                "- packets received : %d\n"
2534                "- too small        : %d\n"
2535                "- too big          : %d\n"
2536                "- fifo full        : %d\n" 
2537                "- crc fail         : %d\n" 
2538                "- dst mac fail     : %d\n" 
2539                "- channel full     : %d\n" 
2540                "- broadcast        : %d\n",
2541                received,
2542                too_small,
2543                too_big,
2544                fifo_full,
2545                crc_fail,
2546                dst_fail,
2547                ch_full,
2548                broadcast );
2549    } 
2550    else
2551    {
2552        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  );
2553        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   );
2554        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL );
2555        unsigned int src_fail   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  );
2556        unsigned int bypass     = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    );
2557        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST );
2558
2559        _printf("\n### Network Controller TX Statistics ###\n"
2560                "- packets received : %d\n"
2561                "- too small        : %d\n"
2562                "- too big          : %d\n"
2563                "- src mac fail     : %d\n" 
2564                "- bypass           : %d\n" 
2565                "- broadcast        : %d\n",
2566                received,
2567                too_big,
2568                too_small,
2569                src_fail,
2570                bypass,
2571                broadcast );
2572    }
[709]2573    return GIET_SYSCALL_OK;
[494]2574}  // end _sys_nic_stats()
[459]2575
[709]2576#endif
2577
[440]2578/////////////////////////////////////////////////////////////////////////////////////////
2579//    FBF related syscall handlers
2580/////////////////////////////////////////////////////////////////////////////////////////
2581
2582/////////////////////////////////////////////
2583int _sys_fbf_sync_write( unsigned int offset,
2584                         void*        buffer,
2585                         unsigned int length )
2586{
2587    char* fbf_address = (char *)SEG_FBF_BASE + offset;
2588    memcpy( fbf_address, buffer, length);
2589
[709]2590    return GIET_SYSCALL_OK;
[440]2591}
2592
2593/////////////////////////////////////////////
2594int _sys_fbf_sync_read(  unsigned int offset,
2595                         void*        buffer,
2596                         unsigned int length )
2597{
2598    char* fbf_address = (char *)SEG_FBF_BASE + offset;
2599    memcpy( buffer, fbf_address, length);
2600
[709]2601    return GIET_SYSCALL_OK;
[440]2602}
2603
2604////////////////////////
2605int _sys_fbf_cma_alloc()
2606{
[709]2607    unsigned int trdid = _get_thread_trdid();
2608
[699]2609    if ( _get_context_slot( CTX_CMA_FB_ID ) < NB_CMA_CHANNELS )
2610    {
[709]2611        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : "
2612                "CMA channel already allocated for thread %x\n", trdid );
2613        return GIET_SYSCALL_OK;
[699]2614    }
[440]2615
[709]2616    // get a CMA channel
[699]2617    unsigned int channel;
2618    for ( channel = 0 ; channel < NB_CMA_CHANNELS ; channel++ )
2619    {
[709]2620        unsigned int*  palloc = &_cma_channel_alloc[channel];
2621        if ( _atomic_test_and_set( palloc , 1 ) == 0 ) break;
[699]2622    }
[440]2623    if ( channel >= NB_CMA_CHANNELS )
2624    {
[699]2625        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : no CMA channel available\n");
[709]2626        return -1111;
[440]2627    }
2628    else
2629    {
[449]2630        _set_context_slot( CTX_CMA_FB_ID, channel );
[709]2631        return GIET_SYSCALL_OK;
[440]2632    }
2633} // end sys_fbf_cma_alloc()
2634
[709]2635//////////////////////////
2636int _sys_fbf_cma_release()  // Not a syscall
[700]2637{
2638    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[709]2639    unsigned int trdid   = _get_thread_trdid();
[614]2640
[700]2641    if ( channel >= NB_CMA_CHANNELS )
2642    {
[709]2643        _printf("\n[GIET_ERROR] in _sys_fbf_cma_release() : "
2644                "CMA_FB channel already releasedifor thread %x\n", trdid );
2645        return -1111;
[700]2646    }
2647
[709]2648    // stop CMA transfer
[700]2649    _sys_fbf_cma_stop();
2650
[709]2651    // reset CTX_CMA_FB_ID for thread
2652    _set_context_slot( CTX_CMA_FB_ID, 0xFFFFFFFF );
[700]2653
2654    // release CMA channel
[709]2655    _cma_channel_alloc[channel] = 0;
[700]2656
[709]2657    return GIET_SYSCALL_OK;
[700]2658}
2659
[648]2660///////////////////////////////////////////////////
2661int _sys_fbf_cma_init_buf( void*        buf0_vbase, 
2662                           void*        buf1_vbase, 
2663                           void*        sts0_vaddr,
2664                           void*        sts1_vaddr )
[440]2665{
2666#if NB_CMA_CHANNELS > 0
2667
2668    unsigned int       vaddr;           // virtual address
[528]2669    unsigned int       flags;           // for _v2p_translate()
[614]2670    unsigned long long fbf_paddr;       // fbf physical address
2671    unsigned long long fbf_sts_paddr;   // fbf status physical address
2672    unsigned long long buf0_pbase;      // buffer 0 base physical address
2673    unsigned long long sts0_paddr;      // buffer 0 status physical address
2674    unsigned long long buf1_pbase;      // buffer 1 base physical address
2675    unsigned long long sts1_paddr;      // buffer 1 status physical address
[440]2676
2677    // get channel index
[449]2678    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[440]2679
2680    if ( channel >= NB_CMA_CHANNELS )
2681    {
[648]2682        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : CMA channel index too large\n");
[709]2683        return -1111;
[440]2684    }
2685
2686#if GIET_DEBUG_FBF_CMA
[614]2687_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_init_buf()\n"
2688        " - channel           = %d\n"
2689        " - buf0        vbase = %x\n"
2690        " - buf1        vbase = %x\n"
2691        " - sts0        vaddr = %x\n"
2692        " - sts1        vaddr = %x\n",
[440]2693        channel,
[614]2694        (unsigned int)buf0_vbase,
2695        (unsigned int)buf1_vbase,
2696        (unsigned int)sts0_vaddr,
2697        (unsigned int)sts1_vaddr );
[440]2698#endif
2699
[614]2700    // checking user buffers virtual addresses alignment
2701    if ( ((unsigned int)buf0_vbase & 0x3F) || 
2702         ((unsigned int)buf1_vbase & 0x3F) ) 
[440]2703    {
[648]2704        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user buffer not aligned\n");
[709]2705        return -1111;
[440]2706    }
2707
[614]2708    // checking user buffers status virtual addresses alignment
2709    if ( ((unsigned int)sts0_vaddr & 0x3F) ||
2710         ((unsigned int)sts1_vaddr & 0x3F) )
2711    {
[648]2712        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user status not aligned\n");
[709]2713        return -1111;
[614]2714    }
2715
[440]2716    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
[528]2717    vaddr = (unsigned int)SEG_FBF_BASE;
[614]2718    fbf_paddr = _v2p_translate( vaddr , &flags );
2719    vaddr = (unsigned int)&_fbf_status[channel];
2720    fbf_sts_paddr = _v2p_translate( vaddr , &flags );
[440]2721
[614]2722    _fbf_chbuf[channel].fbf_desc =
2723        (unsigned long long) ((fbf_sts_paddr & 0xFFFFFFFFULL) >> 6) +
2724        (((fbf_paddr & 0xFFFFFFFFULL) >> 6 ) << 26);
2725
[528]2726    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
[614]2727    vaddr = (unsigned int)buf0_vbase;
2728    buf0_pbase = _v2p_translate( vaddr , &flags );
[440]2729    if ((flags & PTE_U) == 0) 
2730    {
[648]2731        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf0 not in user space\n");
[709]2732        return -1111;
[440]2733    }
2734
[614]2735    vaddr = (unsigned int)sts0_vaddr;
2736    sts0_paddr = _v2p_translate( vaddr , &flags );
2737    if ((flags & PTE_U) == 0) 
2738    {
[648]2739        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts0 not in user space\n");
[709]2740        return -1111;
[614]2741    }
2742
2743    _fbf_chbuf[channel].buf0_desc = 
2744        (unsigned long long) ((sts0_paddr & 0xFFFFFFFFULL) >> 6) +
2745        (((buf0_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
2746
[528]2747    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
[614]2748    vaddr = (unsigned int)buf1_vbase;
2749    buf1_pbase = _v2p_translate( vaddr , &flags );
[440]2750    if ((flags & PTE_U) == 0) 
2751    {
[648]2752        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf1 not in user space\n");
[709]2753        return -1111;
[440]2754    }
2755
[614]2756    vaddr = (unsigned int)sts1_vaddr;
2757    sts1_paddr = _v2p_translate( vaddr , &flags );
2758    if ((flags & PTE_U) == 0) 
2759    {
[648]2760        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts1 not in user space\n");
[709]2761        return -1111;
[614]2762    }
[440]2763
[614]2764    _fbf_chbuf[channel].buf1_desc = 
2765        (unsigned long long) ((sts1_paddr & 0xFFFFFFFFULL) >> 6) +
2766        (((buf1_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
2767
[505]2768    // Compute and register physical adress of the fbf_chbuf descriptor
[528]2769    vaddr = (unsigned int)&_fbf_chbuf[channel];
2770    _fbf_chbuf_paddr[channel] = _v2p_translate( vaddr , &flags );
[440]2771 
[614]2772#if GIET_DEBUG_FBF_CMA
2773_printf(" - fbf         pbase = %l\n"
2774        " - fbf status  paddr = %l\n"
2775        " - buf0        pbase = %l\n"
2776        " - buf0 status paddr = %l\n" 
2777        " - buf1        pbase = %l\n"
2778        " - buf0 status paddr = %l\n" 
2779        " - chbuf       pbase = %l\n",
2780        fbf_paddr,
2781        fbf_sts_paddr,
2782        buf0_pbase,
2783        sts0_paddr,
2784        buf1_pbase,
2785        sts1_paddr,
2786        _fbf_chbuf_paddr[channel] );
2787#endif
2788
[709]2789    return GIET_SYSCALL_OK;
[614]2790
2791#else
2792
2793    _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : NB_CMA_CHANNELS = 0\n");
[709]2794    return -1111;
[614]2795
2796#endif 
2797} // end sys_fbf_cma_init_buf()
2798
2799////////////////////////////////////////////
2800int _sys_fbf_cma_start( unsigned int length ) 
2801{
2802#if NB_CMA_CHANNELS > 0
2803
2804    // get channel index
2805    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
2806
2807    if ( channel >= NB_CMA_CHANNELS )
2808    {
2809        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
[709]2810        return -1111;
[614]2811    }
2812
2813    // check buffers initialization
2814    if ( ( _fbf_chbuf[channel].buf0_desc == 0x0ULL ) &&
2815         ( _fbf_chbuf[channel].buf1_desc == 0x0ULL) &&
2816         ( _fbf_chbuf[channel].fbf_desc == 0x0ULL) )
2817    {
2818        _printf("\n[GIET ERROR] in _sys_fbf_cma_start() :\n"
2819                "Buffer initialization has not been done\n");
[709]2820        return -1111;
[614]2821    }
2822
2823    // initializes buffer length
2824    _fbf_chbuf[channel].length = length;
2825
[440]2826    if ( USE_IOB )
2827    {
[505]2828        // SYNC request for fbf_chbuf descriptor
2829        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
[440]2830    }
2831
[505]2832    // start CMA transfer
2833    unsigned long long paddr = _fbf_chbuf_paddr[channel];
2834    unsigned int src_chbuf_paddr_lsb = (unsigned int)(paddr & 0xFFFFFFFF);
2835    unsigned int src_chbuf_paddr_ext = (unsigned int)(paddr >> 32);
[614]2836    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 16;
[505]2837    unsigned int dst_chbuf_paddr_ext = src_chbuf_paddr_ext;
2838
2839    _cma_set_register( channel, CHBUF_SRC_DESC , src_chbuf_paddr_lsb );
2840    _cma_set_register( channel, CHBUF_SRC_EXT  , src_chbuf_paddr_ext );
2841    _cma_set_register( channel, CHBUF_SRC_NBUFS, 2 );
2842    _cma_set_register( channel, CHBUF_DST_DESC , dst_chbuf_paddr_lsb );
2843    _cma_set_register( channel, CHBUF_DST_EXT  , dst_chbuf_paddr_ext );
2844    _cma_set_register( channel, CHBUF_DST_NBUFS, 1 );
2845    _cma_set_register( channel, CHBUF_BUF_SIZE , length );
2846    _cma_set_register( channel, CHBUF_PERIOD   , 300 );
2847    _cma_set_register( channel, CHBUF_RUN      , 1 );
2848
[709]2849    return GIET_SYSCALL_OK;
[440]2850
2851#else
2852
2853    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
[709]2854    return -1111;
[440]2855
2856#endif
2857} // end _sys_fbf_cma_start()
2858
2859/////////////////////////////////////////////////////
2860int _sys_fbf_cma_display( unsigned int buffer_index )
2861{
2862#if NB_CMA_CHANNELS > 0
2863
[505]2864    volatile unsigned int full = 1;
[440]2865
2866    // get channel index
[449]2867    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[440]2868
2869    if ( channel >= NB_CMA_CHANNELS )
2870    {
[505]2871        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
2872                "CMA channel index too large\n");
[709]2873        return -1111;
[440]2874    }
2875
[505]2876    // get fbf_chbuf descriptor pointer
2877    fbf_chbuf_t* pdesc = &_fbf_chbuf[channel];     
2878
[440]2879#if GIET_DEBUG_FBF_CMA
2880_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
[614]2881        " - cma channel      = %d\n"
2882        " - buffer index     = %d\n"
2883        " - buf0_desc value  = %l\n"
2884        " - buf1_desc value  = %l\n"
2885        " - fbf_desc  value  = %l\n",
[505]2886        channel , buffer_index,
[614]2887        _fbf_chbuf[channel].buf0_desc,
2888        _fbf_chbuf[channel].buf1_desc,
2889        _fbf_chbuf[channel].fbf_desc );
[440]2890#endif
2891
[614]2892    unsigned long long buf_sts_paddr;
2893    unsigned long long buf_paddr;
2894    unsigned long long fbf_sts_paddr;
2895
[478]2896    if ( buffer_index == 0 )    // user buffer 0
2897    {
[614]2898        buf_sts_paddr =
2899            ((pdesc->buf0_desc & 0xFFF0000000000000ULL) >> 20) + // compute address extension
2900            ((pdesc->buf0_desc & 0x3FFFFFFULL) << 6);            // compute 32 LSB of the address
[505]2901
[614]2902        buf_paddr =
2903            (pdesc->buf0_desc & 0xFFFFFFFFFC000000ULL) >> 20;  // compute the entire address
[440]2904    }
[478]2905    else                        // user buffer 1
2906    {
[614]2907        buf_sts_paddr =
2908            ((pdesc->buf1_desc & 0xFFF0000000000000ULL) >> 20) +
2909            ((pdesc->buf1_desc & 0x3FFFFFFULL) << 6);
[505]2910
[614]2911        buf_paddr =
2912            (pdesc->buf1_desc & 0xFFFFFFFFFC000000ULL) >> 20;
2913    }
[478]2914
[614]2915    fbf_sts_paddr =
2916        ((pdesc->fbf_desc & 0xFFF0000000000000ULL) >> 20) +
2917        ((pdesc->fbf_desc & 0x3FFFFFFULL) << 6);
[440]2918
[614]2919#if GIET_DEBUG_FBF_CMA
2920_printf(" - fbf status paddr = %l\n"
2921        " - buf        pbase = %l\n"
2922        " - buf status paddr = %l\n",
2923        fbf_sts_paddr,
2924        buf_paddr,
2925        buf_sts_paddr );
2926#endif
2927       
2928    // waiting user buffer released by the CMA component)
2929    while ( full )
2930    { 
[648]2931        // INVAL L2 cache copy of user buffer status     
[614]2932        // because it has been modified in RAM by the CMA component
2933        _mmc_inval( buf_sts_paddr , 4 );       
[440]2934
[614]2935        full = _physical_read( buf_sts_paddr );
[440]2936    }
2937
[614]2938    // SYNC request for the user buffer, because
2939    // it will be read from XRAM by the CMA component
2940    _mmc_sync( buf_paddr , pdesc->length );
[440]2941
[614]2942    // set user buffer status
2943    _physical_write( buf_sts_paddr, 0x1 );
2944
2945    // reset fbf buffer status
2946    _physical_write( fbf_sts_paddr, 0x0 );
2947   
2948    // SYNC request, because these buffer descriptors
2949    // will be read from XRAM by the CMA component
2950    _mmc_sync( buf_sts_paddr, 4 );
2951    _mmc_sync( fbf_sts_paddr, 4 );
2952
[709]2953    return GIET_SYSCALL_OK;
[440]2954
2955#else
2956
2957    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
[709]2958    return -1111;
[440]2959
2960#endif
2961} // end _sys_fbf_cma_display()
2962
2963///////////////////////
2964int _sys_fbf_cma_stop()
2965{
2966#if NB_CMA_CHANNELS > 0
2967
2968    // get channel index
[449]2969    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[440]2970
2971    if ( channel >= NB_CMA_CHANNELS )
2972    {
2973        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
[709]2974        return -1111;
[440]2975    }
2976
2977    // Desactivate CMA channel
[505]2978    _cma_set_register( channel, CHBUF_RUN, 0 );
[440]2979
[709]2980    return GIET_SYSCALL_OK;
[440]2981
2982#else
2983
2984    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
[709]2985    return -1111;
[440]2986
2987#endif
2988} // end _sys_fbf_cma_stop()
2989
2990
2991//////////////////////////////////////////////////////////////////////////////
2992//           Miscelaneous syscall handlers
2993//////////////////////////////////////////////////////////////////////////////
2994
2995///////////////
2996int _sys_ukn() 
2997{
2998    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
[709]2999    return GIET_SYSCALL_UNDEFINED_SYSTEM_CALL;
[440]3000}
3001
3002////////////////////////////////////
3003int _sys_proc_xyp( unsigned int* x,
3004                   unsigned int* y,
3005                   unsigned int* p )
3006{
[428]3007    unsigned int gpid = _get_procid();  // global processor index from CPO register
3008
3009    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
3010    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
3011    *p = gpid & ((1<<P_WIDTH)-1);
[440]3012
[709]3013    return GIET_SYSCALL_OK;
[428]3014}
[440]3015
[494]3016////////////////////////////////////////////
3017int _sys_procs_number( unsigned int* x_size,
3018                       unsigned int* y_size,
3019                       unsigned int* nprocs )
[258]3020{
[494]3021    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[440]3022    mapping_cluster_t * cluster = _get_cluster_base(header);
3023
[494]3024    unsigned int x;
3025    unsigned int y;
3026    unsigned int okmin = 1;
3027    unsigned int okmax = 1;
3028
3029    // compute max values
3030    unsigned int xmax  = header->x_size;
3031    unsigned int ymax  = header->y_size;
3032    unsigned int procs = cluster[0].procs;
3033
3034    // check the (ymax-1) lower rows
3035    for ( y = 0 ; y < ymax-1 ; y++ )
[440]3036    {
[494]3037        for ( x = 0 ; x < xmax ; x++ )
3038        {
3039            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
3040        }
[440]3041    }
[494]3042
3043    // check the upper row
3044    for ( x = 0 ; x < xmax ; x++ )
[440]3045    {
[494]3046        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
[440]3047    }
[494]3048
3049    // return values
3050    if ( okmin && okmax )
3051    {
3052        *x_size = xmax;
3053        *y_size = ymax;
3054        *nprocs = procs;
3055    }
3056    else if ( okmin )
3057    {
3058        *x_size = xmax;
3059        *y_size = ymax-1;
3060        *nprocs = procs;
3061    }
3062    else
3063    {
3064        *x_size = 0;
3065        *y_size = 0;
3066        *nprocs = 0;
3067    }
[709]3068    return GIET_SYSCALL_OK;
[440]3069}
3070
3071///////////////////////////////////////////////////////
[516]3072int _sys_vseg_get_vbase( char*             vspace_name, 
3073                         char*             vseg_name, 
[440]3074                         unsigned int*     vbase ) 
3075{
[322]3076    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[258]3077    mapping_vspace_t * vspace = _get_vspace_base(header);
[516]3078    mapping_vseg_t * vseg     = _get_vseg_base(header);
[258]3079
3080    unsigned int vspace_id;
[516]3081    unsigned int vseg_id;
[258]3082
3083    // scan vspaces
3084    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
3085    {
3086        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
3087        {
[516]3088            // scan vsegs
3089            for (vseg_id = vspace[vspace_id].vseg_offset; 
3090                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
3091                 vseg_id++) 
[258]3092            {
[516]3093                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
[258]3094                {
[516]3095                    *vbase = vseg[vseg_id].vbase;
[709]3096                    return GIET_SYSCALL_OK;
[258]3097                }
3098            } 
3099        }
3100    } 
[709]3101    return GIET_SYSCALL_VSEG_NOT_FOUND;
[258]3102}
3103
[440]3104/////////////////////////////////////////////////////////
[516]3105int _sys_vseg_get_length( char*         vspace_name, 
3106                          char*         vseg_name,
[440]3107                          unsigned int* length ) 
[258]3108{
[440]3109    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
3110    mapping_vspace_t * vspace = _get_vspace_base(header);
[516]3111    mapping_vseg_t * vseg     = _get_vseg_base(header);
[258]3112
[440]3113    unsigned int vspace_id;
[516]3114    unsigned int vseg_id;
[440]3115
3116    // scan vspaces
3117    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
[258]3118    {
[440]3119        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
3120        {
[516]3121            // scan vsegs
3122            for (vseg_id = vspace[vspace_id].vseg_offset; 
3123                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
3124                 vseg_id++) 
[440]3125            {
[516]3126                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
[440]3127                {
[516]3128                    *length = vseg[vseg_id].length;
[709]3129                    return GIET_SYSCALL_OK;
[440]3130                }
3131            } 
3132        }
3133    } 
[709]3134    return GIET_SYSCALL_VSEG_NOT_FOUND;
[258]3135}
3136
[440]3137////////////////////////////////////////
3138int _sys_xy_from_ptr( void*         ptr,
3139                      unsigned int* x,
3140                      unsigned int* y )
[396]3141{
3142    unsigned int flags;
[528]3143    unsigned long long paddr = _v2p_translate( (unsigned int)ptr , &flags );
[396]3144   
[528]3145    *x = (paddr>>36) & 0xF;
3146    *y = (paddr>>32) & 0xF;
[396]3147
[709]3148    return GIET_SYSCALL_OK;
[396]3149}
3150
[440]3151/////////////////////////////////////////
3152int _sys_heap_info( unsigned int* vaddr, 
3153                    unsigned int* length,
3154                    unsigned int  x,
3155                    unsigned int  y ) 
[258]3156{
[709]3157    // checking parameters
3158    if ( (x >= X_SIZE) || (y >= Y_SIZE) ) 
3159    {
3160        *vaddr  = 0;
3161        *length = 0;
3162        _printf("\n[GIET ERROR] in _sys_heap_info() : "
3163                "illegal (%d,%d) coordinates\n", x , y );
3164        return GIET_SYSCALL_ILLEGAL_CLUSTER_COORDINATES;
3165    }
3166
[440]3167    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[709]3168    mapping_thread_t * thread  = _get_thread_base(header);
[516]3169    mapping_vseg_t *   vseg    = _get_vseg_base(header);
3170    mapping_vspace_t * vspace  = _get_vspace_base(header);
[294]3171
[709]3172    unsigned int thread_id;
[440]3173    unsigned int vspace_id;
[516]3174    unsigned int vseg_id = 0xFFFFFFFF;
[258]3175
[709]3176    // get calling thread vspace index
3177    vspace_id = _get_context_slot(CTX_VSID_ID);
3178
3179    // scan all threads in vspace to find one in clyster[x,y]
3180    unsigned int min = vspace[vspace_id].thread_offset ;
3181    unsigned int max = min + vspace[vspace_id].threads ;
3182    for ( thread_id = min ; thread_id < max ; thread_id++ )
[440]3183    {
[709]3184        if ( thread[thread_id].clusterid == (x * Y_SIZE + y) )
[440]3185        {
[709]3186            vseg_id = thread[thread_id].heap_vseg_id;
3187            break;
[440]3188        }
3189    }
3190
[516]3191    // analysing the vseg_id
3192    if ( vseg_id != 0xFFFFFFFF ) 
[440]3193    {
[516]3194        *vaddr  = vseg[vseg_id].vbase;
3195        *length = vseg[vseg_id].length;
[440]3196    }
3197    else 
3198    {
3199        *vaddr  = 0;
3200        *length = 0;
[709]3201        _printf("error in _sys_heap_info() : no heap in cluster (%d,%d)\n", x , y );
[440]3202    }
[709]3203    return GIET_SYSCALL_OK;
[440]3204}  // end _sys_heap_info()
3205
3206
[258]3207// Local Variables:
3208// tab-width: 4
3209// c-basic-offset: 4
3210// c-file-offsets:((innamespace . 0)(inline-open . 0))
3211// indent-tabs-mode: nil
3212// End:
3213// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
3214
Note: See TracBrowser for help on using the repository browser.