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

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

Major evolution to support physical addresses larger than 32 bits.
The map.xml format has been modified: the vsegs associated to schedulers
are now explicitely defined and mapped in the page tables.

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