source: soft/giet_vm/giet_kernel/kernel_init.c @ 284

Last change on this file since 284 was 281, checked in by cfuguet, 11 years ago

Modifications in GIET_VM:

  • Supporting platforms with more than one IRQ per processor from the XICU.

When this is the case, the IRQ per processor can be signalled
by the XCU peripheric number of channels on the XML file.

The xml_parser will generate a constant on the hard_config.h
file, called IRQ_PER_PROCESSOR and this constant will be use
by the GIET_VM to create accordingly the irq masks on the
ICU

  • Property svn:executable set to *
File size: 15.5 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : kernel_init.c
3// Date     : 26/05/2012
4// Authors  : alain greiner & mohamed karaoui
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////////
7// The kernel_init.c file is part of the GIET-VM nano-kernel.
8//
9// This nano-kernel has been written for the MIPS32 processor.
10// The virtual adresses are on 32 bits and use the (unsigned int) type, but the
11// physicals addresses can have up to 40 bits, and use the  (unsigned long long) type.
12// It natively supports clusterised shared mmemory multi-processors architectures,
13// where each processor is identified by a composite index (cluster_xy, local_id),
14// and where there is one physical memory bank per cluster.
15//
16// This file contains the _kernel_init() function, that performs the second
17// phase of system initialisation.  The three significant actions are:
18// 1) processor 0 makes peripherals and system FAT initialisation.
19// 2) processor 0 awake all other processors by an IPI.
20// 3) all processors running in parallel perform register initialisation,
21//    from their private scheduler, and jump to user code.
22////////////////////////////////////////////////////////////////////////////////////
23
24#include <giet_config.h>
25
26// kernel libraries
27#include <utils.h>
28#include <fat32.h>
29
30//for peripheral initialisation
31#include <dma_driver.h>
32#include <fbf_driver.h>
33#include <tty_driver.h>
34#include <icu_driver.h>
35#include <xcu_driver.h>
36#include <ioc_driver.h>
37#include <mmc_driver.h>
38#include <mwr_driver.h>
39#include <nic_driver.h>
40#include <tim_driver.h>
41
42#include <ctx_handler.h>
43#include <irq_handler.h>
44
45#include <mapping_info.h>
46#include <mips32_registers.h>
47
48///////////////////////////////////////////////////////////////////////////////////
49// array of pointers on the page tables (virtual addresses)
50///////////////////////////////////////////////////////////////////////////////////
51
52__attribute__((section (".kdata"))) 
53unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX];    // virtual addresses
54
55__attribute__((section (".kdata")))       
56unsigned int _ptabs_ptprs[GIET_NB_VSPACE_MAX];    // physical addresses >> 13
57
58///////////////////////////////////////////////////////////////////////////////////
59// array of pointers on the schedulers (physical addresses)
60///////////////////////////////////////////////////////////////////////////////////
61
62__attribute__((section (".kdata"))) 
63static_scheduler_t* _schedulers[NB_PROCS_MAX<<(X_WIDTH+Y_WIDTH)];   // virtual addresses
64
65////////////////////////////////////////////////////////////////////////////////////
66// staks for the "idle" tasks (256 bytes for each processor)
67////////////////////////////////////////////////////////////////////////////////////
68
69__attribute__((section (".kdata"))) 
70unsigned int _idle_stack[X_SIZE*Y_SIZE * NB_PROCS_MAX * 128]; 
71
72////////////////////////////////////////////////////////////////////////////////////
73// This function is the entry point in kernel for all processors.
74// It is executed in parallel by all procesors, and completes the system
75// initialisation that has been started by processor 0 in the boot_init() function.
76//
77// This kernel code makes the following assuptions, regarding the work bone
78// by the boot code:
79//
80// 1) The page tables associated to the various vspaces have been build
81//    in physical memory, and can be used by the kernel code.
82//
83// 2) All schedulers (this include all task contexts) have been initialised,
84//    Both the virtual and the physical base addresses of the page tables
85//    are available in the CTX_PTAB and CTX_PTPR slots.
86//
87// 3) The CP0_SCHED register of each processor contains a pointer on its
88//    private scheduler (virtual address).
89//
90// 4) The CP2_PTPR register of each processor contains a pointer on
91//    the vspace_0 page table (physical address>>13).
92//
93// 5) For all processors, the MMU is activated (CP2_MODE contains 0xF).
94//
95// This code must be loaded in .kinit section, in order to control seg_kinit_base,
96// as this address is used by the boot code to jump into kernel code.
97////////////////////////////////////////////////////////////////////////////////////
98// Each processor performs the following actions:
99// 1/ contribute to _schedulers_paddr[] array initialisation.
100// 2/ contribute to _ptabs_paddr[] and _ptabs_vaddr arrays initialisation
101// 3/ compute and set the ICU mask for its private ICU channel
102// 4/ initialise its private TICK timer (if tasks > 0)
103// 5/ initialise the "idle" task context in its private scheduler
104// 6/ initialise the SP, SR, PTPR, EPC registers
105// 7/ jump to the user code with an eret.
106////////////////////////////////////////////////////////////////////////////////////
107__attribute__((section (".kinit"))) void kernel_parallel_init() 
108{
109    unsigned int global_pid = _get_procid();
110    unsigned int cluster_xy = global_pid / NB_PROCS_MAX;
111    unsigned int local_pid  = global_pid % NB_PROCS_MAX;
112
113#if 0
114////////////// Debug : we can kill all processors but one
115if ( global_pid != 0 )
116{
117    _tty_get_lock( 0 );
118    _puts("\n[GIET] Processor[");
119    _putd( cluster_xy >> Y_WIDTH );
120    _puts(",");
121    _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
122    _puts(",");
123    _putd( local_pid );
124    _puts("] suicide...\n");
125    _tty_release_lock( 0 );
126    _exit();
127}
128#endif
129
130    // Step 1 : each processor get its scheduler virtual address
131    //          and contribute to initialise the _schedulers[] array
132
133    static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
134    unsigned int        tasks      = psched->tasks;
135
136    _schedulers[global_pid] = psched;
137
138#if GIET_DEBUG_INIT
139_tty_get_lock( 0 );
140_puts("\n[GIET DEBUG] Parallel init : step 1 for processor[");
141_putd( cluster_xy >> Y_WIDTH );
142_puts(",");
143_putd( cluster_xy & ((1<<Y_WIDTH)-1) );
144_puts(",");
145_putd( local_pid );
146_puts("]\n - scheduler vbase = ");
147_putx((unsigned int) psched);
148_puts("\n - tasks           = ");
149_putd(tasks);
150_puts("\n");
151_tty_release_lock( 0 );
152#endif
153
154    // step 2 : each processor that is allocated at least one task
155    //          completes its private scheduler initialisation, and
156    //          contribute to _ptabs_vaddr[] and _ptabs_ptprs[] arrays initialisation.
157    //          - set the CTX_RA slot vith the virtual address
158    //            of the _ctx_eret() function (for context switch).
159    //          - set the CTX_EPC slot that must contain the task
160    //            entry point, and contain only the address of the
161    //            memory location containing this entry point.
162
163    unsigned int ltid;
164
165    // loop on all allocated tasks
166    for (ltid = 0; ltid < tasks; ltid++) 
167    {
168        unsigned int vsid = _get_task_slot( global_pid, ltid , CTX_VSID_ID ); 
169        unsigned int ptab = _get_task_slot( global_pid, ltid , CTX_PTAB_ID ); 
170        unsigned int ptpr = _get_task_slot( global_pid, ltid , CTX_PTPR_ID ); 
171
172        _ptabs_vaddr[vsid] = ptab;
173        _ptabs_ptprs[vsid] = ptpr;
174
175        unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
176        _set_task_slot( global_pid, ltid, CTX_RA_ID, ctx_ra );
177
178        unsigned int* ptr = (unsigned int*)_get_task_slot( global_pid, ltid, CTX_EPC_ID );
179        _set_task_slot( global_pid, ltid, CTX_EPC_ID, *ptr );
180
181#if GIET_DEBUG_INIT
182_tty_get_lock( 0 );
183_puts("\n[GIET DEBUG] Parallel init : step 2 for processor[");
184_putd( cluster_xy >> Y_WIDTH );
185_puts(",");
186_putd( cluster_xy & ((1<<Y_WIDTH)-1) );
187_puts(",");
188_putd( local_pid );
189_puts("] / task ");
190_putd( ltid );
191_puts("\n - ctx_vsid  = ");
192_putd( _get_task_slot( global_pid, ltid, CTX_VSID_ID ) );
193_puts("\n - ctx_ptpr  = ");
194_putx( _get_task_slot( global_pid, ltid, CTX_PTPR_ID ) );
195_puts("\n - ctx_ptab  = ");
196_putx( _get_task_slot( global_pid, ltid, CTX_PTAB_ID ) );
197_puts("\n - ctx_ltid  = ");
198_putd( _get_task_slot( global_pid, ltid, CTX_LTID_ID ) );
199_puts("\n - ctx_epc   = ");
200_putx( _get_task_slot( global_pid, ltid, CTX_EPC_ID ) );
201_puts("\n - ctx_ra    = ");
202_putx( _get_task_slot( global_pid, ltid, CTX_RA_ID ) );
203_puts("\n - ctx_gtid  = ");
204_putd( _get_task_slot( global_pid, ltid, CTX_GTID_ID ) );
205_puts("\n - ctx_tty   = ");
206_putd( _get_task_slot( global_pid, ltid, CTX_TTY_ID ) );
207_puts("\n");
208_tty_release_lock( 0 );
209#endif
210
211    }
212
213    // step 3 : compute and set ICU or XICU masks
214    //          there is at most 32 interrupts per processor
215
216    unsigned int isr_switch_index = 0xFFFFFFFF;
217    unsigned int irq_id;            // IN_IRQ index
218    unsigned int hwi_mask = 0;
219    unsigned int swi_mask = 0;
220    unsigned int pti_mask = 0;
221
222    for (irq_id = 0; irq_id < 32; irq_id++) 
223    {
224        unsigned int entry = psched->interrupt_vector[irq_id];
225        unsigned int isr   = (entry & 0x000000FF);
226        unsigned int type  = (entry & 0x0000FF00) >> 8;
227        unsigned int valid = (entry & 0x80000000);
228
229        if      ((type == IRQ_TYPE_HWI) && valid ) hwi_mask = hwi_mask | (1<<irq_id);
230        else if ((type == IRQ_TYPE_SWI) && valid ) swi_mask = swi_mask | (1<<irq_id);
231        else if ((type == IRQ_TYPE_PTI) && valid ) pti_mask = pti_mask | (1<<irq_id);
232        else if ( valid )
233        {
234            _puts("\n[GIET ERROR] _kernel_parallel_start() : illegal IRQ type\n");
235            _puts(" irq_id = ");
236            _putx( irq_id );
237            _puts(" / entry = ");
238            _putx( entry );
239            _puts("\n");
240            _exit();
241        }
242        if (isr == ISR_SWITCH) isr_switch_index = irq_id;
243    }
244
245#if GIET_DEBUG_INIT
246_tty_get_lock( 0 );
247_puts("\n[GIET DEBUG] Parallel init : step 3 for processor[");
248_putd( cluster_xy >> Y_WIDTH );
249_puts(",");
250_putd( cluster_xy & ((1<<Y_WIDTH)-1) );
251_puts(",");
252_putd( local_pid );
253_puts("]\n - ICU HWI_MASK = ");
254_putx(hwi_mask);
255_puts("\n - ICU SWI_MASK = ");
256_putx(swi_mask);
257_puts("\n - ICU PTI_MASK = ");
258_putx(pti_mask);
259_puts("\n");
260_tty_release_lock( 0 );
261#endif
262
263    // GIET-VM constraint : only one IRQ type per irq_id
264    if ( hwi_mask & swi_mask & pti_mask )
265    {
266        _puts("[GIET ERROR] _kernel_parallel_start : conflicting IRQs\n");
267        _exit();
268    }
269
270
271    // The ICU output index is computed as the local processor id multiplied by
272    // the number of ICU outputs connected to each processor.
273    int icu_out_index = local_pid * IRQ_PER_PROCESSOR; 
274
275#if USE_XICU
276    _xcu_set_mask(cluster_xy, icu_out_index, hwi_mask, IRQ_TYPE_HWI); // set HWI_MASK
277    _xcu_set_mask(cluster_xy, icu_out_index, swi_mask, IRQ_TYPE_SWI); // set SWI_MASK
278    _xcu_set_mask(cluster_xy, icu_out_index, pti_mask, IRQ_TYPE_PTI); // set PTI_MASK
279#else
280    _icu_set_mask(cluster_xy, icu_out_index, (hwi_mask | pti_mask | swi_mask) );   
281#endif
282
283    // step 4 : start TICK timer if at least one task
284    if (tasks > 0) 
285    {
286        // one ISR_SWITCH must be defined for each proc
287        if (isr_switch_index == 0xFFFFFFFF) 
288        {
289            _tty_get_lock( 0 );
290            _puts("\n[GIET ERROR] ISR_SWITCH not found for processor ");
291            _putx(global_pid);
292            _puts("\n");
293            _tty_release_lock( 0 );
294            _exit();
295        }
296
297        // the ISR_SWITCH irq index must be NB_PROCS_MAX + local_pid because
298        // the first NB_PROCS_MAX irqs are used by the WAKEUP ones
299        if (isr_switch_index != (NB_PROCS_MAX + local_pid))
300        {
301            _tty_get_lock( 0 );
302            _puts("\n[GIET ERROR] ISR_SWITCH wrong index for processor ");
303            _putx(global_pid);
304            _puts("\n. It should be NB_PROCS_MAX + local_pid =");
305            _putd(NB_PROCS_MAX + local_pid);
306            _puts("\n");
307            _tty_release_lock( 0 );
308            _exit();
309        }
310
311        // start system timer
312        unsigned int ko;
313#if USE_XICU
314        ko = _xcu_timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE ); 
315#else
316        ko = _timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE ); 
317#endif
318        if ( ko )
319        {
320            _tty_get_lock( 0 );
321            _puts("\n[GIET ERROR] cannot start timer for processor ");
322            _putd(local_pid);
323            _puts("\n");
324            _tty_release_lock( 0 );
325            _exit();
326        }
327    } 
328
329#if GIET_DEBUG_INIT
330_tty_get_lock( 0 );
331_puts("\n[GIET DEBUG] Parallel init : step 4 for processor[");
332_putd( cluster_xy >> Y_WIDTH );
333_puts(",");
334_putd( cluster_xy & ((1<<Y_WIDTH)-1) );
335_puts(",");
336_putd( local_pid );
337_puts("]");
338if ( tasks > 1 ) _puts("\n  context switch activated\n");
339else             _puts("\n  context switch  not activated\n");
340_tty_release_lock( 0 );
341#endif
342
343    // step 5 : each processor updates the idle_task context:
344    //          (only CTX_SP, CTX_RA, CTX_EPC).
345    //          The stack size is 256 bytes, reserved in seg_kdata.
346    //          The PTPR register, the CTX_PTPR and CTX_PTAB slots
347    //          have been initialised in boot code.
348
349    unsigned int stack = (unsigned int)_idle_stack + ((global_pid + 1)<<9);
350
351    _set_task_slot( global_pid, IDLE_TASK_INDEX, CTX_SP_ID,  stack);
352    _set_task_slot( global_pid, IDLE_TASK_INDEX, CTX_RA_ID,  (unsigned int) &_ctx_eret);
353    _set_task_slot( global_pid, IDLE_TASK_INDEX, CTX_EPC_ID, (unsigned int) &_idle_task);
354
355#if GIET_DEBUG_INIT
356_tty_get_lock( 0 );
357_puts("\n[GIET DEBUG] Parallel init : step 5 for processor[");
358_putd( cluster_xy >> Y_WIDTH );
359_puts(",");
360_putd( cluster_xy & ((1<<Y_WIDTH)-1) );
361_puts(",");
362_putd( local_pid );
363_puts("] : idle task context set\n");
364_tty_release_lock( 0 );
365#endif
366
367    // step 6 : each processor initialises SP, SR, PTPR, EPC, registers
368    //          with the values corresponding to the first allocated task,
369    //          or to the idle_task if there is no task allocated.
370
371    ltid = 0;
372
373    if (tasks == 0) 
374    {
375        ltid = IDLE_TASK_INDEX;
376
377        _tty_get_lock( 0 );
378        _puts("\n[GIET WARNING] No task allocated to processor ");
379        _putx(global_pid);
380        _puts(" => idle\n");
381        _tty_release_lock ( 0 );
382    }
383
384    unsigned int sp_value   = _get_task_slot(global_pid, ltid, CTX_SP_ID);
385    unsigned int sr_value   = _get_task_slot(global_pid, ltid, CTX_SR_ID);
386    unsigned int ptpr_value = _get_task_slot(global_pid, ltid, CTX_PTPR_ID);
387    unsigned int epc_value  = _get_task_slot(global_pid, ltid, CTX_EPC_ID);
388
389#if GIET_DEBUG_INIT
390_tty_get_lock( 0 );
391_puts("\n[GIET DEBUG] Parallel init : step 6 for processor[");
392_putd( cluster_xy >> Y_WIDTH );
393_puts(",");
394_putd( cluster_xy & ((1<<Y_WIDTH)-1) );
395_puts(",");
396_putd( local_pid );
397_puts("]\n - sp   = ");
398_putx(sp_value);
399_puts("\n - sr   = ");
400_putx(sr_value);
401_puts("\n - ptpr = ");
402_putx(ptpr_value);
403_puts("\n - epc  = ");
404_putx(epc_value);
405_puts("\n");
406_tty_release_lock( 0 );
407#endif
408
409_tty_get_lock( 0 );
410_puts("\n[GIET] Processor[");
411_putd( cluster_xy >> Y_WIDTH );
412_puts(",");
413_putd( cluster_xy & ((1<<Y_WIDTH)-1) );
414_puts(",");
415_putd( local_pid );
416_puts("] completes kernel init at cycle ");
417_putd( _get_proctime() );
418_puts(" / task_entry_point = ");
419_putx( epc_value );
420_puts("\n");
421_tty_release_lock( 0 );
422
423    // Step 7 : set  registers and jump to user code
424    asm volatile (
425            "move    $29,       %0    \n"        /* SP <= ctx[CTX_SP_ID] */
426            "mtc0    %1,        $12   \n"        /* SR <= ctx[CTX_SR_ID] */
427            "mtc2    %2,        $0    \n"        /* PTPR <= ctx[CTX_PTPR_ID] */
428            "mtc0    %3,        $14   \n"        /* EPC <= ctx[CTX_EPC_ID] */
429            "eret                     \n"        /* jump to user code */
430            "nop                      \n"
431            :
432            : "r" (sp_value), "r" (sr_value), "r" (ptpr_value), "r" (epc_value));
433
434} // end kernel_parallel_init()
435
436
437// Local Variables:
438// tab-width: 4
439// c-basic-offset: 4
440// c-file-offsets:((innamespace . 0)(inline-open . 0))
441// indent-tabs-mode: nil
442// End:
443// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
444
Note: See TracBrowser for help on using the repository browser.