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

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

Several bugs have been fixed to support TSAR multi-cluster architecture
such as the "tsarv4-generic_mmu" platform.

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