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

Last change on this file since 230 was 228, checked in by meunier, 11 years ago

Added support for memspaces and const.
Added an interrupt masking to the "giet_context_switch" syscall
Corrected two bugs in boot/boot_init.c (one minor and one regarding barriers initialization)
Reformatted the code in all files.

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