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

Last change on this file since 668 was 656, checked in by guerin, 9 years ago

always set CTX_EPC in task context initialization

all runnable tasks not scheduled at boot but scheduled later would
jump at a random address, including the idle task.

  • Property svn:executable set to *
File size: 14.9 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
[579]115// Kernel uses sqt_lock to protect command allocator in HBA       
116__attribute__((section(".kdata")))
117unsigned int   _hba_boot_mode = 0;
118
[528]119// synchronisation barrier for parallel init by all processors     
[494]120__attribute__((section(".kdata")))
121sqt_barrier_t  _all_procs_barrier  __attribute__((aligned(64)));
[467]122
[528]123////////////////////////////////////////////////////////////////////////////////
124//      Extern variables
125////////////////////////////////////////////////////////////////////////////////
[467]126
[494]127// this variable is defined in tty0.c file
128extern sqt_lock_t _tty0_sqt_lock;
[467]129
[629]130// this variable is allocated in mmc_kernel.c
131extern unsigned int _mmc_boot_mode;
132
[528]133////////////////////////////////////////////////////////////////////////////////
134// This kernel_init() function completes the kernel initialisation in 6 steps:
135// Step 0 is done by processor[0,0,0]. Steps 1 to 4 are executed in parallel
136// by all processors.
137// - step 0 : P[0,0,0] Initialise various global variables.
[494]138// - step 1 : Each processor initialises scheduler pointers array.
139// - step 2 : Each processor initialises PTAB pointers arrays.
[528]140// - step 3 : Each processor initialise idle task and starts TICK timer.
141// - step 4 : Each processor set sp, sr, ptpr, epc registers values.
142////////////////////////////////////////////////////////////////////////////////
[310]143__attribute__((section (".kinit"))) void kernel_init() 
[258]144{
[494]145    // gpid  : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
[528]146    // x,y,p : proc coordinates ( x < X_SIZE / y < Y_SIZE / p < NB_PROCS_MAX )
[428]147
148    unsigned int gpid       = _get_procid();
149    unsigned int cluster_xy = gpid >> P_WIDTH;
150    unsigned int x          = cluster_xy >> Y_WIDTH & ((1<<X_WIDTH)-1);
[294]151    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[440]152    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[547]153    unsigned int unused;
154   
[494]155    ////////////////////////////////////////////////////////////////////////////
[547]156    // Step 0 : P[0,0,0] initialises global variables and peripherals
157   ////////////////////////////////////////////////////////////////////////////
[428]158
[467]159    if ( gpid == 0 )
160    {
[547]161        //////  distributed kernel heap initialisation
[467]162        _heap_init();
163       
164#if GIET_DEBUG_INIT
[547]165_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel heap init\n", x, y, p );
[467]166#endif
[615]167        //////  distributed lock for MMC
[629]168        _mmc_boot_mode = 0;
[615]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.
[648]268    //          - set CTX_ENTRY slot that must contain the task entry point,
[528]269    //            and contain only at this point the virtual address of the
[648]270    //            memory word containing this entry point.
[528]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
[648]285        // set the PTPR to use the local page table
[528]286        asm volatile( "mtc2    %0,   $0"
[294]287                      : : "r" (ptpr) );
288
[648]289        // set CTX_RA slot
[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
[648]293        // set CTX_ENTRY slot
294        unsigned int* ptr = (unsigned int*)_get_task_slot(x , y , p , ltid , CTX_ENTRY_ID);
295        unsigned int ctx_entry = *ptr;
296        _set_task_slot( x , y , p , ltid , CTX_ENTRY_ID , ctx_entry );
[258]297
298#if GIET_DEBUG_INIT
[547]299_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises PTABS arrays"
[528]300        " and context for task %d \n"
301        " - ptabs_vaddr[%d][%d][%d] = %x\n"
302        " - ptabs_paddr[%d][%d][%d] = %l\n"
[648]303        " - ctx_entry            = %x\n"
[528]304        " - ctx_ra               = %x\n",
305        x , y , p , ltid , 
306        vsid , x , y , ptab ,
307        vsid , x , y , ((unsigned long long)ptpr)<<13 ,
[648]308        ctx_entry, ctx_ra );
[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    ////////////////////////////////////////////////////////////////////////////
[648]318    // step 3 : - Each processor complete idle task context initialisation.
[656]319    //            Only CTX_SP, CTX_RA, CTX_EPC, CTX_ENTRY slots, because other
320    //            slots have been initialised in boot code)
[528]321    //            The 4 Kbytes idle stack is implemented in the scheduler itself.
[648]322    //          - Each processor starts TICK timer, if at least one task.
[528]323    //          - P[0,0,0] initialises FAT (not done before, because it must
324    //            be done after the _ptabs_vaddr[v][x][y] array initialisation,
325    //            for V2P translation in _fat_ioc_access() function).
326    ////////////////////////////////////////////////////////////////////////////
[494]327
[648]328    unsigned int sp    = ((unsigned int)psched) + 0x2000;
329    unsigned int ra    = (unsigned int)(&_ctx_eret);
330    unsigned int entry = (unsigned int)(&_idle_task);
[258]331
[648]332    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_SP_ID  , sp    );
333    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_RA_ID  , ra    );
[656]334    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_EPC_ID , entry );
[648]335    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_ENTRY_ID , entry );
[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    ////////////////////////////////////////////////////////////////////////////
[648]360    // step 4 : Each processor computes the task index (ltid), and the values
361    //          to initialize the SP, SR, PTPR, EPC registers.
362    //          It jumps to a runable task if possible, and jumps to IDLE-TASK
363    //          if no task allocated or no runable task.
[528]364    ////////////////////////////////////////////////////////////////////////////
[494]365
[528]366    if (tasks == 0) _printf("\n[GIET WARNING] No task allocated to P[%d,%d,%d]\n",
367                            x, y, p );
[258]368
[648]369    // default value for ltid
370    ltid = IDLE_TASK_INDEX;
[528]371
[648]372    // scan allocated tasks to find a runable task
373    unsigned int  task_id; 
374    for ( task_id = 0 ; task_id < tasks ; task_id++ )
375    {
376        if ( _get_task_slot( x, y, p, task_id, CTX_NORUN_ID ) == 0 )
377        {
378            ltid = task_id;
379            break;
380        }
381    }
382
383    // update scheduler
384    psched->current = ltid;
385
386    // get values from selected task context
[440]387    unsigned int sp_value   = _get_task_slot( x, y, p, ltid, CTX_SP_ID);
388    unsigned int sr_value   = _get_task_slot( x, y, p, ltid, CTX_SR_ID);
389    unsigned int ptpr_value = _get_task_slot( x, y, p, ltid, CTX_PTPR_ID);
[648]390    unsigned int epc_value  = _get_task_slot( x, y, p, ltid, CTX_ENTRY_ID);
[258]391
[391]392#if GIET_DEBUG_INIT
[648]393_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel_init at cycle %d\n"
[528]394        " ltid = %d / sp = %x / sr = %x / ptpr = %x / epc = %x\n",
395        x , y , p , _get_proctime() ,
396        ltid , sp_value , sr_value , ptpr_value , epc_value );
[391]397#endif
398
[294]399    // set registers and jump to user code
400    asm volatile ( "move  $29,  %0                  \n"   /* SP <= ctx[CTX_SP_ID] */
401                   "mtc0  %1,   $12                 \n"   /* SR <= ctx[CTX_SR_ID] */
402                   "mtc2  %2,   $0                  \n"   /* PTPR <= ctx[CTX_PTPR] */
403                   "mtc0  %3,   $14                 \n"   /* EPC <= ctx[CTX_EPC]  */
404                   "eret                            \n"   /* jump to user code  */
405                   "nop                             \n"
406                   : 
407                   : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value)
[345]408                   : "$29", "memory" );
[294]409
[310]410} // end kernel_init()
[258]411
412
413// Local Variables:
414// tab-width: 4
415// c-basic-offset: 4
416// c-file-offsets:((innamespace . 0)(inline-open . 0))
417// indent-tabs-mode: nil
418// End:
419// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
420
Note: See TracBrowser for help on using the repository browser.