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

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

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

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