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
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// This function is the entry point for the last step of the boot sequence.
67// that is done in parallel by all processors, with MMU activated.
68//////////////////////////////////////////////////////////////////////////////////
69__attribute__((section (".kinit"))) void _kernel_init() 
70{
71    // Step 1 : get processor index,
72    //          get scheduler address
73    //          initialise _schedulers[] array
74
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;
80
81    _schedulers[global_pid] = psched;
82
83#if GIET_DEBUG_INIT
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);
93#endif
94
95    // step 2 : initialise ptabs[] & ptprs[] arrays
96    //          each processor scans all tasks contexts in its
97    //          private scheduler and get VSID, PTAB and PTPR values
98
99    unsigned int ltid;
100
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); 
106
107        _ptabs[vsid] = ptab;
108        _ptprs[vsid] = ptpr;
109
110#if GIET_DEBUG_INIT
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);
122#endif
123
124    }
125
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
130    unsigned int isr_switch_channel = 0xFFFFFFFF;
131    unsigned int irq_id;            // IN_IRQ index
132    unsigned int hwi_mask = 0;
133    unsigned int pti_mask = 0;
134
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;
139
140        if ((isr == ISR_DMA) || (isr == ISR_IOC) || (isr == ISR_TTY)) 
141        {
142            hwi_mask = hwi_mask | 0x1 << irq_id;
143        }
144        else if ((isr == ISR_SWITCH)) 
145        { 
146            pti_mask = pti_mask | 0x1 << irq_id;
147            isr_switch_channel = irq_id;
148        }
149        else if ((isr == ISR_TIMER)) 
150        {
151            pti_mask = pti_mask | 0x1 << irq_id;
152        }
153    }
154
155#if GIET_DEBUG_INIT
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);
165#endif
166
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
170    // step 4 : start TICK timer if more than one task
171    if (tasks > 1) 
172    {
173        if (isr_switch_channel == 0xFFFFFFFF) 
174        {
175            _get_lock(&_tty_put_lock);
176            _puts("\n[GIET ERROR] ISR_SWITCH not found on proc ");
177            _putd(proc_id);
178            _puts("\n");
179            _release_lock(&_tty_put_lock);
180            _sys_exit();
181        }
182
183        if (_timer_start( cluster_id, isr_switch_channel, GIET_TICK_VALUE)) 
184        {
185            _get_lock(&_tty_put_lock);
186            _puts("\n[GIET ERROR] ISR_SWITCH init error for proc ");
187            _putd(proc_id);
188            _puts("\n");
189            _release_lock(&_tty_put_lock);
190            _sys_exit();
191        }
192
193#if GIET_DEBUG_INIT
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);
199#endif
200
201    } 
202
203    // step 5 : initialise, for each processor, the "idle" task context:
204    //          the SR initialisation value is 0xFF03 because
205    //          the task _ctx_idle() executes in kernel mode.
206    //          it uses the page table of vspace[0]
207    //          the stack size is 256 bytes
208
209    unsigned int stack = (unsigned int)_idle_stack + ((global_pid + 1)<<8);
210
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
219#if GIET_DEBUG_INIT
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);
225#endif
226
227    // step 6 : each processor initialises SP, SR, PTPR, EPC, registers
228    //          with the values corresponding to the first allocated task,
229    //          and starts the "idle" task if there is no task allocated.
230
231    ltid = 0;
232
233    if (tasks == 0) 
234    {
235        ltid = IDLE_TASK_INDEX;
236
237        _get_lock(&_tty_put_lock);
238        _puts("\n[GIET WARNING] No task allocated to processor ");
239        _putd(global_pid);
240        _puts(" => idle\n");
241        _release_lock (&_tty_put_lock);
242    }
243
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);
248
249    _set_task_slot( ltid, CTX_LTID_ID, ltid);
250
251#if GIET_DEBUG_INIT
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);
269#endif
270
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
279    // set  registers and jump to user code
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));
289
290} // end _kernel_init()
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.