Index: /soft/giet_vm/giet_kernel/irq_handler.c
===================================================================
--- /soft/giet_vm/giet_kernel/irq_handler.c	(revision 493)
+++ /soft/giet_vm/giet_kernel/irq_handler.c	(revision 494)
@@ -27,5 +27,8 @@
 #endif
 
-// ISR_TYPE names for display
+////////////////////////////////////////////
+//     ISR_TYPE names for display
+///////////////////////////////////////////
+__attribute__((section(".kdata")))
 char* _isr_type_name[] = { "DEFAULT",
                            "TICK"   ,
Index: /soft/giet_vm/giet_kernel/kernel.ld
===================================================================
--- /soft/giet_vm/giet_kernel/kernel.ld	(revision 493)
+++ /soft/giet_vm/giet_kernel/kernel.ld	(revision 494)
@@ -22,18 +22,5 @@
     seg_kernel_data : 
     {
-        *(.iommu)
-        *(.fatdata)
-        *(.descriptor)
         *(.kdata)
-        *(.rodata)
-        *(.rodata.*)
-        *(.data)
-        *(.lit8)
-        *(.lit4)
-        *(.sdata)
-        *(.bss)
-        *(COMMON)
-        *(.sbss)
-        *(.scommon)
     }
 
Index: /soft/giet_vm/giet_kernel/kernel_init.c
===================================================================
--- /soft/giet_vm/giet_kernel/kernel_init.c	(revision 493)
+++ /soft/giet_vm/giet_kernel/kernel_init.c	(revision 494)
@@ -13,4 +13,6 @@
 #include <tty0.h>
 #include <kernel_malloc.h>
+#include <kernel_locks.h>
+#include <kernel_barriers.h>
 #include <fat32.h>
 #include <xcu_driver.h>
@@ -72,64 +74,59 @@
 
 
+// Distributed kernel heap descriptors array
+// __attribute__((section(".kdata")))
+// kernel_heap_t  kernel_heap[X_SIZE][Y_SIZE];
+
+// FAT internal representation for kernel code
+__attribute__((section(".kdata")))
+fat32_fs_t     fat      __attribute__((aligned(512)));
+
+// array of page tables virtual addresses
+__attribute__((section(".kdata")))
+volatile unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX]; 
+
+// array of page tables PTPR values (physical addresses >> 13)
+__attribute__((section(".kdata")))
+volatile unsigned int _ptabs_ptprs[GIET_NB_VSPACE_MAX]; 
+
+// Array of pointers on the schedulers
+__attribute__((section(".kdata")))
+volatile static_scheduler_t*    _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
+
+// Synchonisation before entering parallel execution
+__attribute__((section(".kdata")))
+volatile unsigned int _kernel_init_done = 0;
+
+// Kernel uses sqt_lock to protect TTY0        
+__attribute__((section(".kdata")))
+unsigned int   _tty0_boot_mode = 0;
+
+// Distributed synchronisation barrier for parallel init by all processors      
+__attribute__((section(".kdata")))
+sqt_barrier_t  _all_procs_barrier  __attribute__((aligned(64)));
+
+
+
+// this variable is defined in tty0.c file
+extern sqt_lock_t _tty0_sqt_lock;
+
+
+
 ///////////////////////////////////////////////////////////////////////////////////
-// Ditributed kernel heap descriptors array (for dynamic memory allocation)
-///////////////////////////////////////////////////////////////////////////////////
-
-kernel_heap_t  kernel_heap[X_SIZE][Y_SIZE];
-
-///////////////////////////////////////////////////////////////////////////////////
-// FAT internal representation for kernel code
-///////////////////////////////////////////////////////////////////////////////////
-
-fat32_fs_t     fat      __attribute__((aligned(512)));
-
-///////////////////////////////////////////////////////////////////////////////////
-// array of pointers on the page tables (virtual addresses)
-///////////////////////////////////////////////////////////////////////////////////
-
-volatile unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX];    // virtual addresses
-volatile unsigned int _ptabs_ptprs[GIET_NB_VSPACE_MAX];    // physical addresses >> 13
-
-///////////////////////////////////////////////////////////////////////////////////
-// Array of pointers on the schedulers (physical addresses)
-///////////////////////////////////////////////////////////////////////////////////
-
-volatile static_scheduler_t*    _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
-
-////////////////////////////////////////////////////////////////////////////////////
-// Synchonisation barrier before jumping to user code
-////////////////////////////////////////////////////////////////////////////////////
-
-volatile unsigned int kernel_init_barrier = 0;
-
-////////////////////////////////////////////////////////////////////////////////////
-// Global variables for TTY/kernel communications
-////////////////////////////////////////////////////////////////////////////////////
-
-unsigned int   _tty_rx_buf[NB_TTY_CHANNELS];
-unsigned int   _tty_rx_full[NB_TTY_CHANNELS]; 
-
-////////////////////////////////////////////////////////////////////////////////////
-// Distributed locks protecting TTY terminals        
-////////////////////////////////////////////////////////////////////////////////////
-
-sbt_lock_t     _tty_tx_lock[NB_TTY_CHANNELS]  __attribute__((aligned(64)));
-
-///////////////////////////////////////////////////////////////////////////////////
-// This kernel_init() function completes the kernel initialisation in 7 steps:
-// All processors execute this code, but this is done sequencially.
-// - step 0 : Initialise fat, heap descriptors, and tty locks
-// - step 1 : Initialise scheduler pointers array
-// - step 2 : Initialise PTAB pointers arrays
-// - step 3 : Initialise private XCU masks
-// - step 4 :
-// - step 5 :
-// - step 6 :
+// This kernel_init() function completes the kernel initialisation in 7 steps.
+// Step 0 is done by processor[0,0,0]. Steps 1 to 6 are executed in parallel
+// by all procesors.
+// - step 0 : P[0,0,0] Initialise fat, heap descriptors, barrier and TTY0 lock.
+// - step 1 : Each processor initialises scheduler pointers array.
+// - step 2 : Each processor initialises PTAB pointers arrays.
+// - step 3 : Each processor initialises its private XCU masks.
+// - step 4 : Each processor starts its private TICK timer.
+// - step 5 : Each processor initialises its private idle task context.
+// - step 6 : Each processor set sp, sr, ptpr, epc registers values. 
 ///////////////////////////////////////////////////////////////////////////////////
 __attribute__((section (".kinit"))) void kernel_init() 
 {
-    // gpid : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
-    // p    : local processor id in a cluster ( p < NB_PROCS_MAX)
-    // cpid : continuous processor index = (((x * Y_SIZE + y) * NB_PROCS_MAX) + p 
+    // gpid  : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
+    // x,y,p : processor coordinates ( x<X_SIZE / y<Y_SIZE / p<NB_PROCS_MAX )
 
     unsigned int gpid       = _get_procid();
@@ -138,16 +135,11 @@
     unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     unsigned int p          = gpid & ((1<<P_WIDTH)-1);
-    unsigned int cpid       = ((( x * Y_SIZE) + y) * NB_PROCS_MAX) + p;
-
-    // This initialisation is done sequencially by each processor
-    while( cpid != kernel_init_barrier ) asm volatile ( "nop" );
-
-    // Step 0 : P[0,0,0] initialises various complex structures
-    //          - kernel FAT 
-    //          - distributed kernel heaps
-    //          - distributed locks protecting TTY channels 
-    //          - distributed locks protecting MMC components
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Step 0 : P[0,0,0] initialises various structures
+
     if ( gpid == 0 )
     {
+        // distributed kernel heaps
         _heap_init();
         
@@ -155,30 +147,5 @@
 _nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes kernel HEAP init\n", x, y, p );
 #endif
-        unsigned int channel;
-        for ( channel = 0 ; channel < NB_TTY_CHANNELS ; channel++ )
-        {
-            _sbt_lock_init( &_tty_tx_lock[channel] );
-
-#if GIET_DEBUG_INIT
-_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes TTY[%d] lock init\n", 
-               x , y , p , channel );
-#endif
-        }
-
-/*
-        unsigned int cx, cy;
-        for ( cx = 0 ; cx < X_SIZE ; cx++ )
-        {
-            for ( cy = 0 ; cy < X_SIZE ; cy++ )
-            {
-                _sbt_lock_init( &_mmc_lock[cx][cy] );
-
-#if GIET_DEBUG_INIT
-_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes MMC[%d][%d] lock init\n", 
-               x , y , p , cx , cy );
-#endif
-            }
-        }
-*/
+        // kernel FAT 
         _fat_init( IOC_BOOT_MODE ); 
 
@@ -186,9 +153,31 @@
 _nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes kernel FAT init\n", x, y, p );
 #endif
-
-    }
-
-    // Step 1 : each processor get its scheduler virtual address from CP0_SCHED register
-    //          and contributes to _schedulers[] array initialisation
+        // distributed lock for TTY0
+        _sqt_lock_init( &_tty0_sqt_lock );
+
+#if GIET_DEBUG_INIT
+_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes TTY0 lock init\n", 
+               x , y , p );
+#endif
+        // distributed kernel barrier between all processors
+        _sqt_barrier_init( &_all_procs_barrier );
+
+#if GIET_DEBUG_INIT
+_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes barrier init\n", 
+               x , y , p );
+#endif
+
+        // release other processors
+        _kernel_init_done = 1;
+    }
+    else 
+    {
+        while( _kernel_init_done == 0 )  asm volatile ( "nop" );
+    }
+
+    ///////////////////////////////////////////////////////////////////
+    // Step 1 : each processor get its scheduler vaddr from CP0_SCHED, 
+    //          contributes to _schedulers[] array initialisation,
+    //          and wait completion of array initialisation.
 
     static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
@@ -198,10 +187,13 @@
 
 #if GIET_DEBUG_INIT
-_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initialises SCHED array\n"
-               " - scheduler vbase = %x\n"
-               " - tasks           = %d\n",
-               x, y, p, (unsigned int)psched, tasks );
-#endif
-
+_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initialises SCHED array\n"
+        " - scheduler vbase = %x\n"
+        " - tasks           = %d\n",
+        x, y, p, (unsigned int)psched, tasks );
+#endif
+
+    _sqt_barrier_wait( &_all_procs_barrier );    
+
+    ////////////////////////////////////////////////////////////////////////////
     // step 2 : each processor that is allocated at least one task loops 
     //          on all allocated tasks: 
@@ -225,5 +217,5 @@
 
 #if GIET_DEBUG_INIT
-_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initialises PTABS arrays\n"
+_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initialises PTABS arrays\n"
         " - ptabs_vaddr[%d] = %x / ptpr_paddr[%d] = %l\n",
         x, y, p,  
@@ -244,15 +236,18 @@
 
 #if GIET_DEBUG_INIT
-_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] updates context for task %d\n"
-               " - ctx_epc   = %x\n"
-               " - ctx_ra    = %x\n",
-               x, y, p, ltid,
-               _get_task_slot( x, y, p, ltid, CTX_EPC_ID ),
-               _get_task_slot( x, y, p, ltid, CTX_RA_ID ) );
+_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] updates context for task %d\n"
+        " - ctx_epc   = %x\n"
+        " - ctx_ra    = %x\n",
+        x, y, p, ltid,
+        _get_task_slot( x, y, p, ltid, CTX_EPC_ID ),
+        _get_task_slot( x, y, p, ltid, CTX_RA_ID ) );
 #endif
 
     }  // end for tasks
 
-    // step 3 : compute and set XCU masks
+    _sqt_barrier_wait( &_all_procs_barrier );    
+
+    ////////////////////////////////////////////////////////////////////////////
+    // step 3 : compute and set XCU masks for HWI / PTI / WTI interrupts
 
     unsigned int isr_switch_index = 0xFFFFFFFF;
@@ -279,9 +274,12 @@
 
 #if GIET_DEBUG_INIT
-_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] sets XCU masks\n"
-               " - XCU HWI_MASK = %x\n"
-               " - XCU WTI_MASK = %x\n"
-               " - XCU PTI_MASK = %x\n",
-               x, y, p, hwi_mask, wti_mask, pti_mask );
+_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] sets XCU masks\n"
+        " - ISR_TICK_INDEX = %d\n"
+        " - XCU HWI_MASK   = %x\n"
+        " - XCU WTI_MASK   = %x\n"
+        " - XCU PTI_MASK   = %x\n",
+        x, y, p, 
+        isr_switch_index,
+        hwi_mask, wti_mask, pti_mask );
 #endif
 
@@ -292,5 +290,7 @@
     _xcu_set_mask( cluster_xy, channel, pti_mask, IRQ_TYPE_PTI );
 
-    // step 4 : start TICK timer if at least one task
+    ////////////////////////////////////////////////////////////////////////////
+    // step 4 : Each processor start TICK timer if at least one task
+
     if (tasks > 0) 
     {
@@ -298,5 +298,5 @@
         if (isr_switch_index == 0xFFFFFFFF) 
         {
-            _nolock_printf("\n[GIET ERROR] ISR_TICK not found for processor[%d,%d,%d]\n",
+            _printf("\n[GIET ERROR] ISR_TICK not found for processor[%d,%d,%d]\n",
                            x, y, p );
             _exit();
@@ -309,8 +309,9 @@
 
 #if GIET_DEBUG_INIT
-_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] starts TICK timer\n",
-               x, y, p );
-#endif
-
+_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] starts TICK timer\n",
+        x, y, p );
+#endif
+
+    ////////////////////////////////////////////////////////////////////////////
     // step 5 : each processor updates the idle_task context:
     //          (CTX_SP, CTX_RA, CTX_EPC).
@@ -326,22 +327,22 @@
 
 #if GIET_DEBUG_INIT
-_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initializes IDLE task\n"
-               " - stack_base = %x\n"
-               " - stack_size = 0x1000\n",
-               x, y, p, pstack - 0x1000 );
-#endif
-
-    // step 6 : when all processors reach the synchronisation barrier, 
-    //          each processor set registers SP, SR, PTPR, EPC,
-    //          with the values corresponding to the first allocated task,
-    //          or to the idle_task if there is no task allocated,
-    //          and jump to user code 
-
-    if (tasks == 0) 
+_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initializes IDLE task\n"
+        " - stack_base = %x\n"
+        " - stack_size = 0x1000\n",
+        x, y, p, pstack - 0x1000 );
+#endif
+
+    _sqt_barrier_wait( &_all_procs_barrier );    
+
+    ////////////////////////////////////////////////////////////////////////////
+    // step 6 : Each processor compute values for registers SP, SR, PTPR, EPC,
+    //          corresponding to the first allocated task (can be idle task)
+    //          and jump to user code when barrier is reached
+
+    if (tasks == 0)
     {
         ltid = IDLE_TASK_INDEX;
-
-        _nolock_printf("\n[GIET WARNING] No task allocated to processor[%d,%d,%d]\n",
-                       x, y, p );
+        _printf("\n[GIET WARNING] No task allocated to processor[%d,%d,%d]\n",
+                x, y, p );
     }
     else
@@ -355,21 +356,9 @@
     unsigned int epc_value  = _get_task_slot( x, y, p, ltid, CTX_EPC_ID);
 
-#if GIET_DEBUG_INIT
-_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] reach barrier at cycle %d\n",
-               x, y, p, _get_proctime() );
-#endif
-
-    // increment barrier counter 
-    kernel_init_barrier++;
-
-    // busy waiting until all processors synchronized
-    while ( kernel_init_barrier != NB_TOTAL_PROCS );
-
-#if GIET_DEBUG_INIT
-_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initializes registers at cycle %d\n"
-        " - sp   = %x\n"
-        " - sr   = %x\n"
-        " - ptpr = %x\n"
-        " - epc  = %x\n",
+    _sqt_barrier_wait( &_all_procs_barrier );
+
+#if GIET_DEBUG_INIT
+_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] jumps to user code at cycle %d\n"
+        "  sp = %x / sr = %x / ptpr = %x / epc = %x\n",
         x, y, p, _get_proctime(),
         sp_value, sr_value, ptpr_value, epc_value );
Index: /soft/giet_vm/giet_kernel/sys_handler.c
===================================================================
--- /soft/giet_vm/giet_kernel/sys_handler.c	(revision 493)
+++ /soft/giet_vm/giet_kernel/sys_handler.c	(revision 494)
@@ -65,9 +65,28 @@
 ////////////////////////////////////////////////////////////////////////////
 
+__attribute__((section(".kdata")))
 unsigned int _tty_channel_allocator    = 1;
+
+__attribute__((section(".kdata")))
 unsigned int _tim_channel_allocator    = 0;
+
+__attribute__((section(".kdata")))
 unsigned int _cma_channel_allocator    = 0;
+
+__attribute__((section(".kdata")))
 unsigned int _nic_rx_channel_allocator = 0;
+
+__attribute__((section(".kdata")))
 unsigned int _nic_tx_channel_allocator = 0;
+
+////////////////////////////////////////////////////////////////////////////
+// These global variables is defined in tty0.c and tty_driver.c files.
+////////////////////////////////////////////////////////////////////////////
+
+extern sqt_lock_t _tty0_sqt_lock;
+
+extern unsigned int _tty_rx_full[NB_TTY_CHANNELS];
+
+extern unsigned int _tty_rx_buf[NB_TTY_CHANNELS];
 
 ////////////////////////////////////////////////////////////////////////////
@@ -75,6 +94,8 @@
 ////////////////////////////////////////////////////////////////////////////
 
+__attribute__((section(".kdata")))
 nic_chbuf_t  _nic_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
 
+__attribute__((section(".kdata")))
 nic_chbuf_t  _nic_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
 
@@ -84,6 +105,8 @@
 ////////////////////////////////////////////////////////////////////////////
 
+__attribute__((section(".kdata")))
 fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(64)));
 
+__attribute__((section(".kdata")))
 unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
 
@@ -92,4 +115,6 @@
 // Note: This array must be synchronised with the define in file stdio.h
 ////////////////////////////////////////////////////////////////////////////
+
+__attribute__((section(".kdata")))
 const void * _syscall_vector[64] = 
 {
@@ -241,13 +266,12 @@
 
 ///////////////////////////////////////////
-int _sys_tty_get_lock( unsigned int   channel,
+int _sys_tty_get_lock( unsigned int   channel,       // unused
                        unsigned int * save_sr_ptr )
 {
-    // compute and check tty channel
-    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
-    if( channel >= NB_TTY_CHANNELS ) return -1;
+    // check tty channel
+    if( channel != 0 )  return 1;
 
     _it_disable( save_sr_ptr );
-    _sbt_lock_acquire( &_tty_tx_lock[channel] );
+    _sqt_lock_acquire( &_tty0_sqt_lock );
     return 0;
 }
@@ -257,9 +281,8 @@
                            unsigned int * save_sr_ptr )
 {
-    // compute and check tty channel
-    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
-    if( channel >= NB_TTY_CHANNELS ) return -1;
-
-    _sbt_lock_release( &_tty_tx_lock[channel] );
+    // check tty channel
+    if( channel != 0 )  return 1;
+
+    _sqt_lock_release( &_tty0_sqt_lock );
     _it_restore( save_sr_ptr );
     return 0;
@@ -332,35 +355,49 @@
 #define NIC_CONTAINER_SIZE 4096
 
-///////////////////////////////////////////
-int _sys_nic_alloc( unsigned int is_rx )
-{
+////////////////////////////////////////
+int _sys_nic_alloc( unsigned int is_rx,
+                    unsigned int xmax,
+                    unsigned int ymax )
+{
+    // check xmax / ymax parameters
+    if ( xmax > X_SIZE )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_alloc() xmax argument too large\n");
+        return -1;
+    }
+    if ( ymax > Y_SIZE )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_alloc() ymax argument too large\n");
+        return -1;
+    }
+
+    // get a NIC_RX or NIC_TX channel index 
+    unsigned int nic_channel;
+    unsigned int cma_channel;
+
+    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
+    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
+
+    if ( (nic_channel >= NB_NIC_CHANNELS) )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
+        return -1;
+    }
+
+    // get a CMA channel index
+    cma_channel = _atomic_increment( &_cma_channel_allocator, 1 );
+
+    if ( cma_channel >= NB_CMA_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
+        return -1;
+    }
 
 #if GIET_DEBUG_NIC
 unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
-_printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n",
-        thread, _get_proctime() );
-#endif
-
-    unsigned int nic_channel;
-    unsigned int cma_channel;
-
-    // get a NIC_RX or NIC_TX channel index 
-    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
-    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
-
-    if ( (nic_channel >= NB_NIC_CHANNELS) )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
-        return -1;
-    }
-
-    // get a CMA channel index
-    cma_channel = _atomic_increment( &_cma_channel_allocator, 1 );
-
-    if ( cma_channel >= NB_CMA_CHANNELS )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
-        return -1;
-    }
+_printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n"
+        " nic_channel = %d / cma_channel = %d\n"
+        thread , _get_proctime() , nic_channel , cma_channel );
+#endif
 
     // register nic_index and cma_index in task context
@@ -376,56 +413,5 @@
     }
 
-#if GIET_DEBUG_NIC
-_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d : "
-        "NIC channel = %d / CMA channel = %d\n", 
-        thread, _get_proctime(), nic_channel, cma_channel );
-#endif
-
-    return nic_channel;
-} // end _sys_nic_alloc()
-
-////////////////////////////////////////
-int _sys_nic_start( unsigned int is_rx,
-                    unsigned int channel )
-{
-
-#if GIET_DEBUG_NIC
-unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
-_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_start() at cycle %d\n",
-        thread , _get_proctime() );
-#endif
-
-    unsigned int nic_channel;
-    unsigned int cma_channel;
-
-    // get NIC channel index and CMA channel index
-    if ( is_rx )
-    {
-        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
-        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
-    }
-    else
-    {
-        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
-        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
-    }
-
-#if GIET_DEBUG_NIC
-_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d"
-        " get NIC channel = %d / CMA channel = %d\n",
-        thread, _get_proctime(), nic_channel, cma_channel );
-#endif
-
-    if ( nic_channel != channel )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal NIC channel\n");
-        return -1;
-    }
-    if ( cma_channel >= NB_CMA_CHANNELS )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal CMA channel\n");
-        return -1;
-    }
-
+    // physical addresses to be registered in the CMA registers
     unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
     unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
@@ -437,19 +423,26 @@
     unsigned int       vaddr;
 
-    // allocate two containers per cluster
-    unsigned int        cx;           // container X coordinate
-    unsigned int        cy;           // container Y coordinate
-    unsigned int        index;        // container index in chbuf
-    unsigned long long  cont_paddr;   // container physical address
-    
-    for ( cx = 0 ; cx < X_SIZE ; cx++ )
-    {
-        for ( cy = 0 ; cy < Y_SIZE ; cy++ )
+    // allocate one kernel container per cluster in the (xmax / ymax) mesh
+    unsigned int        cx;              // cluster X coordinate
+    unsigned int        cy;              // cluster Y coordinate
+    unsigned int        index;           // container index in chbuf
+    unsigned long long  cont_paddr;      // container physical address
+
+    for ( cx = 0 ; cx < xmax ; cx++ )
+    {
+        for ( cy = 0 ; cy < ymax ; cy++ )
         {
             // compute index in chbuf
-            index = (cx * Y_SIZE) + cy; 
-
-            // allocate the container
+            index = (cx * ymax) + cy; 
+
+            // allocate the kernel container
             vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
+
+            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
+            {
+                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
+                        " in cluster[%d,%d]\n", cx, cy );
+                return -1;
+            }
 
             // compute container physical address
@@ -460,5 +453,5 @@
             cont_paddr = (((unsigned long long)ppn) << 12) | (vaddr & 0x00000FFF);
 
-            // initialize chbuf
+            // initialize chbuf entry
             if ( is_rx ) _nic_rx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
             else         _nic_tx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
@@ -470,4 +463,16 @@
 #endif
         }
+    }
+
+    // complete kernel chbuf initialisation
+    if ( is_rx )
+    {
+        _nic_rx_chbuf[nic_channel].xmax = xmax;
+        _nic_rx_chbuf[nic_channel].ymax = ymax;
+    }
+    else
+    {
+        _nic_tx_chbuf[nic_channel].xmax = xmax;
+        _nic_tx_chbuf[nic_channel].ymax = ymax;
     }
 
@@ -511,5 +516,5 @@
         _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(ker_chbuf_pbase) );
         _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
-        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, X_SIZE*Y_SIZE );
+        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, xmax * ymax );
     }
     else                      // kernel to NIC
@@ -517,8 +522,55 @@
         _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(ker_chbuf_pbase) );
         _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
-        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, X_SIZE*Y_SIZE );
+        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, xmax * ymax );
         _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(nic_chbuf_pbase) );
         _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
         _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
+    }
+
+#if GIET_DEBUG_NIC
+_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d\n",
+        thread, _get_proctime() );
+#endif
+
+    return nic_channel;
+} // end _sys_nic_alloc()
+
+
+////////////////////////////////////////
+int _sys_nic_start( unsigned int is_rx,
+                    unsigned int channel )
+{
+    unsigned int nic_channel;
+    unsigned int cma_channel;
+
+    // get NIC channel index and CMA channel index from task context
+    if ( is_rx )
+    {
+        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
+        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
+    }
+    else
+    {
+        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
+        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
+    }
+
+#if GIET_DEBUG_NIC
+unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
+_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d"
+        " get NIC channel = %d / CMA channel = %d\n",
+        thread, _get_proctime(), nic_channel, cma_channel );
+#endif
+
+    // check NIC and CMA channels index
+    if ( nic_channel != channel )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal NIC channel\n");
+        return -1;
+    }
+    if ( cma_channel >= NB_CMA_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal CMA channel\n");
+        return -1;
     }
 
@@ -539,4 +591,5 @@
 }  // end sys_nic_start()
 
+
 //////////////////////////////////////
 int _sys_nic_move( unsigned int is_rx,
@@ -551,8 +604,38 @@
 #endif
 
+    // check NIC channel index
+    if ( channel >= NB_NIC_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
+        return -1;
+    }
+
+    // get kernel chbuf virtual address
+    nic_chbuf_t* chbuf;
+    if ( is_rx )  chbuf = &_nic_rx_chbuf[channel];
+    else          chbuf = &_nic_tx_chbuf[channel];
+
+    // get xmax / ymax parameters
+    unsigned int xmax = chbuf->xmax;
+    unsigned int ymax = chbuf->ymax;
+
     // get cluster coordinates for the processor running the calling task
     unsigned int  procid = _get_procid();
     unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
     unsigned int  cy     = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
+    
+    // check processor coordinates / (xmax,ymax)
+    if ( cx >= xmax )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
+                " / xmax = %d\n", cx , xmax );
+        return -1;
+    }
+    if ( cy >= ymax )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
+                " / ymax = %d\n", cy , ymax );
+        return -1;
+    }
     
     unsigned long long user_buffer_paddr;    // user buffer physical address 
@@ -588,16 +671,4 @@
 #endif
 
-    // check NIC channel index
-    if ( channel >= NB_NIC_CHANNELS )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
-        return -1;
-    }
-
-    // get kernel chbuf virtual address
-    nic_chbuf_t* chbuf;
-    if ( is_rx )  chbuf = &_nic_rx_chbuf[channel];
-    else          chbuf = &_nic_tx_chbuf[channel];
-
     // compute kernel chbuf physical address (required for sync)
     vaddr = (unsigned int)chbuf;
@@ -608,9 +679,9 @@
     kernel_chbuf_paddr = ((unsigned long long)ppn << 12) | (vaddr & 0x00000FFF);
 
-    // poll chbuf until success
+    // poll local kernel container status until success
     while ( 1 )
     {
         // compute buffer index and buffer descriptor paddr
-        index = (Y_SIZE * cx) + cy;
+        index = (ymax * cx) + cy;
         buffer_desc_paddr = kernel_chbuf_paddr + (index<<6);
 
@@ -633,6 +704,6 @@
     kernel_buffer_paddr = buffer_desc & 0x0000FFFFFFFFFFFFULL;
     
-    // move one container, using a physical_memcpy
-    if ( is_rx )
+    // move one container
+    if ( is_rx )              // RX transfer
     {
         // inval kernel buffer in L2 before read in L2
@@ -650,5 +721,5 @@
 
     }
-    else
+    else                      // TX transfer
     {
         // transfer data from user buffer to kernel buffer
@@ -683,4 +754,5 @@
 } // end _sys_nic_move()
 
+
 ////////////////////////////////////////
 int _sys_nic_stop( unsigned int is_rx,
@@ -702,9 +774,8 @@
     }
 
+    // check NIC and CMA channels index
     if ( nic_channel != channel )
     {
-        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n"
-                "  allocated channel = %d / requested channel = %d\n",
-                   nic_channel , channel );
+        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n");
         return -1;
     }
@@ -722,5 +793,5 @@
 
     return 0;
-}
+}  // end _sys_nic_stop()
 
 ////////////////////////////////////////
@@ -763,5 +834,5 @@
     }
     return 0;
-}
+}  // en _sys_nic_clear()
 
 ////////////////////////////////////////
@@ -834,5 +905,5 @@
     }
     return 0;
-}
+}  // end _sys_nic_stats()
 
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -1231,22 +1302,57 @@
 }
 
-//////////////////////////////////////
-int _sys_procs_number( unsigned int  x, 
-                       unsigned int  y, 
-                       unsigned int* number )
-{
-    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
+////////////////////////////////////////////
+int _sys_procs_number( unsigned int* x_size,
+                       unsigned int* y_size,
+                       unsigned int* nprocs )
+{
+    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     mapping_cluster_t * cluster = _get_cluster_base(header);
 
-    if ( (x < X_SIZE) && (y < Y_SIZE) )
-    {
-        *number = cluster[(x*Y_SIZE)+y].procs;
-        return 0;
-    }
-    else 
-    {
-        _printf("\n[GIET ERROR] in _sys_procs_number() : illegal (x,y) coordinates\n" );
-        return -1;
-    }
+    unsigned int x;
+    unsigned int y;
+    unsigned int okmin = 1;
+    unsigned int okmax = 1;
+
+    // compute max values
+    unsigned int xmax  = header->x_size;
+    unsigned int ymax  = header->y_size;
+    unsigned int procs = cluster[0].procs;
+
+    // check the (ymax-1) lower rows
+    for ( y = 0 ; y < ymax-1 ; y++ )
+    {
+        for ( x = 0 ; x < xmax ; x++ )
+        {
+            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
+        }
+    }
+
+    // check the upper row
+    for ( x = 0 ; x < xmax ; x++ )
+    {
+        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
+    }
+
+    // return values
+    if ( okmin && okmax )
+    {
+        *x_size = xmax;
+        *y_size = ymax;
+        *nprocs = procs;
+    }
+    else if ( okmin )
+    {
+        *x_size = xmax;
+        *y_size = ymax-1;
+        *nprocs = procs;
+    }
+    else
+    {
+        *x_size = 0;
+        *y_size = 0;
+        *nprocs = 0;
+    }
+    return 0;
 }
 
Index: /soft/giet_vm/giet_kernel/sys_handler.h
===================================================================
--- /soft/giet_vm/giet_kernel/sys_handler.h	(revision 493)
+++ /soft/giet_vm/giet_kernel/sys_handler.h	(revision 494)
@@ -14,5 +14,5 @@
 
 #include "giet_config.h"
-#include "locks.h"
+#include "kernel_locks.h"
 
 ///////////////////////////////////////////////////////////////////////////////////
@@ -41,9 +41,9 @@
 // This structure is used by the CMA component to move a stream 
 // of images from two user buffers to the frame buffer in kernel space.
-// it must be 64 bytes aligned.
 // It contains two chbuf arrays:
 // - The SRC chbuf contains two buffers (buf0 & buf1), in user space.
 // - The DST cbuf contains one single buffer (fbf), that is the frame buffer.
 // - The length field define the buffer size (bytes)
+// This structure must be 64 bytes aligned.
 ///////////////////////////////////////////////////////////////////////////////////
 
@@ -60,7 +60,9 @@
 // This structure is used by the CMA component to move a stream of containers 
 // between the NIC chbuf containing 2 buffers, and a kernel chbuf 
-// containing (X_SIZE * Y_SIZE) buffers (one buffer per cluster).
+// containing up to (X_SIZE * Y_SIZE) buffers (one buffer per cluster).
 // The same structure is used for both TX or RX transfers.
-// It must be 64 bytes aligned.
+// The number of distributed containers can be smaller than (X_SIZE * YSIZE).
+// The actual number of buffers used in the chbuf is defined by (xmax * ymax).
+// This structure must be 64 bytes aligned.
 //////////////////////////////////////////////////////////////////////////////////
 
@@ -68,4 +70,6 @@
 {
     buffer_descriptor_t  buffer[X_SIZE*Y_SIZE];  // kernel chbuf
+    unsigned int         xmax;                   // nb clusters in a row
+    unsigned int         ymax;                   // nb clusters in a column
 } nic_chbuf_t;
 
@@ -104,5 +108,8 @@
 //////////////////////////////////////////////////////////////////////////////
 
-int _sys_nic_alloc( unsigned int is_rx );
+int _sys_nic_alloc( unsigned int is_rx,
+                    unsigned int xmax,
+                    unsigned int ymax );
+
 
 int _sys_nic_start( unsigned int is_rx,
@@ -164,7 +171,7 @@
 int _sys_thread_id();
 
-int _sys_procs_number( unsigned int  x,
-                       unsigned int  y, 
-                       unsigned int* number );
+int _sys_procs_number( unsigned int* x_size,
+                       unsigned int* y_size, 
+                       unsigned int* nprocs );
 
 int _sys_vobj_get_vbase( char*         vspace_name,
