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

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

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

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