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

Last change on this file since 23 was 23, checked in by alain, 9 years ago

Introduce syscalls.

File size: 35.7 KB
Line 
1/*
2 * kernel_init.c - kernel parallel initialization
3 *
4 * Authors : Mohamed Lamine Karaoui (2015)
5 * Alain Greiner (2016,2017)
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
25#include <kernel_config.h>
26#include <errno.h>
27#include <hal_types.h>
28#include <hal_special.h>
29#include <hal_context.h>
30#include <barrier.h>
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>
42#include <chdev.h>
43#include <boot_info.h>
44#include <dqdt.h>
45#include <dev_icu.h>
46#include <dev_mmc.h>
47#include <dev_dma.h>
48#include <dev_iob.h>
49#include <dev_ioc.h>
50#include <dev_txt.h>
51#include <dev_pic.h>
52#include <printk.h>
53#include <vfs.h>
54#include <soclib_tty.h>
55#include <devfs.h>
56
57// TODO #include <sysfs.h>
58
59#define KERNEL_INIT_SYNCHRO 0xA5A5B5B5
60
61///////////////////////////////////////////////////////////////////////////////////////////
62// All these global variables are replicated in all clusters.
63// They are initialised by the kernel_init() function.
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.
71///////////////////////////////////////////////////////////////////////////////////////////
72
73// This variable defines the local boot_info structure
74__attribute__((section(".kinfo")))
75boot_info_t boot_info;
76
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
82// This variable defines the local cluster manager
83__attribute__((section(".kdata")))
84cluster_t cluster_manager CONFIG_CACHE_LINE_ALIGNED;
85
86// This variables define the kernel process0 descriptor
87__attribute__((section(".kdata")))
88process_t process_zero CONFIG_CACHE_LINE_ALIGNED;
89
90// This variable defines extended pointers on the distributed chdevs
91__attribute__((section(".kdata")))
92chdev_directory_t chdev_dir CONFIG_CACHE_LINE_ALIGNED;
93
94// This variable contains the input IRQ indexes for the PIC device
95__attribute__((section(".kdata")))
96chdev_pic_input_t chdev_pic_input CONFIG_CACHE_LINE_ALIGNED;
97
98// This variable contains the input IRQ indexes for the ICU device
99__attribute__((section(".kdata")))
100chdev_icu_input_t chdev_icu_input CONFIG_CACHE_LINE_ALIGNED;
101
102// This variable defines the local cluster identifier
103__attribute__((section(".kdata")))
104cxy_t local_cxy CONFIG_CACHE_LINE_ALIGNED;
105
106// This variable defines the TXT0 chdev descriptor
107__attribute__((section(".kdata")))
108chdev_t txt0_chdev CONFIG_CACHE_LINE_ALIGNED;
109
110// This variable is used for CP0 cores sychronisation in kernel_init()
111__attribute__((section(".kdata")))
112remote_barrier_t global_barrier CONFIG_CACHE_LINE_ALIGNED;
113
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
118///////////////////////////////////////////////////////////////////////////////////////////
119// This function displays the ALMOS_MKH banner.
120///////////////////////////////////////////////////////////////////////////////////////////
121static void print_banner( uint32_t nclusters , uint32_t ncores )
122{
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}
135
136
137///////////////////////////////////////////////////////////////////////////////////////////
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.
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
160
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;
164
165 // loop on external peripherals to find TXT device
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 {
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;
181
182 // initialize lock
183 remote_spinlock_init( XPTR( local_cxy , &txt0_chdev.wait_lock ) );
184
185 // Complete TXT specific initialisation
186 if( impl == IMPL_TXT_TTY )
187 {
188 txt0_chdev.cmd = &soclib_tty_cmd;
189 txt0_chdev.isr = &soclib_tty_isr;
190 soclib_tty_init( &txt0_chdev );
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;
199 hal_remote_swd( XPTR( cxy , &chdev_dir.txt[0] ) ,
200 XPTR( local_cxy , &txt0_chdev ) );
201 }
202 }
203
204 kinit_dmsg("\n[INFO] %s : core[%x][0] created TXT0 chdev"
205 " / paddr = %l at cycle %d\n",
206 __FUNCTION__ , local_cxy , chdev_func_str( func ),
207 XPTR(local_cxy , &txt0_chdev) , hal_time_stamp() );
208 }
209
210 } // end loop on devices
211
212} // end txt0_device_init()
213
214///////////////////////////////////////////////////////////////////////////////////////////
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.
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///////////////////////////////////////////////////////////////////////////////////////////
224static void internal_devices_init( boot_info_t * info )
225{
226 boot_device_t * dev; // pointer on boot_info device (ICU/MMC/DMA)
227 uint32_t x; // X cluster coordinate
228 uint32_t y; // Y cluster coordinate
229 chdev_t * chdev_ptr; // local pointer on chdev descriptor
230 xptr_t chdev_xp; // extended pointer on chdev descriptor
231
232 /////////// ICU //////////
233
234 dev = &info->dev_icu;
235
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" );
241
242 assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_ICU ) , __FUNCTION__ ,
243 " inconsistent ICU device type");
244
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 );
251
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
259 dev_icu_init( chdev_ptr , dev->param0 , dev->param1 , dev->param2 );
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++ )
267 {
268 cxy_t cxy = (x<<info->y_width) + y;
269 hal_remote_swd( XPTR( cxy , &chdev_dir.icu[local_cxy] ) , chdev_xp );
270 }
271 }
272
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
288 {
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 }
294
295 kinit_dmsg("\n[INFO] %s : core[%x][0] creates ICU chdev at cycle %d\n",
296 __FUNCTION__ , local_cxy , hal_time_stamp() );
297
298 /////////// MMC internal chdev ///////////
299
300 dev = &info->dev_mmc;
301
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" );
306
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++ )
331 {
332 cxy_t cxy = (x<<info->y_width) + y;
333 hal_remote_swd( XPTR( cxy , &chdev_dir.mmc[local_cxy] ) , chdev_xp );
334 }
335 }
336
337 kinit_dmsg("\n[INFO] %s : core[%x][0] creates MMC chdev at cycle %d\n",
338 __FUNCTION__ , local_cxy , hal_time_stamp() );
339 }
340
341 /////////// DMA internal chdevs //////////
342
343 dev = &info->dev_dma;
344
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");
349
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 );
359
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 );
364
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 }
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.
387// There is three nested loops to build the full set of external channel_devices:
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) )
461 {
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++ )
470 {
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;
476
477 // allocate and initialize a local chdev
478 // if local cluster matches target cluster
479 if( target_cxy == local_cxy )
480 {
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
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;
524 hal_remote_swd( XPTR( cxy , entry ) , chdev_xp );
525 }
526 }
527
528 kinit_dmsg("\n[INFO] %s : core[%x][0] create chdev %s[%d] at cycle %d\n",
529 __FUNCTION__ , local_cxy , chdev_func_str( func ),
530 channel , hal_time_stamp() );
531
532 } // end if match
533
534 // increment chdev global index (matching or not)
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 )
544 {
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++ )
553 {
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;
558
559 if( valid ) // only valid inputs are registered
560 {
561 uint32_t * index; // local pointer on one entry
562 uint16_t dev_func = FUNC_FROM_TYPE( dev_type );
563
564 if( dev_func == DEV_FUNC_TXT )
565 {
566 index = &chdev_pic_input.txt[channel];
567 }
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;
587 }
588 } // end loop on PIC inputs
589 } // end PIC
590 } // end loop on devices
591} // end external_devices_init()
592
593
594///////////////////////////////////////////////////////////////////////////////////////////
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 get_core_identifiers( boot_info_t * info,
604 lid_t * lid,
605 cxy_t * cxy,
606 gid_t * gid )
607{
608 uint32_t i;
609 gid_t global_id;
610
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;
626}
627
628///////////////////////////////////////////////////////////////////////////////////////////
629// This function is the entry point for the kernel initialisation.
630// It is executed by all cores in all clusters, but only core[0], called CP0,
631// initializes the shared resources such as the cluster manager, or the local peripherals.
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.
634///////////////////////////////////////////////////////////////////////////////////////////
635// @ info : pointer on the local boot-info structure.
636///////////////////////////////////////////////////////////////////////////////////////////
637void kernel_init( boot_info_t * info )
638{
639 lid_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
645 error_t error;
646
647 // all cores get core identifiers
648 error = get_core_identifiers( info,
649 &core_lid,
650 &core_cxy,
651 &core_gid );
652
653 // CP0 initialise cluster identifier
654 if( core_lid == 0 ) local_cxy = info->cxy;
655
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 at cycle %d\n",
667 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() );
668
669 // all cores check core identifiers
670 if( error )
671 {
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();
676 }
677
678 // CP0 initializes the local cluster manager (cores and memory allocators)
679 if( core_lid == 0 )
680 {
681 error = cluster_init( info );
682
683 if( error )
684 {
685 printk("\n[PANIC] in %s : cannot initialise cluster manager in cluster %x",
686 __FUNCTION__ , local_cxy );
687 hal_core_sleep();
688 }
689 }
690
691 /////////////////////////////////////////////////////////////////////////////////
692 // global & local synchro, to protect access to cluster manager
693 if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
694 (info->x_size * info->y_size) );
695 barrier_wait( &local_barrier , info->cores_nr );
696 /////////////////////////////////////////////////////////////////////////////////
697
698 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 1 at cycle %d\n",
699 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() );
700
701 // all cores get pointer on local cluster manager and on core descriptor
702 cluster = &cluster_manager;
703 core = &cluster->core_tbl[core_lid];
704
705 // CP0 initializes the process_zero descriptor
706 if( core_lid == 0 ) process_zero_init( info );
707
708 // CP0 allocates and initialises the internal peripheral chdev descriptors.
709 // Each CP0[cxy] scan the set of its internal (private) peripherals,
710 // and allocate memory for the corresponding chdev descriptors.
711 if( core_lid == 0 ) internal_devices_init( info );
712
713 // CP0 allocates one WTI mailbbox per core for Inter Processor Interrupt
714 // this must be done after ICU chdev initialisation, by CP0 only, and before
715 // external devices initialisation to enforce the rule (wti_id == lid)
716 if( core_lid == 0 )
717 {
718 uint32_t wti_id;
719 uint32_t lid;
720 for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ )
721 {
722 wti_id = dev_icu_wti_alloc();
723
724 if( wti_id != lid )
725 {
726 printk("\n[PANIC] in %s : WTI index for IPI = %d / core_lid = %d",
727 __FUNCTION__ , wti_id , lid );
728 hal_core_sleep();
729 }
730
731 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , NULL );
732 }
733 }
734
735 // CP0 contribute to initialise external peripheral chdev descriptors.
736 // Each CP0[cxy] scan the set of external (shared) peripherals (but the TXT0),
737 // and allocates memory for the chdev descriptors that must be placed
738 // on the (cxy) cluster according to the global index value.
739 if( core_lid == 0 ) external_devices_init( info );
740
741 /////////////////////////////////////////////////////////////////////////////////
742 // global &local synchro to protect access to peripherals
743 if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
744 (info->x_size * info->y_size) );
745 barrier_wait( &local_barrier , info->cores_nr );
746 /////////////////////////////////////////////////////////////////////////////////
747
748 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 2 at cycle %d\n",
749 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() );
750
751 // all cores initialize the private idle thread descriptor
752 thread = (thread_t *)( idle_threads + (core_lid * CONFIG_THREAD_DESC_SIZE) );
753
754 error = thread_kernel_init( thread,
755 THREAD_IDLE,
756 &thread_idle_func,
757 NULL,
758 core_lid );
759
760 if( error )
761 {
762 printk("\n[PANIC] in %s : core[%x][%d] cannot initialize idle thread\n",
763 __FUNCTION__ , local_cxy , core_lid );
764 hal_core_sleep();
765 }
766 else
767 {
768 // register idle thread in scheduler
769 core->scheduler.idle = thread;
770
771 // register idle thread pointer in core register
772 hal_set_current_thread( thread );
773
774 // activate the idle thread
775 thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
776
777 kinit_dmsg("\n[INFO] %s : core[%x][%d] created idle thread %x at cycle %d\n",
778 __FUNCTION__ , core_cxy , core_lid , thread , hal_time_stamp());
779 }
780
781printk("\n bloup 0\n");
782
783 // CP0 in all clusters initializes cooperatively VFS and DEVFS
784 if( (core_lid == 0) )
785 {
786 xptr_t root_inode_xp;
787
788 // initialize root File System
789 if( CONFIG_VFS_ROOT_IS_FATFS )
790 {
791 root_inode_xp = fatfs_init();
792 }
793 else
794 {
795 printk("\n[PANIC] in %s : root FS must be FATFS\n", __FUNCTION__ );
796 hal_core_sleep();
797 }
798
799 if( root_inode_xp == XPTR_NULL )
800 {
801 printk("\n[PANIC] in %s : core[%x][%d] cannot initialize file system\n",
802 __FUNCTION__ , local_cxy , core_lid );
803 hal_core_sleep();
804 }
805
806printk("\n bloup 1\n");
807
808 // mount the DEVFS File system
809 devfs_mount( root_inode_xp , "dev" );
810 }
811
812printk("\n bloup 2\n");
813
814 // CP0 in I/O cluster print banner
815 if( (core_lid == 0) && (local_cxy == info->io_cxy) )
816 {
817 print_banner( (info->x_size * info->y_size) , info->cores_nr );
818 }
819
820 /////////////////////////////////////////////////////////////////////////////////
821 // global syncho to protect access to File System
822 if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
823 (info->x_size * info->y_size) );
824 barrier_wait( &local_barrier , info->cores_nr );
825 /////////////////////////////////////////////////////////////////////////////////
826
827 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 3 at cycle %d\n",
828 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() );
829
830 // each core activates its private PTI IRQ
831 dev_icu_set_period( core_lid , CONFIG_SCHED_TICK_PERIOD );
832 dev_icu_enable_irq( core_lid , PTI_TYPE , core_lid , NULL );
833
834 // each core get its private IRQ masks values and
835 uint32_t hwi_mask;
836 uint32_t wti_mask;
837 uint32_t pti_mask;
838 dev_icu_get_masks( core_lid , &hwi_mask , &wti_mask , &pti_mask );
839
840 thread_dmsg("\n[INFO] %s : core[%x][%d] activates scheduler at cycle %d\n"
841 " hwi_mask = %x / wti_mask = %x / pti_mask = %x\n",
842 __FUNCTION__ , local_cxy , core_lid , hal_time_stamp() ,
843 hwi_mask , wti_mask , pti_mask );
844
845 // each core jump to idle thread
846 asm volatile( "j thread_idle_func\n" );
847
848} // end kernel_init()
849
850
851
Note: See TracBrowser for help on using the repository browser.