source: soft/giet_vm/sys/kernel_init.c @ 250

Last change on this file since 250 was 246, checked in by meunier, 11 years ago

Cosmétique + gestion du reset de l'irq du timer ou de l'xicu lors d'un task_switch

File size: 9.6 KB
RevLine 
[165]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 files is part of the GIET-VM nano-kernel.
[189]8// It contains the kernel entry point for the last step of system initialisation.
9// All procs in this phase have their MMU activated, and are running in parallel.
[199]10// Each processor perform the following actions:
11// 1/ contributes to _schedulers_paddr[] initialisation
12// 2/ contributes to _ptabs_paddr[] and _ptabs_vaddr arrays initialisation
13// 3/ computes and set the ICU mask for its private ICU channel
14// 4/ initialises its private TICK timer (if required)
15// 5/ initialises the "idle" task context in its private scheduler
16// 6/ initialises the SP, SR, PTPR, EPC registers
17// 7/ jumps to the user code with an eret.
[165]18////////////////////////////////////////////////////////////////////////////////////
19
20#include <common.h>
[189]21#include <irq_handler.h>
[165]22#include <ctx_handler.h>
23#include <sys_handler.h>
24#include <mapping_info.h>
25#include <giet_config.h>
26#include <mips32_registers.h>
27#include <irq_handler.h>
[166]28#include <vm_handler.h>
[165]29#include <hwr_mapping.h>
30#include <mwmr_channel.h>
31#include <barrier.h>
32#include <drivers.h>
33
34///////////////////////////////////////////////////////////////////////////////////
[238]35// array of pointers on the page tables (virtual addresses)
[167]36///////////////////////////////////////////////////////////////////////////////////
37
[189]38__attribute__((section (".kdata"))) 
[238]39unsigned int _ptabs[GIET_NB_VSPACE_MAX];    // virtual addresses
[167]40
[238]41__attribute__((section (".kdata")))       
42unsigned int _ptprs[GIET_NB_VSPACE_MAX];    // physical addresses >> 13
[165]43
[218]44///////////////////////////////////////////////////////////////////////////////////
45// array of pointers on the schedulers (physical addresses)
46///////////////////////////////////////////////////////////////////////////////////
47
[189]48__attribute__((section (".kdata"))) 
[238]49static_scheduler_t* _schedulers[NB_CLUSTERS * NB_PROCS_MAX]; 
[165]50
[218]51///////////////////////////////////////////////////////////////////////////////////
52// staks for the "idle" tasks (256 bytes for each processor)
53///////////////////////////////////////////////////////////////////////////////////
54
[199]55__attribute__((section (".kdata"))) 
[238]56unsigned int _idle_stack[NB_CLUSTERS * NB_PROCS_MAX * 64]; 
[199]57
[238]58////////////////
59void _sys_exit() 
60{
[228]61    while (1);
[215]62}
63
[228]64
[246]65
[165]66//////////////////////////////////////////////////////////////////////////////////
[189]67// This function is the entry point for the last step of the boot sequence.
[238]68// that is done in parallel by all processors, with MMU activated.
[165]69//////////////////////////////////////////////////////////////////////////////////
[238]70__attribute__((section (".kinit"))) void _kernel_init() 
71{
72    // Step 1 : get processor index,
73    //          get scheduler address
74    //          initialise _schedulers[] array
[165]75
[238]76    unsigned int        global_pid = _procid();
77    unsigned int        cluster_id = global_pid / NB_PROCS_MAX;
78    unsigned int        proc_id    = global_pid % NB_PROCS_MAX;
79    static_scheduler_t* psched     = _get_sched();
80    unsigned int        tasks      = psched->tasks;
[207]81
[238]82    _schedulers[global_pid] = psched;
[207]83
84#if GIET_DEBUG_INIT
[238]85_get_lock(&_tty_put_lock);
86_puts("\n[GIET DEBUG] step 1 for processor ");
87_putd(global_pid);
88_puts(" : tasks = ");
89_putd(tasks);
90_puts(" / scheduler vbase = ");
91_putx((unsigned int) psched);
92_puts("\n");
93_release_lock(&_tty_put_lock);
[207]94#endif
95
[238]96    // step 2 : initialise ptabs[] & ptprs[] arrays
[203]97    //          each processor scans all tasks contexts in its
98    //          private scheduler and get VSID, PTAB and PTPR values
[199]99
100    unsigned int ltid;
101
[238]102    for (ltid = 0; ltid < tasks; ltid++) 
103    {
[246]104        unsigned int vsid = _get_task_slot(ltid , CTX_VSID_ID); 
105        unsigned int ptab = _get_task_slot(ltid , CTX_PTAB_ID); 
106        unsigned int ptpr = _get_task_slot(ltid , CTX_PTPR_ID); 
[203]107
[238]108        _ptabs[vsid] = ptab;
109        _ptprs[vsid] = ptpr;
[199]110
111#if GIET_DEBUG_INIT
[238]112_get_lock(&_tty_put_lock);
113_puts("\n[GIET DEBUG] step 2 for processor ");
114_putd(global_pid);
115_puts(" / vspace ");
116_putd(vsid);
117_puts("\n- ptab = ");
118_putx(ptab);
119_puts("\n- ptpr = ");
120_putx(ptpr);
121_puts("\n");
122_release_lock(&_tty_put_lock);
[199]123#endif
124
125    }
[228]126
[203]127    // step 3 : compute and set ICU masks
128    //          there is at most 32 interrupts per processor
129    //          software interrupts are not supported yet
130
[238]131    unsigned int isr_switch_channel = 0xFFFFFFFF;
132    unsigned int irq_id;            // IN_IRQ index
[203]133    unsigned int hwi_mask = 0;
134    unsigned int pti_mask = 0;
135
[238]136    for (irq_id = 0; irq_id < 32; irq_id++) 
137    {
138        unsigned int entry = psched->interrupt_vector[irq_id];
139        unsigned int isr   = entry & 0x000000FF;
[203]140
[238]141        if ((isr == ISR_DMA) || (isr == ISR_IOC) || (isr == ISR_TTY)) 
142        {
[228]143            hwi_mask = hwi_mask | 0x1 << irq_id;
[203]144        }
[238]145        else if ((isr == ISR_SWITCH)) 
146        { 
[228]147            pti_mask = pti_mask | 0x1 << irq_id;
[215]148            isr_switch_channel = irq_id;
[203]149        }
[238]150        else if ((isr == ISR_TIMER)) 
151        {
[228]152            pti_mask = pti_mask | 0x1 << irq_id;
[215]153        }
[165]154    }
[228]155
[189]156#if GIET_DEBUG_INIT
[238]157_get_lock(&_tty_put_lock);
158_puts("\n[GIET DEBUG] step 3 for processor ");
159_putd(global_pid);
160_puts("\n - ICU HWI_MASK = ");
161_putx(hwi_mask);
162_puts("\n - ICU PTI_MASK = ");
163_putx(pti_mask);
164_puts("\n");
165_release_lock(&_tty_put_lock);
[189]166#endif
[165]167
[238]168    _icu_set_mask(cluster_id, proc_id, hwi_mask, 0); // set HWI_MASK
169    _icu_set_mask(cluster_id, proc_id, pti_mask, 1); // set PTI_MASK
170
[189]171    // step 4 : start TICK timer if more than one task
[238]172    if (tasks > 1) 
173    {
174        if (isr_switch_channel == 0xFFFFFFFF) 
175        {
[216]176            _get_lock(&_tty_put_lock);
[215]177            _puts("\n[GIET ERROR] ISR_SWITCH not found on proc ");
[228]178            _putd(proc_id);
[215]179            _puts("\n");
[216]180            _release_lock(&_tty_put_lock);
[215]181            _sys_exit();
182        }
[216]183
[238]184        if (_timer_start( cluster_id, isr_switch_channel, GIET_TICK_VALUE)) 
185        {
[216]186            _get_lock(&_tty_put_lock);
187            _puts("\n[GIET ERROR] ISR_SWITCH init error for proc ");
[228]188            _putd(proc_id);
[216]189            _puts("\n");
190            _release_lock(&_tty_put_lock);
191            _sys_exit();
192        }
[228]193
[189]194#if GIET_DEBUG_INIT
[238]195_get_lock(&_tty_put_lock);
196_puts("\n[GIET DEBUG] Step 4 for processor ");
197_putd(global_pid);
198_puts(" / context switch activated\n");
199_release_lock(&_tty_put_lock);
[189]200#endif
[228]201
[189]202    } 
203
[218]204    // step 5 : initialise, for each processor, the "idle" task context:
[199]205    //          the SR initialisation value is 0xFF03 because
[218]206    //          the task _ctx_idle() executes in kernel mode.
[199]207    //          it uses the page table of vspace[0]
[218]208    //          the stack size is 256 bytes
[199]209
[238]210    unsigned int stack = (unsigned int)_idle_stack + ((global_pid + 1)<<8);
[228]211
[238]212    _set_task_slot( IDLE_TASK_INDEX, CTX_RUN_ID, 1);
213    _set_task_slot( IDLE_TASK_INDEX, CTX_SR_ID,  0xFF03);
214    _set_task_slot( IDLE_TASK_INDEX, CTX_SP_ID,  stack);
215    _set_task_slot( IDLE_TASK_INDEX, CTX_RA_ID,  (unsigned int) &_ctx_eret);
216    _set_task_slot( IDLE_TASK_INDEX, CTX_EPC_ID, (unsigned int) &_ctx_idle);
217    _set_task_slot( IDLE_TASK_INDEX, CTX_LTID_ID, IDLE_TASK_INDEX);
218    _set_task_slot( IDLE_TASK_INDEX, CTX_PTPR_ID, _ptprs[0]);
219
[199]220#if GIET_DEBUG_INIT
[238]221_get_lock(&_tty_put_lock);
222_puts("\n[GIET DEBUG] Step 5 for processor ");
223_putd(global_pid);
224_puts(" / idle task context set\n");
225_release_lock(&_tty_put_lock);
[199]226#endif
[228]227
[199]228    // step 6 : each processor initialises SP, SR, PTPR, EPC, registers
[189]229    //          with the values corresponding to the first allocated task,
[199]230    //          and starts the "idle" task if there is no task allocated.
[189]231
[238]232    ltid = 0;
[199]233
[238]234    if (tasks == 0) 
235    {
236        ltid = IDLE_TASK_INDEX;
[165]237
[228]238        _get_lock(&_tty_put_lock);
[218]239        _puts("\n[GIET WARNING] No task allocated to processor ");
[228]240        _putd(global_pid);
[199]241        _puts(" => idle\n");
[228]242        _release_lock (&_tty_put_lock);
[199]243    }
244
[238]245    unsigned int sp_value   = _get_task_slot(ltid, CTX_SP_ID);
246    unsigned int sr_value   = _get_task_slot(ltid, CTX_SR_ID);
247    unsigned int ptpr_value = _get_task_slot(ltid, CTX_PTPR_ID);
248    unsigned int epc_value  = _get_task_slot(ltid, CTX_EPC_ID);
[228]249
[238]250    _set_task_slot( ltid, CTX_LTID_ID, ltid);
251
[189]252#if GIET_DEBUG_INIT
[238]253_get_lock(&_tty_put_lock);
254_puts("\n[GIET DEBUG] step 6 for processor ");
255_putd(global_pid);
256_puts(" / registers initialised \n");
257_puts("- sp   = ");
258_putx(sp_value);
259_puts("\n");
260_puts("- sr   = ");
261_putx(sr_value);
262_puts("\n");
263_puts("- ptpr = ");
264_putx(ptpr_value);
265_puts("\n");
266_puts("- epc  = ");
267_putx(epc_value);
268_puts("\n");
269_release_lock(&_tty_put_lock);
[189]270#endif
[165]271
[238]272_get_lock(&_tty_put_lock);
273_puts("\n[GIET] Processor ");
274_putd( global_pid );
275_puts(" starting user code at cycle ");
276_putd( _proctime() );
277_puts("\n");
278_release_lock(&_tty_put_lock);
279
[199]280    // set  registers and jump to user code
[228]281    asm volatile (
282            "move    $29,       %0    \n"        /* SP <= ctx[CTX_SP_ID] */
283            "mtc0    %1,        $12   \n"        /* SR <= ctx[CTX_SR_ID] */
284            "mtc2    %2,        $0    \n"        /* PTPR <= ctx[CTX_PTPR_ID] */
285            "mtc0    %3,        $14   \n"        /* EPC <= ctx[CTX_EPC_ID] */
286            "eret                     \n"        /* jump to user code */
287            "nop                      \n"
288            :
289            : "r" (sp_value), "r" (sr_value), "r" (ptpr_value), "r" (epc_value));
[165]290
291} // end _kernel_init()
[228]292
293// Local Variables:
294// tab-width: 4
295// c-basic-offset: 4
296// c-file-offsets:((innamespace . 0)(inline-open . 0))
297// indent-tabs-mode: nil
298// End:
299// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
300
Note: See TracBrowser for help on using the repository browser.