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
RevLine 
[1]1/*
2 * kernel_init.c - kernel parallel initialization
[127]3 *
[23]4 * Authors :  Mohamed Lamine Karaoui (2015)
[623]5 *            Alain Greiner  (2016,2017,2018,2019)
[1]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
[14]25#include <kernel_config.h>
[1]26#include <errno.h>
[457]27#include <hal_kernel_types.h>
[1]28#include <hal_special.h>
29#include <hal_context.h>
[279]30#include <hal_irqmask.h>
[564]31#include <hal_macros.h>
[296]32#include <hal_ppm.h>
[14]33#include <barrier.h>
[564]34#include <xbarrier.h>
[407]35#include <remote_fifo.h>
[1]36#include <core.h>
37#include <list.h>
[68]38#include <xlist.h>
[204]39#include <xhtab.h>
[1]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>
[5]48#include <chdev.h>
[1]49#include <boot_info.h>
50#include <dqdt.h>
51#include <dev_mmc.h>
[5]52#include <dev_dma.h>
53#include <dev_iob.h>
[1]54#include <dev_ioc.h>
[5]55#include <dev_txt.h>
[1]56#include <dev_pic.h>
57#include <printk.h>
58#include <vfs.h>
[23]59#include <devfs.h>
[68]60#include <mapper.h>
[1]61
62///////////////////////////////////////////////////////////////////////////////////////////
[279]63// All the following global variables are replicated in all clusters.
[1]64// They are initialised by the kernel_init() function.
[14]65//
[127]66// WARNING : The section names have been defined to control the base addresses of the
[14]67// boot_info structure and the idle thread descriptors, through the kernel.ld script:
[127]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.
[14]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.
[1]72///////////////////////////////////////////////////////////////////////////////////////////
73
[5]74// This variable defines the local boot_info structure
75__attribute__((section(".kinfo")))
[14]76boot_info_t          boot_info;
[5]77
[14]78// This variable defines the "idle" threads descriptors array
79__attribute__((section(".kidle")))
[381]80char                 idle_threads[CONFIG_THREAD_DESC_SIZE *
[14]81                                   CONFIG_MAX_LOCAL_CORES]   CONFIG_PPM_PAGE_ALIGNED;
82
[127]83// This variable defines the local cluster manager
[5]84__attribute__((section(".kdata")))
[19]85cluster_t            cluster_manager                         CONFIG_CACHE_LINE_ALIGNED;
[1]86
[564]87// This variable defines the TXT_TX[0] chdev
[188]88__attribute__((section(".kdata")))
[564]89chdev_t              txt0_tx_chdev                           CONFIG_CACHE_LINE_ALIGNED;
[188]90
[564]91// This variable defines the TXT_RX[0] chdev
[539]92__attribute__((section(".kdata")))
[564]93chdev_t              txt0_rx_chdev                           CONFIG_CACHE_LINE_ALIGNED;
[539]94
[14]95// This variables define the kernel process0 descriptor
[5]96__attribute__((section(".kdata")))
[19]97process_t            process_zero                            CONFIG_CACHE_LINE_ALIGNED;
[1]98
[624]99// This variable defines a set of extended pointers on the distributed chdevs
[5]100__attribute__((section(".kdata")))
[14]101chdev_directory_t    chdev_dir                               CONFIG_CACHE_LINE_ALIGNED;
[1]102
[188]103// This variable contains the input IRQ indexes for the IOPIC controller
[5]104__attribute__((section(".kdata")))
[246]105iopic_input_t        iopic_input                             CONFIG_CACHE_LINE_ALIGNED;
[1]106
[188]107// This variable contains the input IRQ indexes for the LAPIC controller
[5]108__attribute__((section(".kdata")))
[188]109lapic_input_t        lapic_input                             CONFIG_CACHE_LINE_ALIGNED;
[1]110
[14]111// This variable defines the local cluster identifier
[5]112__attribute__((section(".kdata")))
[14]113cxy_t                local_cxy                               CONFIG_CACHE_LINE_ALIGNED;
[5]114
[623]115// This variable is used for core[0] cores synchronisation in kernel_init()
[5]116__attribute__((section(".kdata")))
[564]117xbarrier_t           global_barrier                          CONFIG_CACHE_LINE_ALIGNED;
[1]118
[127]119// This variable is used for local cores synchronisation in kernel_init()
[14]120__attribute__((section(".kdata")))
121barrier_t            local_barrier                           CONFIG_CACHE_LINE_ALIGNED;
122
[127]123// This variable defines the array of supported File System contexts
[50]124__attribute__((section(".kdata")))
125vfs_ctx_t            fs_context[FS_TYPES_NR]                 CONFIG_CACHE_LINE_ALIGNED;
126
[564]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.
[624]129__attribute__((section(".kdata")))
[564]130char * lock_type_str[] =
131{
132    "unused_0",              //  0
[408]133
[564]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
[610]145    "XHTAB_STATE",           // 11
[564]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
[619]153    "PROCESS_CWD",           // 19
154    "BARRIER_STATE",         // 20
[564]155
156    "CLUSTER_PREFTBL",       // 21
[601]157
[564]158    "PPM_DIRTY",             // 22
159    "CLUSTER_LOCALS",        // 23
160    "CLUSTER_COPIES",        // 24
161    "PROCESS_CHILDREN",      // 25
162    "PROCESS_USERSYNC",      // 26
163    "PROCESS_FDARRAY",       // 27
[601]164    "FATFS_FREE",            // 28
[611]165    "PROCESS_DIR",           // 29
[564]166
[611]167    "PROCESS_THTBL",         // 30
[564]168
[611]169    "MAPPER_STATE",          // 31
170    "VFS_SIZE",              // 32
171    "VFS_FILE",              // 33
172    "VMM_VSL",               // 34
173    "VMM_GPT",               // 35
174    "VFS_MAIN",              // 36
[564]175};       
176
[601]177// debug variables to analyse the sys_read() and sys_write() syscalls timing
[564]178
[438]179#if DEBUG_SYS_READ
[407]180uint32_t   enter_sys_read;
181uint32_t   exit_sys_read;
182
[435]183uint32_t   enter_devfs_read;
184uint32_t   exit_devfs_read;
[407]185
186uint32_t   enter_txt_read;
187uint32_t   exit_txt_read;
188
[435]189uint32_t   enter_chdev_cmd_read;
190uint32_t   exit_chdev_cmd_read;
[407]191
[435]192uint32_t   enter_chdev_server_read;
193uint32_t   exit_chdev_server_read;
[407]194
[435]195uint32_t   enter_tty_cmd_read;
196uint32_t   exit_tty_cmd_read;
[407]197
[435]198uint32_t   enter_tty_isr_read;
199uint32_t   exit_tty_isr_read;
[407]200#endif
201
[435]202// these debug variables are used to analyse the sys_write() syscall timing
203
[438]204#if DEBUG_SYS_WRITE   
[435]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
[564]227// intrumentation variables : cumulated costs per syscall type in cluster
[624]228
229#if CONFIG_INSTRUMENTATION_SYSCALLS
230__attribute__((section(".kdata")))
[564]231uint32_t   syscalls_cumul_cost[SYSCALLS_NR];
232
[624]233__attribute__((section(".kdata")))
[564]234uint32_t   syscalls_occurences[SYSCALLS_NR];
[624]235#endif
[564]236
[1]237///////////////////////////////////////////////////////////////////////////////////////////
[5]238// This function displays the ALMOS_MKH banner.
[1]239///////////////////////////////////////////////////////////////////////////////////////////
[5]240static void print_banner( uint32_t nclusters , uint32_t ncores )
[127]241{
[5]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"
[457]252           "\n\n\t\t %s / %d cluster(s) / %d core(s) per cluster\n\n",
253           CONFIG_ALMOS_VERSION , nclusters , ncores );
[5]254}
[1]255
256
[5]257///////////////////////////////////////////////////////////////////////////////////////////
[564]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.
[127]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.
[564]265// Note: The TXT_RX[0] chdev is created, but is not used by ALMOS-MKH (september 2018).
[5]266///////////////////////////////////////////////////////////////////////////////////////////
267// @ info    : pointer on the local boot-info structure.
268///////////////////////////////////////////////////////////////////////////////////////////
[564]269static void __attribute__ ((noinline)) txt0_device_init( boot_info_t * info )
[5]270{
271    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
[127]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
[5]275    uint32_t        impl;            // device implementation index
[127]276    uint32_t        i;               // device index in dev_tbl
277    uint32_t        x;               // X cluster coordinate
278    uint32_t        y;               // Y cluster coordinate
[188]279    uint32_t        channels;        // number of channels
[1]280
[5]281    // get number of peripherals and base of devices array from boot_info
[127]282    dev_nr      = info->ext_dev_nr;
[5]283    dev_tbl     = info->ext_dev;
[1]284
[14]285    // loop on external peripherals to find TXT device
[127]286    for( i = 0 ; i < dev_nr ; i++ )
287    {
[5]288        base        = dev_tbl[i].base;
[188]289        func        = FUNC_FROM_TYPE( dev_tbl[i].type );
290        impl        = IMPL_FROM_TYPE( dev_tbl[i].type );
291        channels    = dev_tbl[i].channels;
[5]292
[127]293        if (func == DEV_FUNC_TXT )
[5]294        {
[564]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 );
[188]303           
[564]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 );
[14]316
[564]317            // register TXT_TX[0] & TXT_RX[0] in chdev_dir[x][y]
318            // for all valid clusters             
[5]319            for( x = 0 ; x < info->x_size ; x++ )
320            {
[564]321                for( y = 0 ; y < info->y_size ; y++ )
[5]322                {
[564]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 ) );
[559]331                    }
[5]332                }
333            }
[564]334
335            hal_fence();
[5]336        }
[188]337        } // end loop on devices
338}  // end txt0_device_init()
[5]339
[1]340///////////////////////////////////////////////////////////////////////////////////////////
[188]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.
[1]345///////////////////////////////////////////////////////////////////////////////////////////
346// @ info    : pointer on the local boot-info structure.
347///////////////////////////////////////////////////////////////////////////////////////////
[564]348static void __attribute__ ((noinline)) internal_devices_init( boot_info_t * info )
[1]349{
[188]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
[1]361
[188]362    // get number of internal peripherals and base from boot_info
363        dev_nr  = info->int_dev_nr;
364    dev_tbl = info->int_dev;
[1]365
[188]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 );
[204]373 
[188]374        //////////////////////////
375        if( func == DEV_FUNC_MMC ) 
[5]376        {
[1]377
[564]378            // check channels
379            if( channels != 1 )
[580]380            {
381                printk("\n[PANIC] in %s : MMC device must be single channel\n",
382                __FUNCTION__ );
383                hal_core_sleep();
384            }
[564]385
[188]386            // create chdev in local cluster
387            chdev_ptr = chdev_create( func,
388                                      impl,
389                                      0,          // channel
390                                      false,      // direction
391                                      base );
[14]392
[564]393            // check memory
394            if( chdev_ptr == NULL )
[580]395            {
396                printk("\n[PANIC] in %s : cannot create MMC chdev\n",
397                __FUNCTION__ );
398                hal_core_sleep();
399            }
[188]400           
401            // make MMC specific initialisation
402            dev_mmc_init( chdev_ptr );
[1]403
[188]404            // set the MMC field in all chdev_dir[x][y] structures
405            for( x = 0 ; x < info->x_size ; x++ )
[1]406            {
[564]407                for( y = 0 ; y < info->y_size ; y++ )
[188]408                {
[564]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] ), 
[559]414                                        XPTR( local_cxy , chdev_ptr ) );
415                    }
[188]416                }
[1]417            }
[188]418
[438]419#if( DEBUG_KERNEL_INIT & 0x1 )
420if( hal_time_stamp() > DEBUG_KERNEL_INIT )
[601]421printk("\n[%s] : created MMC in cluster %x / chdev = %x\n",
[407]422__FUNCTION__ , local_cxy , chdev_ptr );
[389]423#endif
[14]424        }
[188]425        ///////////////////////////////
426        else if( func == DEV_FUNC_DMA )
[127]427        {
[188]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 );
[5]437
[564]438                // check memory
439                if( chdev_ptr == NULL )
[580]440                {
441                    printk("\n[PANIC] in %s : cannot create DMA chdev\n",
442                    __FUNCTION__ );
443                    hal_core_sleep();
444                }
[564]445           
[188]446                // make DMA specific initialisation
447                dev_dma_init( chdev_ptr );     
[127]448
[188]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 );
[5]452
[438]453#if( DEBUG_KERNEL_INIT & 0x1 )
454if( hal_time_stamp() > DEBUG_KERNEL_INIT )
[601]455printk("\n[%s] : created DMA[%d] in cluster %x / chdev = %x\n",
[389]456__FUNCTION__ , channel , local_cxy , chdev_ptr );
457#endif
[188]458            }
[14]459        }
[127]460    }
[5]461}  // end internal_devices_init()
462
463///////////////////////////////////////////////////////////////////////////////////////////
[188]464// This function allocates memory and initializes the chdev descriptors for the 
[408]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.
[188]467// These chdev descriptors are distributed on all clusters, using a modulo on a global
[408]468// index, identically computed in all clusters.
[623]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
[408]471// the local cluster, because the global index matches the local index.
[188]472// The relevant entries in all copies of the devices directory are initialised.
[5]473///////////////////////////////////////////////////////////////////////////////////////////
474// @ info    : pointer on the local boot-info structure.
475///////////////////////////////////////////////////////////////////////////////////////////
476static void external_devices_init( boot_info_t * info )
477{
[188]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
[5]481    uint32_t        func;            // device functionnal index
482    uint32_t        impl;            // device implementation index
[188]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)
[127]490    chdev_t       * chdev;           // local pointer on one channel_device descriptor
[188]491    uint32_t        ext_chdev_gid;   // global index of external chdev
[5]492
493    // get number of peripherals and base of devices array from boot_info
[127]494    dev_nr      = info->ext_dev_nr;
[5]495    dev_tbl     = info->ext_dev;
496
[188]497    // initializes global index (PIC is already placed in cluster 0
498    ext_chdev_gid = 1;
499
[5]500    // loop on external peripherals
[127]501    for( i = 0 ; i < dev_nr ; i++ )
502    {
[188]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 );
[5]507
[407]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;
[5]511
[407]512        // do nothing for ROM, that does not require a device descriptor.
[5]513        if( func == DEV_FUNC_ROM ) continue;
514
[188]515        // do nothing for PIC, that is already initialized
516        if( func == DEV_FUNC_PIC ) continue;
[5]517
[188]518        // check PIC device initialized
[564]519        if( chdev_dir.pic == XPTR_NULL )
[580]520        {
521            printk("\n[PANIC] in %s : PIC device must be initialized first\n",
522            __FUNCTION__ );
523            hal_core_sleep();
524        }
[188]525
526        // check external device functionnal type
[564]527        if( (func != DEV_FUNC_IOB) && (func != DEV_FUNC_IOC) && (func != DEV_FUNC_TXT) &&
528            (func != DEV_FUNC_NIC) && (func != DEV_FUNC_FBF) )
[580]529        {
530            printk("\n[PANIC] in %s : undefined peripheral type\n",
531            __FUNCTION__ );
532            hal_core_sleep();
533        }
[188]534
[127]535        // loops on channels
[428]536        for( channel = 0 ; channel < channels ; channel++ )
[127]537        {
[5]538            // loop on directions
[188]539            for( rx = 0 ; rx < directions ; rx++ )
[1]540            {
[564]541                // skip TXT0 that has already been initialized
542                if( (func == DEV_FUNC_TXT) && (channel == 0) ) continue;
[428]543
[564]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 )
[536]548                {
[564]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;
[536]552
[564]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++;
[550]560                }
561
[5]562                // allocate and initialize a local chdev
[407]563                // when local cluster matches target cluster
[5]564                if( target_cxy == local_cxy )
[1]565                {
[5]566                    chdev = chdev_create( func,
567                                          impl,
568                                          channel,
[188]569                                          rx,          // direction
[5]570                                          base );
571
[564]572                    if( chdev == NULL )
[580]573                    {
574                        printk("\n[PANIC] in %s : cannot allocate chdev\n",
575                        __FUNCTION__ );
576                        hal_core_sleep();
577                    }
[5]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 );
[188]584                    else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev );
[5]585
[127]586                    // all external (shared) devices are remotely accessible
[5]587                    // initialize the replicated chdev_dir[x][y] structures
[127]588                    // defining the extended pointers on chdev descriptors
589                    xptr_t * entry;
590
[188]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];
[407]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];
[188]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];
[127]598
[1]599                    for( x = 0 ; x < info->x_size ; x++ )
600                    {
[564]601                        for( y = 0 ; y < info->y_size ; y++ )
[1]602                        {
[564]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 ),
[559]608                                                XPTR( local_cxy , chdev ) );
609                            }
[5]610                        }
[1]611                    }
612
[438]613#if( DEBUG_KERNEL_INIT & 0x1 )
614if( hal_time_stamp() > DEBUG_KERNEL_INIT )
[601]615printk("\n[%s] : create chdev %s / channel = %d / rx = %d / cluster %x / chdev = %x\n",
[407]616__FUNCTION__ , chdev_func_str( func ), channel , rx , local_cxy , chdev );
[389]617#endif
[5]618                }  // end if match
619
[19]620                // increment chdev global index (matching or not)
[188]621                ext_chdev_gid++;
[5]622
623            } // end loop on directions
624        }  // end loop on channels
[188]625        } // end loop on devices
626}  // end external_devices_init()
[5]627
[188]628///////////////////////////////////////////////////////////////////////////////////////////
[623]629// This function is called by core[0] in cluster 0 to allocate memory and initialize the PIC
[407]630// device, namely the informations attached to the external IOPIC controller, that
631// must be replicated in all clusters (struct iopic_input).
[188]632// This initialisation must be done before other devices initialisation because the IRQ
[407]633// routing infrastructure is required for both internal and external devices init.
[188]634///////////////////////////////////////////////////////////////////////////////////////////
635// @ info    : pointer on the local boot-info structure.
636///////////////////////////////////////////////////////////////////////////////////////////
[564]637static void __attribute__ ((noinline)) iopic_init( boot_info_t * info )
[188]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
[564]654    // avoid GCC warning
655    base        = XPTR_NULL;
656    impl        = 0;
657
[188]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
[127]663        if( func == DEV_FUNC_PIC )
[1]664        {
[188]665            base     = dev_tbl[i].base;
666            impl     = IMPL_FROM_TYPE( dev_tbl[i].type );
667            found    = true;
668            break;
669        }
670    }
[5]671
[564]672    // check PIC existence
673    if( found == false )
[580]674    {
675        printk("\n[PANIC] in %s : PIC device not found\n",
676        __FUNCTION__ );
677        hal_core_sleep();
678    }
[1]679
[407]680    // allocate and initialize the PIC chdev in cluster 0
681    chdev = chdev_create( DEV_FUNC_PIC,
[188]682                          impl,
683                          0,      // channel
684                          0,      // direction,
685                          base );
[5]686
[564]687    // check memory
688    if( chdev == NULL )
[580]689    {
690        printk("\n[PANIC] in %s : no memory for PIC chdev\n",
691        __FUNCTION__ );
692        hal_core_sleep();
693    }
[5]694
[188]695    // make PIC device type specific initialisation
696    dev_pic_init( chdev );
[1]697
[407]698    // register, in all clusters, the extended pointer
699    // on PIC chdev in "chdev_dir" array
[188]700    xptr_t * entry = &chdev_dir.pic;   
701               
702    for( x = 0 ; x < info->x_size ; x++ )
703    {
[564]704        for( y = 0 ; y < info->y_size ; y++ )
[188]705        {
[564]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 ) , 
[559]711                                XPTR( local_cxy , chdev ) );
712            }
[188]713        }
714    }
[1]715
[407]716    // initialize, in all clusters, the "iopic_input" structure
[188]717    // defining how external IRQs are connected to IOPIC
718
[407]719    // register default value for unused inputs
720    for( x = 0 ; x < info->x_size ; x++ )
721    {
[564]722        for( y = 0 ; y < info->y_size ; y++ )
[407]723        {
[564]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) );
[559]730            }
[407]731        }
732    }
733
734    // register input IRQ index for valid inputs
[577]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
[407]741
[188]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;
[407]748        func    = FUNC_FROM_TYPE( type );
[188]749
[407]750        // get pointer on relevant field in iopic_input
751        if( valid )
[188]752        {
[407]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];
[492]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;
[580]759            else
760            {
761                printk("\n[PANIC] in %s : illegal source device for IOPIC input\n",
762                __FUNCTION__ );
763                hal_core_sleep();
764            }
[188]765
[407]766            // set one entry in all "iopic_input" structures
767            for( x = 0 ; x < info->x_size ; x++ )
768            {
[564]769                for( y = 0 ; y < info->y_size ; y++ )
[407]770                {
[564]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 ); 
[559]776                    }
[407]777                }
778            }
[188]779        }
780    } 
781
[438]782#if( DEBUG_KERNEL_INIT & 0x1 )
[601]783if( hal_time_stamp() > DEBUG_KERNEL_INIT )
[407]784{
[601]785    printk("\n[%s] created PIC chdev in cluster %x at cycle %d\n",
[407]786    __FUNCTION__ , local_cxy , (uint32_t)hal_time_stamp() );
787    dev_pic_inputs_display();
788}
[389]789#endif
[188]790   
791}  // end iopic_init()
792
[1]793///////////////////////////////////////////////////////////////////////////////////////////
[623]794// This function is called by all core[0]s in all cluster to complete the PIC device
[188]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///////////////////////////////////////////////////////////////////////////////////////////
[564]802static void __attribute__ ((noinline)) lapic_init( boot_info_t * info )
[188]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;
[580]855                else
856                {
857                    printk("\n[PANIC] in %s : illegal source device for LAPIC input\n",
858                    __FUNCTION__ );
859                    hal_core_sleep();
860                }
[188]861            }
862        }
863    }
864}  // end lapic_init()
865
866///////////////////////////////////////////////////////////////////////////////////////////
[14]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///////////////////////////////////////////////////////////////////////////////////////////
[564]875static error_t __attribute__ ((noinline)) get_core_identifiers( boot_info_t * info,
876                                                                lid_t       * lid,
877                                                                cxy_t       * cxy,
878                                                                gid_t       * gid )
[14]879{
[127]880    uint32_t   i;
[14]881    gid_t      global_id;
[19]882
[14]883    // get global identifier from hardware register
[127]884    global_id = hal_get_gid();
[14]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;
[19]898}
[14]899
900///////////////////////////////////////////////////////////////////////////////////////////
[1]901// This function is the entry point for the kernel initialisation.
[623]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.
[19]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.
[623]906// Only core[0] in cluster 0 print the log messages.
[1]907///////////////////////////////////////////////////////////////////////////////////////////
908// @ info    : pointer on the local boot-info structure.
909///////////////////////////////////////////////////////////////////////////////////////////
910void kernel_init( boot_info_t * info )
911{
[204]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
[1]924    error_t      error;
[285]925    reg_t        status;                    // running core status register
[1]926
[188]927    /////////////////////////////////////////////////////////////////////////////////
[623]928    // STEP 1 : Each core get its core identifier from boot_info, and makes
[188]929    //          a partial initialisation of its private idle thread descriptor.
[623]930    //          core[0] initializes the "local_cxy" global variable.
931    //          core[0] in cluster[0] initializes the TXT0 chdev for log messages.
[188]932    /////////////////////////////////////////////////////////////////////////////////
933
[23]934    error = get_core_identifiers( info,
[14]935                                  &core_lid,
936                                  &core_cxy,
937                                  &core_gid );
[1]938
[623]939    // core[0] initialize cluster identifier
[14]940    if( core_lid == 0 ) local_cxy = info->cxy;
[1]941
[127]942    // each core gets a pointer on its private idle thread descriptor
943    thread = (thread_t *)( idle_threads + (core_lid * CONFIG_THREAD_DESC_SIZE) );
[68]944
[127]945    // each core registers this thread pointer in hardware register
[68]946    hal_set_current_thread( thread );
[71]947
[407]948    // each core register core descriptor pointer in idle thread descriptor
949    thread->core = &LOCAL_CLUSTER->core_tbl[core_lid];
950
[564]951    // each core initializes the idle thread locks counters
952    thread->busylocks = 0;
[124]953
[564]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
[14]958
[623]959    // core[0] initializes cluster info
[564]960    if( core_lid == 0 ) cluster_info_init( info );
961
[623]962    // core[0] in cluster[0] initialises TXT0 chdev descriptor
[564]963    if( (core_lid == 0) && (core_cxy == 0) ) txt0_device_init( info );
964
[623]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
[14]973    /////////////////////////////////////////////////////////////////////////////////
[564]974    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
975                                        (info->x_size * info->y_size) );
[14]976    barrier_wait( &local_barrier , info->cores_nr );
[437]977    /////////////////////////////////////////////////////////////////////////////////
[14]978
[438]979#if DEBUG_KERNEL_INIT
[583]980if( (core_lid ==  0) & (local_cxy == 0) ) 
[624]981printk("\n[%s] exit barrier 1 : TXT0 initialized / cycle %d\n",
[610]982__FUNCTION__, (uint32_t)hal_get_cycles() );
[437]983#endif
[14]984
[623]985    /////////////////////////////////////////////////////////////////////////////////
986    // STEP 2 : core[0] initializes the cluter manager,
987    //          including the physical memory allocator.
988    /////////////////////////////////////////////////////////////////////////////////
[188]989
[623]990    // core[0] initialises DQDT (only core[0] in cluster 0 build the quad-tree)
[582]991    if( core_lid == 0 ) dqdt_init();
992   
[623]993    // core[0] initialize other cluster manager complex structures
[14]994    if( core_lid == 0 )
[1]995    {
[564]996        error = cluster_manager_init( info );
[1]997
[14]998        if( error )
[580]999        {
1000             printk("\n[PANIC] in %s : cannot initialize cluster manager in cluster %x\n",
1001             __FUNCTION__, local_cxy );
1002             hal_core_sleep();
1003        }
[14]1004    }
[5]1005
[14]1006    /////////////////////////////////////////////////////////////////////////////////
[564]1007    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1008                                        (info->x_size * info->y_size) );
[14]1009    barrier_wait( &local_barrier , info->cores_nr );
1010    /////////////////////////////////////////////////////////////////////////////////
[1]1011
[438]1012#if DEBUG_KERNEL_INIT
1013if( (core_lid ==  0) & (local_cxy == 0) ) 
[624]1014printk("\n[%s] exit barrier 2 : cluster manager initialized / cycle %d\n",
[610]1015__FUNCTION__, (uint32_t)hal_get_cycles() );
[437]1016#endif
[1]1017
[188]1018    /////////////////////////////////////////////////////////////////////////////////
[624]1019    // STEP 3 : all cores initialize the idle thread descriptor.
1020    //          core[0] initializes the process_zero descriptor,
[623]1021    //          including the kernel VMM (both GPT and VSL)
[188]1022    /////////////////////////////////////////////////////////////////////////////////
1023
1024    // all cores get pointer on local cluster manager & core descriptor
[14]1025    cluster = &cluster_manager;
[127]1026    core    = &cluster->core_tbl[core_lid];
[1]1027
[624]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
[623]1041    // core[0] initializes the process_zero descriptor,
1042    if( core_lid == 0 ) process_zero_create( &process_zero , info );
[5]1043
[623]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) ) 
[624]1052printk("\n[%s] exit barrier 3 : kernel processs initialized / cycle %d\n",
[623]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,
[188]1065    if( (core_lid == 0) && (local_cxy == 0) ) iopic_init( info );
1066   
1067    ////////////////////////////////////////////////////////////////////////////////
[564]1068    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1069                                        (info->x_size * info->y_size) );
[188]1070    barrier_wait( &local_barrier , info->cores_nr );
1071    ////////////////////////////////////////////////////////////////////////////////
[127]1072
[438]1073#if DEBUG_KERNEL_INIT
1074if( (core_lid ==  0) & (local_cxy == 0) ) 
[624]1075printk("\n[%s] exit barrier 4 : MMU and IOPIC initialized / cycle %d\n",
[610]1076__FUNCTION__, (uint32_t)hal_get_cycles() );
[437]1077#endif
[1]1078
[188]1079    ////////////////////////////////////////////////////////////////////////////////
[623]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
[188]1083    ////////////////////////////////////////////////////////////////////////////////
[5]1084
[623]1085    // all core[0]s initialize their local LAPIC extension,
[279]1086    if( core_lid == 0 ) lapic_init( info );
1087
[623]1088    // core[0] scan the internal (private) peripherals,
[188]1089    // and allocates memory for the corresponding chdev descriptors.
1090    if( core_lid == 0 ) internal_devices_init( info );
1091       
[1]1092
[623]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),
[14]1095    // and allocates memory for the chdev descriptors that must be placed
[127]1096    // on the (cxy) cluster according to the global index value.
[188]1097
[14]1098    if( core_lid == 0 ) external_devices_init( info );
[1]1099
[14]1100    /////////////////////////////////////////////////////////////////////////////////
[564]1101    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1102                                        (info->x_size * info->y_size) );
[14]1103    barrier_wait( &local_barrier , info->cores_nr );
1104    /////////////////////////////////////////////////////////////////////////////////
[5]1105
[438]1106#if DEBUG_KERNEL_INIT
1107if( (core_lid ==  0) & (local_cxy == 0) ) 
[624]1108printk("\n[%s] exit barrier 5 : chdevs initialised / cycle %d\n",
[610]1109__FUNCTION__, (uint32_t)hal_get_cycles() );
[437]1110#endif
[1]1111
[438]1112#if( DEBUG_KERNEL_INIT & 1 )
[443]1113if( (core_lid ==  0) & (local_cxy == 0) ) 
[437]1114chdev_dir_display();
1115#endif
1116   
[188]1117    /////////////////////////////////////////////////////////////////////////////////
[624]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.
[188]1121    //          It access the boot device to initialize the file system context.
1122    /////////////////////////////////////////////////////////////////////////////////
1123
[564]1124    // All cores enable IPI
[279]1125    dev_pic_enable_ipi();
1126    hal_enable_irq( &status );
1127
[624]1128    // all cores unblock the idle thread, and register it in scheduler
[296]1129    thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
[103]1130    core->scheduler.idle = thread;
[1]1131
[438]1132#if( DEBUG_KERNEL_INIT & 1 )
[407]1133sched_display( core_lid );
[389]1134#endif
[14]1135
[623]1136    // core[O] in cluster[0] creates the VFS root
[188]1137    if( (core_lid ==  0) && (local_cxy == 0 ) ) 
[14]1138    {
[188]1139        vfs_root_inode_xp = XPTR_NULL;
[23]1140
[614]1141        // Only FATFS is supported yet,
1142        // other File System can be introduced here
[23]1143        if( CONFIG_VFS_ROOT_IS_FATFS )
1144        {
[601]1145            // 1. allocate memory for FATFS context extension in cluster 0
[188]1146            fatfs_ctx_t * fatfs_ctx = fatfs_ctx_alloc();
1147
[564]1148            if( fatfs_ctx == NULL )
[580]1149            {
1150                printk("\n[PANIC] in %s : cannot create FATFS context in cluster 0\n",
1151                __FUNCTION__ );
1152                hal_core_sleep();
1153            }
[188]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 
[601]1164            // 4. create VFS root inode in cluster 0
[610]1165            error = vfs_inode_create( FS_TYPE_FATFS,                       // fs_type
[188]1166                                      0,                                   // attr
1167                                      0,                                   // rights
1168                                      0,                                   // uid
1169                                      0,                                   // gid
1170                                      &vfs_root_inode_xp );                // return
[564]1171            if( error )
[580]1172            {
1173                printk("\n[PANIC] in %s : cannot create VFS root inode in cluster 0\n",
1174                __FUNCTION__ );
1175                hal_core_sleep();
1176            }
[188]1177
[623]1178            // 5. update FATFS root inode "type" and "extend" fields 
[601]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 );
[624]1181            hal_remote_s32( XPTR( vfs_root_cxy , &vfs_root_ptr->type ), INODE_TYPE_DIR );
[601]1182            hal_remote_spt( XPTR( vfs_root_cxy , &vfs_root_ptr->extend ), 
1183                            (void*)(intptr_t)root_dir_cluster );
[188]1184
[601]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
[23]1192        }
1193        else
1194        {
[564]1195            printk("\n[PANIC] in %s : unsupported VFS type in cluster 0\n",
1196            __FUNCTION__ );
[580]1197            hal_core_sleep();
[23]1198        }
1199
[614]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
[389]1205        // register VFS root inode in process_zero descriptor of cluster 0
[188]1206        process_zero.vfs_root_xp = vfs_root_inode_xp;
[610]1207        process_zero.cwd_xp      = vfs_root_inode_xp;
[188]1208    }
1209
1210    /////////////////////////////////////////////////////////////////////////////////
[564]1211    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1212                                        (info->x_size * info->y_size) );
[188]1213    barrier_wait( &local_barrier , info->cores_nr );
1214    /////////////////////////////////////////////////////////////////////////////////
1215
[438]1216#if DEBUG_KERNEL_INIT
1217if( (core_lid ==  0) & (local_cxy == 0) ) 
[624]1218printk("\n[%s] exit barrier 6 : VFS root (%x,%x) in cluster 0 / cycle %d\n",
[610]1219__FUNCTION__, GET_CXY(process_zero.vfs_root_xp),
1220GET_PTR(process_zero.vfs_root_xp), (uint32_t)hal_get_cycles() );
[437]1221#endif
[188]1222
1223    /////////////////////////////////////////////////////////////////////////////////
[623]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.
[188]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 )
[23]1235        {
[389]1236            // 1. allocate memory for local FATFS context
1237            fatfs_ctx_t * local_fatfs_ctx = fatfs_ctx_alloc();
[188]1238
[564]1239            // check memory
1240            if( local_fatfs_ctx == NULL )
[580]1241            {
1242                printk("\n[PANIC] in %s : cannot create FATFS context in cluster %x\n",
1243                __FUNCTION__ , local_cxy );
1244                hal_core_sleep();
1245            }
[188]1246
[389]1247            // 2. get local pointer on VFS context for FATFS
[188]1248            vfs_ctx_t   * vfs_ctx = &fs_context[FS_TYPE_FATFS];
1249
[389]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
[188]1258            hal_remote_memcpy( XPTR( local_cxy , vfs_ctx ), 
[389]1259                               XPTR( 0 ,         vfs_ctx ), sizeof(vfs_ctx_t) );
[188]1260
[389]1261            // 6. update extend field in local copy of VFS context
1262            vfs_ctx->extend = local_fatfs_ctx;
[188]1263
[564]1264            if( ((fatfs_ctx_t *)vfs_ctx->extend)->sectors_per_cluster != 8 )
[580]1265            {
1266                printk("\n[PANIC] in %s : illegal FATFS context in cluster %x\n",
1267                __FUNCTION__ , local_cxy );
1268                hal_core_sleep();
1269            }
[23]1270        }
1271
[188]1272        // get extended pointer on VFS root inode from cluster 0
[564]1273        vfs_root_inode_xp = hal_remote_l64( XPTR( 0 , &process_zero.vfs_root_xp ) );
[101]1274
[188]1275        // update local process_zero descriptor
1276        process_zero.vfs_root_xp = vfs_root_inode_xp;
[610]1277        process_zero.cwd_xp      = vfs_root_inode_xp;
[14]1278    }
1279
[188]1280    /////////////////////////////////////////////////////////////////////////////////
[564]1281    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1282                                        (info->x_size * info->y_size) );
[188]1283    barrier_wait( &local_barrier , info->cores_nr );
[204]1284    /////////////////////////////////////////////////////////////////////////////////
[101]1285
[438]1286#if DEBUG_KERNEL_INIT
[564]1287if( (core_lid ==  0) & (local_cxy == 1) ) 
[624]1288printk("\n[%s] exit barrier 7 : VFS root (%x,%x) in cluster 1 / cycle %d\n",
[610]1289__FUNCTION__, GET_CXY(process_zero.vfs_root_xp),
1290GET_PTR(process_zero.vfs_root_xp), (uint32_t)hal_get_cycles() );
[437]1291#endif
[188]1292
1293    /////////////////////////////////////////////////////////////////////////////////
[623]1294    // STEP 8 : core[0] in cluster 0 makes the global DEVFS initialisation:
[564]1295    //          It initializes the DEVFS context, and creates the DEVFS
1296    //          "dev" and "external" inodes in cluster 0.
[188]1297    /////////////////////////////////////////////////////////////////////////////////
1298
[564]1299    if( (core_lid ==  0) && (local_cxy == 0) ) 
[1]1300    {
[564]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 )
[580]1305        {
1306            printk("\n[PANIC] in %s : cannot create DEVFS context in cluster 0\n",
1307            __FUNCTION__ , local_cxy );
1308            hal_core_sleep();
1309        }
[564]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)
[188]1320        devfs_global_init( process_zero.vfs_root_xp,
[204]1321                           &devfs_dev_inode_xp,
[188]1322                           &devfs_external_inode_xp );
1323
[564]1324        // 4. initializes DEVFS context extension
1325        devfs_ctx_init( devfs_ctx,
1326                        devfs_dev_inode_xp,
1327                        devfs_external_inode_xp );
[188]1328    }   
1329
1330    /////////////////////////////////////////////////////////////////////////////////
[564]1331    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1332                                        (info->x_size * info->y_size) );
[188]1333    barrier_wait( &local_barrier , info->cores_nr );
[204]1334    /////////////////////////////////////////////////////////////////////////////////
[188]1335
[438]1336#if DEBUG_KERNEL_INIT
1337if( (core_lid ==  0) & (local_cxy == 0) ) 
[624]1338printk("\n[%s] exit barrier 8 : DEVFS root initialized in cluster 0 / cycle %d\n",
[610]1339__FUNCTION__, (uint32_t)hal_get_cycles() );
[437]1340#endif
[188]1341
1342    /////////////////////////////////////////////////////////////////////////////////
[624]1343    // STEP 9 : In all clusters in parallel, core[0] completes DEVFS initialization.
[623]1344    //          Each core[0] get the "dev" and "external" extended pointers from
[624]1345    //          values stored in cluster(0), creates the DEVFS "internal" directory,
1346    //          and creates the pseudo-files for all chdevs in local cluster.
[188]1347    /////////////////////////////////////////////////////////////////////////////////
1348
1349    if( core_lid == 0 )
1350    {
[564]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 );
[188]1353
[457]1354        // get pointer on DEVFS context in cluster 0
[188]1355        devfs_ctx_t * devfs_ctx = hal_remote_lpt( extend_xp );
1356       
[564]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 ) );
[188]1359
[204]1360        // populate DEVFS in all clusters
1361        devfs_local_init( devfs_dev_inode_xp,
1362                          devfs_external_inode_xp,
1363                          &devfs_internal_inode_xp );
[188]1364    }
1365
1366    /////////////////////////////////////////////////////////////////////////////////
[564]1367    if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), 
1368                                        (info->x_size * info->y_size) );
[188]1369    barrier_wait( &local_barrier , info->cores_nr );
[204]1370    /////////////////////////////////////////////////////////////////////////////////
[188]1371
[438]1372#if DEBUG_KERNEL_INIT
1373if( (core_lid ==  0) & (local_cxy == 0) ) 
[624]1374printk("\n[%s] exit barrier 9 : DEVFS initialized in cluster 0 / cycle %d\n",
[610]1375__FUNCTION__, (uint32_t)hal_get_cycles() );
[437]1376#endif
[188]1377
[623]1378#if( DEBUG_KERNEL_INIT & 1 )
1379if( (core_lid ==  0) & (local_cxy == 0) ) 
1380vfs_display( vfs_root_inode_xp );
1381#endif
1382
[188]1383    /////////////////////////////////////////////////////////////////////////////////
[623]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.
[188]1387    /////////////////////////////////////////////////////////////////////////////////
1388
[457]1389    if( (core_lid == 0) && (local_cxy == 0) ) 
[188]1390    {
[428]1391       process_init_create();
[188]1392    }
[101]1393
[624]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
[443]1400#if (DEBUG_KERNEL_INIT & 1)
[564]1401if( (core_lid ==  0) & (local_cxy == 0) ) 
[443]1402sched_display( 0 );
1403#endif
1404
[564]1405    if( (core_lid == 0) && (local_cxy == 0) ) 
[188]1406    {
[5]1407        print_banner( (info->x_size * info->y_size) , info->cores_nr );
[623]1408    }
[68]1409
[438]1410#if( DEBUG_KERNEL_INIT & 1 )
[623]1411if( (core_lid ==  0) & (local_cxy == 0) ) 
[437]1412printk("\n\n***** memory fooprint for main kernel objects\n\n"
[68]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"
[564]1429                   " - busylock           : %d bytes\n"
1430                   " - remote busylock    : %d bytes\n"
1431                   " - queuelock          : %d bytes\n"
1432                   " - remote queuelock   : %d bytes\n"
[68]1433                   " - rwlock             : %d bytes\n"
1434                   " - remote rwlock      : %d bytes\n",
[564]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    ));
[406]1457#endif
1458
[398]1459    // each core activates its private TICK IRQ
1460    dev_pic_enable_timer( CONFIG_SCHED_TICK_MS_PERIOD );
[14]1461
[610]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
[623]1468#if( DEBUG_KERNEL_INIT & 1 )
[610]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() );
[440]1473#endif
1474
[407]1475    // each core jump to thread_idle_func
[50]1476    thread_idle_func();
[14]1477
[610]1478}  // end kernel_init()
1479
Note: See TracBrowser for help on using the repository browser.