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

Last change on this file since 218 was 218, checked in by alain, 12 years ago

Introducing support for Network controller

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