source: soft/giet_vm/giet_kernel/kernel_init.c@ 546

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

Blap.

  • Property svn:executable set to *
File size: 13.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// This kernel_init.c file is part of the GIET-VM nano-kernel.
8////////////////////////////////////////////////////////////////////////////////////
9
10#include <giet_config.h>
11#include <hard_config.h>
12#include <utils.h>
13#include <vmem.h>
14#include <tty0.h>
15#include <kernel_malloc.h>
16#include <kernel_locks.h>
17#include <kernel_barriers.h>
18#include <fat32.h>
19#include <xcu_driver.h>
20#include <mmc_driver.h>
21#include <ctx_handler.h>
22#include <irq_handler.h>
23#include <mapping_info.h>
24#include <mips32_registers.h>
25
26#if !defined(X_SIZE)
27# error: You must define X_SIZE in the hard_config.h file
28#endif
29
30#if !defined(Y_SIZE)
31# error: You must define Y_SIZE in the hard_config.h file
32#endif
33
34#if !defined(Y_WIDTH)
35# error: You must define Y_WIDTH in the hard_config.h file
36#endif
37
38#if !defined(Y_WIDTH)
39# error: You must define Y_WIDTH in the hard_config.h file
40#endif
41
42#if !defined(NB_PROCS_MAX)
43# error: You must define NB_PROCS_MAX in the hard_config.h file
44#endif
45
46#if !defined(NB_TOTAL_PROCS)
47# error: You must define NB_TOTAL_PROCS in the hard_config.h file
48#endif
49
50#if !defined(USE_XCU)
51# error: You must define USE_XCU in the hard_config.h file
52#endif
53
54#if !defined(USE_PIC)
55# error: You must define USE_PIC in the hard_config.h file
56#endif
57
58#if !defined(IDLE_TASK_INDEX)
59# error: You must define IDLE_TASK_INDEX in the ctx_handler.h file
60#endif
61
62#if !defined(GIET_TICK_VALUE)
63# error: You must define GIET_TICK_VALUE in the giet_config.h file
64#endif
65
66#if !defined(GIET_NB_VSPACE_MAX)
67# error: You must define GIET_NB_VSPACE_MAX in the giet_config.h file
68#endif
69
70#if !defined(NB_TTY_CHANNELS)
71# error: You must define NB_TTY_CHANNELS in the hard_config.h file
72#endif
73
74#if (NB_TTY_CHANNELS < 1)
75# error: NB_TTY_CHANNELS cannot be smaller than 1
76#endif
77
78#if !defined(GIET_ISR_TYPE_MAX)
79# error: You must define GIET_ISR_TYPE_MAX in the giet_config.h file
80#endif
81
82#if !defined(GIET_ISR_CHANNEL_MAX)
83# error: You must define GIET_ISR_CHANNEL_MAX in the giet_config.h file
84#endif
85
86
87////////////////////////////////////////////////////////////////////////////////
88// Global variables
89////////////////////////////////////////////////////////////////////////////////
90
91// FAT internal representation for kernel code
92__attribute__((section(".kdata")))
93fat32_fs_t _fat __attribute__((aligned(512)));
94
95// array of page tables virtual addresses
96__attribute__((section(".kdata")))
97volatile unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
98
99// array of page tables PTPR values (physical addresses >> 13)
100__attribute__((section(".kdata")))
101volatile unsigned int _ptabs_ptprs[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
102
103// Array of pointers on the schedulers
104__attribute__((section(".kdata")))
105volatile static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
106
107// Synchonisation before entering parallel execution
108__attribute__((section(".kdata")))
109volatile unsigned int _kernel_init_done = 0;
110
111// Kernel uses sqt_lock to protect TTY0
112__attribute__((section(".kdata")))
113unsigned int _tty0_boot_mode = 0;
114
115// synchronisation barrier for parallel init by all processors
116__attribute__((section(".kdata")))
117sqt_barrier_t _all_procs_barrier __attribute__((aligned(64)));
118
119////////////////////////////////////////////////////////////////////////////////
120// Extern variables
121////////////////////////////////////////////////////////////////////////////////
122
123// this variable is defined in tty0.c file
124extern sqt_lock_t _tty0_sqt_lock;
125
126////////////////////////////////////////////////////////////////////////////////
127// This kernel_init() function completes the kernel initialisation in 6 steps:
128// Step 0 is done by processor[0,0,0]. Steps 1 to 4 are executed in parallel
129// by all processors.
130// - step 0 : P[0,0,0] Initialise various global variables.
131// - step 1 : Each processor initialises scheduler pointers array.
132// - step 2 : Each processor initialises PTAB pointers arrays.
133// - step 3 : Each processor initialise idle task and starts TICK timer.
134// - step 4 : Each processor set sp, sr, ptpr, epc registers values.
135////////////////////////////////////////////////////////////////////////////////
136__attribute__((section (".kinit"))) void kernel_init()
137{
138 // gpid : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
139 // x,y,p : proc coordinates ( x < X_SIZE / y < Y_SIZE / p < NB_PROCS_MAX )
140
141 unsigned int gpid = _get_procid();
142 unsigned int cluster_xy = gpid >> P_WIDTH;
143 unsigned int x = cluster_xy >> Y_WIDTH & ((1<<X_WIDTH)-1);
144 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
145 unsigned int p = gpid & ((1<<P_WIDTH)-1);
146
147 ////////////////////////////////////////////////////////////////////////////
148 // Step 0 : P[0,0,0] initialises various global vaiables
149 ////////////////////////////////////////////////////////////////////////////
150
151 if ( gpid == 0 )
152 {
153 // distributed kernel heap initialisation
154 _heap_init();
155
156#if GIET_DEBUG_INIT
157_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes kernel HEAP init\n",
158 x, y, p );
159#endif
160 // distributed lock for TTY0
161 _sqt_lock_init( &_tty0_sqt_lock );
162
163#if GIET_DEBUG_INIT
164_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes TTY0 lock init\n",
165 x , y , p );
166#endif
167 // distributed kernel barrier between all processors
168 _sqt_barrier_init( &_all_procs_barrier );
169
170#if GIET_DEBUG_INIT
171_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes barrier init\n",
172 x , y , p );
173#endif
174
175#if USE_PIC
176
177 // _ext_irq_index[isr][channel] initialisation
178 _ext_irq_init();
179
180 // routing HBA IRQ to proc[0,0,0] EXT_IRQ_ONE
181 unsigned int unused = 0;
182 if ( USE_IOC_HBA ) _ext_irq_alloc( ISR_HBA , 0 , &unused );
183
184#if GIET_DEBUG_INIT
185_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes ext_irq init\n",
186 x , y , p );
187#endif
188
189#endif // USE_PIC
190
191 // release other processors
192 _kernel_init_done = 1;
193 }
194 else
195 {
196 while( _kernel_init_done == 0 ) asm volatile ( "nop" );
197 }
198
199 ///////////////////////////////////////////////////////////////////////////
200 // Step 1 : each processor get its scheduler vaddr from CP0_SCHED,
201 // contributes to _schedulers[] array initialisation,
202 // and wait completion of array initialisation.
203 ///////////////////////////////////////////////////////////////////////////
204
205 static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
206 unsigned int tasks = psched->tasks;
207
208 _schedulers[x][y][p] = psched;
209
210#if GIET_DEBUG_INIT
211_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initialises SCHED array\n"
212 " - scheduler vbase = %x\n"
213 " - tasks = %d\n",
214 x, y, p, (unsigned int)psched, tasks );
215#endif
216
217 /////////////////////////////////////////
218 _sqt_barrier_wait( &_all_procs_barrier );
219 /////////////////////////////////////////
220
221 ////////////////////////////////////////////////////////////////////////////
222 // step 2 : each processor that is allocated at least one task loops
223 // on its allocated tasks:
224 // - contributes to _ptabs_vaddr[][][] & _ptabs_ptprs[][][]
225 // initialisation, from values stored in the tasks contexts.
226 // - set CTX_RA slot with the kernel _ctx_eret() virtual address.
227 // - set CTX_EPC slot that must contain the task entry point,
228 // and contain only at this point the virtual address of the
229 // memory slot containing this entry point.
230 ////////////////////////////////////////////////////////////////////////////
231
232 unsigned int ltid;
233
234 for (ltid = 0; ltid < tasks; ltid++)
235 {
236 unsigned int vsid = _get_task_slot( x, y, p, ltid , CTX_VSID_ID );
237 unsigned int ptab = _get_task_slot( x, y, p, ltid , CTX_PTAB_ID );
238 unsigned int ptpr = _get_task_slot( x, y, p, ltid , CTX_PTPR_ID );
239
240 // initialize PTABS arrays
241 _ptabs_vaddr[vsid][x][y] = ptab;
242 _ptabs_ptprs[vsid][x][y] = ptpr;
243
244 // set the ptpr to use the local page table
245 asm volatile( "mtc2 %0, $0"
246 : : "r" (ptpr) );
247
248 // compute ctx_ra
249 unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
250 _set_task_slot( x, y, p, ltid, CTX_RA_ID, ctx_ra );
251
252 // compute ctx_epc
253 unsigned int* ptr = (unsigned int*)_get_task_slot(x,y,p,ltid,CTX_EPC_ID);
254 _set_task_slot(x,y,p,ltid,CTX_EPC_ID,*ptr);
255
256#if GIET_DEBUG_INIT
257_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initialises PTABS arrays"
258 " and context for task %d \n"
259 " - ptabs_vaddr[%d][%d][%d] = %x\n"
260 " - ptabs_paddr[%d][%d][%d] = %l\n"
261 " - ctx_epc = %x\n"
262 " - ctx_ra = %x\n",
263 x , y , p , ltid ,
264 vsid , x , y , ptab ,
265 vsid , x , y , ((unsigned long long)ptpr)<<13 ,
266 _get_task_slot( x, y, p, ltid, CTX_EPC_ID ),
267 _get_task_slot( x, y, p, ltid, CTX_RA_ID ) );
268#endif
269
270 } // end for tasks
271
272 /////////////////////////////////////////
273 _sqt_barrier_wait( &_all_procs_barrier );
274 /////////////////////////////////////////
275
276 ////////////////////////////////////////////////////////////////////////////
277 // step 3 : - Each processor complete idle task context initialisation,
278 // (only the CTX_SP, CTX_RA, CTX_EPC slot, because the CTX_PTPR
279 // and CTX_PTAB slots have been initialised in boot code)
280 // The 4 Kbytes idle stack is implemented in the scheduler itself.
281 // - Each processor starts TICK timer, as soon as at least one task
282 // is allocated.
283 // - P[0,0,0] initialises FAT (not done before, because it must
284 // be done after the _ptabs_vaddr[v][x][y] array initialisation,
285 // for V2P translation in _fat_ioc_access() function).
286 ////////////////////////////////////////////////////////////////////////////
287
288 unsigned int sp = ((unsigned int)psched) + 0x2000;
289 unsigned int ra = (unsigned int)(&_ctx_eret);
290 unsigned int epc = (unsigned int)(&_idle_task);
291
292 _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_SP_ID , sp );
293 _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_RA_ID , ra );
294 _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_EPC_ID , epc );
295
296 if (tasks > 0) _xcu_timer_start( cluster_xy, p, GIET_TICK_VALUE );
297
298#if GIET_DEBUG_INIT
299_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initializes idle_task and starts TICK\n",
300 x, y, p );
301#endif
302
303 if ( gpid == 0 )
304 {
305 _fat_init( 0 ); // no IRQ
306
307#if GIET_DEBUG_INIT
308_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes kernel FAT init\n",
309 x, y, p );
310#endif
311
312 }
313
314 /////////////////////////////////////////
315 _sqt_barrier_wait( &_all_procs_barrier );
316 /////////////////////////////////////////
317
318 ////////////////////////////////////////////////////////////////////////////
319 // step 4 : Each processor compute values for registers SP, SR, PTPR, EPC,
320 // corresponding to the first allocated task (can be idle task)
321 // and jumps to user code.
322 ////////////////////////////////////////////////////////////////////////////
323
324 if (tasks == 0) _printf("\n[GIET WARNING] No task allocated to P[%d,%d,%d]\n",
325 x, y, p );
326
327 if (tasks == 0) ltid = IDLE_TASK_INDEX;
328 else ltid = 0;
329
330 unsigned int sp_value = _get_task_slot( x, y, p, ltid, CTX_SP_ID);
331 unsigned int sr_value = _get_task_slot( x, y, p, ltid, CTX_SR_ID);
332 unsigned int ptpr_value = _get_task_slot( x, y, p, ltid, CTX_PTPR_ID);
333 unsigned int epc_value = _get_task_slot( x, y, p, ltid, CTX_EPC_ID);
334
335#if GIET_DEBUG_INIT
336_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] jumps to user code at cycle %d\n"
337 " ltid = %d / sp = %x / sr = %x / ptpr = %x / epc = %x\n",
338 x , y , p , _get_proctime() ,
339 ltid , sp_value , sr_value , ptpr_value , epc_value );
340#endif
341
342 // set registers and jump to user code
343 asm volatile ( "move $29, %0 \n" /* SP <= ctx[CTX_SP_ID] */
344 "mtc0 %1, $12 \n" /* SR <= ctx[CTX_SR_ID] */
345 "mtc2 %2, $0 \n" /* PTPR <= ctx[CTX_PTPR] */
346 "mtc0 %3, $14 \n" /* EPC <= ctx[CTX_EPC] */
347 "eret \n" /* jump to user code */
348 "nop \n"
349 :
350 : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value)
351 : "$29", "memory" );
352
353} // end kernel_init()
354
355
356// Local Variables:
357// tab-width: 4
358// c-basic-offset: 4
359// c-file-offsets:((innamespace . 0)(inline-open . 0))
360// indent-tabs-mode: nil
361// End:
362// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
363
Note: See TracBrowser for help on using the repository browser.