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

Last change on this file since 19 was 19, checked in by max@…, 7 years ago

cosmetic, and a few typos

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