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

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

First import

File size: 19.8 KB
Line 
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>
42#include <device.h>
43#include <boot_info.h>
44#include <dqdt.h>
45#include <dev_icu.h>
46#include <dev_mmc.h>
47#include <dev_mwr.h>
48#include <dev_iox.h>
49#include <dev_ioc.h>
50#include <dev_pic.h>
51#include <printk.h>
52#include <vfs.h>
53
54
55#define KERNEL_INIT_SYNCRO  0xA5A5B5B5
56
57///////////////////////////////////////////////////////////////////////////////////////////
58// All these global variables are replicated in all clusters.
59// They are initialised by the kernel_init() function.
60///////////////////////////////////////////////////////////////////////////////////////////
61
62// This variable defines the local cluster manager
63cluster_t            cluster_manager    CACHELINE_ALIGNED; 
64
65// This variable defines the kernel process descriptor and associated thread
66process_t            process_zero       CACHELINE_ALIGNED;           
67thread_t             thread_zero        CACHELINE_ALIGNED;
68
69// This variable contains the extended pointers on the device descriptors
70devices_directory_t  devices_dir        CACHELINE_ALIGNED;
71
72// This variable contains the input IRQ indexes for the PIC and ICU devices
73devices_input_irq_t  devices_input_irq   CACHELINE_ALIGNED;
74
75// This variable synchronizes the cores during kernel_init()
76volatile uint32_t    local_sync_init = 0; 
77
78// This variable defines the local cluster identifier
79cxy_t                local_cxy;
80
81
82///////////////////////////////////////////////////////////////////////////////////////////
83// This function displays the ALMOS_MKH.banner.
84///////////////////////////////////////////////////////////////////////////////////////////
85static void print_boot_banner()
86{ 
87        printk("\n           ____        ___        ___       ___    _______    ________         ___       ___   ___     ___   \n");
88        printk("          /    \\      |   |      |   \\     /   |  /  ___  \\  /  ____  |       |   \\     /   | |   |   /  / \n");
89        printk("         /  __  \\      | |        |   \\___/   |  |  /   \\  | | /    |_/        |   \\___/   |   | |   /  /  \n");
90        printk("        /  /  \\  \\     | |        |  _     _  |  | |     | | | |______   ___   |  _     _  |   | |__/  /     \n");
91        printk("       /  /____\\  \\    | |        | | \\   / | |  | |     | | \\______  \\ |___|  | | \\   / | |   |  __  <  \n");
92        printk("      /   ______   \\   | |     _  | |  \\_/  | |  | |     | |  _     | |        | |  \\_/  | |   | |  \\  \\  \n");
93        printk("     /   /      \\   \\  | |____/ | | |       | |  |  \\___/  | | \\____/ |        | |       | |   | |   \\  \\\n");
94        printk("    /_____/    \\_____\\|_________/|___|     |___|  \\_______/  |________/       |___|     |___| |___|   \\__\\\n");
95
96
97        printk("\n\n\t\t\t\t Multi-Kernel Advanced Locality Management Operating System\n");
98        printk("\t\t\t\t   %s \n\n\n", CONFIG_ALMOS_VERSION );
99}
100
101
102///////////////////////////////////////////////////////////////////////////////////////////
103// This static function allocates memory for all devices descriptors associated
104// to peripherals contained in the local cluster:
105// - the internal (replicated) devices are placed in the local cluster.
106// - the external devices are pseudo-randomly distributed on all clusters.
107// It initialises these device descriptors as specified by the boot_info_t structure,
108// including the dynamic linking with the driver for the specified implementation.
109// Finally, all copies of the devices directory are initialised.
110// TODO check that cluster IO contains a PIC and IOB [AG]
111///////////////////////////////////////////////////////////////////////////////////////////
112// @ info    : pointer on the local boot-info structure.
113///////////////////////////////////////////////////////////////////////////////////////////
114static void devices_init( boot_info_t * info )
115{
116    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
117        uint32_t        dev_nr;          // actual number of devices in this cluster
118        xptr_t          xp_dev;          // extended pointer on device descriptor
119        xptr_t          xp_dev_bis;      // extended pointer on second device descriptor
120        xptr_t          base;            // remote pointer on segment base
121        uint32_t        size;            // channel size (bytes)
122    uint32_t        type;            // peripheral type
123    uint32_t        func;            // device functionnal index
124    uint32_t        impl;            // device implementation index
125        uint32_t        i;               // device index in dev_tbl
126        uint32_t        x;               // X cluster coordinate
127        uint32_t        y;               // Y cluster coordinate
128        uint32_t        channels;        // number of channels
129        uint32_t        chl;             // channel index
130        uint32_t        p0;              // device parameter 0
131        uint32_t        p1;              // device parameter 1
132        uint32_t        p2;              // device parameter 2
133        uint32_t        p3;              // device parameter 3
134    bool_t          is_local;        // true for internal peripherals
135
136    // get number of peripherals from boot_info
137        dev_nr      = info->devices_nr;
138    dev_tbl     = info->dev;
139
140    // loop on all peripherals in cluster
141        for( i = 0 ; i < dev_nr ; i++ )
142        {
143        size     = dev_tbl[i].size;
144        base     = dev_tbl[i].base;
145        type     = dev_tbl[i].type;
146        channels = dev_tbl[i].channels;
147        p0       = dev_tbl[i].param0;
148        p1       = dev_tbl[i].param1;
149        p2       = dev_tbl[i].param2;
150        p3       = dev_tbl[i].param3;
151
152        func     = FUNC_FROM_TYPE( type );
153        impl     = IMPL_FROM_TYPE( type );
154
155        // do nothing for RAM and ROM functional types
156        if( (type == DEV_FUNC_RAM) || (type == DEV_FUNC_ROM) ) continue;
157
158        // loop on channels in peripheral
159        for( chl = 0 ; chl < channels ; chl++ )
160        { 
161            // target cluster is local for internal (replicated) peripherals
162            if( (func == DEV_FUNC_ICU) || 
163                (func == DEV_FUNC_MMC) ||
164                (func == DEV_FUNC_MWR) )   is_local = true;
165            else                           is_local = false;
166
167            // allocate memory and initialize device descriptor
168                    xp_dev = device_alloc( info , is_local );
169
170            if( xp_dev == XPTR_NULL ) hal_core_sleep();
171           
172            device_init( xp_dev ,
173                         func ,
174                         impl,
175                         chl,
176                         false,                    // TX
177                         base + size*chl,
178                         size );
179
180            // allocate memory and initialise another device descriptor if NIC,
181            // ALMOS-MKH uses two separate devices descriptor for NIC_RX and NIC_TX
182            if( func == DEV_FUNC_NIC )
183            {
184                xp_dev_bis = device_alloc( info , is_local );
185
186                if( xp_dev_bis == XPTR_NULL ) hal_core_sleep();
187
188                device_init( xp_dev_bis ,
189                             func ,
190                             impl,
191                             chl,
192                             true,                // RX
193                             (base + size*chl),
194                             size );
195             }
196
197            // TODO ??? AG
198                    // devfs_register( dev );
199
200            // make device type specific initialisation
201            // the number of parameters depends on the device type
202            if     ( func == DEV_FUNC_ICU ) dev_icu_init( xp_dev , p0 , p1 , p2 );     
203            else if( func == DEV_FUNC_MMC ) dev_mmc_init( xp_dev );
204// TODO     else if( func == DEV_FUNC_MWR ) dev_mwr_init( xp_dev , p0 , p1 , p2 , p3 );
205            else if( func == DEV_FUNC_IOB ) dev_iox_init( xp_dev );
206            else if( func == DEV_FUNC_IOC ) dev_ioc_init( xp_dev );
207            else if( func == DEV_FUNC_TXT ) dev_txt_init( xp_dev );
208            else if( func == DEV_FUNC_PIC ) dev_pic_init( xp_dev , p0 );
209            else if( func == DEV_FUNC_NIC ) dev_nic_init( xp_dev );
210            else                            hal_core_sleep();
211
212           // initialize the replicated devices_dir[x][y] structures
213           // defining the extended pointers on all devices descriptors
214           xptr_t * ptr_dev;   
215           xptr_t * ptr_dev_bis;   
216
217           if( func == DEV_FUNC_ICU ) ptr_dev     = &devices_dir.icu[local_cxy];
218           if( func == DEV_FUNC_MMC ) ptr_dev     = &devices_dir.mmc[local_cxy];
219           if( func == DEV_FUNC_MWR ) ptr_dev     = &devices_dir.mwr[local_cxy];
220
221           if( func == DEV_FUNC_TXT ) ptr_dev     = &devices_dir.txt[chl];
222           if( func == DEV_FUNC_IOB ) ptr_dev     = &devices_dir.iob;
223           if( func == DEV_FUNC_IOC ) ptr_dev     = &devices_dir.ioc;
224           if( func == DEV_FUNC_PIC ) ptr_dev     = &devices_dir.pic;
225           if( func == DEV_FUNC_NIC ) ptr_dev     = &devices_dir.nic_tx[chl];
226           if( func == DEV_FUNC_NIC ) ptr_dev_bis = &devices_dir.nic_rx[chl];
227 
228            for( x = 0 ; x < info->x_size ; x++ )
229            {
230                for( y = 0 ; y < info->y_size ; y++ )
231                {
232                    cxy_t  cxy = (x<<info->y_width) + y;
233                     
234                    hal_remote_swd( XPTR( cxy , ptr_dev ) , xp_dev );
235
236                    if( func == DEV_FUNC_NIC )
237                    {
238                       hal_remote_swd( XPTR( cxy , ptr_dev_bis ) , xp_dev_bis );
239                    }
240                }
241            }
242           
243                    kinit_dmsg("[INFO] %s created device %s / channel %d / in cluster %x\n",
244                       __FUNCTION__ , device_func_str[func] , chl , dev_cxy );
245
246        } // end loop on channels
247
248        // initialize the replicated devices_irq[x][y] structures
249        // defining how peripherals are connected to PIC or ICU components
250        uint32_t   id;
251        uint8_t    valid;
252        uint32_t   dev_type;
253        uint8_t    channel;
254        uint8_t    is_rx;
255        uint32_t * ptr_irq; 
256
257        // default initiialization for devices_irq structure
258       
259        // only external peripherals can be connected to PIC
260        if( func == DEV_FUNC_PIC ) 
261        {
262            // loop on PIC inputs
263            for( id = 0 ; id < CONFIG_MAX_IRQS_PER_PIC ; id++ )
264            {
265                valid     = dev_tbl[i].irq[id].valid;
266                dev_type  = dev_tbl[i].irq[id].dev_type;
267                channel   = dev_tbl[i].irq[id].channel;
268                is_rx     = dev_tbl[i].irq[id].is_rx;
269
270                // only valid IRQs are registered in the devices_input_irq structure
271                // ptr_irq is a local pointer on the entry to be set in devices_irq
272                if( valid )
273                {
274                    uint16_t dev_func = FUNC_FROM_TYPE( dev_type );
275                    if( dev_func == DEV_FUNC_TXT )   
276                        ptr_irq = &devices_input_irq.txt[channel];
277                    if( dev_func == DEV_FUNC_IOC )                   
278                        ptr_irq = &devices_input_irq.ioc; 
279                    if( (dev_func == DEV_FUNC_NIC) && (is_rx == 0) ) 
280                        ptr_irq = &devices_input_irq.nic_tx[channel]; 
281                    if( (dev_func == DEV_FUNC_NIC) && (is_rx != 0) ) 
282                        ptr_irq = &devices_input_irq.nic_rx[channel]; 
283                   
284                    // all copies of devices_irq must be updated in all clusters
285                    for( x = 0 ; x < info->x_size ; x++ )
286                    {
287                        for( y = 0 ; y < info->y_size ; y++ )
288                        {
289                            cxy_t  cxy = (x<<info->y_width) + y;
290                            hal_remote_sw( XPTR( cxy , ptr_irq ) , id );
291                        }       
292                    }
293                }
294            } // end loop on PIC inputs
295        } // end PIC
296
297        // only internal peripherals can be connected to ICU
298        if( func == DEV_FUNC_ICU ) 
299        {
300            // loop on ICU inputs
301            for( id = 0 ; id < CONFIG_MAX_HWIS_PER_ICU ; id++ )
302            {
303                valid    = dev_tbl[i].irq[id].valid;
304                dev_type = dev_tbl[i].irq[id].dev_type;
305                channel  = dev_tbl[i].irq[id].channel;
306
307                // only valid IRQs are registered in the devices_input_irq structure
308                // ptr_irq is a local pointer on the entry to be set in devices_irq
309                if( valid )
310                {
311                    uint16_t dev_func = FUNC_FROM_TYPE( dev_type );
312                    if( dev_func == DEV_FUNC_MMC ) 
313                        ptr_irq = &devices_input_irq.mmc[local_cxy];
314                    if( dev_func == DEV_FUNC_MWR ) 
315                        ptr_irq = &devices_input_irq.mwr[local_cxy]; 
316                   
317                    // all copies of devices_irq must be updated in all clusters
318                    for( x = 0 ; x < info->x_size ; x++ )
319                    {
320                        for( y = 0 ; y < info->y_size ; y++ )
321                        {
322                            cxy_t  cxy = (x<<info->y_width) + y;
323                            hal_remote_sw( XPTR( cxy , ptr_irq ) , id );
324                        }
325                    }
326                }
327            }  // end loop on ICU inputs
328        }  // end ICU
329        } // end loop on peripherals
330}  // end devices_init()
331
332
333
334///////////////////////////////////////////////////////////////////////////////////////////
335// This function is the entry point for the kernel initialisation.
336// It is executed by all cores in all clusters, but only core[0] in each cluster
337// initialize the cluster manager, ant the other local shared resources.
338// To comply with the multi-kernels paradigm, it access only local cluster memory,
339// using only informations contained in the local boot_info_t structure,
340// that has been set by the bootloader.
341// All cores TODO ...
342///////////////////////////////////////////////////////////////////////////////////////////
343// @ info    : pointer on the local boot-info structure.
344///////////////////////////////////////////////////////////////////////////////////////////
345void kernel_init( boot_info_t * info )
346{
347    uint32_t     core_lid;      // running core local index
348    cxy_t        core_cxy;      // running core cluster identifier
349    gid_t        core_gid;      // running core hardware identifier
350    cluster_t  * cluster;       // pointer on local cluster manager
351    core_t     * core;          // pointer on running core descriptor
352    thread_t   * thread_idle;   // pointer on thread_idle 
353
354        uint32_t     i;
355    bool_t       found;
356    error_t      error;
357
358    // initialise global cluster identifier
359    local_cxy = info->cxy;
360
361    // each core get its global index from hardware register
362    core_gid = hal_get_gid(); 
363
364    // Each core makes an associative search in boot_info
365    // to get its (cxy,lid) composite index
366    found    = false;
367    core_cxy = 0;
368    core_lid = 0;
369    for( i = 0 ; i < info->cores_nr ; i++ )
370    {
371        if( core_gid == info->core[i].gid )
372        {
373            core_lid = info->core[i].lid;
374            core_cxy = info->core[i].cxy;
375            found = true;
376            break;
377        }
378    }
379         
380    if ( found == false )
381    {
382        printk("PANIC in %s : Core %d not registered in cluster %x\n",
383               __FUNCTION__ , core_gid , local_cxy );
384        hal_core_sleep();
385    }
386
387    if ( core_cxy != local_cxy) 
388    {
389        printk("PANIC in %s : Core %d has wrong cxy in cluster %x\n",
390               __FUNCTION__ , core_gid , local_cxy );
391        hal_core_sleep();
392    }
393
394    // from this point, only core[0] initialises local resources
395    if( core_lid == 0 )   
396    {
397        // initialize local cluster manager (cores and memory allocators)
398        error = cluster_init( info );
399        if ( error == 0 ) 
400        {
401            printk("PANIC in %s : Failed to initialize cluster manager in cluster %x\n",
402                   __FUNCTION__ , local_cxy );
403            hal_core_sleep();
404        }
405
406        // initialize process_zero descriptor
407                process_zero_init( info );
408
409        // initialize thread_zero descriptor
410            memset( &thread_zero , 0 , sizeof(thread_t) );
411            thread_zero.type     = THREAD_KERNEL;
412            thread_zero.process  = &process_zero;
413            hal_set_current_thread( &thread_zero );
414
415        // initialise local devices descriptors
416        devices_init( info );
417
418        // TODO initialize devFS and sysFS
419                // devfs_root_init();
420                // sysfs_root_init();
421
422                // TODO dire précisément ce qu'on fait ici [AG]
423                // hal_arch_init( info );
424
425        // TODO ??? [AG]
426                // clusters_sysfs_register();
427
428        // initialize virtual file system
429        // vfs_init();
430
431        // TODO ??? [AG]
432                // sysconf_init();
433
434        // activate other cores in same cluster
435                local_sync_init = KERNEL_INIT_SYNCRO;
436                hal_wbflush();
437    }
438    else   // other cores                                 
439    {
440        // other cores wait synchro from core[0]
441                while( local_sync_init != KERNEL_INIT_SYNCRO )
442        {
443                   uint32_t retval = hal_time_stamp() + 1000;
444                   while( hal_time_stamp() < retval )  asm volatile ("nop");
445        }
446
447        // other cores initialise thread_zero descriptor
448            memset( &thread_zero , 0 , sizeof(thread_t) );
449            thread_zero.type     = THREAD_KERNEL;
450            thread_zero.process  = &process_zero;
451            hal_set_current_thread( &thread_zero );
452    }
453
454
455    // each core get pointer on local cluster manager and on core descriptor
456    cluster = LOCAL_CLUSTER;
457        core    = &cluster->core_tbl[core_lid];
458
459        // each core creates its private idle thread descriptor
460        error = thread_kernel_create( &thread_idle,
461                                  THREAD_IDLE, 
462                                  &thread_idle_func, 
463                                  NULL,
464                                  core_lid );
465    if( error )
466        {
467                printk("ERROR in %s: failed to create idle thread for core %d in cluster %x\n",
468               __FUNCTION__ , core_lid , core_cxy );
469        hal_core_sleep();
470    }
471
472    // each core register thread_idle in scheduler
473    core->scheduler.idle = thread_idle;
474
475    // each core register thread pointer in core hardware register
476    hal_set_current_thread( thread_idle );
477
478    kinit_dmsg("INFO %s  Created thread idle %x for core %d at cycle %d ]\n",
479               thread, hal_get_gid(), hal_time_stamp());
480
481    // global syncho for all core[0] in all clusters
482    if( core_lid == 0 )
483    {
484        remote_barrier( XPTR( info->io_cxy , &cluster->barrier ) , 
485                        (cluster->x_size * cluster->y_size) );
486    }
487
488    // local synchro for all cores in local cluster
489    remote_barrier( XPTR( local_cxy , &cluster->barrier ) , 
490                    cluster->cores_nr );
491
492    if( core_lid ==  0 )
493    {
494        kinit_dmsg("INFO %s completed for cluster %x at cycle %d\n",
495                   __FUNCTION__ , local_cxy , hal_time_stamp() );
496
497        if( local_cxy == info->io_cxy ) print_boot_banner();
498    }
499
500    // load idle thread context in calling core
501        hal_cpu_context_load( thread_idle );
502
503} // end kernel_init()
504
505
506
Note: See TracBrowser for help on using the repository browser.