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

Last change on this file since 59 was 50, checked in by alain, 7 years ago

bloup

File size: 36.0 KB
RevLine 
[1]1/*
2 * kernel_init.c - kernel parallel initialization
3 *
[23]4 * Authors :  Mohamed Lamine Karaoui (2015)
5 *            Alain Greiner  (2016,2017)
[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>
27#include <hal_types.h>
28#include <hal_special.h>
29#include <hal_context.h>
[14]30#include <barrier.h>
[1]31#include <remote_barrier.h>
32#include <core.h>
33#include <list.h>
34#include <thread.h>
35#include <scheduler.h>
36#include <kmem.h>
37#include <cluster.h>
38#include <string.h>
39#include <memcpy.h>
40#include <ppm.h>
41#include <page.h>
[5]42#include <chdev.h>
[1]43#include <boot_info.h>
44#include <dqdt.h>
45#include <dev_icu.h>
46#include <dev_mmc.h>
[5]47#include <dev_dma.h>
48#include <dev_iob.h>
[1]49#include <dev_ioc.h>
[5]50#include <dev_txt.h>
[1]51#include <dev_pic.h>
52#include <printk.h>
53#include <vfs.h>
[5]54#include <soclib_tty.h>
[23]55#include <devfs.h>
[1]56
57
[5]58#define KERNEL_INIT_SYNCHRO  0xA5A5B5B5
[1]59
60///////////////////////////////////////////////////////////////////////////////////////////
61// All these global variables are replicated in all clusters.
62// They are initialised by the kernel_init() function.
[14]63//
64// WARNING : The section names have been defined to control the base addresses of the
65// boot_info structure and the idle thread descriptors, through the kernel.ld script:
66// - the boot_info structure is build by the bootloader, and used by kernel_init.
67//   it must be first object in the kdata segment.
68// - the array of idle threads descriptors must be placed on the first page boundary after
69//   the boot_info structure in the kdata segment.
[1]70///////////////////////////////////////////////////////////////////////////////////////////
71
[5]72// This variable defines the local boot_info structure
73__attribute__((section(".kinfo")))
[14]74boot_info_t          boot_info;
[5]75
[14]76// This variable defines the "idle" threads descriptors array
77__attribute__((section(".kidle")))
78char                  idle_threads[CONFIG_THREAD_DESC_SIZE *
79                                   CONFIG_MAX_LOCAL_CORES]   CONFIG_PPM_PAGE_ALIGNED;
80
[1]81// This variable defines the local cluster manager
[5]82__attribute__((section(".kdata")))
[19]83cluster_t            cluster_manager                         CONFIG_CACHE_LINE_ALIGNED;
[1]84
[14]85// This variables define the kernel process0 descriptor
[5]86__attribute__((section(".kdata")))
[19]87process_t            process_zero                            CONFIG_CACHE_LINE_ALIGNED;
[1]88
[14]89// This variable defines extended pointers on the distributed chdevs
[5]90__attribute__((section(".kdata")))
[14]91chdev_directory_t    chdev_dir                               CONFIG_CACHE_LINE_ALIGNED;
[1]92
[5]93// This variable contains the input IRQ indexes for the PIC device
94__attribute__((section(".kdata")))
[14]95chdev_pic_input_t    chdev_pic_input                         CONFIG_CACHE_LINE_ALIGNED;
[1]96
[5]97// This variable contains the input IRQ indexes for the ICU device
98__attribute__((section(".kdata")))
[14]99chdev_icu_input_t    chdev_icu_input                         CONFIG_CACHE_LINE_ALIGNED;
[1]100
[14]101// This variable defines the local cluster identifier
[5]102__attribute__((section(".kdata")))
[14]103cxy_t                local_cxy                               CONFIG_CACHE_LINE_ALIGNED;
[5]104
[14]105// This variable defines the TXT0 chdev descriptor
[5]106__attribute__((section(".kdata")))
[14]107chdev_t              txt0_chdev                              CONFIG_CACHE_LINE_ALIGNED;
[1]108
[14]109// This variable is used for CP0 cores sychronisation in kernel_init()
[5]110__attribute__((section(".kdata")))
[14]111remote_barrier_t     global_barrier                          CONFIG_CACHE_LINE_ALIGNED;
[1]112
[14]113// This variable is used for local cores sychronisation in kernel_init()
114__attribute__((section(".kdata")))
115barrier_t            local_barrier                           CONFIG_CACHE_LINE_ALIGNED;
116
[50]117// This variable defines the array of supported File System contexts
118__attribute__((section(".kdata")))
119vfs_ctx_t            fs_context[FS_TYPES_NR]                 CONFIG_CACHE_LINE_ALIGNED;
120
121
[1]122///////////////////////////////////////////////////////////////////////////////////////////
[5]123// This function displays the ALMOS_MKH banner.
[1]124///////////////////////////////////////////////////////////////////////////////////////////
[5]125static void print_banner( uint32_t nclusters , uint32_t ncores )
[1]126{ 
[5]127    printk("\n"
128           "                    _        __    __     _____     ______         __    __    _   __   _     _   \n"
129           "          /\\       | |      |  \\  /  |   / ___ \\   / _____|       |  \\  /  |  | | / /  | |   | |  \n"
130           "         /  \\      | |      |   \\/   |  | /   \\ | | /             |   \\/   |  | |/ /   | |   | |  \n"
131           "        / /\\ \\     | |      | |\\  /| |  | |   | | | |_____   ___  | |\\  /| |  |   /    | |___| |  \n"
132           "       / /__\\ \\    | |      | | \\/ | |  | |   | | \\_____  \\ |___| | | \\/ | |  |   \\    |  ___  |  \n"
133           "      / ______ \\   | |      | |    | |  | |   | |       | |       | |    | |  | |\\ \\   | |   | |  \n"
134           "     / /      \\ \\  | |____  | |    | |  | \\___/ |  _____/ |       | |    | |  | | \\ \\  | |   | |  \n"
135           "    /_/        \\_\\ |______| |_|    |_|   \\_____/  |______/        |_|    |_|  |_|  \\_\\ |_|   |_|  \n"
136           "\n\n\t\t Advanced Locality Management Operating System / Multi Kernel Hybrid\n"
137           "\n\n\t\t\t Version 0.0   :   %d clusters   /   %d cores per cluster\n\n", nclusters , ncores ); 
138}
[1]139
140
[5]141///////////////////////////////////////////////////////////////////////////////////////////
[14]142// This static function initializes the TXT0 chdev descriptor, associated to the "kernel
143// terminal", and shared by all kernel instances for debug messages. It also register it
144// in the chdev directory, containing extended pointers on all chdevs.
145// The global variable txt0_chdev is replicated in all clusters, but only the chdev
146// allocated in I/O cluster is used by ALMOS-MKH.
147// Therefore, this function must be called by a thread running in the I/O cluster.
148// As this TXT0 chdev supports only the TXT_SYNC_WRITE command,  we don't create
149// a server thread,  we don't allocate a WTI, and we don't initialize the waiting queue.
[5]150///////////////////////////////////////////////////////////////////////////////////////////
151// @ info    : pointer on the local boot-info structure.
152///////////////////////////////////////////////////////////////////////////////////////////
153static void txt0_device_init( boot_info_t * info )
154{
155    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
156        uint32_t        dev_nr;          // actual number of devices in this cluster
157        xptr_t          base;            // remote pointer on segment base
158    uint32_t        type;            // peripheral type
159    uint32_t        func;            // device functionnal index
160    uint32_t        impl;            // device implementation index
161        uint32_t        i;               // device index in dev_tbl
162        uint32_t        x;               // X cluster coordinate
163        uint32_t        y;               // Y cluster coordinate
[1]164
[5]165    // get number of peripherals and base of devices array from boot_info
166        dev_nr      = info->ext_dev_nr;
167    dev_tbl     = info->ext_dev;
[1]168
[14]169    // loop on external peripherals to find TXT device
[5]170        for( i = 0 ; i < dev_nr ; i++ )
171        {
172        base        = dev_tbl[i].base;
173        type        = dev_tbl[i].type;
174        func        = FUNC_FROM_TYPE( type );
175        impl        = IMPL_FROM_TYPE( type );
176
177        if (func == DEV_FUNC_TXT ) 
178        {
[14]179            // initialize basic fields
180            txt0_chdev.func     = func;
181            txt0_chdev.impl     = impl;
182            txt0_chdev.channel  = 0;
183            txt0_chdev.is_rx    = 0;
184            txt0_chdev.base     = base;
[5]185
[14]186            // initialize lock
187            remote_spinlock_init( XPTR( local_cxy , &txt0_chdev.wait_lock ) );
188
[5]189            // Complete TXT specific initialisation
190            if( impl == IMPL_TXT_TTY )
191            {
[14]192                txt0_chdev.cmd = &soclib_tty_cmd;
193                txt0_chdev.isr = &soclib_tty_isr;
194                soclib_tty_init( &txt0_chdev );
[5]195            }
196
197            // initialize the replicated chdev_dir[x][y] structures
198            for( x = 0 ; x < info->x_size ; x++ )
199            {
200                for( y = 0 ; y < info->y_size ; y++ )
201                {
202                    cxy_t  cxy = (x<<info->y_width) + y;
[19]203                    hal_remote_swd( XPTR( cxy , &chdev_dir.txt[0] ) ,
[14]204                                    XPTR( local_cxy , &txt0_chdev ) );
[5]205                }
206            }
207
[14]208                    kinit_dmsg("\n[INFO] %s : core[%x][0] created TXT0 chdev"
209                       " / paddr = %l at cycle %d\n",
[19]210                       __FUNCTION__ , local_cxy , chdev_func_str( func ),
[14]211                       XPTR(local_cxy , &txt0_chdev) , hal_time_stamp() );
[5]212        }
213
214        } // end loop on devices
215
216}  // end txt0_device_init()
217
[1]218///////////////////////////////////////////////////////////////////////////////////////////
[5]219// This static function allocates memory for the chdev (channel_device) descriptors
220// associated to the internal peripherals contained in the local cluster. These internal
221// devices (ICU, MMC, DMA) chdev descriptors are placed in the local cluster.
[1]222// It initialises these device descriptors as specified by the boot_info_t structure,
223// including the dynamic linking with the driver for the specified implementation.
224// Finally, all copies of the devices directory are initialised.
225///////////////////////////////////////////////////////////////////////////////////////////
226// @ info    : pointer on the local boot-info structure.
227///////////////////////////////////////////////////////////////////////////////////////////
[5]228static void internal_devices_init( boot_info_t * info )
[1]229{
[14]230    boot_device_t * dev;             // pointer on boot_info device (ICU/MMC/DMA)
[1]231        uint32_t        x;               // X cluster coordinate
232        uint32_t        y;               // Y cluster coordinate
[14]233        chdev_t       * chdev_ptr;       // local pointer on chdev descriptor
234    xptr_t          chdev_xp;        // extended pointer on chdev descriptor
[1]235
[14]236    ///////////  ICU   //////////
[1]237
[14]238    dev = &info->dev_icu;
[5]239
[14]240    assert( ((info->cores_nr == 0) || (dev->channels != 0)) , __FUNCTION__ ,
241            "ICU device must exist in cluster containing cores" );
242       
243    assert( (dev->channels == 1) , __FUNCTION__ ,
244            "channels number must be 1 for ICU device" );
[1]245
[14]246    assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_ICU ) , __FUNCTION__ ,
247            " inconsistent ICU  device type");
[1]248
[14]249    // create one chdev in local cluster
250    chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ),
251                              IMPL_FROM_TYPE( dev->type ),
252                              0,                              // channel
253                              false,                          // TX
254                              dev->base );
[1]255
[14]256    assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate ICU chdev" );
257           
258    // get extended pointer on chdev descriptor
259    chdev_xp = XPTR( local_cxy , chdev_ptr );
260
261    // make ICU specific initialisation
262    // TODO remove these three parameters
[19]263    dev_icu_init( chdev_ptr , dev->param0 , dev->param1 , dev->param2 );
[14]264
265    // initialize the ICU field in the chdev_dir[x][y] structures
266    // replicated in all clusters, and containing extended pointers
267    // on all remotely accessible devices
268    for( x = 0 ; x < info->x_size ; x++ )
269    {
270        for( y = 0 ; y < info->y_size ; y++ )
[5]271        {
[14]272            cxy_t  cxy = (x<<info->y_width) + y;
273            hal_remote_swd( XPTR( cxy , &chdev_dir.icu[local_cxy] ) , chdev_xp );
[5]274        }
[14]275    }
[1]276
[14]277    // initialize the entries of the local chdev_icu_input structure
278    // defining how internal peripherals are connected to ICU
279    uint32_t   id;
280    uint8_t    valid;
281    uint32_t   src_type;
282    uint8_t    src_ch;
283    uint32_t   src_func;
284    for( id = 0 ; id < CONFIG_MAX_HWIS_PER_ICU ; id++ )
285    {
286        valid    = dev->irq[id].valid;
287        src_type = dev->irq[id].dev_type;
288        src_ch   = dev->irq[id].channel;
289        src_func = FUNC_FROM_TYPE( src_type );
290
291        if( valid ) // only valid local IRQs are registered
[5]292        {
[14]293            if     ( src_func == DEV_FUNC_MMC ) chdev_icu_input.mmc = id;
294            else if( src_func == DEV_FUNC_DMA ) chdev_icu_input.dma[src_ch] = id;
295            else assert( false , __FUNCTION__ , "illegal source device for ICU input" );
296        }
297    }
[1]298
[50]299    kinit_dmsg("\n[INFO] %s : core[%x][0] created ICU chdev at cycle %d\n",
[14]300               __FUNCTION__ , local_cxy , hal_time_stamp() );
[1]301
[14]302    /////////// MMC internal chdev /////////// 
[1]303
[14]304    dev = &info->dev_mmc;
[1]305
[14]306    if( dev->channels != 0 )   // MMC device is defined
307    {
308        assert( (dev->channels == 1) , __FUNCTION__ , 
309            "channels number must be 1 for MMC device" );
[1]310
[14]311        assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_MMC ) , __FUNCTION__ ,
312            " inconsistent MMC device type");
313
314        // create one chdev in local cluster
315        chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ),
316                                  IMPL_FROM_TYPE( dev->type ),
317                                  0,                              // channel
318                                  false,                          // TX
319                                  dev->base );
320
321        assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate MMC chdev" );
322           
323        // get extended pointer on chdev descriptor
324        chdev_xp = XPTR( local_cxy , chdev_ptr );
325
326        // make MMC specific initialisation
327        dev_mmc_init( chdev_ptr );     
328
329        // initialize the MMC field in the chdev_dir[x][y] structures
330        // replicated in all clusters, and containing extended pointers
331        // on all remotely accessible devices
332        for( x = 0 ; x < info->x_size ; x++ )
333        {
334            for( y = 0 ; y < info->y_size ; y++ )
[1]335            {
[14]336                cxy_t  cxy = (x<<info->y_width) + y;
337                hal_remote_swd( XPTR( cxy , &chdev_dir.mmc[local_cxy] ) , chdev_xp );
[1]338            }
[14]339        }
[1]340
[50]341        kinit_dmsg("\n[INFO] %s : core[%x][0] created MMC chdev at cycle %d\n",
[14]342                   __FUNCTION__ , local_cxy , hal_time_stamp() );
343    }
[5]344
[14]345    /////////// DMA internal chdevs //////////
[1]346
[14]347    dev = &info->dev_dma;
[1]348
[14]349    if( dev->channels != 0 )   // DMA device is defined
350    {
351        assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_DMA ) , __FUNCTION__ ,
352                " inconsistent DMA  device type");
[5]353
[14]354        // create one chdev per channel in local cluster
355        uint32_t channel;
356        for( channel = 0 ; channel < dev->channels ; channel++ )
357        { 
358            chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ),
359                                      IMPL_FROM_TYPE( dev->type ),
360                                      channel,                        // channel
361                                      false,                          // TX
362                                      dev->base );
[5]363
[14]364            assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate DMA chdev" );
365           
366            // get extended pointer on channel descriptor
367            chdev_xp = XPTR( local_cxy , chdev_ptr );
[5]368
[14]369            // make DMA specific initialisation
370            dev_dma_init( chdev_ptr );     
371
372            // initialize only the DMA[channel] field in the local chdev_dir[x][y]
373            // structure because the DMA device is not remotely accessible.
374            chdev_dir.dma[channel] = chdev_xp;
375
[50]376            kinit_dmsg("\n[INFO] %s : core[%x][0] created DMA[%d] chdev at cycle %d\n",
[14]377                       __FUNCTION__ , local_cxy , channel , hal_time_stamp() );
378        }
379    } 
[5]380}  // end internal_devices_init()
381
382///////////////////////////////////////////////////////////////////////////////////////////
383// This static function allocates memory for the chdev descriptors associated
384// to the external (shared) peripherals contained in the local cluster. These external
385// devices (IOB, IOC, TXT, NIC, etc ) are distributed on all clusters.
386// It initialises these device descriptors as specified by the boot_info_t structure,
387// including the dynamic linking with the driver for the specified implementation.
388// Finally, all copies of the devices directory are initialised.
389//
390// The number of channel_devices depends on the device functionnal type.
[14]391// There is three nested loops to build the full set of external channel_devices:
[5]392// - loop on external devices.
393// - loop on channels for multi-channels devices.
394// - loop on directions (RX/TX) for NIC device.
395// The set of channel_devices is indexed by the chdev_gid global index, that is used
396// to select the cluster containing a given chdev[func,channel,direction].
397// All clusters scan the full set of chdevs, but only the cluster matching
398// (chdev_gid % (x_size*y_size)) create the corresponding chdev.
399//
400// TODO check that cluster IO contains a PIC [AG]
[50]401// TODO make a default initialisation for the chdev_dir structure (XPTR_NULL )  [AG]
[5]402///////////////////////////////////////////////////////////////////////////////////////////
403// @ info    : pointer on the local boot-info structure.
404///////////////////////////////////////////////////////////////////////////////////////////
405static void external_devices_init( boot_info_t * info )
406{
407    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
408        uint32_t        dev_nr;          // actual number of devices in this cluster
409        xptr_t          base;            // remote pointer on segment base
410    uint32_t        type;            // peripheral type
411    uint32_t        func;            // device functionnal index
412    uint32_t        impl;            // device implementation index
413        uint32_t        i;               // device index in dev_tbl
414        uint32_t        x;               // X cluster coordinate
415        uint32_t        y;               // Y cluster coordinate
416        uint32_t        channels_nr;     // number of channels
417        uint32_t        channel;         // channel index
418        uint32_t        directions_nr;   // number of directions
419        uint32_t        direction;       // direction index
420        uint32_t        p0;              // device parameter 0
421        uint32_t        p1;              // device parameter 1
422        uint32_t        p2;              // device parameter 2
423        uint32_t        p3;              // device parameter 3
424    uint32_t        first_channel;   // used in loop on channels
425
426        chdev_t       * chdev;           // local pointer on one channel_device descriptor
427    xptr_t          chdev_xp;        // extended pointer on channel_device descriptor
428    uint32_t        chdev_gid = 0;   // global index of channel_device descriptor
429
430    // get number of peripherals and base of devices array from boot_info
431        dev_nr      = info->ext_dev_nr;
432    dev_tbl     = info->ext_dev;
433
434    // loop on external peripherals
435        for( i = 0 ; i < dev_nr ; i++ )
436        {
437        base        = dev_tbl[i].base;
438        type        = dev_tbl[i].type;
439        channels_nr = dev_tbl[i].channels;
440        p0          = dev_tbl[i].param0;
441        p1          = dev_tbl[i].param1;
442        p2          = dev_tbl[i].param2;
443        p3          = dev_tbl[i].param3;
444
445        func     = FUNC_FROM_TYPE( type );
446        impl     = IMPL_FROM_TYPE( type );
447
448        // There is one chdev per direction for NIC
449        if (func == DEV_FUNC_NIC) directions_nr = 2;
450        else                      directions_nr = 1;
451
452        // The TXT0 chdev has already been created
453        if (func == DEV_FUNC_TXT) first_channel = 1;
454        else                      first_channel = 0;
455
456        // do nothing for ROM, that does not require a device descriptor.
457        if( func == DEV_FUNC_ROM ) continue;
458
459        // check external device functionnal type
460        if( (func != DEV_FUNC_IOB) &&
461            (func != DEV_FUNC_PIC) &&
462            (func != DEV_FUNC_IOC) &&
463            (func != DEV_FUNC_TXT) &&
464            (func != DEV_FUNC_NIC) &&
465            (func != DEV_FUNC_FBF) ) 
[1]466        {
[5]467            assert( false , __FUNCTION__ , "undefined external peripheral type" );
468        }
469
470        // loops on channels
471        for( channel = first_channel ; channel < channels_nr ; channel++ )
472        { 
473            // loop on directions
474            for( direction = 0 ; direction < directions_nr ; direction++ )
[1]475            {
[5]476                // get target cluster for chdev[func,channel,direction]
477                uint32_t offset     = chdev_gid % ( info->x_size * info->y_size );
478                uint32_t cx         = offset / info->y_size;
479                uint32_t cy         = offset % info->y_size;
480                uint32_t target_cxy = (cx<<info->y_width) + cy;
[1]481
[5]482                // allocate and initialize a local chdev
483                // if local cluster matches target cluster
484                if( target_cxy == local_cxy )
[1]485                {
[5]486                    chdev = chdev_create( func,
487                                          impl,
488                                          channel,
489                                          direction,
490                                          base );
491
492                    assert( (chdev != NULL), __FUNCTION__ , 
493                            "cannot allocate external device" );
494
495                    // get extended pointer on chdev
496                    chdev_xp = XPTR( local_cxy , chdev );
497
498                    // make device type specific initialisation
499                    // the number of parameters depends on the device type
500                    // TODO : remove the parameters that  must be provided by the drivers
501                    if     ( func == DEV_FUNC_IOB ) dev_iob_init( chdev );
502                    else if( func == DEV_FUNC_IOC ) dev_ioc_init( chdev );
503                    else if( func == DEV_FUNC_TXT ) dev_txt_init( chdev );
504                    else if( func == DEV_FUNC_NIC ) dev_nic_init( chdev );
505                    else if( func == DEV_FUNC_PIC ) dev_pic_init( chdev , p0 );
506                    else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev , p0 , p1 );
507                    else
508                    {
509                        assert( false , __FUNCTION__ , "undefined device type" );
510                    }
511
512                    // all external (shared) devices are remotely accessible
513                    // initialize the replicated chdev_dir[x][y] structures
514                    // defining the extended pointers on chdev descriptors
515                    xptr_t * entry;   
516               
517                    if( func == DEV_FUNC_IOB ) entry  = &chdev_dir.iob;
518                    if( func == DEV_FUNC_PIC ) entry  = &chdev_dir.pic;
519                    if( func == DEV_FUNC_TXT ) entry  = &chdev_dir.txt[channel];
520                    if( func == DEV_FUNC_IOC ) entry  = &chdev_dir.ioc[channel];
521                    if( func == DEV_FUNC_FBF ) entry  = &chdev_dir.fbf[channel];
522                    if( func == DEV_FUNC_NIC ) entry  = &chdev_dir.nic_tx[channel];
523 
[1]524                    for( x = 0 ; x < info->x_size ; x++ )
525                    {
526                        for( y = 0 ; y < info->y_size ; y++ )
527                        {
528                            cxy_t  cxy = (x<<info->y_width) + y;
[5]529                            hal_remote_swd( XPTR( cxy , entry ) , chdev_xp );
530                        }
[1]531                    }
532
[14]533                            kinit_dmsg("\n[INFO] %s : core[%x][0] create chdev %s[%d] at cycle %d\n",
[5]534                               __FUNCTION__ , local_cxy , chdev_func_str( func ),
[14]535                               channel , hal_time_stamp() );
[5]536
537                }  // end if match
538
[19]539                // increment chdev global index (matching or not)
[5]540                chdev_gid++;
541
542            } // end loop on directions
543
544        }  // end loop on channels
545
546        // initialize the entries of the local chdev_pic_input structure
547        // defining how external peripherals are connected to PIC
548        if( func == DEV_FUNC_PIC ) 
[1]549        {
[5]550            uint32_t   id;
551            uint8_t    valid;
552            uint32_t   dev_type;
553            uint8_t    channel;
554            uint8_t    is_rx;
555
556            // loop on PIC inputs
557            for( id = 0 ; id < CONFIG_MAX_IRQS_PER_PIC ; id++ )
[1]558            {
[5]559                valid     = dev_tbl[i].irq[id].valid;
560                dev_type  = dev_tbl[i].irq[id].dev_type;
561                channel   = dev_tbl[i].irq[id].channel;
562                is_rx     = dev_tbl[i].irq[id].is_rx;
[1]563
[5]564                if( valid )  // only valid inputs are registered
[1]565                {
[5]566                    uint32_t * index;  // local pointer on one entry
[1]567                    uint16_t dev_func = FUNC_FROM_TYPE( dev_type );
[5]568
569                    if( dev_func == DEV_FUNC_TXT )
[1]570                    {
[5]571                        index = &chdev_pic_input.txt[channel];
[1]572                    }
[5]573                    else if( dev_func == DEV_FUNC_IOC )
574                    {
575                        index = &chdev_pic_input.ioc[channel]; 
576                    }
577                    else if( (dev_func == DEV_FUNC_NIC) && (is_rx == 0) )
578                    {
579                        index = &chdev_pic_input.nic_tx[channel]; 
580                    }
581                    else if( (dev_func == DEV_FUNC_NIC) && (is_rx != 0) )
582                    {
583                        index = &chdev_pic_input.nic_rx[channel]; 
584                    }
585                    else
586                    {
587                        assert( false , __FUNCTION__ , "illegal source device for PIC input" );
588                    }                   
589
590                    // set entry in local structure
591                    *index = id; 
[1]592                }
[5]593            } // end loop on PIC inputs
594        } // end PIC
595        } // end loop on devices
596}  // end external_devices_init()
[1]597
598
599///////////////////////////////////////////////////////////////////////////////////////////
[14]600// This static function returns the identifiers of the calling core.
601///////////////////////////////////////////////////////////////////////////////////////////
602// @ info    : pointer on boot_info structure.
603// @ lid     : [out] core local index in cluster.
604// @ cxy     : [out] cluster identifier.
605// @ lid     : [out] core global identifier (hardware).
606// @ return 0 if success / return EINVAL if not found.
607///////////////////////////////////////////////////////////////////////////////////////////
[23]608static error_t get_core_identifiers( boot_info_t * info,
609                                     lid_t       * lid,
[14]610                                     cxy_t       * cxy,
611                                     gid_t       * gid )
612{
613        uint32_t   i;
614    gid_t      global_id;
[19]615
[14]616    // get global identifier from hardware register
617    global_id = hal_get_gid(); 
618
619    // makes an associative search in boot_info to get (cxy,lid) from global_id
620    for( i = 0 ; i < info->cores_nr ; i++ )
621    {
622        if( global_id == info->core[i].gid )
623        {
624            *lid = info->core[i].lid;
625            *cxy = info->core[i].cxy;
626            *gid = global_id;
627            return 0;
628        }
629    }
630    return EINVAL;
[19]631}
[14]632
633///////////////////////////////////////////////////////////////////////////////////////////
[1]634// This function is the entry point for the kernel initialisation.
[19]635// It is executed by all cores in all clusters, but only core[0], called CP0,
[14]636// initializes the shared resources such as the cluster manager, or the local peripherals.
[19]637// To comply with the multi-kernels paradigm, it accesses only local cluster memory, using
638// only information contained in the local boot_info_t structure, set by the bootloader.
[1]639///////////////////////////////////////////////////////////////////////////////////////////
640// @ info    : pointer on the local boot-info structure.
641///////////////////////////////////////////////////////////////////////////////////////////
642void kernel_init( boot_info_t * info )
643{
[23]644    lid_t        core_lid = -1;      // running core local index
[14]645    cxy_t        core_cxy = -1;      // running core cluster identifier
646    gid_t        core_gid;           // running core hardware identifier
647    cluster_t  * cluster;            // pointer on local cluster manager
648    core_t     * core;               // pointer on running core descriptor
649    thread_t   * thread;             // pointer on idle thread descriptor
[1]650    error_t      error;
651
[14]652    // all cores get core identifiers
[23]653    error = get_core_identifiers( info,
[14]654                                  &core_lid,
655                                  &core_cxy,
656                                  &core_gid );
[1]657
[14]658    // CP0 initialise cluster identifier
659    if( core_lid == 0 ) local_cxy = info->cxy;
[1]660
[14]661    // CP0 in I/O cluster initialises TXT0 chdev descriptor
662    if( (core_lid == 0) && (core_cxy == info->io_cxy) ) txt0_device_init( info );
663
664    /////////////////////////////////////////////////////////////////////////////////
665    // global & local synchro to protect access to TXT0 terminal
666    if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 
667                                        (info->x_size * info->y_size) );
668    barrier_wait( &local_barrier , info->cores_nr );
669    /////////////////////////////////////////////////////////////////////////////////
670
[23]671    kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 0 at cycle %d\n",
672               __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() );
[14]673
674    // all cores check core identifiers
675    if( error )
[1]676    {
[14]677        printk("\n[PANIC] in %s : illegal core identifiers"
678               " gid = %x / cxy = %x / lid = %d\n",
679               __FUNCTION__ , core_lid , core_cxy , core_lid );
680        hal_core_sleep();
[1]681    }
682
[19]683    // CP0 initializes the local cluster manager (cores and memory allocators)
[14]684    if( core_lid == 0 )
[1]685    {
686        error = cluster_init( info );
687
[14]688        if( error )
689        {
690            printk("\n[PANIC] in %s : cannot initialise cluster manager in cluster %x",
691                   __FUNCTION__ , local_cxy );
692            hal_core_sleep();
693        }
694    }
[5]695
[14]696    /////////////////////////////////////////////////////////////////////////////////
697    // global & local synchro, to protect access to cluster manager
698    if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 
699                                        (info->x_size * info->y_size) );
700    barrier_wait( &local_barrier , info->cores_nr );
701    /////////////////////////////////////////////////////////////////////////////////
[1]702
[23]703    kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 1 at cycle %d\n",
704               __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() );
[1]705
[14]706    // all cores get pointer on local cluster manager and on core descriptor
707    cluster = &cluster_manager;
708        core    = &cluster->core_tbl[core_lid];
[1]709
[19]710    // CP0 initializes the process_zero descriptor
[14]711    if( core_lid == 0 ) process_zero_init( info );
[5]712
[19]713    // CP0 allocates and initialises the internal peripheral chdev descriptors.
[14]714    // Each CP0[cxy] scan the set of its internal (private) peripherals,
715    // and allocate memory for the corresponding chdev descriptors.
716    if( core_lid == 0 ) internal_devices_init( info );
[5]717       
[14]718    // CP0 allocates one WTI mailbbox per core for Inter Processor Interrupt
719    // this must be done after ICU chdev initialisation, by CP0 only, and before
[50]720    // external devices initialisation to enforce the rule :
721    // "The WTI index for the IPI routed to core[lid] is lid"
[14]722    if( core_lid == 0 )
[1]723    {
[14]724        uint32_t  wti_id;
725        uint32_t  lid;
726        for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ )
[1]727        {
[14]728            wti_id = dev_icu_wti_alloc();
[1]729
[14]730            if( wti_id != lid )
731            {
732                printk("\n[PANIC] in %s : WTI index for IPI = %d / core_lid = %d",
733                       __FUNCTION__ , wti_id , lid );
734                hal_core_sleep();
735            }
[5]736
[14]737            dev_icu_enable_irq( lid , WTI_TYPE , wti_id , NULL );
738        }
[1]739    }
740
[50]741    // All CP0s contribute to initialise external peripheral chdev descriptors.
[14]742    // Each CP0[cxy] scan the set of external (shared) peripherals (but the TXT0),
743    // and allocates memory for the chdev descriptors that must be placed
744    // on the (cxy) cluster according to the global index value. 
745    if( core_lid == 0 ) external_devices_init( info );
[1]746
[14]747    /////////////////////////////////////////////////////////////////////////////////
748    // global &local synchro to protect access to peripherals
749    if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ), 
750                                        (info->x_size * info->y_size) );
751    barrier_wait( &local_barrier , info->cores_nr );
752    /////////////////////////////////////////////////////////////////////////////////
[5]753
[23]754    kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 2 at cycle %d\n", 
755               __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() );
[1]756
[14]757    // all cores initialize the private idle thread descriptor
758        thread = (thread_t *)( idle_threads + (core_lid * CONFIG_THREAD_DESC_SIZE) );
[1]759
[14]760    error = thread_kernel_init( thread,
761                                THREAD_IDLE, 
762                                &thread_idle_func, 
763                                NULL,
764                                core_lid );
[1]765
[14]766    if( error )
[1]767    {
[14]768        printk("\n[PANIC] in %s : core[%x][%d] cannot initialize idle thread\n",
769               __FUNCTION__ , local_cxy , core_lid );
770        hal_core_sleep();
[1]771    }
[14]772    else
773    {
774        // register idle thread in scheduler
775        core->scheduler.idle = thread;
[1]776
[14]777        // register idle thread pointer in core register
778        hal_set_current_thread( thread );
779   
780        // activate the idle thread
781        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
[1]782
[14]783        kinit_dmsg("\n[INFO] %s : core[%x][%d] created idle thread %x at cycle %d\n",
784                   __FUNCTION__ , core_cxy , core_lid , thread , hal_time_stamp());
785    }
786
[23]787    // CP0 in all clusters initializes cooperatively VFS and DEVFS
788    if( (core_lid == 0)  )
[14]789    {
[23]790        xptr_t  root_inode_xp;
791
[50]792        // initialize root File System (must be FATFS in this implementation)
[23]793        if( CONFIG_VFS_ROOT_IS_FATFS )
794        {
795            root_inode_xp = fatfs_init();
796        }
797        else
798        {
799            printk("\n[PANIC] in %s : root FS must be FATFS\n", __FUNCTION__ );
800            hal_core_sleep();
801        }
802
803        if( root_inode_xp == XPTR_NULL )
804        {
805            printk("\n[PANIC] in %s : core[%x][%d] cannot initialize file system\n",
806                   __FUNCTION__ , local_cxy , core_lid );
807            hal_core_sleep();
808        }
809
810        // mount the DEVFS File system
811            devfs_mount( root_inode_xp , "dev" );
[14]812    }
813
814    // CP0 in I/O cluster print banner
[5]815    if( (core_lid ==  0) && (local_cxy == info->io_cxy) ) 
[1]816    {
[5]817        print_banner( (info->x_size * info->y_size) , info->cores_nr );
[1]818    }
819
[14]820    /////////////////////////////////////////////////////////////////////////////////
821    // global syncho to protect access to File System
822    if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
823                                        (info->x_size * info->y_size) );
824    barrier_wait( &local_barrier , info->cores_nr );
825    /////////////////////////////////////////////////////////////////////////////////
[1]826
[23]827    kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 3 at cycle %d\n", 
828               __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() );
[14]829
830    // each core activates its private PTI IRQ
831    dev_icu_set_period( core_lid , CONFIG_SCHED_TICK_PERIOD );
832    dev_icu_enable_irq( core_lid , PTI_TYPE , core_lid , NULL );
833
834    // each core get its private IRQ masks values and
835    uint32_t hwi_mask;
836    uint32_t wti_mask;
837    uint32_t pti_mask;
838    dev_icu_get_masks( core_lid , &hwi_mask , &wti_mask , &pti_mask );
839
840    thread_dmsg("\n[INFO] %s : core[%x][%d] activates scheduler at cycle %d\n"
841                "   hwi_mask = %x / wti_mask = %x / pti_mask = %x\n",
842                    __FUNCTION__ , local_cxy , core_lid , hal_time_stamp() ,
843                    hwi_mask , wti_mask , pti_mask );
844
845    // each core jump to idle thread
[50]846    thread_idle_func();
[14]847
[1]848} // end kernel_init()
849
Note: See TracBrowser for help on using the repository browser.