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

Last change on this file since 529 was 528, checked in by alain, 10 years ago

1) Introducing support for external IRQs dynamic routing.
2) Simplifying the _v2p_translate() function.
3) Removing the generic IOC driver (integrated in the FAT library).

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