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

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

Introduce the chdev_t structure in place of the device_t structure.

File size: 30.6 KB
RevLine 
[1]1/*
2 * kernel_init.c - kernel parallel initialization
3 *
4 * Authors :  Alain Greiner  (2016)
5 *
6 * Copyright (c) Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <almos_config.h>
25#include <errno.h>
26#include <hal_types.h>
27#include <hal_special.h>
28#include <hal_context.h>
29#include <remote_barrier.h>
30#include <core.h>
31#include <list.h>
32#include <thread.h>
33#include <scheduler.h>
34#include <kmem.h>
35#include <cluster.h>
36#include <devfs.h>
37#include <sysfs.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
56
[5]57#define KERNEL_INIT_SYNCHRO  0xA5A5B5B5
[1]58
59///////////////////////////////////////////////////////////////////////////////////////////
60// All these global variables are replicated in all clusters.
61// They are initialised by the kernel_init() function.
62///////////////////////////////////////////////////////////////////////////////////////////
63
[5]64// This variable defines the local boot_info structure
65__attribute__((section(".kinfo")))
66boot_info_t          boot_info          CACHELINE_ALIGNED;
67
[1]68// This variable defines the local cluster manager
[5]69__attribute__((section(".kdata")))
[1]70cluster_t            cluster_manager    CACHELINE_ALIGNED; 
71
[5]72// These variables define the kernel process0 descriptor and associated thread
73__attribute__((section(".kdata")))
[1]74process_t            process_zero       CACHELINE_ALIGNED;           
75thread_t             thread_zero        CACHELINE_ALIGNED;
76
77// This variable contains the extended pointers on the device descriptors
[5]78__attribute__((section(".kdata")))
79chdev_directory_t    chdev_dir          CACHELINE_ALIGNED;
[1]80
[5]81// This variable contains the input IRQ indexes for the PIC device
82__attribute__((section(".kdata")))
83chdev_pic_input_t    chdev_pic_input    CACHELINE_ALIGNED;
[1]84
[5]85// This variable contains the input IRQ indexes for the ICU device
86__attribute__((section(".kdata")))
87chdev_icu_input_t    chdev_icu_input    CACHELINE_ALIGNED;
[1]88
[5]89// This variable synchronizes the local cores during kernel_init()
90__attribute__((section(".kdata")))
91volatile uint32_t    local_sync_init    CACHELINE_ALIGNED; 
92
[1]93// This variable defines the local cluster identifier
[5]94__attribute__((section(".kdata")))
95cxy_t                local_cxy          CACHELINE_ALIGNED;
[1]96
[5]97// This variable is the lock protecting the kernel TXT terminal (used by printk)
98__attribute__((section(".kdata")))
99remote_spinlock_t    txt0_lock          CACHELINE_ALIGNED;
[1]100
101///////////////////////////////////////////////////////////////////////////////////////////
[5]102// This function displays the ALMOS_MKH banner.
[1]103///////////////////////////////////////////////////////////////////////////////////////////
[5]104static void print_banner( uint32_t nclusters , uint32_t ncores )
[1]105{ 
[5]106    printk("\n"
107           "                    _        __    __     _____     ______         __    __    _   __   _     _   \n"
108           "          /\\       | |      |  \\  /  |   / ___ \\   / _____|       |  \\  /  |  | | / /  | |   | |  \n"
109           "         /  \\      | |      |   \\/   |  | /   \\ | | /             |   \\/   |  | |/ /   | |   | |  \n"
110           "        / /\\ \\     | |      | |\\  /| |  | |   | | | |_____   ___  | |\\  /| |  |   /    | |___| |  \n"
111           "       / /__\\ \\    | |      | | \\/ | |  | |   | | \\_____  \\ |___| | | \\/ | |  |   \\    |  ___  |  \n"
112           "      / ______ \\   | |      | |    | |  | |   | |       | |       | |    | |  | |\\ \\   | |   | |  \n"
113           "     / /      \\ \\  | |____  | |    | |  | \\___/ |  _____/ |       | |    | |  | | \\ \\  | |   | |  \n"
114           "    /_/        \\_\\ |______| |_|    |_|   \\_____/  |______/        |_|    |_|  |_|  \\_\\ |_|   |_|  \n"
115           "\n\n\t\t Advanced Locality Management Operating System / Multi Kernel Hybrid\n"
116           "\n\n\t\t\t Version 0.0   :   %d clusters   /   %d cores per cluster\n\n", nclusters , ncores ); 
117}
[1]118
119
[5]120///////////////////////////////////////////////////////////////////////////////////////////
121// This static function allocates memory and initializes the TXT0 chdev descriptor,
122// associated to the kernel terminal, shared by all kernel instances for debug messages.
123// It should be called by a thread running in the I/O cluster, because the TXT0 chdev
124// is created in the I/O cluster.
125///////////////////////////////////////////////////////////////////////////////////////////
126// @ info    : pointer on the local boot-info structure.
127///////////////////////////////////////////////////////////////////////////////////////////
128static void txt0_device_init( boot_info_t * info )
129{
130    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
131        uint32_t        dev_nr;          // actual number of devices in this cluster
132        xptr_t          base;            // remote pointer on segment base
133        uint32_t        size;            // channel size (bytes)
134    uint32_t        type;            // peripheral type
135    uint32_t        func;            // device functionnal index
136    uint32_t        impl;            // device implementation index
137        uint32_t        i;               // device index in dev_tbl
138        uint32_t        x;               // X cluster coordinate
139        uint32_t        y;               // Y cluster coordinate
140        chdev_t       * chdev;           // local pointer on created chdev
[1]141
[5]142    // get number of peripherals and base of devices array from boot_info
143        dev_nr      = info->ext_dev_nr;
144    dev_tbl     = info->ext_dev;
[1]145
[5]146    // loop on external peripherals to find TXT
147        for( i = 0 ; i < dev_nr ; i++ )
148        {
149        size        = dev_tbl[i].size;
150        base        = dev_tbl[i].base;
151        type        = dev_tbl[i].type;
152        func        = FUNC_FROM_TYPE( type );
153        impl        = IMPL_FROM_TYPE( type );
154
155        if (func == DEV_FUNC_TXT ) 
156        {
157            // allocate and initialize a local chdev for TXT0
158            chdev = chdev_create( func,
159                                  impl,
160                                  0,        // channel
161                                  0,        // direction
162                                  base );
163
164            // Complete TXT specific initialisation
165            if( impl == IMPL_TXT_TTY )
166            {
167                chdev->cmd = &soclib_tty_cmd;
168                chdev->isr = &soclib_tty_isr;
169                soclib_tty_init( chdev );
170            }
171
172            // initialize the replicated chdev_dir[x][y] structures
173            for( x = 0 ; x < info->x_size ; x++ )
174            {
175                for( y = 0 ; y < info->y_size ; y++ )
176                {
177                    cxy_t  cxy = (x<<info->y_width) + y;
178                    hal_remote_swd( XPTR( cxy , &chdev_dir.txt[0] ) , XPTR( local_cxy , chdev ) );
179                }
180            }
181
182                    kinit_dmsg("\n[INFO] %s : core[%x][0] created TXT0 chdev / paddr = %l at cycle %d\n",
183                       __FUNCTION__ , local_cxy , chdev_func_str( func ), chdev_xp , hal_time_stamp() );
184        }
185
186        } // end loop on devices
187
188}  // end txt0_device_init()
189
[1]190///////////////////////////////////////////////////////////////////////////////////////////
[5]191// This static function allocates memory for the chdev (channel_device) descriptors
192// associated to the internal peripherals contained in the local cluster. These internal
193// devices (ICU, MMC, DMA) chdev descriptors are placed in the local cluster.
[1]194// It initialises these device descriptors as specified by the boot_info_t structure,
195// including the dynamic linking with the driver for the specified implementation.
196// Finally, all copies of the devices directory are initialised.
197///////////////////////////////////////////////////////////////////////////////////////////
198// @ info    : pointer on the local boot-info structure.
199///////////////////////////////////////////////////////////////////////////////////////////
[5]200static void internal_devices_init( boot_info_t * info )
[1]201{
202    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
203        uint32_t        dev_nr;          // actual number of devices in this cluster
204        xptr_t          base;            // remote pointer on segment base
205        uint32_t        size;            // channel size (bytes)
206    uint32_t        type;            // peripheral type
207    uint32_t        func;            // device functionnal index
208    uint32_t        impl;            // device implementation index
209        uint32_t        i;               // device index in dev_tbl
210        uint32_t        x;               // X cluster coordinate
211        uint32_t        y;               // Y cluster coordinate
[5]212        uint32_t        channels_nr;     // number of channels in device
213        uint32_t        channel;         // channel index
[1]214        uint32_t        p0;              // device parameter 0
215        uint32_t        p1;              // device parameter 1
216        uint32_t        p2;              // device parameter 2
217        uint32_t        p3;              // device parameter 3
218
[5]219        chdev_t       * chdev;           // local pointer on one channel_device descriptor
220    xptr_t          chdev_xp;        // extended pointer on channel_device descriptor
[1]221
[5]222    // get number of internal devices and base of devices array from boot_info
223        dev_nr      = info->int_dev_nr;
224    dev_tbl     = info->int_dev;
225
226    // loop on all internal devices in cluster
[1]227        for( i = 0 ; i < dev_nr ; i++ )
228        {
[5]229        size        = dev_tbl[i].size;
230        base        = dev_tbl[i].base;
231        type        = dev_tbl[i].type;
232        channels_nr = dev_tbl[i].channels;
233        p0          = dev_tbl[i].param0;
234        p1          = dev_tbl[i].param1;
235        p2          = dev_tbl[i].param2;
236        p3          = dev_tbl[i].param3;
[1]237
238        func     = FUNC_FROM_TYPE( type );
239        impl     = IMPL_FROM_TYPE( type );
240
[5]241        // do nothing for RAM, that does not require a chdev descriptor.
242        if( func == DEV_FUNC_RAM ) continue;
[1]243
[5]244        // check internal device functional type
245        if( (func != DEV_FUNC_MMC) &&
246            (func != DEV_FUNC_ICU) &&
247            (func != DEV_FUNC_DMA) ) 
248        {
249            assert( false , __FUNCTION__ , "illegal internal peripheral type" );
250        }
[1]251
[5]252        // loop on channels
253        for( channel = 0 ; channel < channels_nr ; channel++ )
254        {
255            // create one chdev in local cluster
256            chdev = chdev_create( func ,
257                                  impl,
258                                  channel,     
259                                  false,           // TX
260                                  base );
[1]261
[5]262            assert( (chdev != NULL) , __FUNCTION__ , "cannot allocate internal chdev" );
[1]263           
[5]264            // get extended pointer on channel descriptor
265            chdev_xp = XPTR( local_cxy , chdev );
[1]266
267            // TODO ??? AG
268                    // devfs_register( dev );
269
270            // make device type specific initialisation
271            // the number of parameters depends on the device type
[5]272            // TODO : remove these parameters that  must be provided by the driver
273            if     ( func == DEV_FUNC_ICU ) dev_icu_init( chdev , p0 , p1 , p2 );     
274            else if( func == DEV_FUNC_MMC ) dev_mmc_init( chdev );
275            else                            dev_dma_init( chdev );
[1]276
[5]277            // initialize the replicated chdev_dir[x][y] structures
278            // containing extended pointers on all devices descriptors
279            xptr_t * entry;   
[1]280
[5]281            if     ( func == DEV_FUNC_ICU ) entry  = &chdev_dir.icu[local_cxy];
282            else if( func == DEV_FUNC_MMC ) entry  = &chdev_dir.mmc[local_cxy];
283            else                            entry  = &chdev_dir.dma[channel];
[1]284 
[5]285            if( func != DEV_FUNC_DMA )  // ICU and MMC devices are remotely accessible
[1]286            {
[5]287                for( x = 0 ; x < info->x_size ; x++ )
[1]288                {
[5]289                    for( y = 0 ; y < info->y_size ; y++ )
[1]290                    {
[5]291                        cxy_t  cxy = (x<<info->y_width) + y;
292                        hal_remote_swd( XPTR( cxy , entry ) , chdev_xp );
[1]293                    }
294                }
295            }
[5]296            else                      // DMA devices are NOT remotely accessible
297            {
298                *entry = chdev_xp;
299            }
[1]300
[5]301            kinit_dmsg("\n[INFO] %s :core[%x][0] created chdev %s / channel %d"
302                       " / paddr = %l at cycle %d\n",
303                       __FUNCTION__ , local_cxy , chdev_func_str( func ) , 
304                       channel , chdev_xp , hal_time_stamp() );
305
[1]306        } // end loop on channels
307
[5]308        // initialize the entries of the local chdev_icu_input structure
309        // defining how internal peripherals are connected to ICU
310        if( func == DEV_FUNC_ICU ) 
311        {
312            uint32_t   id;
313            uint8_t    valid;
314            uint32_t   dev_type;
315            uint8_t    channel;
[1]316
[5]317            // loop on ICU inputs
318            for( id = 0 ; id < CONFIG_MAX_HWIS_PER_ICU ; id++ )
319            {
320                valid    = dev_tbl[i].irq[id].valid;
321                dev_type = dev_tbl[i].irq[id].dev_type;
322                channel  = dev_tbl[i].irq[id].channel;
323
324                if( valid ) // only valid local IRQs are registered
325                {
326                    uint32_t * index;   // local pointer on the entry to be set
327                    uint16_t   dev_func = FUNC_FROM_TYPE( dev_type );
328                    if( dev_func == DEV_FUNC_MMC ) 
329                        index = &chdev_icu_input.mmc;
330                    else if( dev_func == DEV_FUNC_DMA ) 
331                        index = &chdev_icu_input.dma[channel]; 
332                    else
333                    {
334                        assert( false , __FUNCTION__ , "illegal source device for ICU input" );
335                    }                   
336
337                    // set entry in local structure
338                    *index = id;
339                }
340
341            }  // end loop on ICU inputs
342        }  // end if ICU
343        } // end loop on peripherals
344}  // end internal_devices_init()
345
346///////////////////////////////////////////////////////////////////////////////////////////
347// This static function allocates memory for the chdev descriptors associated
348// to the external (shared) peripherals contained in the local cluster. These external
349// devices (IOB, IOC, TXT, NIC, etc ) are distributed on all clusters.
350// It initialises these device descriptors as specified by the boot_info_t structure,
351// including the dynamic linking with the driver for the specified implementation.
352// Finally, all copies of the devices directory are initialised.
353//
354// The number of channel_devices depends on the device functionnal type.
355// There is three nested loops to scan the full set of external channel_devices:
356// - loop on external devices.
357// - loop on channels for multi-channels devices.
358// - loop on directions (RX/TX) for NIC device.
359// The set of channel_devices is indexed by the chdev_gid global index, that is used
360// to select the cluster containing a given chdev[func,channel,direction].
361// All clusters scan the full set of chdevs, but only the cluster matching
362// (chdev_gid % (x_size*y_size)) create the corresponding chdev.
363//
364// TODO check that cluster IO contains a PIC [AG]
365///////////////////////////////////////////////////////////////////////////////////////////
366// @ info    : pointer on the local boot-info structure.
367///////////////////////////////////////////////////////////////////////////////////////////
368static void external_devices_init( boot_info_t * info )
369{
370    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
371        uint32_t        dev_nr;          // actual number of devices in this cluster
372        xptr_t          base;            // remote pointer on segment base
373        uint32_t        size;            // channel size (bytes)
374    uint32_t        type;            // peripheral type
375    uint32_t        func;            // device functionnal index
376    uint32_t        impl;            // device implementation index
377        uint32_t        i;               // device index in dev_tbl
378        uint32_t        x;               // X cluster coordinate
379        uint32_t        y;               // Y cluster coordinate
380        uint32_t        channels_nr;     // number of channels
381        uint32_t        channel;         // channel index
382        uint32_t        directions_nr;   // number of directions
383        uint32_t        direction;       // direction index
384        uint32_t        p0;              // device parameter 0
385        uint32_t        p1;              // device parameter 1
386        uint32_t        p2;              // device parameter 2
387        uint32_t        p3;              // device parameter 3
388    uint32_t        first_channel;   // used in loop on channels
389
390        chdev_t       * chdev;           // local pointer on one channel_device descriptor
391    xptr_t          chdev_xp;        // extended pointer on channel_device descriptor
392    uint32_t        chdev_gid = 0;   // global index of channel_device descriptor
393
394    // get number of peripherals and base of devices array from boot_info
395        dev_nr      = info->ext_dev_nr;
396    dev_tbl     = info->ext_dev;
397
398    // loop on external peripherals
399        for( i = 0 ; i < dev_nr ; i++ )
400        {
401        size        = dev_tbl[i].size;
402        base        = dev_tbl[i].base;
403        type        = dev_tbl[i].type;
404        channels_nr = dev_tbl[i].channels;
405        p0          = dev_tbl[i].param0;
406        p1          = dev_tbl[i].param1;
407        p2          = dev_tbl[i].param2;
408        p3          = dev_tbl[i].param3;
409
410        func     = FUNC_FROM_TYPE( type );
411        impl     = IMPL_FROM_TYPE( type );
412
413        // There is one chdev per direction for NIC
414        if (func == DEV_FUNC_NIC) directions_nr = 2;
415        else                      directions_nr = 1;
416
417        // The TXT0 chdev has already been created
418        if (func == DEV_FUNC_TXT) first_channel = 1;
419        else                      first_channel = 0;
420
421        // do nothing for ROM, that does not require a device descriptor.
422        if( func == DEV_FUNC_ROM ) continue;
423
424        // check external device functionnal type
425        if( (func != DEV_FUNC_IOB) &&
426            (func != DEV_FUNC_PIC) &&
427            (func != DEV_FUNC_IOC) &&
428            (func != DEV_FUNC_TXT) &&
429            (func != DEV_FUNC_NIC) &&
430            (func != DEV_FUNC_FBF) ) 
[1]431        {
[5]432            assert( false , __FUNCTION__ , "undefined external peripheral type" );
433        }
434
435        // loops on channels
436        for( channel = first_channel ; channel < channels_nr ; channel++ )
437        { 
438            // loop on directions
439            for( direction = 0 ; direction < directions_nr ; direction++ )
[1]440            {
[5]441                // get target cluster for chdev[func,channel,direction]
442                uint32_t offset     = chdev_gid % ( info->x_size * info->y_size );
443                uint32_t cx         = offset / info->y_size;
444                uint32_t cy         = offset % info->y_size;
445                uint32_t target_cxy = (cx<<info->y_width) + cy;
[1]446
[5]447                // allocate and initialize a local chdev
448                // if local cluster matches target cluster
449                if( target_cxy == local_cxy )
[1]450                {
[5]451                    chdev = chdev_create( func,
452                                          impl,
453                                          channel,
454                                          direction,
455                                          base );
456
457                    assert( (chdev != NULL), __FUNCTION__ , 
458                            "cannot allocate external device" );
459
460                    // get extended pointer on chdev
461                    chdev_xp = XPTR( local_cxy , chdev );
462
463                    // make device type specific initialisation
464                    // the number of parameters depends on the device type
465                    // TODO : remove the parameters that  must be provided by the drivers
466                    if     ( func == DEV_FUNC_IOB ) dev_iob_init( chdev );
467                    else if( func == DEV_FUNC_IOC ) dev_ioc_init( chdev );
468                    else if( func == DEV_FUNC_TXT ) dev_txt_init( chdev );
469                    else if( func == DEV_FUNC_NIC ) dev_nic_init( chdev );
470                    else if( func == DEV_FUNC_PIC ) dev_pic_init( chdev , p0 );
471                    else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev , p0 , p1 );
472                    else
473                    {
474                        assert( false , __FUNCTION__ , "undefined device type" );
475                    }
476
477                    // all external (shared) devices are remotely accessible
478                    // initialize the replicated chdev_dir[x][y] structures
479                    // defining the extended pointers on chdev descriptors
480                    xptr_t * entry;   
481               
482                    if( func == DEV_FUNC_IOB ) entry  = &chdev_dir.iob;
483                    if( func == DEV_FUNC_PIC ) entry  = &chdev_dir.pic;
484                    if( func == DEV_FUNC_TXT ) entry  = &chdev_dir.txt[channel];
485                    if( func == DEV_FUNC_IOC ) entry  = &chdev_dir.ioc[channel];
486                    if( func == DEV_FUNC_FBF ) entry  = &chdev_dir.fbf[channel];
487                    if( func == DEV_FUNC_NIC ) entry  = &chdev_dir.nic_tx[channel];
488 
[1]489                    for( x = 0 ; x < info->x_size ; x++ )
490                    {
491                        for( y = 0 ; y < info->y_size ; y++ )
492                        {
493                            cxy_t  cxy = (x<<info->y_width) + y;
[5]494                            hal_remote_swd( XPTR( cxy , entry ) , chdev_xp );
495                        }
[1]496                    }
497
[5]498                            kinit_dmsg("\n[INFO] %s : core[%x][0] created chdev %s / channel = %d"
499                               " / paddr = %l at cycle %d\n",
500                               __FUNCTION__ , local_cxy , chdev_func_str( func ),
501                               channel , chdev_xp , hal_time_stamp() );
502
503                }  // end if match
504
505                // increment chdev global index (matching or not)           
506                chdev_gid++;
507
508            } // end loop on directions
509
510        }  // end loop on channels
511
512        // initialize the entries of the local chdev_pic_input structure
513        // defining how external peripherals are connected to PIC
514        if( func == DEV_FUNC_PIC ) 
[1]515        {
[5]516            uint32_t   id;
517            uint8_t    valid;
518            uint32_t   dev_type;
519            uint8_t    channel;
520            uint8_t    is_rx;
521
522            // loop on PIC inputs
523            for( id = 0 ; id < CONFIG_MAX_IRQS_PER_PIC ; id++ )
[1]524            {
[5]525                valid     = dev_tbl[i].irq[id].valid;
526                dev_type  = dev_tbl[i].irq[id].dev_type;
527                channel   = dev_tbl[i].irq[id].channel;
528                is_rx     = dev_tbl[i].irq[id].is_rx;
[1]529
[5]530                if( valid )  // only valid inputs are registered
[1]531                {
[5]532                    uint32_t * index;  // local pointer on one entry
[1]533                    uint16_t dev_func = FUNC_FROM_TYPE( dev_type );
[5]534
535                    if( dev_func == DEV_FUNC_TXT )
[1]536                    {
[5]537                        index = &chdev_pic_input.txt[channel];
[1]538                    }
[5]539                    else if( dev_func == DEV_FUNC_IOC )
540                    {
541                        index = &chdev_pic_input.ioc[channel]; 
542                    }
543                    else if( (dev_func == DEV_FUNC_NIC) && (is_rx == 0) )
544                    {
545                        index = &chdev_pic_input.nic_tx[channel]; 
546                    }
547                    else if( (dev_func == DEV_FUNC_NIC) && (is_rx != 0) )
548                    {
549                        index = &chdev_pic_input.nic_rx[channel]; 
550                    }
551                    else
552                    {
553                        assert( false , __FUNCTION__ , "illegal source device for PIC input" );
554                    }                   
555
556                    // set entry in local structure
557                    *index = id; 
[1]558                }
[5]559            } // end loop on PIC inputs
560        } // end PIC
561        } // end loop on devices
562}  // end external_devices_init()
[1]563
564
565///////////////////////////////////////////////////////////////////////////////////////////
566// This function is the entry point for the kernel initialisation.
567// It is executed by all cores in all clusters, but only core[0] in each cluster
[5]568// initialize the cluster manager, ant the local peripherals.
569// To comply with the multi-kernels paradigm, it access only local cluster memory, using
570// only informations contained in the local boot_info_t structure, set by the bootloader.
[1]571///////////////////////////////////////////////////////////////////////////////////////////
572// @ info    : pointer on the local boot-info structure.
573///////////////////////////////////////////////////////////////////////////////////////////
574void kernel_init( boot_info_t * info )
575{
576    uint32_t     core_lid;      // running core local index
577    cxy_t        core_cxy;      // running core cluster identifier
578    gid_t        core_gid;      // running core hardware identifier
579    cluster_t  * cluster;       // pointer on local cluster manager
580    core_t     * core;          // pointer on running core descriptor
581    thread_t   * thread_idle;   // pointer on thread_idle 
582
583        uint32_t     i;
584    bool_t       found;
585    error_t      error;
586
587    // initialise global cluster identifier
588    local_cxy = info->cxy;
589
590    // each core get its global index from hardware register
591    core_gid = hal_get_gid(); 
592
593    // Each core makes an associative search in boot_info
[5]594    // to get its (cxy,lid) composite index from its gid
[1]595    found    = false;
596    core_cxy = 0;
597    core_lid = 0;
598    for( i = 0 ; i < info->cores_nr ; i++ )
599    {
600        if( core_gid == info->core[i].gid )
601        {
602            core_lid = info->core[i].lid;
603            core_cxy = info->core[i].cxy;
604            found = true;
605            break;
606        }
607    }
608         
[5]609    // suicide if not found
610    if( (found == false) || (core_cxy != local_cxy) ) hal_core_sleep();
[1]611
[5]612    //////////////////////////////////////////////////////////////
613    // In first step, only CP0 initialises local resources
614    //////////////////////////////////////////////////////////////
[1]615
616    if( core_lid == 0 )   
617    {
618        // initialize local cluster manager (cores and memory allocators)
619        error = cluster_init( info );
[5]620 
621        // suicide if failure
622        if( error ) hal_core_sleep();
[1]623
[5]624        // get pointer on local cluster manager and on core descriptor
625        cluster = LOCAL_CLUSTER;
626            core    = &cluster->core_tbl[core_lid];
627
[1]628        // initialize process_zero descriptor
629                process_zero_init( info );
630
[5]631        // CP0 initialize its private thread_zero descriptor
[1]632            memset( &thread_zero , 0 , sizeof(thread_t) );
633            thread_zero.type     = THREAD_KERNEL;
634            thread_zero.process  = &process_zero;
635            hal_set_current_thread( &thread_zero );
636
[5]637        // CP0 in I/O cluster initialize the kernel TXT0 chdev descriptor.
638        // this TXTO device is shared by the all kernel instances for debug messages:
639        // the printk() function call the dev_txt_sync_write() function that call
640        // directly the relevant TXT driver, without desheduling.
641        if( core_cxy == info->io_cxy ) txt0_device_init( info );
[1]642
[5]643        // synchronise all CP0s before using TXT0
644        remote_barrier( XPTR( info->io_cxy , &cluster->barrier ) , 
645                        (cluster->x_size * cluster->y_size) );
646
647        // All CP0 initialise internal peripheral chdev descriptors.
648        // Each CP0[cxy] scan the set of its internal (private) peripherals,
649        // and allocate memory for the corresponding chdev descriptors.
650        internal_devices_init( info );
651       
652        // All CP0 contribute to initialise external peripheral chdev descriptors.
653        // Each CP0[cxy] scan the set of external (shared) peripherals (but the TXT0),
654        // and allocates memory for the chdev descriptors that must be placed
655        // on the (cxy) cluster according to its global index. 
656        external_devices_init( info );
657
[1]658        // TODO initialize devFS and sysFS
659                // devfs_root_init();
660                // sysfs_root_init();
661
662        // TODO ??? [AG]
663                // clusters_sysfs_register();
664
[5]665        // TODO initialize virtual file system
[1]666        // vfs_init();
667
668        // TODO ??? [AG]
669                // sysconf_init();
670
671        // activate other cores in same cluster
[5]672                local_sync_init = KERNEL_INIT_SYNCHRO;
[1]673                hal_wbflush();
674    }
675    else   // other cores                                 
676    {
677        // other cores wait synchro from core[0]
[5]678                while( local_sync_init != KERNEL_INIT_SYNCHRO )
[1]679        {
680                   uint32_t retval = hal_time_stamp() + 1000;
681                   while( hal_time_stamp() < retval )  asm volatile ("nop");
682        }
683
[5]684        // get pointer on local cluster manager and on core descriptor
685        cluster = LOCAL_CLUSTER;
686            core    = &cluster->core_tbl[core_lid];
687
688        // core initialise its private thread_zero descriptor
[1]689            memset( &thread_zero , 0 , sizeof(thread_t) );
690            thread_zero.type     = THREAD_KERNEL;
691            thread_zero.process  = &process_zero;
692            hal_set_current_thread( &thread_zero );
693    }
694
695        // each core creates its private idle thread descriptor
696        error = thread_kernel_create( &thread_idle,
697                                  THREAD_IDLE, 
698                                  &thread_idle_func, 
699                                  NULL,
700                                  core_lid );
701
[5]702    assert( (error == 0) , __FUNCTION__ , "cannot create idle thread" );
703
[1]704    // each core register thread_idle in scheduler
705    core->scheduler.idle = thread_idle;
706
707    // each core register thread pointer in core hardware register
708    hal_set_current_thread( thread_idle );
709
[5]710    kinit_dmsg("\n[INFO] %s : thread idle created for core[%x][%d] at cycle %d\n",
711               __FUNCTION__ , core_cxy , core_lid , hal_time_stamp());
[1]712
713    // global syncho for all core[0] in all clusters
714    if( core_lid == 0 )
715    {
716        remote_barrier( XPTR( info->io_cxy , &cluster->barrier ) , 
717                        (cluster->x_size * cluster->y_size) );
718    }
719
720    // local synchro for all cores in local cluster
721    remote_barrier( XPTR( local_cxy , &cluster->barrier ) , 
722                    cluster->cores_nr );
723
[5]724    if( (core_lid ==  0) && (local_cxy == info->io_cxy) ) 
[1]725    {
[5]726        print_banner( (info->x_size * info->y_size) , info->cores_nr );
[1]727    }
728
[5]729    // load idle thread context on calling core
[1]730        hal_cpu_context_load( thread_idle );
731
732} // end kernel_init()
733
734
735
Note: See TracBrowser for help on using the repository browser.