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

Last change on this file since 252 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
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 files is part of the GIET-VM nano-kernel.
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.
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.
18////////////////////////////////////////////////////////////////////////////////////
19
20#include <common.h>
21#include <irq_handler.h>
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>
28#include <vm_handler.h>
29#include <hwr_mapping.h>
30#include <mwmr_channel.h>
31#include <barrier.h>
32#include <drivers.h>
33
34///////////////////////////////////////////////////////////////////////////////////
35// array of pointers on the page tables (virtual addresses)
36///////////////////////////////////////////////////////////////////////////////////
37
38__attribute__((section (".kdata"))) 
39unsigned int _ptabs[GIET_NB_VSPACE_MAX];    // virtual addresses
40
41__attribute__((section (".kdata")))       
42unsigned int _ptprs[GIET_NB_VSPACE_MAX];    // physical addresses >> 13
43
44///////////////////////////////////////////////////////////////////////////////////
45// array of pointers on the schedulers (physical addresses)
46///////////////////////////////////////////////////////////////////////////////////
47
48__attribute__((section (".kdata"))) 
49static_scheduler_t* _schedulers[NB_CLUSTERS * NB_PROCS_MAX]; 
50
51///////////////////////////////////////////////////////////////////////////////////
52// staks for the "idle" tasks (256 bytes for each processor)
53///////////////////////////////////////////////////////////////////////////////////
54
55__attribute__((section (".kdata"))) 
56unsigned int _idle_stack[NB_CLUSTERS * NB_PROCS_MAX * 64]; 
57
58////////////////
59void _sys_exit() 
60{
61    while (1);
62}
63
64
65
66//////////////////////////////////////////////////////////////////////////////////
67// This function is the entry point for the last step of the boot sequence.
68// that is done in parallel by all processors, with MMU activated.
69//////////////////////////////////////////////////////////////////////////////////
70__attribute__((section (".kinit"))) void _kernel_init() 
71{
72    // Step 1 : get processor index,
73    //          get scheduler address
74    //          initialise _schedulers[] array
75
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;
81
82    _schedulers[global_pid] = psched;
83
84#if GIET_DEBUG_INIT
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);
94#endif
95
96    // step 2 : initialise ptabs[] & ptprs[] arrays
97    //          each processor scans all tasks contexts in its
98    //          private scheduler and get VSID, PTAB and PTPR values
99
100    unsigned int ltid;
101
102    for (ltid = 0; ltid < tasks; ltid++) 
103    {
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); 
107
108        _ptabs[vsid] = ptab;
109        _ptprs[vsid] = ptpr;
110
111#if GIET_DEBUG_INIT
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);
123#endif
124
125    }
126
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
131    unsigned int isr_switch_channel = 0xFFFFFFFF;
132    unsigned int irq_id;            // IN_IRQ index
133    unsigned int hwi_mask = 0;
134    unsigned int pti_mask = 0;
135
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;
140
141        if ((isr == ISR_DMA) || (isr == ISR_IOC) || (isr == ISR_TTY)) 
142        {
143            hwi_mask = hwi_mask | 0x1 << irq_id;
144        }
145        else if ((isr == ISR_SWITCH)) 
146        { 
147            pti_mask = pti_mask | 0x1 << irq_id;
148            isr_switch_channel = irq_id;
149        }
150        else if ((isr == ISR_TIMER)) 
151        {
152            pti_mask = pti_mask | 0x1 << irq_id;
153        }
154    }
155
156#if GIET_DEBUG_INIT
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);
166#endif
167
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
171    // step 4 : start TICK timer if more than one task
172    if (tasks > 1) 
173    {
174        if (isr_switch_channel == 0xFFFFFFFF) 
175        {
176            _get_lock(&_tty_put_lock);
177            _puts("\n[GIET ERROR] ISR_SWITCH not found on proc ");
178            _putd(proc_id);
179            _puts("\n");
180            _release_lock(&_tty_put_lock);
181            _sys_exit();
182        }
183
184        if (_timer_start( cluster_id, isr_switch_channel, GIET_TICK_VALUE)) 
185        {
186            _get_lock(&_tty_put_lock);
187            _puts("\n[GIET ERROR] ISR_SWITCH init error for proc ");
188            _putd(proc_id);
189            _puts("\n");
190            _release_lock(&_tty_put_lock);
191            _sys_exit();
192        }
193
194#if GIET_DEBUG_INIT
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);
200#endif
201
202    } 
203
204    // step 5 : initialise, for each processor, the "idle" task context:
205    //          the SR initialisation value is 0xFF03 because
206    //          the task _ctx_idle() executes in kernel mode.
207    //          it uses the page table of vspace[0]
208    //          the stack size is 256 bytes
209
210    unsigned int stack = (unsigned int)_idle_stack + ((global_pid + 1)<<8);
211
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
220#if GIET_DEBUG_INIT
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);
226#endif
227
228    // step 6 : each processor initialises SP, SR, PTPR, EPC, registers
229    //          with the values corresponding to the first allocated task,
230    //          and starts the "idle" task if there is no task allocated.
231
232    ltid = 0;
233
234    if (tasks == 0) 
235    {
236        ltid = IDLE_TASK_INDEX;
237
238        _get_lock(&_tty_put_lock);
239        _puts("\n[GIET WARNING] No task allocated to processor ");
240        _putd(global_pid);
241        _puts(" => idle\n");
242        _release_lock (&_tty_put_lock);
243    }
244
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);
249
250    _set_task_slot( ltid, CTX_LTID_ID, ltid);
251
252#if GIET_DEBUG_INIT
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);
270#endif
271
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
280    // set  registers and jump to user code
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));
290
291} // end _kernel_init()
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.