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

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

Introducing the "idle" to improve the exit mechanism.

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