source: trunk/kernel/kern/kernel_init.c @ 623

Last change on this file since 623 was 623, checked in by alain, 5 years ago

Introduce three new types of vsegs (KCODE,KDATA,KDEV)
to map the kernel vsegs in the process VSL and GPT.
This now used by both the TSAR and the I86 architectures.

File size: 61.2 KB
Line 
1/*
2 * kernel_init.c - kernel parallel initialization
3 *
4 * Authors :  Mohamed Lamine Karaoui (2015)
5 *            Alain Greiner  (2016,2017,2018,2019)
6 *
7 * Copyright (c) Sorbonne Universites
8 *
9 * This file is part of ALMOS-MKH.
10 *
11 * ALMOS-MKH is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2.0 of the License.
14 *
15 * ALMOS-MKH is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#include <kernel_config.h>
26#include <errno.h>
27#include <hal_kernel_types.h>
28#include <hal_special.h>
29#include <hal_context.h>
30#include <hal_irqmask.h>
31#include <hal_macros.h>
32#include <hal_ppm.h>
33#include <barrier.h>
34#include <xbarrier.h>
35#include <remote_fifo.h>
36#include <core.h>
37#include <list.h>
38#include <xlist.h>
39#include <xhtab.h>
40#include <thread.h>
41#include <scheduler.h>
42#include <kmem.h>
43#include <cluster.h>
44#include <string.h>
45#include <memcpy.h>
46#include <ppm.h>
47#include <page.h>
48#include <chdev.h>
49#include <boot_info.h>
50#include <dqdt.h>
51#include <dev_mmc.h>
52#include <dev_dma.h>
53#include <dev_iob.h>
54#include <dev_ioc.h>
55#include <dev_txt.h>
56#include <dev_pic.h>
57#include <printk.h>
58#include <vfs.h>
59#include <devfs.h>
60#include <mapper.h>
61
62///////////////////////////////////////////////////////////////////////////////////////////
63// All the following global variables are replicated in all clusters.
64// They are initialised by the kernel_init() function.
65//
66// WARNING : The section names have been defined to control the base addresses of the
67// boot_info structure and the idle thread descriptors, through the kernel.ld script:
68// - the boot_info structure is built by the bootloader, and used by kernel_init.
69//   it must be the first object in the kdata segment.
70// - the array of idle threads descriptors must be placed on the first page boundary after
71//   the boot_info structure in the kdata segment.
72///////////////////////////////////////////////////////////////////////////////////////////
73
74// This variable defines the local boot_info structure
75__attribute__((section(".kinfo")))
76boot_info_t          boot_info;
77
78// This variable defines the "idle" threads descriptors array
79__attribute__((section(".kidle")))
80char                 idle_threads[CONFIG_THREAD_DESC_SIZE *
81                                   CONFIG_MAX_LOCAL_CORES]   CONFIG_PPM_PAGE_ALIGNED;
82
83// This variable defines the local cluster manager
84__attribute__((section(".kdata")))
85cluster_t            cluster_manager                         CONFIG_CACHE_LINE_ALIGNED;
86
87// This variable defines the TXT_TX[0] chdev
88__attribute__((section(".kdata")))
89chdev_t              txt0_tx_chdev                           CONFIG_CACHE_LINE_ALIGNED;
90
91// This variable defines the TXT_RX[0] chdev
92__attribute__((section(".kdata")))
93chdev_t              txt0_rx_chdev                           CONFIG_CACHE_LINE_ALIGNED;
94
95// This variables define the kernel process0 descriptor
96__attribute__((section(".kdata")))
97process_t            process_zero                            CONFIG_CACHE_LINE_ALIGNED;
98
99// This variable defines extended pointers on the distributed chdevs
100__attribute__((section(".kdata")))
101chdev_directory_t    chdev_dir                               CONFIG_CACHE_LINE_ALIGNED;
102
103// This variable contains the input IRQ indexes for the IOPIC controller
104__attribute__((section(".kdata")))
105iopic_input_t        iopic_input                             CONFIG_CACHE_LINE_ALIGNED;
106
107// This variable contains the input IRQ indexes for the LAPIC controller
108__attribute__((section(".kdata")))
109lapic_input_t        lapic_input                             CONFIG_CACHE_LINE_ALIGNED;
110
111// This variable defines the local cluster identifier
112__attribute__((section(".kdata")))
113cxy_t                local_cxy                               CONFIG_CACHE_LINE_ALIGNED;
114
115// This variable is used for core[0] cores synchronisation in kernel_init()
116__attribute__((section(".kdata")))
117xbarrier_t           global_barrier                          CONFIG_CACHE_LINE_ALIGNED;
118
119// This variable is used for local cores synchronisation in kernel_init()
120__attribute__((section(".kdata")))
121barrier_t            local_barrier                           CONFIG_CACHE_LINE_ALIGNED;
122
123// This variable defines the array of supported File System contexts
124__attribute__((section(".kdata")))
125vfs_ctx_t            fs_context[FS_TYPES_NR]                 CONFIG_CACHE_LINE_ALIGNED;
126
127// kernel_init is the entry point defined in hal/tsar_mips32/kernel.ld
128// It is used by the bootloader to tranfer control to kernel.
129extern void kernel_init( boot_info_t * info );
130
131// This array is used for debug, and describes the kernel locks usage,
132// It must be kept consistent with the defines in kernel_config.h file.
133char * lock_type_str[] =
134{
135    "unused_0",              //  0
136
137    "CLUSTER_KCM",           //  1
138    "PPM_FREE",              //  2
139    "SCHED_STATE",           //  3
140    "VMM_STACK",             //  4
141    "VMM_MMAP",              //  5
142    "VFS_CTX",               //  6
143    "KCM_STATE",             //  7
144    "KHM_STATE",             //  8
145    "HTAB_STATE",            //  9
146
147    "THREAD_JOIN",           // 10
148    "XHTAB_STATE",           // 11
149    "CHDEV_QUEUE",           // 12
150    "CHDEV_TXT0",            // 13
151    "CHDEV_TXTLIST",         // 14
152    "PAGE_STATE",            // 15
153    "MUTEX_STATE",           // 16
154    "CONDVAR_STATE",         // 17
155    "SEM_STATE",             // 18
156    "PROCESS_CWD",           // 19
157    "BARRIER_STATE",         // 20
158
159    "CLUSTER_PREFTBL",       // 21
160
161    "PPM_DIRTY",             // 22
162    "CLUSTER_LOCALS",        // 23
163    "CLUSTER_COPIES",        // 24
164    "PROCESS_CHILDREN",      // 25
165    "PROCESS_USERSYNC",      // 26
166    "PROCESS_FDARRAY",       // 27
167    "FATFS_FREE",            // 28
168    "PROCESS_DIR",           // 29
169
170    "PROCESS_THTBL",         // 30
171
172    "MAPPER_STATE",          // 31
173    "VFS_SIZE",              // 32
174    "VFS_FILE",              // 33
175    "VMM_VSL",               // 34
176    "VMM_GPT",               // 35
177    "VFS_MAIN",              // 36
178};       
179
180// debug variables to analyse the sys_read() and sys_write() syscalls timing
181
182#if DEBUG_SYS_READ
183uint32_t   enter_sys_read;
184uint32_t   exit_sys_read;
185
186uint32_t   enter_devfs_read;
187uint32_t   exit_devfs_read;
188
189uint32_t   enter_txt_read;
190uint32_t   exit_txt_read;
191
192uint32_t   enter_chdev_cmd_read;
193uint32_t   exit_chdev_cmd_read;
194
195uint32_t   enter_chdev_server_read;
196uint32_t   exit_chdev_server_read;
197
198uint32_t   enter_tty_cmd_read;
199uint32_t   exit_tty_cmd_read;
200
201uint32_t   enter_tty_isr_read;
202uint32_t   exit_tty_isr_read;
203#endif
204
205// these debug variables are used to analyse the sys_write() syscall timing
206
207#if DEBUG_SYS_WRITE   
208uint32_t   enter_sys_write;
209uint32_t   exit_sys_write;
210
211uint32_t   enter_devfs_write;
212uint32_t   exit_devfs_write;
213
214uint32_t   enter_txt_write;
215uint32_t   exit_txt_write;
216
217uint32_t   enter_chdev_cmd_write;
218uint32_t   exit_chdev_cmd_write;
219
220uint32_t   enter_chdev_server_write;
221uint32_t   exit_chdev_server_write;
222
223uint32_t   enter_tty_cmd_write;
224uint32_t   exit_tty_cmd_write;
225
226uint32_t   enter_tty_isr_write;
227uint32_t   exit_tty_isr_write;
228#endif
229
230// intrumentation variables : cumulated costs per syscall type in cluster
231uint32_t   syscalls_cumul_cost[SYSCALLS_NR];
232
233// intrumentation variables : number of syscalls per syscal type in cluster
234uint32_t   syscalls_occurences[SYSCALLS_NR];
235
236///////////////////////////////////////////////////////////////////////////////////////////
237// This function displays the ALMOS_MKH banner.
238///////////////////////////////////////////////////////////////////////////////////////////
239static void print_banner( uint32_t nclusters , uint32_t ncores )
240{
241    printk("\n"
242           "                    _        __    __     _____     ______         __    __    _   __   _     _   \n"
243           "          /\\       | |      |  \\  /  |   / ___ \\   / _____|       |  \\  /  |  | | / /  | |   | |  \n"
244           "         /  \\      | |      |   \\/   |  | /   \\ | | /             |   \\/   |  | |/ /   | |   | |  \n"
245           "        / /\\ \\     | |      | |\\  /| |  | |   | | | |_____   ___  | |\\  /| |  |   /    | |___| |  \n"
246           "       / /__\\ \\    | |      | | \\/ | |  | |   | | \\_____  \\ |___| | | \\/ | |  |   \\    |  ___  |  \n"
247           "      / ______ \\   | |      | |    | |  | |   | |       | |       | |    | |  | |\\ \\   | |   | |  \n"
248           "     / /      \\ \\  | |____  | |    | |  | \\___/ |  _____/ |       | |    | |  | | \\ \\  | |   | |  \n"
249           "    /_/        \\_\\ |______| |_|    |_|   \\_____/  |______/        |_|    |_|  |_|  \\_\\ |_|   |_|  \n"
250           "\n\n\t\t Advanced Locality Management Operating System / Multi Kernel Hybrid\n"
251           "\n\n\t\t %s / %d cluster(s) / %d core(s) per cluster\n\n",
252           CONFIG_ALMOS_VERSION , nclusters , ncores );
253}
254
255
256///////////////////////////////////////////////////////////////////////////////////////////
257// This function initializes the TXT_TX[0] and TXT_RX[0] chdev descriptors, implementing
258// the "kernel terminal", shared by all kernel instances for debug messages.
259// These chdev are implemented as global variables (replicated in all clusters),
260// because this terminal is used before the kmem allocator initialisation, but only
261// the chdevs in cluster 0 are registered in the "chdev_dir" directory.
262// As this TXT0 chdev supports only the TXT_SYNC_WRITE command, we don't create
263// a server thread, we don't allocate a WTI, and we don't initialize the waiting queue.
264// Note: The TXT_RX[0] chdev is created, but is not used by ALMOS-MKH (september 2018).
265///////////////////////////////////////////////////////////////////////////////////////////
266// @ info    : pointer on the local boot-info structure.
267///////////////////////////////////////////////////////////////////////////////////////////
268static void __attribute__ ((noinline)) txt0_device_init( boot_info_t * info )
269{
270    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
271    uint32_t        dev_nr;          // actual number of devices in this cluster
272    xptr_t          base;            // remote pointer on segment base
273    uint32_t        func;            // device functional index
274    uint32_t        impl;            // device implementation index
275    uint32_t        i;               // device index in dev_tbl
276    uint32_t        x;               // X cluster coordinate
277    uint32_t        y;               // Y cluster coordinate
278    uint32_t        channels;        // number of channels
279
280    // get number of peripherals and base of devices array from boot_info
281    dev_nr      = info->ext_dev_nr;
282    dev_tbl     = info->ext_dev;
283
284    // loop on external peripherals to find TXT device
285    for( i = 0 ; i < dev_nr ; i++ )
286    {
287        base        = dev_tbl[i].base;
288        func        = FUNC_FROM_TYPE( dev_tbl[i].type );
289        impl        = IMPL_FROM_TYPE( dev_tbl[i].type );
290        channels    = dev_tbl[i].channels;
291
292        if (func == DEV_FUNC_TXT )
293        {
294            // initialize TXT_TX[0] chdev
295            txt0_tx_chdev.func    = func;
296            txt0_tx_chdev.impl    = impl;
297            txt0_tx_chdev.channel = 0;
298            txt0_tx_chdev.base    = base;
299            txt0_tx_chdev.is_rx   = false;
300            remote_busylock_init( XPTR( local_cxy , &txt0_tx_chdev.wait_lock ),
301                                  LOCK_CHDEV_TXT0 );
302           
303            // initialize TXT_RX[0] chdev
304            txt0_rx_chdev.func    = func;
305            txt0_rx_chdev.impl    = impl;
306            txt0_rx_chdev.channel = 0;
307            txt0_rx_chdev.base    = base;
308            txt0_rx_chdev.is_rx   = true;
309            remote_busylock_init( XPTR( local_cxy , &txt0_rx_chdev.wait_lock ),
310                                  LOCK_CHDEV_TXT0 );
311           
312            // make TXT specific initialisations
313            dev_txt_init( &txt0_tx_chdev );                 
314            dev_txt_init( &txt0_rx_chdev );
315
316            // register TXT_TX[0] & TXT_RX[0] in chdev_dir[x][y]
317            // for all valid clusters             
318            for( x = 0 ; x < info->x_size ; x++ )
319            {
320                for( y = 0 ; y < info->y_size ; y++ )
321                {
322                    cxy_t cxy = HAL_CXY_FROM_XY( x , y );
323
324                    if( cluster_is_active( cxy ) )
325                    {
326                        hal_remote_s64( XPTR( cxy , &chdev_dir.txt_tx[0] ) ,
327                                        XPTR( local_cxy , &txt0_tx_chdev ) );
328                        hal_remote_s64( XPTR( cxy , &chdev_dir.txt_rx[0] ) ,
329                                        XPTR( local_cxy , &txt0_rx_chdev ) );
330                    }
331                }
332            }
333
334            hal_fence();
335        }
336        } // end loop on devices
337}  // end txt0_device_init()
338
339///////////////////////////////////////////////////////////////////////////////////////////
340// This function allocates memory and initializes the chdev descriptors for the internal
341// peripherals contained in the local cluster, other than the LAPIC, as specified by
342// the boot_info, including the linking with the driver for the specified implementation.
343// The relevant entries in all copies of the devices directory are initialised.
344///////////////////////////////////////////////////////////////////////////////////////////
345// @ info    : pointer on the local boot-info structure.
346///////////////////////////////////////////////////////////////////////////////////////////
347static void __attribute__ ((noinline)) internal_devices_init( boot_info_t * info )
348{
349    boot_device_t * dev_tbl;         // pointer on array of internaldevices in boot_info
350        uint32_t        dev_nr;          // actual number of devices in this cluster
351        xptr_t          base;            // remote pointer on segment base
352    uint32_t        func;            // device functionnal index
353    uint32_t        impl;            // device implementation index
354        uint32_t        i;               // device index in dev_tbl
355        uint32_t        x;               // X cluster coordinate
356        uint32_t        y;               // Y cluster coordinate
357        uint32_t        channels;        // number of channels
358        uint32_t        channel;         // channel index
359        chdev_t       * chdev_ptr;       // local pointer on created chdev
360
361    // get number of internal peripherals and base from boot_info
362        dev_nr  = info->int_dev_nr;
363    dev_tbl = info->int_dev;
364
365    // loop on internal peripherals
366        for( i = 0 ; i < dev_nr ; i++ )
367        {
368        base        = dev_tbl[i].base;
369        channels    = dev_tbl[i].channels;
370        func        = FUNC_FROM_TYPE( dev_tbl[i].type );
371        impl        = IMPL_FROM_TYPE( dev_tbl[i].type );
372 
373        //////////////////////////
374        if( func == DEV_FUNC_MMC ) 
375        {
376
377            // check channels
378            if( channels != 1 )
379            {
380                printk("\n[PANIC] in %s : MMC device must be single channel\n",
381                __FUNCTION__ );
382                hal_core_sleep();
383            }
384
385            // create chdev in local cluster
386            chdev_ptr = chdev_create( func,
387                                      impl,
388                                      0,          // channel
389                                      false,      // direction
390                                      base );
391
392            // check memory
393            if( chdev_ptr == NULL )
394            {
395                printk("\n[PANIC] in %s : cannot create MMC chdev\n",
396                __FUNCTION__ );
397                hal_core_sleep();
398            }
399           
400            // make MMC specific initialisation
401            dev_mmc_init( chdev_ptr );
402
403            // set the MMC field in all chdev_dir[x][y] structures
404            for( x = 0 ; x < info->x_size ; x++ )
405            {
406                for( y = 0 ; y < info->y_size ; y++ )
407                {
408                    cxy_t cxy = HAL_CXY_FROM_XY( x , y );
409
410                    if( cluster_is_active( cxy ) )
411                    {
412                        hal_remote_s64( XPTR( cxy , &chdev_dir.mmc[local_cxy] ), 
413                                        XPTR( local_cxy , chdev_ptr ) );
414                    }
415                }
416            }
417
418#if( DEBUG_KERNEL_INIT & 0x1 )
419if( hal_time_stamp() > DEBUG_KERNEL_INIT )
420printk("\n[%s] : created MMC in cluster %x / chdev = %x\n",
421__FUNCTION__ , local_cxy , chdev_ptr );
422#endif
423        }
424        ///////////////////////////////
425        else if( func == DEV_FUNC_DMA )
426        {
427            // create one chdev per channel in local cluster
428            for( channel = 0 ; channel < channels ; channel++ )
429            {   
430                // create chdev[channel] in local cluster
431                chdev_ptr = chdev_create( func,
432                                          impl,
433                                          channel,
434                                          false,     // direction
435                                          base );
436
437                // check memory
438                if( chdev_ptr == NULL )
439                {
440                    printk("\n[PANIC] in %s : cannot create DMA chdev\n",
441                    __FUNCTION__ );
442                    hal_core_sleep();
443                }
444           
445                // make DMA specific initialisation
446                dev_dma_init( chdev_ptr );     
447
448                // initialize only the DMA[channel] field in the local chdev_dir[x][y]
449                // structure because the DMA device is not remotely accessible.
450                chdev_dir.dma[channel] = XPTR( local_cxy , chdev_ptr );
451
452#if( DEBUG_KERNEL_INIT & 0x1 )
453if( hal_time_stamp() > DEBUG_KERNEL_INIT )
454printk("\n[%s] : created DMA[%d] in cluster %x / chdev = %x\n",
455__FUNCTION__ , channel , local_cxy , chdev_ptr );
456#endif
457            }
458        }
459    }
460}  // end internal_devices_init()
461
462///////////////////////////////////////////////////////////////////////////////////////////
463// This function allocates memory and initializes the chdev descriptors for the 
464// external (shared) peripherals other than the IOPIC, as specified by the boot_info.
465// This includes the dynamic linking with the driver for the specified implementation.
466// These chdev descriptors are distributed on all clusters, using a modulo on a global
467// index, identically computed in all clusters.
468// This function is executed in all clusters by the core[0] core, that computes a global index
469// for all external chdevs. Each core[0] core creates only the chdevs that must be placed in
470// the local cluster, because the global index matches the local index.
471// The relevant entries in all copies of the devices directory are initialised.
472///////////////////////////////////////////////////////////////////////////////////////////
473// @ info    : pointer on the local boot-info structure.
474///////////////////////////////////////////////////////////////////////////////////////////
475static void external_devices_init( boot_info_t * info )
476{
477    boot_device_t * dev_tbl;         // pointer on array of external devices in boot_info
478        uint32_t        dev_nr;          // actual number of external devices
479        xptr_t          base;            // remote pointer on segment base
480    uint32_t        func;            // device functionnal index
481    uint32_t        impl;            // device implementation index
482        uint32_t        i;               // device index in dev_tbl
483        uint32_t        x;               // X cluster coordinate
484        uint32_t        y;               // Y cluster coordinate
485        uint32_t        channels;        // number of channels
486        uint32_t        channel;         // channel index
487        uint32_t        directions;      // number of directions (1 or 2)
488        uint32_t        rx;              // direction index (0 or 1)
489    chdev_t       * chdev;           // local pointer on one channel_device descriptor
490    uint32_t        ext_chdev_gid;   // global index of external chdev
491
492    // get number of peripherals and base of devices array from boot_info
493    dev_nr      = info->ext_dev_nr;
494    dev_tbl     = info->ext_dev;
495
496    // initializes global index (PIC is already placed in cluster 0
497    ext_chdev_gid = 1;
498
499    // loop on external peripherals
500    for( i = 0 ; i < dev_nr ; i++ )
501    {
502        base     = dev_tbl[i].base;
503        channels = dev_tbl[i].channels;
504        func     = FUNC_FROM_TYPE( dev_tbl[i].type );
505        impl     = IMPL_FROM_TYPE( dev_tbl[i].type );
506
507        // There is one chdev per direction for NIC and for TXT
508        if((func == DEV_FUNC_NIC) || (func == DEV_FUNC_TXT)) directions = 2;
509        else                                                 directions = 1;
510
511        // do nothing for ROM, that does not require a device descriptor.
512        if( func == DEV_FUNC_ROM ) continue;
513
514        // do nothing for PIC, that is already initialized
515        if( func == DEV_FUNC_PIC ) continue;
516
517        // check PIC device initialized
518        if( chdev_dir.pic == XPTR_NULL )
519        {
520            printk("\n[PANIC] in %s : PIC device must be initialized first\n",
521            __FUNCTION__ );
522            hal_core_sleep();
523        }
524
525        // check external device functionnal type
526        if( (func != DEV_FUNC_IOB) && (func != DEV_FUNC_IOC) && (func != DEV_FUNC_TXT) &&
527            (func != DEV_FUNC_NIC) && (func != DEV_FUNC_FBF) )
528        {
529            printk("\n[PANIC] in %s : undefined peripheral type\n",
530            __FUNCTION__ );
531            hal_core_sleep();
532        }
533
534        // loops on channels
535        for( channel = 0 ; channel < channels ; channel++ )
536        {
537            // loop on directions
538            for( rx = 0 ; rx < directions ; rx++ )
539            {
540                // skip TXT0 that has already been initialized
541                if( (func == DEV_FUNC_TXT) && (channel == 0) ) continue;
542
543                // all kernel instances compute the target cluster for all chdevs,
544                // computing the global index ext_chdev_gid[func,channel,direction]
545                cxy_t target_cxy;
546                while( 1 )
547                {
548                    uint32_t offset     = ext_chdev_gid % ( info->x_size * info->y_size );
549                    uint32_t x          = offset / info->y_size;
550                    uint32_t y          = offset % info->y_size;
551
552                    target_cxy = HAL_CXY_FROM_XY( x , y );
553
554                    // exit loop if target cluster is active
555                    if( cluster_is_active( target_cxy ) ) break;
556               
557                    // increment global index otherwise
558                    ext_chdev_gid++;
559                }
560
561                // allocate and initialize a local chdev
562                // when local cluster matches target cluster
563                if( target_cxy == local_cxy )
564                {
565                    chdev = chdev_create( func,
566                                          impl,
567                                          channel,
568                                          rx,          // direction
569                                          base );
570
571                    if( chdev == NULL )
572                    {
573                        printk("\n[PANIC] in %s : cannot allocate chdev\n",
574                        __FUNCTION__ );
575                        hal_core_sleep();
576                    }
577
578                    // make device type specific initialisation
579                    if     ( func == DEV_FUNC_IOB ) dev_iob_init( chdev );
580                    else if( func == DEV_FUNC_IOC ) dev_ioc_init( chdev );
581                    else if( func == DEV_FUNC_TXT ) dev_txt_init( chdev );
582                    else if( func == DEV_FUNC_NIC ) dev_nic_init( chdev );
583                    else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev );
584
585                    // all external (shared) devices are remotely accessible
586                    // initialize the replicated chdev_dir[x][y] structures
587                    // defining the extended pointers on chdev descriptors
588                    xptr_t * entry;
589
590                    if(func==DEV_FUNC_IOB             ) entry  = &chdev_dir.iob;
591                    if(func==DEV_FUNC_IOC             ) entry  = &chdev_dir.ioc[channel];
592                    if(func==DEV_FUNC_FBF             ) entry  = &chdev_dir.fbf[channel];
593                    if((func==DEV_FUNC_TXT) && (rx==0)) entry  = &chdev_dir.txt_tx[channel];
594                    if((func==DEV_FUNC_TXT) && (rx==1)) entry  = &chdev_dir.txt_rx[channel];
595                    if((func==DEV_FUNC_NIC) && (rx==0)) entry  = &chdev_dir.nic_tx[channel];
596                    if((func==DEV_FUNC_NIC) && (rx==1)) entry  = &chdev_dir.nic_rx[channel];
597
598                    for( x = 0 ; x < info->x_size ; x++ )
599                    {
600                        for( y = 0 ; y < info->y_size ; y++ )
601                        {
602                            cxy_t cxy = HAL_CXY_FROM_XY( x , y );
603
604                            if( cluster_is_active( cxy ) )
605                            {
606                                hal_remote_s64( XPTR( cxy , entry ),
607                                                XPTR( local_cxy , chdev ) );
608                            }
609                        }
610                    }
611
612#if( DEBUG_KERNEL_INIT & 0x1 )
613if( hal_time_stamp() > DEBUG_KERNEL_INIT )
614printk("\n[%s] : create chdev %s / channel = %d / rx = %d / cluster %x / chdev = %x\n",
615__FUNCTION__ , chdev_func_str( func ), channel , rx , local_cxy , chdev );
616#endif
617                }  // end if match
618
619                // increment chdev global index (matching or not)
620                ext_chdev_gid++;
621
622            } // end loop on directions
623        }  // end loop on channels
624        } // end loop on devices
625}  // end external_devices_init()
626
627///////////////////////////////////////////////////////////////////////////////////////////
628// This function is called by core[0] in cluster 0 to allocate memory and initialize the PIC
629// device, namely the informations attached to the external IOPIC controller, that
630// must be replicated in all clusters (struct iopic_input).
631// This initialisation must be done before other devices initialisation because the IRQ
632// routing infrastructure is required for both internal and external devices init.
633///////////////////////////////////////////////////////////////////////////////////////////
634// @ info    : pointer on the local boot-info structure.
635///////////////////////////////////////////////////////////////////////////////////////////
636static void __attribute__ ((noinline)) iopic_init( boot_info_t * info )
637{
638    boot_device_t * dev_tbl;         // pointer on boot_info external devices array
639        uint32_t        dev_nr;          // actual number of external devices
640        xptr_t          base;            // remote pointer on segment base
641    uint32_t        func;            // device functionnal index
642    uint32_t        impl;            // device implementation index
643        uint32_t        i;               // device index in dev_tbl
644    uint32_t        x;               // cluster X coordinate
645    uint32_t        y;               // cluster Y coordinate
646    bool_t          found;           // IOPIC found
647        chdev_t       * chdev;           // pointer on PIC chdev descriptor
648
649    // get number of external peripherals and base of array from boot_info
650        dev_nr      = info->ext_dev_nr;
651    dev_tbl     = info->ext_dev;
652
653    // avoid GCC warning
654    base        = XPTR_NULL;
655    impl        = 0;
656
657    // loop on external peripherals to get the IOPIC 
658        for( i = 0 , found = false ; i < dev_nr ; i++ )
659        {
660        func = FUNC_FROM_TYPE( dev_tbl[i].type );
661
662        if( func == DEV_FUNC_PIC )
663        {
664            base     = dev_tbl[i].base;
665            impl     = IMPL_FROM_TYPE( dev_tbl[i].type );
666            found    = true;
667            break;
668        }
669    }
670
671    // check PIC existence
672    if( found == false )
673    {
674        printk("\n[PANIC] in %s : PIC device not found\n",
675        __FUNCTION__ );
676        hal_core_sleep();
677    }
678
679    // allocate and initialize the PIC chdev in cluster 0
680    chdev = chdev_create( DEV_FUNC_PIC,
681                          impl,
682                          0,      // channel
683                          0,      // direction,
684                          base );
685
686    // check memory
687    if( chdev == NULL )
688    {
689        printk("\n[PANIC] in %s : no memory for PIC chdev\n",
690        __FUNCTION__ );
691        hal_core_sleep();
692    }
693
694    // make PIC device type specific initialisation
695    dev_pic_init( chdev );
696
697    // register, in all clusters, the extended pointer
698    // on PIC chdev in "chdev_dir" array
699    xptr_t * entry = &chdev_dir.pic;   
700               
701    for( x = 0 ; x < info->x_size ; x++ )
702    {
703        for( y = 0 ; y < info->y_size ; y++ )
704        {
705            cxy_t cxy = HAL_CXY_FROM_XY( x , y );
706
707            if( cluster_is_active( cxy ) )
708            {
709                hal_remote_s64( XPTR( cxy , entry ) , 
710                                XPTR( local_cxy , chdev ) );
711            }
712        }
713    }
714
715    // initialize, in all clusters, the "iopic_input" structure
716    // defining how external IRQs are connected to IOPIC
717
718    // register default value for unused inputs
719    for( x = 0 ; x < info->x_size ; x++ )
720    {
721        for( y = 0 ; y < info->y_size ; y++ )
722        {
723            cxy_t cxy = HAL_CXY_FROM_XY( x , y );
724
725            if( cluster_is_active( cxy ) )
726            {
727                hal_remote_memset( XPTR( cxy , &iopic_input ), 
728                                   0xFF , sizeof(iopic_input_t) );
729            }
730        }
731    }
732
733    // register input IRQ index for valid inputs
734    uint32_t   id;             // input IRQ index
735    uint8_t    valid;          // input IRQ is connected
736    uint32_t   type;           // source device type
737    uint8_t    channel;        // source device channel
738    uint8_t    is_rx;          // source device direction
739    uint32_t * ptr = NULL;     // local pointer on one field in iopic_input stucture
740
741    for( id = 0 ; id < CONFIG_MAX_EXTERNAL_IRQS ; id++ )
742    {
743        valid   = dev_tbl[i].irq[id].valid;
744        type    = dev_tbl[i].irq[id].dev_type;
745        channel = dev_tbl[i].irq[id].channel;
746        is_rx   = dev_tbl[i].irq[id].is_rx;
747        func    = FUNC_FROM_TYPE( type );
748
749        // get pointer on relevant field in iopic_input
750        if( valid )
751        {
752            if     ( func == DEV_FUNC_IOC )                 ptr = &iopic_input.ioc[channel]; 
753            else if((func == DEV_FUNC_TXT) && (is_rx == 0)) ptr = &iopic_input.txt_tx[channel];
754            else if((func == DEV_FUNC_TXT) && (is_rx != 0)) ptr = &iopic_input.txt_rx[channel];
755            else if((func == DEV_FUNC_NIC) && (is_rx == 0)) ptr = &iopic_input.nic_tx[channel];
756            else if((func == DEV_FUNC_NIC) && (is_rx != 0)) ptr = &iopic_input.nic_rx[channel];
757            else if( func == DEV_FUNC_IOB )                 ptr = &iopic_input.iob;
758            else
759            {
760                printk("\n[PANIC] in %s : illegal source device for IOPIC input\n",
761                __FUNCTION__ );
762                hal_core_sleep();
763            }
764
765            // set one entry in all "iopic_input" structures
766            for( x = 0 ; x < info->x_size ; x++ )
767            {
768                for( y = 0 ; y < info->y_size ; y++ )
769                {
770                    cxy_t cxy = HAL_CXY_FROM_XY( x , y );
771
772                    if( cluster_is_active( cxy ) )
773                    {
774                        hal_remote_s64( XPTR( cxy , ptr ) , id ); 
775                    }
776                }
777            }
778        }
779    } 
780
781#if( DEBUG_KERNEL_INIT & 0x1 )
782if( hal_time_stamp() > DEBUG_KERNEL_INIT )
783{
784    printk("\n[%s] created PIC chdev in cluster %x at cycle %d\n",
785    __FUNCTION__ , local_cxy , (uint32_t)hal_time_stamp() );
786    dev_pic_inputs_display();
787}
788#endif
789   
790}  // end iopic_init()
791
792///////////////////////////////////////////////////////////////////////////////////////////
793// This function is called by all core[0]s in all cluster to complete the PIC device
794// initialisation, namely the informations attached to the LAPIC controller.
795// This initialisation must be done after the IOPIC initialisation, but before other
796// devices initialisation because the IRQ routing infrastructure is required for both
797// internal and external devices initialisation.
798///////////////////////////////////////////////////////////////////////////////////////////
799// @ info    : pointer on the local boot-info structure.
800///////////////////////////////////////////////////////////////////////////////////////////
801static void __attribute__ ((noinline)) lapic_init( boot_info_t * info )
802{
803    boot_device_t * dev_tbl;      // pointer on boot_info internal devices array
804    uint32_t        dev_nr;       // number of internal devices
805    uint32_t        i;            // device index in dev_tbl
806        xptr_t          base;         // remote pointer on segment base
807    uint32_t        func;         // device functionnal type in boot_info
808    bool_t          found;        // LAPIC found
809
810    // get number of internal peripherals and base
811        dev_nr      = info->int_dev_nr;
812    dev_tbl     = info->int_dev;
813
814    // loop on internal peripherals to get the lapic device
815        for( i = 0 , found = false ; i < dev_nr ; i++ )
816        {
817        func = FUNC_FROM_TYPE( dev_tbl[i].type );
818
819        if( func == DEV_FUNC_ICU )
820        {
821            base     = dev_tbl[i].base;
822            found    = true;
823            break;
824        }
825    }
826
827    // if the LAPIC controller is not defined in the boot_info,
828    // we simply don't initialize the PIC extensions in the kernel,
829    // making the assumption that the LAPIC related informations
830    // are hidden in the hardware specific PIC driver.
831    if( found )
832    {
833        // initialise the PIC extensions for
834        // the core descriptor and core manager extensions
835        dev_pic_extend_init( (uint32_t *)GET_PTR( base ) );
836
837        // initialize the "lapic_input" structure
838        // defining how internal IRQs are connected to LAPIC
839        uint32_t        id;
840        uint8_t         valid;
841        uint8_t         channel;
842        uint32_t        func;
843
844        for( id = 0 ; id < CONFIG_MAX_INTERNAL_IRQS ; id++ )
845        {
846            valid    = dev_tbl[i].irq[id].valid;
847            func     = FUNC_FROM_TYPE( dev_tbl[i].irq[id].dev_type );
848            channel  = dev_tbl[i].irq[id].channel;
849
850            if( valid ) // only valid local IRQs are registered
851            {
852                if     ( func == DEV_FUNC_MMC ) lapic_input.mmc = id;
853                else if( func == DEV_FUNC_DMA ) lapic_input.dma[channel] = id;
854                else
855                {
856                    printk("\n[PANIC] in %s : illegal source device for LAPIC input\n",
857                    __FUNCTION__ );
858                    hal_core_sleep();
859                }
860            }
861        }
862    }
863}  // end lapic_init()
864
865///////////////////////////////////////////////////////////////////////////////////////////
866// This static function returns the identifiers of the calling core.
867///////////////////////////////////////////////////////////////////////////////////////////
868// @ info    : pointer on boot_info structure.
869// @ lid     : [out] core local index in cluster.
870// @ cxy     : [out] cluster identifier.
871// @ lid     : [out] core global identifier (hardware).
872// @ return 0 if success / return EINVAL if not found.
873///////////////////////////////////////////////////////////////////////////////////////////
874static error_t __attribute__ ((noinline)) get_core_identifiers( boot_info_t * info,
875                                                                lid_t       * lid,
876                                                                cxy_t       * cxy,
877                                                                gid_t       * gid )
878{
879    uint32_t   i;
880    gid_t      global_id;
881
882    // get global identifier from hardware register
883    global_id = hal_get_gid();
884
885    // makes an associative search in boot_info to get (cxy,lid) from global_id
886    for( i = 0 ; i < info->cores_nr ; i++ )
887    {
888        if( global_id == info->core[i].gid )
889        {
890            *lid = info->core[i].lid;
891            *cxy = info->core[i].cxy;
892            *gid = global_id;
893            return 0;
894        }
895    }
896    return EINVAL;
897}
898
899///////////////////////////////////////////////////////////////////////////////////////////
900// This function is the entry point for the kernel initialisation.
901// It is executed by all cores in all clusters, but only core[0] initializes
902// the shared resources such as the cluster manager, or the local peripherals.
903// To comply with the multi-kernels paradigm, it accesses only local cluster memory, using
904// only information contained in the local boot_info_t structure, set by the bootloader.
905// Only core[0] in cluster 0 print the log messages.
906///////////////////////////////////////////////////////////////////////////////////////////
907// @ info    : pointer on the local boot-info structure.
908///////////////////////////////////////////////////////////////////////////////////////////
909void kernel_init( boot_info_t * info )
910{
911    lid_t        core_lid = -1;             // running core local index
912    cxy_t        core_cxy = -1;             // running core cluster identifier
913    gid_t        core_gid;                  // running core hardware identifier
914    cluster_t  * cluster;                   // pointer on local cluster manager
915    core_t     * core;                      // pointer on running core descriptor
916    thread_t   * thread;                    // pointer on idle thread descriptor
917
918    xptr_t       vfs_root_inode_xp;         // extended pointer on VFS root inode
919    xptr_t       devfs_dev_inode_xp;        // extended pointer on DEVFS dev inode   
920    xptr_t       devfs_external_inode_xp;   // extended pointer on DEVFS external inode       
921    xptr_t       devfs_internal_inode_xp;   // extended pointer on DEVFS internal inode       
922
923    error_t      error;
924    reg_t        status;                    // running core status register
925
926    /////////////////////////////////////////////////////////////////////////////////
927    // STEP 1 : Each core get its core identifier from boot_info, and makes
928    //          a partial initialisation of its private idle thread descriptor.
929    //          core[0] initializes the "local_cxy" global variable.
930    //          core[0] in cluster[0] initializes the TXT0 chdev for log messages.
931    /////////////////////////////////////////////////////////////////////////////////
932
933    error = get_core_identifiers( info,
934                                  &core_lid,
935                                  &core_cxy,
936                                  &core_gid );
937
938    // core[0] initialize cluster identifier
939    if( core_lid == 0 ) local_cxy = info->cxy;
940
941    // each core gets a pointer on its private idle thread descriptor
942    thread = (thread_t *)( idle_threads + (core_lid * CONFIG_THREAD_DESC_SIZE) );
943
944    // each core registers this thread pointer in hardware register
945    hal_set_current_thread( thread );
946
947    // each core register core descriptor pointer in idle thread descriptor
948    thread->core = &LOCAL_CLUSTER->core_tbl[core_lid];
949
950    // each core initializes the idle thread locks counters
951    thread->busylocks = 0;
952
953#if DEBUG_BUSYLOCK
954    // each core initialise the idle thread list of busylocks
955    xlist_root_init( XPTR( local_cxy , &thread->busylocks_root ) );
956#endif
957
958    // core[0] initializes cluster info
959    if( core_lid == 0 ) cluster_info_init( info );
960
961    // core[0] in cluster[0] initialises TXT0 chdev descriptor
962    if( (core_lid == 0) && (core_cxy == 0) ) txt0_device_init( info );
963
964    // all cores check identifiers
965    if( error )
966    {
967        printk("\n[PANIC] in %s : illegal core : gid %x / cxy %x / lid %d",
968        __FUNCTION__, core_lid, core_cxy, core_lid );
969        hal_core_sleep();
970    }
971
972    /////////////////////////////////////////////////////////////////////////////////
973    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
974                                        (info->x_size * info->y_size) );
975    barrier_wait( &local_barrier , info->cores_nr );
976    /////////////////////////////////////////////////////////////////////////////////
977
978#if DEBUG_KERNEL_INIT
979if( (core_lid ==  0) & (local_cxy == 0) ) 
980printk("\n[%s] : exit barrier 1 : TXT0 initialized / cycle %d\n",
981__FUNCTION__, (uint32_t)hal_get_cycles() );
982#endif
983
984    /////////////////////////////////////////////////////////////////////////////////
985    // STEP 2 : core[0] initializes the cluter manager,
986    //          including the physical memory allocator.
987    /////////////////////////////////////////////////////////////////////////////////
988
989    // core[0] initialises DQDT (only core[0] in cluster 0 build the quad-tree)
990    if( core_lid == 0 ) dqdt_init();
991   
992    // core[0] initialize other cluster manager complex structures
993    if( core_lid == 0 )
994    {
995        error = cluster_manager_init( info );
996
997        if( error )
998        {
999             printk("\n[PANIC] in %s : cannot initialize cluster manager in cluster %x\n",
1000             __FUNCTION__, local_cxy );
1001             hal_core_sleep();
1002        }
1003    }
1004
1005    /////////////////////////////////////////////////////////////////////////////////
1006    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1007                                        (info->x_size * info->y_size) );
1008    barrier_wait( &local_barrier , info->cores_nr );
1009    /////////////////////////////////////////////////////////////////////////////////
1010
1011#if DEBUG_KERNEL_INIT
1012if( (core_lid ==  0) & (local_cxy == 0) ) 
1013printk("\n[%s] : exit barrier 2 : cluster manager initialized / cycle %d\n",
1014__FUNCTION__, (uint32_t)hal_get_cycles() );
1015#endif
1016
1017    /////////////////////////////////////////////////////////////////////////////////
1018    // STEP 3 : core[0] initializes the process_zero descriptor,
1019    //          including the kernel VMM (both GPT and VSL)
1020    /////////////////////////////////////////////////////////////////////////////////
1021
1022    // all cores get pointer on local cluster manager & core descriptor
1023    cluster = &cluster_manager;
1024    core    = &cluster->core_tbl[core_lid];
1025
1026    // core[0] initializes the process_zero descriptor,
1027    if( core_lid == 0 ) process_zero_create( &process_zero , info );
1028
1029    /////////////////////////////////////////////////////////////////////////////////
1030    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1031                                        (info->x_size * info->y_size) );
1032    barrier_wait( &local_barrier , info->cores_nr );
1033    /////////////////////////////////////////////////////////////////////////////////
1034
1035#if DEBUG_KERNEL_INIT
1036if( (core_lid ==  0) & (local_cxy == 0) ) 
1037printk("\n[%s] : exit barrier 3 : kernel processs initialized / cycle %d\n",
1038__FUNCTION__, (uint32_t)hal_get_cycles() );
1039#endif
1040
1041    /////////////////////////////////////////////////////////////////////////////////
1042    // STEP 4 : all cores initialize their private MMU
1043    //          core[0] in cluster 0 initializes the IOPIC device.
1044    /////////////////////////////////////////////////////////////////////////////////
1045
1046    // all cores initialise their MMU
1047    hal_mmu_init( &process_zero.vmm.gpt );
1048
1049    // core[0] in cluster[0] initializes the PIC chdev,
1050    if( (core_lid == 0) && (local_cxy == 0) ) iopic_init( info );
1051   
1052    ////////////////////////////////////////////////////////////////////////////////
1053    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1054                                        (info->x_size * info->y_size) );
1055    barrier_wait( &local_barrier , info->cores_nr );
1056    ////////////////////////////////////////////////////////////////////////////////
1057
1058#if DEBUG_KERNEL_INIT
1059if( (core_lid ==  0) & (local_cxy == 0) ) 
1060printk("\n[%s] : exit barrier 4 : MMU and IOPIC initialized / cycle %d\n",
1061__FUNCTION__, (uint32_t)hal_get_cycles() );
1062#endif
1063
1064    ////////////////////////////////////////////////////////////////////////////////
1065    // STEP 5 : core[0] initializes the distibuted LAPIC descriptor.
1066    //          core[0] initializes the internal chdev descriptors
1067    //          core[0] initialize the local external chdev descriptors
1068    ////////////////////////////////////////////////////////////////////////////////
1069
1070    // all core[0]s initialize their local LAPIC extension,
1071    if( core_lid == 0 ) lapic_init( info );
1072
1073    // core[0] scan the internal (private) peripherals,
1074    // and allocates memory for the corresponding chdev descriptors.
1075    if( core_lid == 0 ) internal_devices_init( info );
1076       
1077
1078    // All core[0]s contribute to initialise external peripheral chdev descriptors.
1079    // Each core[0][cxy] scan the set of external (shared) peripherals (but the TXT0),
1080    // and allocates memory for the chdev descriptors that must be placed
1081    // on the (cxy) cluster according to the global index value.
1082
1083    if( core_lid == 0 ) external_devices_init( info );
1084
1085    /////////////////////////////////////////////////////////////////////////////////
1086    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1087                                        (info->x_size * info->y_size) );
1088    barrier_wait( &local_barrier , info->cores_nr );
1089    /////////////////////////////////////////////////////////////////////////////////
1090
1091#if DEBUG_KERNEL_INIT
1092if( (core_lid ==  0) & (local_cxy == 0) ) 
1093printk("\n[%s] : exit barrier 5 : all chdevs initialised / cycle %d\n",
1094__FUNCTION__, (uint32_t)hal_get_cycles() );
1095#endif
1096
1097#if( DEBUG_KERNEL_INIT & 1 )
1098if( (core_lid ==  0) & (local_cxy == 0) ) 
1099chdev_dir_display();
1100#endif
1101   
1102    /////////////////////////////////////////////////////////////////////////////////
1103    // STEP 6 : All cores enable IPI (Inter Procesor Interrupt),
1104    //          Alh cores initialize IDLE thread.
1105    //          Only core[0] in cluster[0] creates the VFS root inode.
1106    //          It access the boot device to initialize the file system context.
1107    /////////////////////////////////////////////////////////////////////////////////
1108
1109    // All cores enable IPI
1110    dev_pic_enable_ipi();
1111    hal_enable_irq( &status );
1112
1113    // all cores initialize the idle thread descriptor
1114    thread_idle_init( thread,
1115                      THREAD_IDLE,
1116                      &thread_idle_func,
1117                      NULL,
1118                      core_lid );
1119
1120    // all cores unblock idle thread, and register it in scheduler
1121    thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1122    core->scheduler.idle = thread;
1123
1124#if( DEBUG_KERNEL_INIT & 1 )
1125sched_display( core_lid );
1126#endif
1127
1128    // core[O] in cluster[0] creates the VFS root
1129    if( (core_lid ==  0) && (local_cxy == 0 ) ) 
1130    {
1131        vfs_root_inode_xp = XPTR_NULL;
1132
1133        // Only FATFS is supported yet,
1134        // other File System can be introduced here
1135        if( CONFIG_VFS_ROOT_IS_FATFS )
1136        {
1137            // 1. allocate memory for FATFS context extension in cluster 0
1138            fatfs_ctx_t * fatfs_ctx = fatfs_ctx_alloc();
1139
1140            if( fatfs_ctx == NULL )
1141            {
1142                printk("\n[PANIC] in %s : cannot create FATFS context in cluster 0\n",
1143                __FUNCTION__ );
1144                hal_core_sleep();
1145            }
1146
1147            // 2. access boot device to initialize FATFS context
1148            fatfs_ctx_init( fatfs_ctx );
1149 
1150            // 3. get various informations from FATFS context
1151            uint32_t root_dir_cluster = fatfs_ctx->root_dir_cluster;
1152            uint32_t cluster_size     = fatfs_ctx->bytes_per_sector * 
1153                                        fatfs_ctx->sectors_per_cluster;
1154            uint32_t total_clusters   = fatfs_ctx->fat_sectors_count << 7;
1155 
1156            // 4. create VFS root inode in cluster 0
1157            error = vfs_inode_create( FS_TYPE_FATFS,                       // fs_type
1158                                      0,                                   // attr
1159                                      0,                                   // rights
1160                                      0,                                   // uid
1161                                      0,                                   // gid
1162                                      &vfs_root_inode_xp );                // return
1163            if( error )
1164            {
1165                printk("\n[PANIC] in %s : cannot create VFS root inode in cluster 0\n",
1166                __FUNCTION__ );
1167                hal_core_sleep();
1168            }
1169
1170            // 5. update FATFS root inode "type" and "extend" fields 
1171            cxy_t         vfs_root_cxy = GET_CXY( vfs_root_inode_xp );
1172            vfs_inode_t * vfs_root_ptr = GET_PTR( vfs_root_inode_xp );
1173            hal_remote_s32( XPTR( vfs_root_cxy , &vfs_root_ptr->extend ), INODE_TYPE_DIR );
1174            hal_remote_spt( XPTR( vfs_root_cxy , &vfs_root_ptr->extend ), 
1175                            (void*)(intptr_t)root_dir_cluster );
1176
1177            // 6. initialize the generic VFS context for FATFS
1178            vfs_ctx_init( FS_TYPE_FATFS,                               // fs type
1179                          0,                                           // attributes: unused
1180                              total_clusters,                              // number of clusters
1181                              cluster_size,                                // bytes
1182                              vfs_root_inode_xp,                           // VFS root
1183                          fatfs_ctx );                                 // extend
1184        }
1185        else
1186        {
1187            printk("\n[PANIC] in %s : unsupported VFS type in cluster 0\n",
1188            __FUNCTION__ );
1189            hal_core_sleep();
1190        }
1191
1192        // create the <.> and <..> dentries in VFS root directory
1193        // the VFS root parent inode is the VFS root inode itself
1194        vfs_add_special_dentries( vfs_root_inode_xp,
1195                                  vfs_root_inode_xp );
1196
1197        // register VFS root inode in process_zero descriptor of cluster 0
1198        process_zero.vfs_root_xp = vfs_root_inode_xp;
1199        process_zero.cwd_xp      = vfs_root_inode_xp;
1200    }
1201
1202    /////////////////////////////////////////////////////////////////////////////////
1203    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1204                                        (info->x_size * info->y_size) );
1205    barrier_wait( &local_barrier , info->cores_nr );
1206    /////////////////////////////////////////////////////////////////////////////////
1207
1208#if DEBUG_KERNEL_INIT
1209if( (core_lid ==  0) & (local_cxy == 0) ) 
1210printk("\n[%s] : exit barrier 6 : VFS root (%x,%x) in cluster 0 / cycle %d\n",
1211__FUNCTION__, GET_CXY(process_zero.vfs_root_xp),
1212GET_PTR(process_zero.vfs_root_xp), (uint32_t)hal_get_cycles() );
1213#endif
1214
1215    /////////////////////////////////////////////////////////////////////////////////
1216    // STEP 7 : In all other clusters than cluster[0], the core[0] allocates memory
1217    //          for the selected FS context, and initialise the local FS context and
1218    //          the local VFS context from values stored in cluster 0.
1219    //          They get the VFS root inode extended pointer from cluster 0.
1220    /////////////////////////////////////////////////////////////////////////////////
1221
1222    if( (core_lid ==  0) && (local_cxy != 0) ) 
1223    {
1224        // File System must be FATFS in this implementation,
1225        // but other File System can be introduced here
1226        if( CONFIG_VFS_ROOT_IS_FATFS )
1227        {
1228            // 1. allocate memory for local FATFS context
1229            fatfs_ctx_t * local_fatfs_ctx = fatfs_ctx_alloc();
1230
1231            // check memory
1232            if( local_fatfs_ctx == NULL )
1233            {
1234                printk("\n[PANIC] in %s : cannot create FATFS context in cluster %x\n",
1235                __FUNCTION__ , local_cxy );
1236                hal_core_sleep();
1237            }
1238
1239            // 2. get local pointer on VFS context for FATFS
1240            vfs_ctx_t   * vfs_ctx = &fs_context[FS_TYPE_FATFS];
1241
1242            // 3. get local pointer on FATFS context in cluster 0
1243            fatfs_ctx_t * remote_fatfs_ctx = hal_remote_lpt( XPTR( 0 , &vfs_ctx->extend ) );
1244
1245            // 4. copy FATFS context from cluster 0 to local cluster
1246            hal_remote_memcpy( XPTR( local_cxy , local_fatfs_ctx ), 
1247                               XPTR( 0 ,         remote_fatfs_ctx ), sizeof(fatfs_ctx_t) );
1248
1249            // 5. copy VFS context from cluster 0 to local cluster
1250            hal_remote_memcpy( XPTR( local_cxy , vfs_ctx ), 
1251                               XPTR( 0 ,         vfs_ctx ), sizeof(vfs_ctx_t) );
1252
1253            // 6. update extend field in local copy of VFS context
1254            vfs_ctx->extend = local_fatfs_ctx;
1255
1256            if( ((fatfs_ctx_t *)vfs_ctx->extend)->sectors_per_cluster != 8 )
1257            {
1258                printk("\n[PANIC] in %s : illegal FATFS context in cluster %x\n",
1259                __FUNCTION__ , local_cxy );
1260                hal_core_sleep();
1261            }
1262        }
1263
1264        // get extended pointer on VFS root inode from cluster 0
1265        vfs_root_inode_xp = hal_remote_l64( XPTR( 0 , &process_zero.vfs_root_xp ) );
1266
1267        // update local process_zero descriptor
1268        process_zero.vfs_root_xp = vfs_root_inode_xp;
1269        process_zero.cwd_xp      = vfs_root_inode_xp;
1270    }
1271
1272    /////////////////////////////////////////////////////////////////////////////////
1273    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1274                                        (info->x_size * info->y_size) );
1275    barrier_wait( &local_barrier , info->cores_nr );
1276    /////////////////////////////////////////////////////////////////////////////////
1277
1278#if DEBUG_KERNEL_INIT
1279if( (core_lid ==  0) & (local_cxy == 1) ) 
1280printk("\n[%s] : exit barrier 7 : VFS root (%x,%x) in cluster 1 / cycle %d\n",
1281__FUNCTION__, GET_CXY(process_zero.vfs_root_xp),
1282GET_PTR(process_zero.vfs_root_xp), (uint32_t)hal_get_cycles() );
1283#endif
1284
1285    /////////////////////////////////////////////////////////////////////////////////
1286    // STEP 8 : core[0] in cluster 0 makes the global DEVFS initialisation:
1287    //          It initializes the DEVFS context, and creates the DEVFS
1288    //          "dev" and "external" inodes in cluster 0.
1289    /////////////////////////////////////////////////////////////////////////////////
1290
1291    if( (core_lid ==  0) && (local_cxy == 0) ) 
1292    {
1293        // 1. allocate memory for DEVFS context extension in cluster 0
1294        devfs_ctx_t * devfs_ctx = devfs_ctx_alloc();
1295
1296        if( devfs_ctx == NULL )
1297        {
1298            printk("\n[PANIC] in %s : cannot create DEVFS context in cluster 0\n",
1299            __FUNCTION__ , local_cxy );
1300            hal_core_sleep();
1301        }
1302
1303        // 2. initialize the DEVFS entry in the vfs_context[] array
1304        vfs_ctx_init( FS_TYPE_DEVFS,                                // fs type
1305                      0,                                            // attributes: unused
1306                          0,                                            // total_clusters: unused
1307                          0,                                            // cluster_size: unused
1308                          vfs_root_inode_xp,                            // VFS root
1309                      devfs_ctx );                                  // extend
1310
1311        // 3. create "dev" and "external" inodes (directories)
1312        devfs_global_init( process_zero.vfs_root_xp,
1313                           &devfs_dev_inode_xp,
1314                           &devfs_external_inode_xp );
1315
1316        // 4. initializes DEVFS context extension
1317        devfs_ctx_init( devfs_ctx,
1318                        devfs_dev_inode_xp,
1319                        devfs_external_inode_xp );
1320    }   
1321
1322    /////////////////////////////////////////////////////////////////////////////////
1323    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1324                                        (info->x_size * info->y_size) );
1325    barrier_wait( &local_barrier , info->cores_nr );
1326    /////////////////////////////////////////////////////////////////////////////////
1327
1328#if DEBUG_KERNEL_INIT
1329if( (core_lid ==  0) & (local_cxy == 0) ) 
1330printk("\n[%s] : exit barrier 8 : DEVFS root initialized in cluster 0 / cycle %d\n",
1331__FUNCTION__, (uint32_t)hal_get_cycles() );
1332#endif
1333
1334    /////////////////////////////////////////////////////////////////////////////////
1335    // STEP 9 : All core[0]s complete in parallel the DEVFS initialization.
1336    //          Each core[0] get the "dev" and "external" extended pointers from
1337    //          values stored in cluster 0.
1338    //          Then each core[0] in cluster(i) creates the DEVFS "internal" directory,
1339    //          and creates the pseudo-files for all chdevs in cluster (i).
1340    /////////////////////////////////////////////////////////////////////////////////
1341
1342    if( core_lid == 0 )
1343    {
1344        // get extended pointer on "extend" field of VFS context for DEVFS in cluster 0
1345        xptr_t  extend_xp = XPTR( 0 , &fs_context[FS_TYPE_DEVFS].extend );
1346
1347        // get pointer on DEVFS context in cluster 0
1348        devfs_ctx_t * devfs_ctx = hal_remote_lpt( extend_xp );
1349       
1350        devfs_dev_inode_xp      = hal_remote_l64( XPTR( 0 , &devfs_ctx->dev_inode_xp ) );
1351        devfs_external_inode_xp = hal_remote_l64( XPTR( 0 , &devfs_ctx->external_inode_xp ) );
1352
1353        // populate DEVFS in all clusters
1354        devfs_local_init( devfs_dev_inode_xp,
1355                          devfs_external_inode_xp,
1356                          &devfs_internal_inode_xp );
1357    }
1358
1359    /////////////////////////////////////////////////////////////////////////////////
1360    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1361                                        (info->x_size * info->y_size) );
1362    barrier_wait( &local_barrier , info->cores_nr );
1363    /////////////////////////////////////////////////////////////////////////////////
1364
1365#if DEBUG_KERNEL_INIT
1366if( (core_lid ==  0) & (local_cxy == 0) ) 
1367printk("\n[%s] : exit barrier 9 : DEVFS initialized in cluster 0 / cycle %d\n",
1368__FUNCTION__, (uint32_t)hal_get_cycles() );
1369#endif
1370
1371#if( DEBUG_KERNEL_INIT & 1 )
1372if( (core_lid ==  0) & (local_cxy == 0) ) 
1373vfs_display( vfs_root_inode_xp );
1374#endif
1375
1376    /////////////////////////////////////////////////////////////////////////////////
1377    // STEP 10 : core[0] in cluster 0 creates the first user process (process_init).
1378    //           This include the first user process VMM (GPT and VSL) creation.
1379    //           Finally, it prints the ALMOS-MKH banner.
1380    /////////////////////////////////////////////////////////////////////////////////
1381
1382    if( (core_lid == 0) && (local_cxy == 0) ) 
1383    {
1384       process_init_create();
1385    }
1386
1387#if (DEBUG_KERNEL_INIT & 1)
1388if( (core_lid ==  0) & (local_cxy == 0) ) 
1389sched_display( 0 );
1390#endif
1391
1392    if( (core_lid == 0) && (local_cxy == 0) ) 
1393    {
1394        print_banner( (info->x_size * info->y_size) , info->cores_nr );
1395    }
1396
1397#if( DEBUG_KERNEL_INIT & 1 )
1398if( (core_lid ==  0) & (local_cxy == 0) ) 
1399printk("\n\n***** memory fooprint for main kernel objects\n\n"
1400                   " - thread descriptor  : %d bytes\n"
1401                   " - process descriptor : %d bytes\n"
1402                   " - cluster manager    : %d bytes\n"
1403                   " - chdev descriptor   : %d bytes\n"
1404                   " - core descriptor    : %d bytes\n"
1405                   " - scheduler          : %d bytes\n"
1406                   " - rpc fifo           : %d bytes\n"
1407                   " - page descriptor    : %d bytes\n"
1408                   " - mapper root        : %d bytes\n"
1409                   " - ppm manager        : %d bytes\n"
1410                   " - kcm manager        : %d bytes\n"
1411                   " - khm manager        : %d bytes\n"
1412                   " - vmm manager        : %d bytes\n"
1413                   " - gpt root           : %d bytes\n"
1414                   " - list item          : %d bytes\n"
1415                   " - xlist item         : %d bytes\n"
1416                   " - busylock           : %d bytes\n"
1417                   " - remote busylock    : %d bytes\n"
1418                   " - queuelock          : %d bytes\n"
1419                   " - remote queuelock   : %d bytes\n"
1420                   " - rwlock             : %d bytes\n"
1421                   " - remote rwlock      : %d bytes\n",
1422                   sizeof( thread_t           ),
1423                   sizeof( process_t          ),
1424                   sizeof( cluster_t          ),
1425                   sizeof( chdev_t            ),
1426                   sizeof( core_t             ),
1427                   sizeof( scheduler_t        ),
1428                   sizeof( remote_fifo_t      ),
1429                   sizeof( page_t             ),
1430                   sizeof( mapper_t           ),
1431                   sizeof( ppm_t              ),
1432                   sizeof( kcm_t              ),
1433                   sizeof( khm_t              ),
1434                   sizeof( vmm_t              ),
1435                   sizeof( gpt_t              ),
1436                   sizeof( list_entry_t       ),
1437                   sizeof( xlist_entry_t      ),
1438                   sizeof( busylock_t         ),
1439                   sizeof( remote_busylock_t  ),
1440                   sizeof( queuelock_t        ),
1441                   sizeof( remote_queuelock_t ),
1442                   sizeof( rwlock_t           ),
1443                   sizeof( remote_rwlock_t    ));
1444#endif
1445
1446    // each core updates the register(s) definig the kernel
1447    // entry points for interrupts, exceptions and syscalls...
1448    hal_set_kentry();
1449
1450    // each core activates its private TICK IRQ
1451    dev_pic_enable_timer( CONFIG_SCHED_TICK_MS_PERIOD );
1452
1453    /////////////////////////////////////////////////////////////////////////////////
1454    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),
1455                                        (info->x_size * info->y_size) );
1456    barrier_wait( &local_barrier , info->cores_nr );
1457    /////////////////////////////////////////////////////////////////////////////////
1458
1459#if( DEBUG_KERNEL_INIT & 1 )
1460thread_t * this = CURRENT_THREAD;
1461printk("\n[%s] : thread[%x,%x] on core[%x,%d] jumps to thread_idle_func() / cycle %d\n",
1462__FUNCTION__ , this->process->pid, this->trdid,
1463local_cxy, core_lid, (uint32_t)hal_get_cycles() );
1464#endif
1465
1466    // each core jump to thread_idle_func
1467    thread_idle_func();
1468
1469}  // end kernel_init()
1470
Note: See TracBrowser for help on using the repository browser.