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
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : kernel_init.c
3// Date     : 26/05/2012
4// Authors  : alain greiner & mohamed karaoui
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////////
[440]7// This kernel_init.c file is part of the GIET-VM nano-kernel.
[258]8////////////////////////////////////////////////////////////////////////////////////
9
10#include <giet_config.h>
[440]11#include <hard_config.h>
[258]12#include <utils.h>
[528]13#include <vmem.h>
[459]14#include <tty0.h>
[467]15#include <kernel_malloc.h>
[494]16#include <kernel_locks.h>
17#include <kernel_barriers.h>
[258]18#include <fat32.h>
19#include <xcu_driver.h>
[547]20#include <nic_driver.h>
21#include <hba_driver.h>
[568]22#include <sdc_driver.h>
23#include <bdv_driver.h>
[478]24#include <mmc_driver.h>
[258]25#include <ctx_handler.h>
26#include <irq_handler.h>
27#include <mapping_info.h>
28#include <mips32_registers.h>
29
[322]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
[528]58#if !defined(USE_PIC)
59# error: You must define USE_PIC in the hard_config.h file
60#endif
61
[322]62#if !defined(IDLE_TASK_INDEX)
[391]63# error: You must define IDLE_TASK_INDEX in the ctx_handler.h file
[322]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
[467]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
[528]82#if !defined(GIET_ISR_TYPE_MAX)
83# error: You must define GIET_ISR_TYPE_MAX in the giet_config.h file
84#endif
[467]85
[528]86#if !defined(GIET_ISR_CHANNEL_MAX)
87# error: You must define GIET_ISR_CHANNEL_MAX in the giet_config.h file
88#endif
[467]89
90
[528]91////////////////////////////////////////////////////////////////////////////////
92//       Global variables
93////////////////////////////////////////////////////////////////////////////////
94
[494]95// array of page tables virtual addresses
96__attribute__((section(".kdata")))
[528]97volatile unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 
[258]98
[494]99// array of page tables PTPR values (physical addresses >> 13)
100__attribute__((section(".kdata")))
[528]101volatile unsigned int _ptabs_ptprs[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 
[258]102
[494]103// Array of pointers on the schedulers
104__attribute__((section(".kdata")))
[528]105volatile static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
[258]106
[494]107// Synchonisation before entering parallel execution
108__attribute__((section(".kdata")))
109volatile unsigned int _kernel_init_done = 0;
[258]110
[494]111// Kernel uses sqt_lock to protect TTY0       
112__attribute__((section(".kdata")))
113unsigned int   _tty0_boot_mode = 0;
[294]114
[615]115// Kernel uses distributed locks to protect MMC   
116__attribute__((section(".kdata")))
117unsigned int   _mmc_boot_mode = 0;
118
[579]119// Kernel uses sqt_lock to protect command allocator in HBA       
120__attribute__((section(".kdata")))
121unsigned int   _hba_boot_mode = 0;
122
[528]123// synchronisation barrier for parallel init by all processors     
[494]124__attribute__((section(".kdata")))
125sqt_barrier_t  _all_procs_barrier  __attribute__((aligned(64)));
[467]126
[528]127////////////////////////////////////////////////////////////////////////////////
128//      Extern variables
129////////////////////////////////////////////////////////////////////////////////
[467]130
[494]131// this variable is defined in tty0.c file
132extern sqt_lock_t _tty0_sqt_lock;
[467]133
[528]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.
[494]139// - step 1 : Each processor initialises scheduler pointers array.
140// - step 2 : Each processor initialises PTAB pointers arrays.
[528]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////////////////////////////////////////////////////////////////////////////////
[310]144__attribute__((section (".kinit"))) void kernel_init() 
[258]145{
[494]146    // gpid  : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
[528]147    // x,y,p : proc coordinates ( x < X_SIZE / y < Y_SIZE / p < NB_PROCS_MAX )
[428]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);
[294]152    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[440]153    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[547]154    unsigned int unused;
155   
[494]156    ////////////////////////////////////////////////////////////////////////////
[547]157    // Step 0 : P[0,0,0] initialises global variables and peripherals
158   ////////////////////////////////////////////////////////////////////////////
[428]159
[467]160    if ( gpid == 0 )
161    {
[547]162        //////  distributed kernel heap initialisation
[467]163        _heap_init();
164       
165#if GIET_DEBUG_INIT
[547]166_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel heap init\n", x, y, p );
[467]167#endif
[615]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
[547]174        //////  distributed lock for TTY0
[494]175        _sqt_lock_init( &_tty0_sqt_lock );
[459]176
[467]177#if GIET_DEBUG_INIT
[547]178_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes TTY0 lock init\n", x , y , p );
[467]179#endif
[547]180        //////  distributed kernel barrier between all processors
[494]181        _sqt_barrier_init( &_all_procs_barrier );
[467]182
183#if GIET_DEBUG_INIT
[547]184_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes barrier init\n", x , y , p );
[467]185#endif
186
[547]187        ////// _ext_irq_index[isr][channel] initialisation
188        if ( USE_PIC ) _ext_irq_init();
[528]189
[547]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
[528]193
[547]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
[528]202
[568]203        //////  IOC peripheral initialisation
[547]204        if ( USE_IOC_HBA )
205        {
206            _hba_init();
207            _ext_irq_alloc( ISR_HBA , 0 , &unused );
208
[528]209#if GIET_DEBUG_INIT
[547]210_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes HBA init\n", x , y , p );
[528]211#endif
[568]212        }
213        if ( USE_IOC_SDC )
214        {
215            _sdc_init();
216            _ext_irq_alloc( ISR_SDC , 0 , &unused );
[528]217
[568]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
[547]232        //////  release other processors
[494]233        _kernel_init_done = 1;
[467]234    }
[494]235    else 
236    {
237        while( _kernel_init_done == 0 )  asm volatile ( "nop" );
238    }
[467]239
[528]240    ///////////////////////////////////////////////////////////////////////////
[494]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.
[528]244    ///////////////////////////////////////////////////////////////////////////
[258]245
246    static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
247    unsigned int        tasks      = psched->tasks;
248
[440]249    _schedulers[x][y][p] = psched;
[258]250
251#if GIET_DEBUG_INIT
[547]252_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises SCHED array\n"
[494]253        " - scheduler vbase = %x\n"
254        " - tasks           = %d\n",
255        x, y, p, (unsigned int)psched, tasks );
[258]256#endif
257
[528]258    /////////////////////////////////////////
[494]259    _sqt_barrier_wait( &_all_procs_barrier );   
[528]260    /////////////////////////////////////////
[494]261
262    ////////////////////////////////////////////////////////////////////////////
[294]263    // step 2 : each processor that is allocated at least one task loops
[528]264    //          on its allocated tasks:
265    //          - contributes to _ptabs_vaddr[][][] & _ptabs_ptprs[][][]
266    //            initialisation, from values stored in the tasks contexts.
[294]267    //          - set CTX_RA slot  with the kernel _ctx_eret() virtual address.
268    //          - set CTX_EPC slot that must contain the task entry point,
[528]269    //            and contain only at this point the virtual address of the
270    //            memory slot containing this entry point.
271    ////////////////////////////////////////////////////////////////////////////
[258]272
273    unsigned int ltid;
274
275    for (ltid = 0; ltid < tasks; ltid++) 
276    {
[440]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 ); 
[258]280
[294]281        // initialize PTABS arrays
[528]282        _ptabs_vaddr[vsid][x][y] = ptab;
283        _ptabs_ptprs[vsid][x][y] = ptpr;
[258]284
[528]285        // set the ptpr to use the local page table
286        asm volatile( "mtc2    %0,   $0"
[294]287                      : : "r" (ptpr) );
288
289        // compute ctx_ra
[258]290        unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
[440]291        _set_task_slot( x, y, p, ltid, CTX_RA_ID, ctx_ra );
[258]292
[294]293        // compute ctx_epc
[528]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);
[258]296
297#if GIET_DEBUG_INIT
[547]298_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises PTABS arrays"
[528]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 ,
[494]307        _get_task_slot( x, y, p, ltid, CTX_EPC_ID ),
308        _get_task_slot( x, y, p, ltid, CTX_RA_ID ) );
[258]309#endif
310
[294]311    }  // end for tasks
[258]312
[528]313    /////////////////////////////////////////
[494]314    _sqt_barrier_wait( &_all_procs_barrier );   
[528]315    /////////////////////////////////////////
[258]316
[494]317    ////////////////////////////////////////////////////////////////////////////
[528]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    ////////////////////////////////////////////////////////////////////////////
[494]328
[528]329    unsigned int sp  = ((unsigned int)psched) + 0x2000;
330    unsigned int ra  = (unsigned int)(&_ctx_eret);
331    unsigned int epc = (unsigned int)(&_idle_task);
[258]332
[528]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 );
[258]336
[528]337    if (tasks > 0) _xcu_timer_start( cluster_xy, p, GIET_TICK_VALUE ); 
[294]338
[258]339#if GIET_DEBUG_INIT
[547]340_printf("\n[DEBUG KINIT] P[%d,%d,%d] initializes idle_task and starts TICK\n", 
[528]341        x, y, p );
[258]342#endif
343
[528]344    if ( gpid == 0 )
[258]345    {
[592]346        _fat_init( 1 );   // kernel mode => Inode-Tree, Fat-Cache and File-Caches
[258]347
348#if GIET_DEBUG_INIT
[547]349_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel FAT init\n",
[494]350        x, y, p );
[258]351#endif
352
[528]353    }
[258]354
[528]355    /////////////////////////////////////////
[494]356    _sqt_barrier_wait( &_all_procs_barrier );   
[528]357    /////////////////////////////////////////
[258]358
[494]359    ////////////////////////////////////////////////////////////////////////////
[528]360    // step 4 : Each processor compute values for registers SP, SR, PTPR, EPC,
[494]361    //          corresponding to the first allocated task (can be idle task)
[528]362    //          and jumps to user code.
363    ////////////////////////////////////////////////////////////////////////////
[494]364
[528]365    if (tasks == 0) _printf("\n[GIET WARNING] No task allocated to P[%d,%d,%d]\n",
366                            x, y, p );
[258]367
[528]368    if (tasks == 0) ltid = IDLE_TASK_INDEX;
369    else            ltid = 0;
370
[440]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);
[258]375
[391]376#if GIET_DEBUG_INIT
[547]377_printf("\n[DEBUG KINIT] P[%d,%d,%d] jumps to user code at cycle %d\n"
[528]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 );
[391]381#endif
382
[294]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)
[345]392                   : "$29", "memory" );
[294]393
[310]394} // end kernel_init()
[258]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.