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

Last change on this file since 618 was 615, checked in by bellefin, 10 years ago

Introduce mmc distributed lock
The locks are distributed in the kernel heaps (one lock in each cluster) and there is a global table in the kernel data segment which contains the addresses of all the locks.
The _mmc_boot_mode variable is defined in boot.c and kernel_init.c and defines which kind of lock is used.
The distributed locks are initialized inside the kernel_init() function.

  • Property svn:executable set to *
File size: 14.4 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// 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// Kernel uses distributed locks to protect MMC   
116__attribute__((section(".kdata")))
117unsigned int   _mmc_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 MMC
169        _mmc_init_locks();
170
171#if GIET_DEBUG_INIT
172_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes MMC distributed lock init\n", x , y , p );
173#endif
174        //////  distributed lock for TTY0
175        _sqt_lock_init( &_tty0_sqt_lock );
176
177#if GIET_DEBUG_INIT
178_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes TTY0 lock init\n", x , y , p );
179#endif
180        //////  distributed kernel barrier between all processors
181        _sqt_barrier_init( &_all_procs_barrier );
182
183#if GIET_DEBUG_INIT
184_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes barrier init\n", x , y , p );
185#endif
186
187        ////// _ext_irq_index[isr][channel] initialisation
188        if ( USE_PIC ) _ext_irq_init();
189
190#if GIET_DEBUG_INIT
191_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes ext_irq init\n", x , y , p );
192#endif
193
194        //////  NIC peripheral initialization
195        if ( USE_NIC ) _nic_global_init( 1,      // broadcast accepted
196                                         1,      // bypass activated
197                                         0,      // tdm non activated
198                                         0 );    // tdm period
199#if GIET_DEBUG_INIT
200_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes NIC init\n", x , y , p );
201#endif
202
203        //////  IOC peripheral initialisation
204        if ( USE_IOC_HBA )
205        {
206            _hba_init();
207            _ext_irq_alloc( ISR_HBA , 0 , &unused );
208
209#if GIET_DEBUG_INIT
210_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes HBA init\n", x , y , p );
211#endif
212        }
213        if ( USE_IOC_SDC )
214        {
215            _sdc_init();
216            _ext_irq_alloc( ISR_SDC , 0 , &unused );
217
218#if GIET_DEBUG_INIT
219_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes SDC init\n", x , y , p );
220#endif
221        }
222        if ( USE_IOC_BDV )
223        {
224            _bdv_init();
225            _ext_irq_alloc( ISR_BDV , 0 , &unused );
226
227#if GIET_DEBUG_INIT
228_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes BDV init\n", x , y , p );
229#endif
230        }
231
232        //////  release other processors
233        _kernel_init_done = 1;
234    }
235    else 
236    {
237        while( _kernel_init_done == 0 )  asm volatile ( "nop" );
238    }
239
240    ///////////////////////////////////////////////////////////////////////////
241    // Step 1 : each processor get its scheduler vaddr from CP0_SCHED,
242    //          contributes to _schedulers[] array initialisation,
243    //          and wait completion of array initialisation.
244    ///////////////////////////////////////////////////////////////////////////
245
246    static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
247    unsigned int        tasks      = psched->tasks;
248
249    _schedulers[x][y][p] = psched;
250
251#if GIET_DEBUG_INIT
252_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises SCHED array\n"
253        " - scheduler vbase = %x\n"
254        " - tasks           = %d\n",
255        x, y, p, (unsigned int)psched, tasks );
256#endif
257
258    /////////////////////////////////////////
259    _sqt_barrier_wait( &_all_procs_barrier );   
260    /////////////////////////////////////////
261
262    ////////////////////////////////////////////////////////////////////////////
263    // step 2 : each processor that is allocated at least one task loops
264    //          on its allocated tasks:
265    //          - contributes to _ptabs_vaddr[][][] & _ptabs_ptprs[][][]
266    //            initialisation, from values stored in the tasks contexts.
267    //          - set CTX_RA slot  with the kernel _ctx_eret() virtual address.
268    //          - set CTX_EPC slot that must contain the task entry point,
269    //            and contain only at this point the virtual address of the
270    //            memory slot containing this entry point.
271    ////////////////////////////////////////////////////////////////////////////
272
273    unsigned int ltid;
274
275    for (ltid = 0; ltid < tasks; ltid++) 
276    {
277        unsigned int vsid = _get_task_slot( x, y, p, ltid , CTX_VSID_ID ); 
278        unsigned int ptab = _get_task_slot( x, y, p, ltid , CTX_PTAB_ID ); 
279        unsigned int ptpr = _get_task_slot( x, y, p, ltid , CTX_PTPR_ID ); 
280
281        // initialize PTABS arrays
282        _ptabs_vaddr[vsid][x][y] = ptab;
283        _ptabs_ptprs[vsid][x][y] = ptpr;
284
285        // set the ptpr to use the local page table
286        asm volatile( "mtc2    %0,   $0"
287                      : : "r" (ptpr) );
288
289        // compute ctx_ra
290        unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
291        _set_task_slot( x, y, p, ltid, CTX_RA_ID, ctx_ra );
292
293        // compute ctx_epc
294        unsigned int* ptr = (unsigned int*)_get_task_slot(x,y,p,ltid,CTX_EPC_ID);
295        _set_task_slot(x,y,p,ltid,CTX_EPC_ID,*ptr);
296
297#if GIET_DEBUG_INIT
298_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises PTABS arrays"
299        " and context for task %d \n"
300        " - ptabs_vaddr[%d][%d][%d] = %x\n"
301        " - ptabs_paddr[%d][%d][%d] = %l\n"
302        " - ctx_epc              = %x\n"
303        " - ctx_ra               = %x\n",
304        x , y , p , ltid , 
305        vsid , x , y , ptab ,
306        vsid , x , y , ((unsigned long long)ptpr)<<13 ,
307        _get_task_slot( x, y, p, ltid, CTX_EPC_ID ),
308        _get_task_slot( x, y, p, ltid, CTX_RA_ID ) );
309#endif
310
311    }  // end for tasks
312
313    /////////////////////////////////////////
314    _sqt_barrier_wait( &_all_procs_barrier );   
315    /////////////////////////////////////////
316
317    ////////////////////////////////////////////////////////////////////////////
318    // step 3 : - Each processor complete idle task context initialisation,
319    //            (only the CTX_SP, CTX_RA, CTX_EPC slot, because the CTX_PTPR
320    //            and CTX_PTAB slots have been initialised in boot code)
321    //            The 4 Kbytes idle stack is implemented in the scheduler itself.
322    //          - Each processor starts TICK timer, as soon as at least one task
323    //            is allocated.
324    //          - P[0,0,0] initialises FAT (not done before, because it must
325    //            be done after the _ptabs_vaddr[v][x][y] array initialisation,
326    //            for V2P translation in _fat_ioc_access() function).
327    ////////////////////////////////////////////////////////////////////////////
328
329    unsigned int sp  = ((unsigned int)psched) + 0x2000;
330    unsigned int ra  = (unsigned int)(&_ctx_eret);
331    unsigned int epc = (unsigned int)(&_idle_task);
332
333    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_SP_ID  , sp  );
334    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_RA_ID  , ra  );
335    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_EPC_ID , epc );
336
337    if (tasks > 0) _xcu_timer_start( cluster_xy, p, GIET_TICK_VALUE ); 
338
339#if GIET_DEBUG_INIT
340_printf("\n[DEBUG KINIT] P[%d,%d,%d] initializes idle_task and starts TICK\n", 
341        x, y, p );
342#endif
343
344    if ( gpid == 0 )
345    {
346        _fat_init( 1 );   // kernel mode => Inode-Tree, Fat-Cache and File-Caches
347
348#if GIET_DEBUG_INIT
349_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel FAT init\n",
350        x, y, p );
351#endif
352
353    }
354
355    /////////////////////////////////////////
356    _sqt_barrier_wait( &_all_procs_barrier );   
357    /////////////////////////////////////////
358
359    ////////////////////////////////////////////////////////////////////////////
360    // step 4 : Each processor compute values for registers SP, SR, PTPR, EPC,
361    //          corresponding to the first allocated task (can be idle task)
362    //          and jumps to user code.
363    ////////////////////////////////////////////////////////////////////////////
364
365    if (tasks == 0) _printf("\n[GIET WARNING] No task allocated to P[%d,%d,%d]\n",
366                            x, y, p );
367
368    if (tasks == 0) ltid = IDLE_TASK_INDEX;
369    else            ltid = 0;
370
371    unsigned int sp_value   = _get_task_slot( x, y, p, ltid, CTX_SP_ID);
372    unsigned int sr_value   = _get_task_slot( x, y, p, ltid, CTX_SR_ID);
373    unsigned int ptpr_value = _get_task_slot( x, y, p, ltid, CTX_PTPR_ID);
374    unsigned int epc_value  = _get_task_slot( x, y, p, ltid, CTX_EPC_ID);
375
376#if GIET_DEBUG_INIT
377_printf("\n[DEBUG KINIT] P[%d,%d,%d] jumps to user code at cycle %d\n"
378        " ltid = %d / sp = %x / sr = %x / ptpr = %x / epc = %x\n",
379        x , y , p , _get_proctime() ,
380        ltid , sp_value , sr_value , ptpr_value , epc_value );
381#endif
382
383    // set registers and jump to user code
384    asm volatile ( "move  $29,  %0                  \n"   /* SP <= ctx[CTX_SP_ID] */
385                   "mtc0  %1,   $12                 \n"   /* SR <= ctx[CTX_SR_ID] */
386                   "mtc2  %2,   $0                  \n"   /* PTPR <= ctx[CTX_PTPR] */
387                   "mtc0  %3,   $14                 \n"   /* EPC <= ctx[CTX_EPC]  */
388                   "eret                            \n"   /* jump to user code  */
389                   "nop                             \n"
390                   : 
391                   : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value)
392                   : "$29", "memory" );
393
394} // end kernel_init()
395
396
397// Local Variables:
398// tab-width: 4
399// c-basic-offset: 4
400// c-file-offsets:((innamespace . 0)(inline-open . 0))
401// indent-tabs-mode: nil
402// End:
403// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
404
Note: See TracBrowser for help on using the repository browser.