Index: trunk/kernel/kern/kernel_init.c
===================================================================
--- trunk/kernel/kern/kernel_init.c	(revision 5)
+++ trunk/kernel/kern/kernel_init.c	(revision 14)
@@ -3,4 +3,5 @@
  * 
  * Authors :  Alain Greiner  (2016)
+ *            Mohamed Lamine Karaoui (2016)
  *
  * Copyright (c) Sorbonne Universites
@@ -22,9 +23,10 @@
  */
 
-#include <almos_config.h>
+#include <kernel_config.h>
 #include <errno.h>
 #include <hal_types.h>
 #include <hal_special.h>
 #include <hal_context.h>
+#include <barrier.h>
 #include <remote_barrier.h>
 #include <core.h>
@@ -34,6 +36,4 @@
 #include <kmem.h>
 #include <cluster.h>
-#include <devfs.h>
-#include <sysfs.h>
 #include <string.h>
 #include <memcpy.h>
@@ -54,4 +54,6 @@
 #include <soclib_tty.h>
 
+// TODO #include <devfs.h>
+// TODO #include <sysfs.h>
 
 #define KERNEL_INIT_SYNCHRO  0xA5A5B5B5
@@ -60,42 +62,57 @@
 // All these global variables are replicated in all clusters.
 // They are initialised by the kernel_init() function.
+//
+// WARNING : The section names have been defined to control the base addresses of the 
+// boot_info structure and the idle thread descriptors, through the kernel.ld script:
+// - the boot_info structure is build by the bootloader, and used by kernel_init.
+//   it must be first object in the kdata segment.
+// - the array of idle threads descriptors must be placed on the first page boundary after
+//   the boot_info structure in the kdata segment.
 ///////////////////////////////////////////////////////////////////////////////////////////
 
 // This variable defines the local boot_info structure
 __attribute__((section(".kinfo")))
-boot_info_t          boot_info          CACHELINE_ALIGNED;
+boot_info_t          boot_info;
+
+// This variable defines the "idle" threads descriptors array
+__attribute__((section(".kidle")))
+char                  idle_threads[CONFIG_THREAD_DESC_SIZE *
+                                   CONFIG_MAX_LOCAL_CORES]   CONFIG_PPM_PAGE_ALIGNED;
 
 // This variable defines the local cluster manager 
 __attribute__((section(".kdata")))
-cluster_t            cluster_manager    CACHELINE_ALIGNED; 
-
-// These variables define the kernel process0 descriptor and associated thread
+cluster_t            cluster_manager                         CONFIG_CACHE_LINE_ALIGNED; 
+
+// This variables define the kernel process0 descriptor
 __attribute__((section(".kdata")))
-process_t            process_zero       CACHELINE_ALIGNED;            
-thread_t             thread_zero        CACHELINE_ALIGNED;
-
-// This variable contains the extended pointers on the device descriptors
+process_t            process_zero                            CONFIG_CACHE_LINE_ALIGNED;            
+
+// This variable defines extended pointers on the distributed chdevs
 __attribute__((section(".kdata")))
-chdev_directory_t    chdev_dir          CACHELINE_ALIGNED;
+chdev_directory_t    chdev_dir                               CONFIG_CACHE_LINE_ALIGNED;
 
 // This variable contains the input IRQ indexes for the PIC device
 __attribute__((section(".kdata")))
-chdev_pic_input_t    chdev_pic_input    CACHELINE_ALIGNED;
+chdev_pic_input_t    chdev_pic_input                         CONFIG_CACHE_LINE_ALIGNED;
 
 // This variable contains the input IRQ indexes for the ICU device
 __attribute__((section(".kdata")))
-chdev_icu_input_t    chdev_icu_input    CACHELINE_ALIGNED;
-
-// This variable synchronizes the local cores during kernel_init()
-__attribute__((section(".kdata")))
-volatile uint32_t    local_sync_init    CACHELINE_ALIGNED;  
+chdev_icu_input_t    chdev_icu_input                         CONFIG_CACHE_LINE_ALIGNED;
 
 // This variable defines the local cluster identifier
 __attribute__((section(".kdata")))
-cxy_t                local_cxy          CACHELINE_ALIGNED;
-
-// This variable is the lock protecting the kernel TXT terminal (used by printk)
+cxy_t                local_cxy                               CONFIG_CACHE_LINE_ALIGNED;
+
+// This variable defines the TXT0 chdev descriptor 
 __attribute__((section(".kdata")))
-remote_spinlock_t    txt0_lock          CACHELINE_ALIGNED;
+chdev_t              txt0_chdev                              CONFIG_CACHE_LINE_ALIGNED;
+
+// This variable is used for CP0 cores sychronisation in kernel_init()
+__attribute__((section(".kdata")))
+remote_barrier_t     global_barrier                          CONFIG_CACHE_LINE_ALIGNED;
+
+// This variable is used for local cores sychronisation in kernel_init()
+__attribute__((section(".kdata")))
+barrier_t            local_barrier                           CONFIG_CACHE_LINE_ALIGNED;
 
 ///////////////////////////////////////////////////////////////////////////////////////////
@@ -119,8 +136,12 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////
-// This static function allocates memory and initializes the TXT0 chdev descriptor,
-// associated to the kernel terminal, shared by all kernel instances for debug messages.
-// It should be called by a thread running in the I/O cluster, because the TXT0 chdev
-// is created in the I/O cluster.
+// This static function initializes the TXT0 chdev descriptor, associated to the "kernel 
+// terminal", and shared by all kernel instances for debug messages. It also register it
+// in the chdev directory, containing extended pointers on all chdevs.
+// The global variable txt0_chdev is replicated in all clusters, but only the chdev
+// allocated in I/O cluster is used by ALMOS-MKH.
+// Therefore, this function must be called by a thread running in the I/O cluster.
+// As this TXT0 chdev supports only the TXT_SYNC_WRITE command,  we don't create
+// a server thread,  we don't allocate a WTI, and we don't initialize the waiting queue.
 ///////////////////////////////////////////////////////////////////////////////////////////
 // @ info    : pointer on the local boot-info structure.
@@ -131,5 +152,4 @@
 	uint32_t        dev_nr;          // actual number of devices in this cluster
 	xptr_t          base;            // remote pointer on segment base
-	uint32_t        size;            // channel size (bytes)
     uint32_t        type;            // peripheral type
     uint32_t        func;            // device functionnal index
@@ -138,5 +158,4 @@
 	uint32_t        x;               // X cluster coordinate
 	uint32_t        y;               // Y cluster coordinate
-	chdev_t       * chdev;           // local pointer on created chdev
 
     // get number of peripherals and base of devices array from boot_info
@@ -144,8 +163,7 @@
     dev_tbl     = info->ext_dev;
 
-    // loop on external peripherals to find TXT
+    // loop on external peripherals to find TXT device
 	for( i = 0 ; i < dev_nr ; i++ )
 	{
-        size        = dev_tbl[i].size;
         base        = dev_tbl[i].base;
         type        = dev_tbl[i].type;
@@ -155,17 +173,20 @@
         if (func == DEV_FUNC_TXT ) 
         {
-            // allocate and initialize a local chdev for TXT0
-            chdev = chdev_create( func,
-                                  impl,
-                                  0,        // channel
-                                  0,        // direction
-                                  base );
+            // initialize basic fields
+            txt0_chdev.func     = func;
+            txt0_chdev.impl     = impl;
+            txt0_chdev.channel  = 0;
+            txt0_chdev.is_rx    = 0;
+            txt0_chdev.base     = base;
+
+            // initialize lock
+            remote_spinlock_init( XPTR( local_cxy , &txt0_chdev.wait_lock ) );
 
             // Complete TXT specific initialisation
             if( impl == IMPL_TXT_TTY )
             {
-                chdev->cmd = &soclib_tty_cmd;
-                chdev->isr = &soclib_tty_isr;
-                soclib_tty_init( chdev );
+                txt0_chdev.cmd = &soclib_tty_cmd;
+                txt0_chdev.isr = &soclib_tty_isr;
+                soclib_tty_init( &txt0_chdev );
             }
 
@@ -176,10 +197,13 @@
                 {
                     cxy_t  cxy = (x<<info->y_width) + y;
-                    hal_remote_swd( XPTR( cxy , &chdev_dir.txt[0] ) , XPTR( local_cxy , chdev ) );
+                    hal_remote_swd( XPTR( cxy , &chdev_dir.txt[0] ) , 
+                                    XPTR( local_cxy , &txt0_chdev ) );
                 }
             }
 
-		    kinit_dmsg("\n[INFO] %s : core[%x][0] created TXT0 chdev / paddr = %l at cycle %d\n",
-                       __FUNCTION__ , local_cxy , chdev_func_str( func ), chdev_xp , hal_time_stamp() );
+		    kinit_dmsg("\n[INFO] %s : core[%x][0] created TXT0 chdev"
+                       " / paddr = %l at cycle %d\n",
+                       __FUNCTION__ , local_cxy , chdev_func_str( func ), 
+                       XPTR(local_cxy , &txt0_chdev) , hal_time_stamp() );
         }
 
@@ -200,146 +224,154 @@
 static void internal_devices_init( boot_info_t * info )
 {
-    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
-	uint32_t        dev_nr;          // actual number of devices in this cluster
-	xptr_t          base;            // remote pointer on segment base
-	uint32_t        size;            // channel size (bytes)
-    uint32_t        type;            // peripheral type
-    uint32_t        func;            // device functionnal index
-    uint32_t        impl;            // device implementation index
-	uint32_t        i;               // device index in dev_tbl
+    boot_device_t * dev;             // pointer on boot_info device (ICU/MMC/DMA)
 	uint32_t        x;               // X cluster coordinate
 	uint32_t        y;               // Y cluster coordinate
-	uint32_t        channels_nr;     // number of channels in device
-	uint32_t        channel;         // channel index
-	uint32_t        p0;              // device parameter 0
-	uint32_t        p1;              // device parameter 1
-	uint32_t        p2;              // device parameter 2
-	uint32_t        p3;              // device parameter 3
-
-	chdev_t       * chdev;           // local pointer on one channel_device descriptor
-    xptr_t          chdev_xp;        // extended pointer on channel_device descriptor
-
-    // get number of internal devices and base of devices array from boot_info
-	dev_nr	    = info->int_dev_nr;
-    dev_tbl     = info->int_dev;
-
-    // loop on all internal devices in cluster
-	for( i = 0 ; i < dev_nr ; i++ )
-	{
-        size        = dev_tbl[i].size;
-        base        = dev_tbl[i].base;
-        type        = dev_tbl[i].type;
-        channels_nr = dev_tbl[i].channels;
-        p0          = dev_tbl[i].param0;
-        p1          = dev_tbl[i].param1;
-        p2          = dev_tbl[i].param2;
-        p3          = dev_tbl[i].param3;
-
-        func     = FUNC_FROM_TYPE( type );
-        impl     = IMPL_FROM_TYPE( type );
-
-        // do nothing for RAM, that does not require a chdev descriptor.
-        if( func == DEV_FUNC_RAM ) continue;
-
-        // check internal device functional type
-        if( (func != DEV_FUNC_MMC) &&
-            (func != DEV_FUNC_ICU) &&
-            (func != DEV_FUNC_DMA) ) 
-        {
-            assert( false , __FUNCTION__ , "illegal internal peripheral type" );
-        }
-
-        // loop on channels 
-        for( channel = 0 ; channel < channels_nr ; channel++ )
-        {
-            // create one chdev in local cluster
-            chdev = chdev_create( func ,
-                                  impl,
-                                  channel,      
-                                  false,           // TX
-                                  base );
-
-            assert( (chdev != NULL) , __FUNCTION__ , "cannot allocate internal chdev" );
+	chdev_t       * chdev_ptr;       // local pointer on chdev descriptor
+    xptr_t          chdev_xp;        // extended pointer on chdev descriptor
+
+    ///////////  ICU   //////////
+
+    dev = &info->dev_icu;
+
+    assert( ((info->cores_nr == 0) || (dev->channels != 0)) , __FUNCTION__ ,
+            "ICU device must exist in cluster containing cores" );
+        
+    assert( (dev->channels == 1) , __FUNCTION__ ,
+            "channels number must be 1 for ICU device" );
+
+    assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_ICU ) , __FUNCTION__ ,
+            " inconsistent ICU  device type");
+
+    // create one chdev in local cluster
+    chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ),
+                              IMPL_FROM_TYPE( dev->type ),
+                              0,                              // channel
+                              false,                          // TX
+                              dev->base );
+
+    assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate ICU chdev" );
+            
+    // get extended pointer on chdev descriptor 
+    chdev_xp = XPTR( local_cxy , chdev_ptr );
+
+    // make ICU specific initialisation 
+    // TODO remove these three parameters
+    dev_icu_init( chdev_ptr , dev->param0 , dev->param1 , dev->param2 );     
+
+    // initialize the ICU field in the chdev_dir[x][y] structures
+    // replicated in all clusters, and containing extended pointers 
+    // on all remotely accessible devices 
+    for( x = 0 ; x < info->x_size ; x++ )
+    {
+        for( y = 0 ; y < info->y_size ; y++ )
+        {
+            cxy_t  cxy = (x<<info->y_width) + y;
+            hal_remote_swd( XPTR( cxy , &chdev_dir.icu[local_cxy] ) , chdev_xp );
+        }
+    }
+
+    // initialize the entries of the local chdev_icu_input structure
+    // defining how internal peripherals are connected to ICU 
+    uint32_t   id;
+    uint8_t    valid;
+    uint32_t   src_type;
+    uint8_t    src_ch;
+    uint32_t   src_func;
+    for( id = 0 ; id < CONFIG_MAX_HWIS_PER_ICU ; id++ )
+    {
+        valid    = dev->irq[id].valid;
+        src_type = dev->irq[id].dev_type;
+        src_ch   = dev->irq[id].channel;
+        src_func = FUNC_FROM_TYPE( src_type );
+
+        if( valid ) // only valid local IRQs are registered
+        {
+            if     ( src_func == DEV_FUNC_MMC ) chdev_icu_input.mmc = id;
+            else if( src_func == DEV_FUNC_DMA ) chdev_icu_input.dma[src_ch] = id;
+            else assert( false , __FUNCTION__ , "illegal source device for ICU input" );
+        }
+    }
+
+    kinit_dmsg("\n[INFO] %s : core[%x][0] creates ICU chdev at cycle %d\n",
+               __FUNCTION__ , local_cxy , hal_time_stamp() );
+
+    /////////// MMC internal chdev ///////////  
+
+    dev = &info->dev_mmc;
+
+    if( dev->channels != 0 )   // MMC device is defined
+    {
+        assert( (dev->channels == 1) , __FUNCTION__ , 
+            "channels number must be 1 for MMC device" );
+
+        assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_MMC ) , __FUNCTION__ ,
+            " inconsistent MMC device type");
+
+        // create one chdev in local cluster
+        chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ),
+                                  IMPL_FROM_TYPE( dev->type ),
+                                  0,                              // channel
+                                  false,                          // TX
+                                  dev->base );
+
+        assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate MMC chdev" );
+            
+        // get extended pointer on chdev descriptor 
+        chdev_xp = XPTR( local_cxy , chdev_ptr );
+
+        // make MMC specific initialisation
+        dev_mmc_init( chdev_ptr );     
+
+        // initialize the MMC field in the chdev_dir[x][y] structures
+        // replicated in all clusters, and containing extended pointers 
+        // on all remotely accessible devices 
+        for( x = 0 ; x < info->x_size ; x++ )
+        {
+            for( y = 0 ; y < info->y_size ; y++ )
+            {
+                cxy_t  cxy = (x<<info->y_width) + y;
+                hal_remote_swd( XPTR( cxy , &chdev_dir.mmc[local_cxy] ) , chdev_xp );
+            }
+        }
+
+        kinit_dmsg("\n[INFO] %s : core[%x][0] creates MMC chdev at cycle %d\n",
+                   __FUNCTION__ , local_cxy , hal_time_stamp() );
+    }
+
+    /////////// DMA internal chdevs //////////
+
+    dev = &info->dev_dma;
+
+    if( dev->channels != 0 )   // DMA device is defined
+    {
+        assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_DMA ) , __FUNCTION__ ,
+                " inconsistent DMA  device type");
+
+        // create one chdev per channel in local cluster
+        uint32_t channel;
+        for( channel = 0 ; channel < dev->channels ; channel++ )
+        { 
+            chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ),
+                                      IMPL_FROM_TYPE( dev->type ),
+                                      channel,                        // channel
+                                      false,                          // TX
+                                      dev->base );
+
+            assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate DMA chdev" );
             
             // get extended pointer on channel descriptor 
-            chdev_xp = XPTR( local_cxy , chdev );
-
-            // TODO ??? AG
-		    // devfs_register( dev );
-
-            // make device type specific initialisation
-            // the number of parameters depends on the device type
-            // TODO : remove these parameters that  must be provided by the driver
-            if     ( func == DEV_FUNC_ICU ) dev_icu_init( chdev , p0 , p1 , p2 );     
-            else if( func == DEV_FUNC_MMC ) dev_mmc_init( chdev );
-            else                            dev_dma_init( chdev );
-
-            // initialize the replicated chdev_dir[x][y] structures
-            // containing extended pointers on all devices descriptors 
-            xptr_t * entry;    
-
-            if     ( func == DEV_FUNC_ICU ) entry  = &chdev_dir.icu[local_cxy];
-            else if( func == DEV_FUNC_MMC ) entry  = &chdev_dir.mmc[local_cxy];
-            else                            entry  = &chdev_dir.dma[channel];
-  
-            if( func != DEV_FUNC_DMA )  // ICU and MMC devices are remotely accessible
-            {
-                for( x = 0 ; x < info->x_size ; x++ )
-                {
-                    for( y = 0 ; y < info->y_size ; y++ )
-                    {
-                        cxy_t  cxy = (x<<info->y_width) + y;
-                        hal_remote_swd( XPTR( cxy , entry ) , chdev_xp );
-                    }
-                }
-            }
-            else                      // DMA devices are NOT remotely accessible
-            {
-                *entry = chdev_xp;
-            }
-
-            kinit_dmsg("\n[INFO] %s :core[%x][0] created chdev %s / channel %d"
-                       " / paddr = %l at cycle %d\n",
-                       __FUNCTION__ , local_cxy , chdev_func_str( func ) , 
-                       channel , chdev_xp , hal_time_stamp() );
-
-        } // end loop on channels
-
-        // initialize the entries of the local chdev_icu_input structure
-        // defining how internal peripherals are connected to ICU 
-        if( func == DEV_FUNC_ICU )  
-        {
-            uint32_t   id;
-            uint8_t    valid;
-            uint32_t   dev_type;
-            uint8_t    channel;
-
-            // loop on ICU inputs
-            for( id = 0 ; id < CONFIG_MAX_HWIS_PER_ICU ; id++ )
-            {
-                valid    = dev_tbl[i].irq[id].valid;
-                dev_type = dev_tbl[i].irq[id].dev_type;
-                channel  = dev_tbl[i].irq[id].channel;
-
-                if( valid ) // only valid local IRQs are registered
-                {
-                    uint32_t * index;   // local pointer on the entry to be set
-                    uint16_t   dev_func = FUNC_FROM_TYPE( dev_type );
-                    if( dev_func == DEV_FUNC_MMC )  
-                        index = &chdev_icu_input.mmc;
-                    else if( dev_func == DEV_FUNC_DMA )  
-                        index = &chdev_icu_input.dma[channel]; 
-                    else
-                    {
-                        assert( false , __FUNCTION__ , "illegal source device for ICU input" );
-                    }                   
-
-                    // set entry in local structure
-                    *index = id;
-                }
-
-            }  // end loop on ICU inputs
-        }  // end if ICU
-	} // end loop on peripherals
+            chdev_xp = XPTR( local_cxy , chdev_ptr );
+
+            // make DMA specific initialisation
+            dev_dma_init( chdev_ptr );     
+
+            // initialize only the DMA[channel] field in the local chdev_dir[x][y]
+            // structure because the DMA device is not remotely accessible.
+            chdev_dir.dma[channel] = chdev_xp;
+
+            kinit_dmsg("\n[INFO] %s : core[%x][0] creates DMA[%d] chdev at cycle %d\n",
+                       __FUNCTION__ , local_cxy , channel , hal_time_stamp() );
+        }
+    } 
 }  // end internal_devices_init()
 
@@ -353,5 +385,5 @@
 //
 // The number of channel_devices depends on the device functionnal type.
-// There is three nested loops to scan the full set of external channel_devices:
+// There is three nested loops to build the full set of external channel_devices:
 // - loop on external devices.
 // - loop on channels for multi-channels devices.
@@ -371,5 +403,4 @@
 	uint32_t        dev_nr;          // actual number of devices in this cluster
 	xptr_t          base;            // remote pointer on segment base
-	uint32_t        size;            // channel size (bytes)
     uint32_t        type;            // peripheral type
     uint32_t        func;            // device functionnal index
@@ -399,5 +430,4 @@
 	for( i = 0 ; i < dev_nr ; i++ )
 	{
-        size        = dev_tbl[i].size;
         base        = dev_tbl[i].base;
         type        = dev_tbl[i].type;
@@ -496,8 +526,7 @@
                     }
 
-		            kinit_dmsg("\n[INFO] %s : core[%x][0] created chdev %s / channel = %d"
-                               " / paddr = %l at cycle %d\n",
+		            kinit_dmsg("\n[INFO] %s : core[%x][0] create chdev %s[%d] at cycle %d\n",
                                __FUNCTION__ , local_cxy , chdev_func_str( func ),
-                               channel , chdev_xp , hal_time_stamp() );
+                               channel , hal_time_stamp() );
 
                 }  // end if match
@@ -564,7 +593,41 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////
+// This static function returns the identifiers of the calling core.
+///////////////////////////////////////////////////////////////////////////////////////////
+// @ info    : pointer on boot_info structure.
+// @ lid     : [out] core local index in cluster.
+// @ cxy     : [out] cluster identifier.
+// @ lid     : [out] core global identifier (hardware).
+// @ return 0 if success / return EINVAL if not found.
+///////////////////////////////////////////////////////////////////////////////////////////
+static error_t core_get_identifiers( boot_info_t * info,
+                                     uint32_t    * lid,
+                                     cxy_t       * cxy,
+                                     gid_t       * gid )
+{
+	uint32_t   i;
+    gid_t      global_id;
+    
+    // get global identifier from hardware register
+    global_id = hal_get_gid(); 
+
+    // makes an associative search in boot_info to get (cxy,lid) from global_id
+    for( i = 0 ; i < info->cores_nr ; i++ )
+    {
+        if( global_id == info->core[i].gid )
+        {
+            *lid = info->core[i].lid;
+            *cxy = info->core[i].cxy;
+            *gid = global_id;
+            return 0;
+        }
+    }
+    return EINVAL;
+}                      
+
+///////////////////////////////////////////////////////////////////////////////////////////
 // This function is the entry point for the kernel initialisation.
-// It is executed by all cores in all clusters, but only core[0] in each cluster
-// initialize the cluster manager, ant the local peripherals. 
+// It is executed by all cores in all clusters, but only core[0], called CP0,   
+// initializes the shared resources such as the cluster manager, or the local peripherals.
 // To comply with the multi-kernels paradigm, it access only local cluster memory, using
 // only informations contained in the local boot_info_t structure, set by the bootloader.
@@ -574,152 +637,166 @@
 void kernel_init( boot_info_t * info )
 {
-    uint32_t     core_lid;      // running core local index
-    cxy_t        core_cxy;      // running core cluster identifier
-    gid_t        core_gid;      // running core hardware identifier 
-    cluster_t  * cluster;       // pointer on local cluster manager
-    core_t     * core;          // pointer on running core descriptor
-    thread_t   * thread_idle;   // pointer on thread_idle  
-
-	uint32_t     i;
-    bool_t       found;
+    uint32_t     core_lid = -1;      // running core local index
+    cxy_t        core_cxy = -1;      // running core cluster identifier
+    gid_t        core_gid;           // running core hardware identifier 
+    cluster_t  * cluster;            // pointer on local cluster manager
+    core_t     * core;               // pointer on running core descriptor
+    thread_t   * thread;             // pointer on idle thread descriptor
     error_t      error;
 
-    // initialise global cluster identifier
-    local_cxy = info->cxy;
-
-    // each core get its global index from hardware register
-    core_gid = hal_get_gid(); 
-
-    // Each core makes an associative search in boot_info
-    // to get its (cxy,lid) composite index from its gid
-    found    = false;
-    core_cxy = 0;
-    core_lid = 0;
-    for( i = 0 ; i < info->cores_nr ; i++ )
-    {
-        if( core_gid == info->core[i].gid )
-        {
-            core_lid = info->core[i].lid;
-            core_cxy = info->core[i].cxy;
-            found = true;
-            break;
-        }
-    }
-         
-    // suicide if not found
-    if( (found == false) || (core_cxy != local_cxy) ) hal_core_sleep();
-
-    //////////////////////////////////////////////////////////////
-    // In first step, only CP0 initialises local resources
-    //////////////////////////////////////////////////////////////
-
-    if( core_lid == 0 )    
-    {
-        // initialize local cluster manager (cores and memory allocators)
+    // all cores get core identifiers
+    error = core_get_identifiers( info,
+                                  &core_lid,
+                                  &core_cxy,
+                                  &core_gid );
+
+    // CP0 initialise cluster identifier
+    if( core_lid == 0 ) local_cxy = info->cxy;
+
+    // CP0 in I/O cluster initialises TXT0 chdev descriptor
+    if( (core_lid == 0) && (core_cxy == info->io_cxy) ) txt0_device_init( info );
+
+    /////////////////////////////////////////////////////////////////////////////////
+    // global & local synchro to protect access to TXT0 terminal
+    if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 
+                                        (info->x_size * info->y_size) );
+    barrier_wait( &local_barrier , info->cores_nr );
+    /////////////////////////////////////////////////////////////////////////////////
+
+    kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 0\n",
+               __FUNCTION__ , core_cxy , core_lid );
+
+    // all cores check core identifiers
+    if( error )
+    {
+        printk("\n[PANIC] in %s : illegal core identifiers"
+               " gid = %x / cxy = %x / lid = %d\n",
+               __FUNCTION__ , core_lid , core_cxy , core_lid );
+        hal_core_sleep();
+    }
+    else
+    {
+        kinit_dmsg("\n[INFO] %s : core[%x][%d] enters at cycle %d / sp = %x\n",
+                   __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() , hal_get_stack() );
+    }
+
+    // CP0 initialize local cluster manager (cores and memory allocators)
+    if( core_lid == 0 )
+    {
         error = cluster_init( info );
- 
-        // suicide if failure
-        if( error ) hal_core_sleep();
-
-        // get pointer on local cluster manager and on core descriptor
-        cluster = LOCAL_CLUSTER;
-  	    core    = &cluster->core_tbl[core_lid];
-
-        // initialize process_zero descriptor
-		process_zero_init( info );
-
-        // CP0 initialize its private thread_zero descriptor
-	    memset( &thread_zero , 0 , sizeof(thread_t) );
-	    thread_zero.type     = THREAD_KERNEL;
-	    thread_zero.process  = &process_zero;
-	    hal_set_current_thread( &thread_zero );
-
-        // CP0 in I/O cluster initialize the kernel TXT0 chdev descriptor.
-        // this TXTO device is shared by the all kernel instances for debug messages:
-        // the printk() function call the dev_txt_sync_write() function that call
-        // directly the relevant TXT driver, without desheduling.
-        if( core_cxy == info->io_cxy ) txt0_device_init( info );
-
-        // synchronise all CP0s before using TXT0
-        remote_barrier( XPTR( info->io_cxy , &cluster->barrier ) , 
-                        (cluster->x_size * cluster->y_size) );
-
-        // All CP0 initialise internal peripheral chdev descriptors.
-        // Each CP0[cxy] scan the set of its internal (private) peripherals,
-        // and allocate memory for the corresponding chdev descriptors.
-        internal_devices_init( info );
+
+        if( error )
+        {
+            printk("\n[PANIC] in %s : cannot initialise cluster manager in cluster %x",
+                   __FUNCTION__ , local_cxy );
+            hal_core_sleep();
+        }
+        else
+        {
+            kinit_dmsg("\n[INFO] %s : core[%x][%d] initialised cluster at cycle %d\n",
+                       __FUNCTION__ , core_cxy , core_lid , hal_time_stamp());
+        }
+    }
+
+    /////////////////////////////////////////////////////////////////////////////////
+    // global & local synchro, to protect access to cluster manager
+    if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 
+                                        (info->x_size * info->y_size) );
+    barrier_wait( &local_barrier , info->cores_nr );
+    /////////////////////////////////////////////////////////////////////////////////
+
+    kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 1\n",
+               __FUNCTION__ , core_cxy , core_lid );
+
+    // all cores get pointer on local cluster manager and on core descriptor
+    cluster = &cluster_manager;
+  	core    = &cluster->core_tbl[core_lid];
+
+    // CP0 initialize process_zero descriptor
+    if( core_lid == 0 ) process_zero_init( info );
+
+    // CP0 allocate and initialise internal peripheral chdev descriptors.
+    // Each CP0[cxy] scan the set of its internal (private) peripherals,
+    // and allocate memory for the corresponding chdev descriptors.
+    if( core_lid == 0 ) internal_devices_init( info );
         
-        // All CP0 contribute to initialise external peripheral chdev descriptors.
-        // Each CP0[cxy] scan the set of external (shared) peripherals (but the TXT0),
-        // and allocates memory for the chdev descriptors that must be placed
-        // on the (cxy) cluster according to its global index.  
-        external_devices_init( info );
-
-        // TODO initialize devFS and sysFS
-		// devfs_root_init();
-		// sysfs_root_init();
-
-        // TODO ??? [AG]
-		// clusters_sysfs_register();
-
-        // TODO initialize virtual file system
+    // CP0 allocates one WTI mailbbox per core for Inter Processor Interrupt
+    // this must be done after ICU chdev initialisation, by CP0 only, and before
+    // external devices initialisation to enforce the rule (wti_id == lid)
+    if( core_lid == 0 )
+    {
+        uint32_t  wti_id;
+        uint32_t  lid;
+        for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ )
+        {
+            wti_id = dev_icu_wti_alloc();
+
+            if( wti_id != lid )
+            {
+                printk("\n[PANIC] in %s : WTI index for IPI = %d / core_lid = %d",
+                       __FUNCTION__ , wti_id , lid );
+                hal_core_sleep();
+            }
+
+            dev_icu_enable_irq( lid , WTI_TYPE , wti_id , NULL );
+        }
+    }
+
+    // CP0 contribute to initialise external peripheral chdev descriptors.
+    // Each CP0[cxy] scan the set of external (shared) peripherals (but the TXT0),
+    // and allocates memory for the chdev descriptors that must be placed
+    // on the (cxy) cluster according to the global index value.  
+    if( core_lid == 0 ) external_devices_init( info );
+
+    /////////////////////////////////////////////////////////////////////////////////
+    // global &local synchro to protect access to peripherals
+    if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 
+                                        (info->x_size * info->y_size) );
+    barrier_wait( &local_barrier , info->cores_nr );
+    /////////////////////////////////////////////////////////////////////////////////
+
+    kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 2\n", 
+               __FUNCTION__ , core_cxy , core_lid );
+
+    // all cores initialize the private idle thread descriptor
+ 	thread = (thread_t *)( idle_threads + (core_lid * CONFIG_THREAD_DESC_SIZE) );
+
+    error = thread_kernel_init( thread,
+                                THREAD_IDLE, 
+                                &thread_idle_func, 
+                                NULL,
+                                core_lid );
+
+    if( error )
+    {
+        printk("\n[PANIC] in %s : core[%x][%d] cannot initialize idle thread\n",
+               __FUNCTION__ , local_cxy , core_lid );
+        hal_core_sleep();
+    }
+    else
+    {
+        // register idle thread in scheduler
+        core->scheduler.idle = thread;
+
+        // register idle thread pointer in core register 
+        hal_set_current_thread( thread );
+    
+        // activate the idle thread
+        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
+
+        kinit_dmsg("\n[INFO] %s : core[%x][%d] created idle thread %x at cycle %d\n",
+                   __FUNCTION__ , core_cxy , core_lid , thread , hal_time_stamp());
+    }
+
+    // TODO CP0 in IO cluster initialize VFS, devFS and sysFS
+    {
+	    // devfs_root_init();
+	    // sysfs_root_init();
+	    // clusters_sysfs_register();
         // vfs_init();
-
-        // TODO ??? [AG]
-		// sysconf_init();
-
-        // activate other cores in same cluster
-		local_sync_init = KERNEL_INIT_SYNCHRO;
-		hal_wbflush();
-    }
-    else   // other cores                                  
-    {
-        // other cores wait synchro from core[0]
-		while( local_sync_init != KERNEL_INIT_SYNCHRO )
-        {
-		   uint32_t retval = hal_time_stamp() + 1000;
-		   while( hal_time_stamp() < retval )  asm volatile ("nop");
-        }
-
-        // get pointer on local cluster manager and on core descriptor
-        cluster = LOCAL_CLUSTER;
-  	    core    = &cluster->core_tbl[core_lid];
-
-        // core initialise its private thread_zero descriptor 
-	    memset( &thread_zero , 0 , sizeof(thread_t) );
-	    thread_zero.type     = THREAD_KERNEL;
-	    thread_zero.process  = &process_zero;
-	    hal_set_current_thread( &thread_zero );
-    }
-
-	// each core creates its private idle thread descriptor	
-	error = thread_kernel_create( &thread_idle,
-                                  THREAD_IDLE, 
-                                  &thread_idle_func, 
-                                  NULL,
-                                  core_lid );
-
-    assert( (error == 0) , __FUNCTION__ , "cannot create idle thread" );
-
-    // each core register thread_idle in scheduler 
-    core->scheduler.idle = thread_idle;
-
-    // each core register thread pointer in core hardware register
-    hal_set_current_thread( thread_idle );
-
-    kinit_dmsg("\n[INFO] %s : thread idle created for core[%x][%d] at cycle %d\n",
-               __FUNCTION__ , core_cxy , core_lid , hal_time_stamp());
-
-    // global syncho for all core[0] in all clusters
-    if( core_lid == 0 )
-    {
-        remote_barrier( XPTR( info->io_cxy , &cluster->barrier ) , 
-                        (cluster->x_size * cluster->y_size) );
-    }
-
-    // local synchro for all cores in local cluster
-    remote_barrier( XPTR( local_cxy , &cluster->barrier ) , 
-                    cluster->cores_nr );
-
+	    // sysconf_init();
+    }
+
+    // CP0 in I/O cluster print banner
     if( (core_lid ==  0) && (local_cxy == info->io_cxy) ) 
     {
@@ -727,6 +804,31 @@
     }
 
-    // load idle thread context on calling core
-	hal_cpu_context_load( thread_idle );
+    /////////////////////////////////////////////////////////////////////////////////
+    // global syncho to protect access to File System
+    if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
+                                        (info->x_size * info->y_size) );
+    barrier_wait( &local_barrier , info->cores_nr );
+    /////////////////////////////////////////////////////////////////////////////////
+
+    kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 3\n", 
+               __FUNCTION__ , core_cxy , core_lid );
+
+    // each core activates its private PTI IRQ 
+    dev_icu_set_period( core_lid , CONFIG_SCHED_TICK_PERIOD );
+    dev_icu_enable_irq( core_lid , PTI_TYPE , core_lid , NULL );
+
+    // each core get its private IRQ masks values and
+    uint32_t hwi_mask;
+    uint32_t wti_mask;
+    uint32_t pti_mask;
+    dev_icu_get_masks( core_lid , &hwi_mask , &wti_mask , &pti_mask );
+
+    thread_dmsg("\n[INFO] %s : core[%x][%d] activates scheduler at cycle %d\n"
+                "   hwi_mask = %x / wti_mask = %x / pti_mask = %x\n",
+                    __FUNCTION__ , local_cxy , core_lid , hal_time_stamp() ,
+                    hwi_mask , wti_mask , pti_mask );
+
+    // each core jump to idle thread
+    asm volatile( "j thread_idle_func\n" );
 
 } // end kernel_init()
