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

Last change on this file since 589 was 579, checked in by bellefin, 10 years ago

Improve hba driver : adding the _hba_boot_mode variable to indicate which mode is used

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