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

Last change on this file since 216 was 216, checked in by karaoui, 12 years ago
  • updating irq_handler.c/drivers.c to support the nex affectations of timers
  • When using an xicu the number of timer is set to 32
File size: 9.0 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// Kernel Global variables
36///////////////////////////////////////////////////////////////////////////////////
37
38__attribute__((section (".kdata"))) 
39unsigned int                    _ptabs_paddr[GIET_NB_VSPACE_MAX]; 
40
41__attribute__((section (".kdata"))) 
42unsigned int                    _ptabs_vaddr[GIET_NB_VSPACE_MAX]; 
43
44__attribute__((section (".kdata"))) 
45static_scheduler_t*             _schedulers_paddr[NB_CLUSTERS*NB_PROCS_MAX]; 
46
47__attribute__((section (".kdata"))) 
48unsigned int                    _idle_stack[NB_CLUSTERS*NB_PROCS_MAX*64]; 
49
50void _sys_exit()
51{
52    while(1);
53}
54
55//////////////////////////////////////////////////////////////////////////////////
56// This function is the entry point for the last step of the boot sequence.
57//////////////////////////////////////////////////////////////////////////////////
58__attribute__((section (".kinit"))) void _kernel_init()
59{
60    // compute cluster and local processor index
61    unsigned int        global_pid = _procid();
62    unsigned int    cluster_id = global_pid / NB_PROCS_MAX;
63    unsigned int    proc_id    = global_pid % NB_PROCS_MAX;
64
65    // Step 0 : Compute number of tasks allocated to proc
66
67    unsigned int tasks = _get_tasks_number();
68
69#if GIET_DEBUG_INIT
70_get_lock(&_tty_put_lock);
71_puts("\n[GIET DEBUG] step 0 for processor ");
72_putd( global_pid );
73_puts(" : tasks = ");
74_putd( tasks );
75_puts("\n");
76_release_lock(&_tty_put_lock);
77#endif
78
79    // step 1 : Initialise scheduler physical addresses array
80    //          get scheduler physical address (from CP0 register)
81
82    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
83    _schedulers_paddr[global_pid]  = psched;
84
85#if GIET_DEBUG_INIT
86_get_lock(&_tty_put_lock);
87_puts("\n[GIET DEBUG] step 1 for processor ");
88_putd( global_pid );
89_puts(" / scheduler pbase = ");
90_putx( (unsigned int)psched );
91_puts("\n");
92_release_lock(&_tty_put_lock);
93#endif
94
95    // step 2 : initialise page table addresse 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 vspace_id  = _get_context_slot( ltid , CTX_VSID_ID ); 
104        unsigned int ptab_vaddr = _get_context_slot( ltid , CTX_PTAB_ID ); 
105        unsigned int ptab_paddr = _get_context_slot( ltid , CTX_PTPR_ID ) << 13; 
106
107        _ptabs_vaddr[vspace_id] = ptab_vaddr;
108        _ptabs_paddr[vspace_id] = ptab_paddr;
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( vspace_id );
116_puts("\n- ptab vbase = ");
117_putx( ptab_vaddr );
118_puts("\n- ptab pbase = ");
119_putx( ptab_paddr );
120_puts("\n");
121_release_lock(&_tty_put_lock);
122#endif
123
124    }
125 
126    unsigned int isr_switch_channel = 0xFFFFFFFF;
127
128    // step 3 : compute and set ICU masks
129    //          there is at most 32 interrupts per processor
130    //          software interrupts are not supported yet
131
132    unsigned int irq_id;
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  = _get_interrupt_vector_entry(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    _icu_set_mask( cluster_id, proc_id, hwi_mask, 0 ); // set HWI_MASK
156    _icu_set_mask( cluster_id, proc_id, pti_mask, 1 );  // set PTI_MASK
157   
158#if GIET_DEBUG_INIT
159_get_lock(&_tty_put_lock);
160_puts("\n[GIET DEBUG] step 3 for processor ");
161_putd( global_pid );
162_puts("\n - ICU HWI_MASK = ");
163_putx( hwi_mask );
164_puts("\n - ICU PTI_MASK = ");
165_putx( pti_mask );
166_puts("\n");
167_release_lock(&_tty_put_lock);
168#endif
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 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 
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] + 64 );
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
216#if GIET_DEBUG_INIT
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);
222#endif
223   
224    // step 6 : each processor initialises SP, SR, PTPR, EPC, registers
225    //          with the values corresponding to the first allocated task,
226    //          and starts the "idle" task if there is no task allocated.
227
228    unsigned int task_id;
229
230    if ( tasks == 0 )
231    {
232        task_id = IDLE_TASK_INDEX;
233
234        _get_lock( &_tty_put_lock );
235        _puts("\n [GIET WARNING] No task allocated to processor ");
236        _putd( global_pid );
237        _puts(" => idle\n");
238        _release_lock ( &_tty_put_lock );
239    }
240    else
241    {
242        task_id = 0;
243    }
244       
245    unsigned int    sp_value   = _get_context_slot( task_id, CTX_SP_ID );
246    unsigned int    sr_value   = _get_context_slot( task_id, CTX_SR_ID );
247    unsigned int    ptpr_value = _get_context_slot( task_id, CTX_PTPR_ID );
248    unsigned int    epc_value  = _get_context_slot( task_id, CTX_EPC_ID );
249
250#if GIET_DEBUG_INIT
251_get_lock(&_tty_put_lock);
252_puts("\n[GIET DEBUG] step 6 for processor ");
253_putd( global_pid );
254_puts(" / registers initialised \n");
255_puts("- sp   = ");
256_putx( sp_value );
257_puts("\n");
258_puts("- sr   = ");
259_putx( sr_value );
260_puts("\n");
261_puts("- ptpr = ");
262_putx( ptpr_value<<13 );
263_puts("\n");
264_puts("- epc  = ");
265_putx( epc_value );
266_puts("\n");
267_release_lock(&_tty_put_lock);
268#endif
269
270    // set  registers and jump to user code
271    asm volatile ( "move        $29,    %0              \n"             /* SP <= ctx[CTX_SP_ID] */
272                   "mtc0        %1,             $12             \n"             /* SR <= ctx[CTX_SR_ID] */
273                   "mtc2        %2,             $0              \n"             /* PTPR <= ctx[CTX_PTPR_ID] */
274                   "mtc0        %3,             $14             \n"             /* EPC <= ctx[CTX_EPC_ID] */
275                   "eret                                        \n"             /* jump to user code */
276                   "nop                                         \n"
277                   :
278                   : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value) );
279
280} // end _kernel_init()
Note: See TracBrowser for help on using the repository browser.