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

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

Introducing support for Network controller

File size: 9.5 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"))) 
[199]39unsigned int                    _ptabs_paddr[GIET_NB_VSPACE_MAX]; 
[167]40
[189]41__attribute__((section (".kdata"))) 
[199]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"))) 
[199]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"))) 
56unsigned int                    _idle_stack[NB_CLUSTERS*NB_PROCS_MAX*64]; 
57
[215]58void _sys_exit()
59{
60    while(1);
61}
62
[165]63//////////////////////////////////////////////////////////////////////////////////
[189]64// This function is the entry point for the last step of the boot sequence.
[165]65//////////////////////////////////////////////////////////////////////////////////
[189]66__attribute__((section (".kinit"))) void _kernel_init()
[165]67{
[199]68    // compute cluster and local processor index
[207]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;
[165]72
[207]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
[189]87    // step 1 : Initialise scheduler physical addresses array
[207]88    //          get scheduler physical address (from CP0 register)
[189]89
90    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
[207]91    _schedulers_paddr[global_pid]  = psched;
[189]92
93#if GIET_DEBUG_INIT
94_get_lock(&_tty_put_lock);
95_puts("\n[GIET DEBUG] step 1 for processor ");
[207]96_putd( global_pid );
[199]97_puts(" / scheduler pbase = ");
[207]98_putx( (unsigned int)psched );
[189]99_puts("\n");
100_release_lock(&_tty_put_lock);
101#endif
102
[199]103    // step 2 : initialise page table addresse arrays
[203]104    //          each processor scans all tasks contexts in its
105    //          private scheduler and get VSID, PTAB and PTPR values
[199]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; 
[203]114
[199]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 ");
[207]121_putd( global_pid );
[199]122_puts(" / vspace ");
123_putd( vspace_id );
124_puts("\n- ptab vbase = ");
[207]125_putx( ptab_vaddr );
[199]126_puts("\n- ptab pbase = ");
[207]127_putx( ptab_paddr );
[199]128_puts("\n");
129_release_lock(&_tty_put_lock);
130#endif
131
132    }
133 
[216]134    unsigned int isr_switch_channel = 0xFFFFFFFF;
135
[203]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
[189]140    unsigned int irq_id;
[203]141    unsigned int hwi_mask = 0;
142    unsigned int pti_mask = 0;
143
[189]144    for ( irq_id = 0 ; irq_id < 32 ; irq_id++ )
[165]145    {
[203]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        }
[215]153        else if ( (isr == ISR_SWITCH) )
[203]154        { 
155            pti_mask = pti_mask | 0x1<< irq_id;
[215]156            isr_switch_channel = irq_id;
[203]157        }
[215]158        else if ( (isr == ISR_TIMER) )
159        {
160            pti_mask = pti_mask | 0x1<< irq_id;
161        }
[165]162    }
[207]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
[189]165   
166#if GIET_DEBUG_INIT
167_get_lock(&_tty_put_lock);
[199]168_puts("\n[GIET DEBUG] step 3 for processor ");
[207]169_putd( global_pid );
[203]170_puts("\n - ICU HWI_MASK = ");
[207]171_putx( hwi_mask );
[203]172_puts("\n - ICU PTI_MASK = ");
[207]173_putx( pti_mask );
[189]174_puts("\n");
175_release_lock(&_tty_put_lock);
176#endif
[165]177
[189]178    // step 4 : start TICK timer if more than one task
179    if ( tasks > 1 )
[165]180    {
[215]181        if(isr_switch_channel == 0xFFFFFFFF)
182        {
[216]183            _get_lock(&_tty_put_lock);
[215]184            _puts("\n[GIET ERROR] ISR_SWITCH not found on proc ");
185            _putd( proc_id);
186            _puts("\n");
[216]187            _release_lock(&_tty_put_lock);
[215]188            _sys_exit();
189        }
[216]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        }
[189]200       
201#if GIET_DEBUG_INIT
202_get_lock(&_tty_put_lock);
203_puts("\n[GIET DEBUG] Step 4 for processor ");
[207]204_putd( global_pid );
[203]205_puts(" / context switch activated\n");
[189]206_release_lock(&_tty_put_lock);
207#endif
208   
209    } 
210
[218]211    // step 5 : initialise, for each processor, the "idle" task context:
[199]212    //          the SR initialisation value is 0xFF03 because
[218]213    //          the task _ctx_idle() executes in kernel mode.
[199]214    //          it uses the page table of vspace[0]
[218]215    //          the stack size is 256 bytes
[199]216 
217    _set_context_slot( IDLE_TASK_INDEX, CTX_RUN_ID,  1 );
218    _set_context_slot( IDLE_TASK_INDEX, CTX_SR_ID,   0xFF03 );
[218]219    _set_context_slot( IDLE_TASK_INDEX, CTX_SP_ID,   (unsigned int)_idle_stack + (global_pid<<8) );
[199]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 ");
[207]228_putd( global_pid );
[199]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
[189]234    //          with the values corresponding to the first allocated task,
[199]235    //          and starts the "idle" task if there is no task allocated.
[189]236
[199]237    unsigned int task_id;
238
239    if ( tasks == 0 )
[189]240    {
[199]241        task_id = IDLE_TASK_INDEX;
[165]242
[199]243        _get_lock( &_tty_put_lock );
[218]244        _puts("\n[GIET WARNING] No task allocated to processor ");
[207]245        _putd( global_pid );
[199]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
[189]259#if GIET_DEBUG_INIT
260_get_lock(&_tty_put_lock);
[199]261_puts("\n[GIET DEBUG] step 6 for processor ");
[207]262_putd( global_pid );
[199]263_puts(" / registers initialised \n");
[189]264_puts("- sp   = ");
[207]265_putx( sp_value );
[189]266_puts("\n");
267_puts("- sr   = ");
[207]268_putx( sr_value );
[189]269_puts("\n");
270_puts("- ptpr = ");
[207]271_putx( ptpr_value<<13 );
[189]272_puts("\n");
273_puts("- epc  = ");
[207]274_putx( epc_value );
[189]275_puts("\n");
276_release_lock(&_tty_put_lock);
277#endif
[165]278
[199]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) );
[165]288
289} // end _kernel_init()
Note: See TracBrowser for help on using the repository browser.