source: soft/giet_vm/giet_kernel/kernel_init.c

Last change on this file was 760, checked in by alain, 8 years ago
  • Property svn:executable set to *
File size: 16.2 KB
RevLine 
[688]1////////////////////////////////////////////////////////////////////////////////////
[258]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>
[709]25#include <tty_driver.h>
[258]26#include <ctx_handler.h>
27#include <irq_handler.h>
[709]28#include <sys_handler.h>
[258]29#include <mapping_info.h>
30#include <mips32_registers.h>
31
[322]32#if !defined(X_SIZE)
33# error: You must define X_SIZE in the hard_config.h file
34#endif
35
36#if !defined(Y_SIZE)
37# error: You must define Y_SIZE in the hard_config.h file
38#endif
39
40#if !defined(Y_WIDTH)
41# error: You must define Y_WIDTH in the hard_config.h file
42#endif
43
44#if !defined(Y_WIDTH)
45# error: You must define Y_WIDTH in the hard_config.h file
46#endif
47
48#if !defined(NB_PROCS_MAX)
49# error: You must define NB_PROCS_MAX in the hard_config.h file
50#endif
51
52#if !defined(NB_TOTAL_PROCS)
53# error: You must define NB_TOTAL_PROCS in the hard_config.h file
54#endif
55
56#if !defined(USE_XCU)
57# error: You must define USE_XCU in the hard_config.h file
58#endif
59
[528]60#if !defined(USE_PIC)
61# error: You must define USE_PIC in the hard_config.h file
62#endif
63
[709]64#if !defined(IDLE_THREAD_INDEX)
65# error: You must define IDLE_THREAD_INDEX in the ctx_handler.h file
[322]66#endif
67
68#if !defined(GIET_TICK_VALUE)
69# error: You must define GIET_TICK_VALUE in the giet_config.h file
70#endif
71
72#if !defined(GIET_NB_VSPACE_MAX)
73# error: You must define GIET_NB_VSPACE_MAX in the giet_config.h file
74#endif
75
[467]76#if !defined(NB_TTY_CHANNELS)
77# error: You must define NB_TTY_CHANNELS in the hard_config.h file
78#endif
79
80#if (NB_TTY_CHANNELS < 1)
81# error: NB_TTY_CHANNELS cannot be smaller than 1
82#endif
83
[528]84#if !defined(GIET_ISR_TYPE_MAX)
85# error: You must define GIET_ISR_TYPE_MAX in the giet_config.h file
86#endif
[467]87
[528]88#if !defined(GIET_ISR_CHANNEL_MAX)
89# error: You must define GIET_ISR_CHANNEL_MAX in the giet_config.h file
90#endif
[467]91
92
[528]93////////////////////////////////////////////////////////////////////////////////
94//       Global variables
95////////////////////////////////////////////////////////////////////////////////
96
[760]97// Array of page tables virtual addresses (one per vspace and per cluster)
[494]98__attribute__((section(".kdata")))
[760]99unsigned int        _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 
[258]100
[760]101// Array of page tables physical addresses (one per vspace and per cluster)
[494]102__attribute__((section(".kdata")))
[760]103unsigned long long  _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 
[258]104
[760]105// Array of pt2 allocators (one per vspace and per cluster)
106__attribute__((section(".kdata")))
107unsigned int        _ptabs_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
108
109// Page tables max_pt2  (same value for all page tables)
110__attribute__((section(".kdata")))
111unsigned int        _ptabs_max_pt2;
112
[494]113// Array of pointers on the schedulers
114__attribute__((section(".kdata")))
[528]115volatile static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
[258]116
[494]117// Synchonisation before entering parallel execution
118__attribute__((section(".kdata")))
119volatile unsigned int _kernel_init_done = 0;
[258]120
[709]121// Kernel uses a sqt_lock to protect TTY0       
[494]122__attribute__((section(".kdata")))
123unsigned int   _tty0_boot_mode = 0;
[294]124
[709]125// Kernel uses a sqt_lock to protect command allocator in HBA       
[579]126__attribute__((section(".kdata")))
127unsigned int   _hba_boot_mode = 0;
128
[528]129// synchronisation barrier for parallel init by all processors     
[494]130__attribute__((section(".kdata")))
131sqt_barrier_t  _all_procs_barrier  __attribute__((aligned(64)));
[467]132
[760]133// required for concurrent PTAB building
134__attribute__((section(".kdata")))
135spin_lock_t    _ptabs_spin_lock[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
136
137
[528]138////////////////////////////////////////////////////////////////////////////////
139//      Extern variables
140////////////////////////////////////////////////////////////////////////////////
[467]141
[709]142// this variable is allocated in tty0.c file
[494]143extern sqt_lock_t _tty0_sqt_lock;
[467]144
[709]145// this variable is allocated in mmc_driver.c file
[629]146extern unsigned int _mmc_boot_mode;
147
[709]148// this variable is allocated in sys_handler.c file
149extern unsigned int _tty_channel_alloc[NB_TTY_CHANNELS];
150
[528]151////////////////////////////////////////////////////////////////////////////////
[742]152// This _kernel_init() function completes the kernel initialisation in 5 steps:
[528]153// Step 0 is done by processor[0,0,0]. Steps 1 to 4 are executed in parallel
154// by all processors.
155// - step 0 : P[0,0,0] Initialise various global variables.
[494]156// - step 1 : Each processor initialises scheduler pointers array.
157// - step 2 : Each processor initialises PTAB pointers arrays.
[709]158// - step 3 : Each processor initialise idle thread and starts TICK timer.
[528]159// - step 4 : Each processor set sp, sr, ptpr, epc registers values.
160////////////////////////////////////////////////////////////////////////////////
[742]161__attribute__((section (".kinit"))) void _kernel_init() 
[258]162{
[494]163    // gpid  : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
[528]164    // x,y,p : proc coordinates ( x < X_SIZE / y < Y_SIZE / p < NB_PROCS_MAX )
[428]165
166    unsigned int gpid       = _get_procid();
167    unsigned int cluster_xy = gpid >> P_WIDTH;
168    unsigned int x          = cluster_xy >> Y_WIDTH & ((1<<X_WIDTH)-1);
[294]169    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[440]170    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[547]171    unsigned int unused;
172   
[494]173    ////////////////////////////////////////////////////////////////////////////
[547]174    // Step 0 : P[0,0,0] initialises global variables and peripherals
175   ////////////////////////////////////////////////////////////////////////////
[428]176
[467]177    if ( gpid == 0 )
178    {
[547]179        //////  distributed kernel heap initialisation
[467]180        _heap_init();
181       
182#if GIET_DEBUG_INIT
[547]183_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel heap init\n", x, y, p );
[467]184#endif
[709]185        //////  distributed locks for MMC
[629]186        _mmc_boot_mode = 0;
[615]187        _mmc_init_locks();
188
189#if GIET_DEBUG_INIT
[709]190_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes MMC distributed locks init\n", x , y , p );
[615]191#endif
[547]192        //////  distributed lock for TTY0
[494]193        _sqt_lock_init( &_tty0_sqt_lock );
[709]194        _tty_channel_alloc[0] = 1;
[459]195
[467]196#if GIET_DEBUG_INIT
[547]197_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes TTY0 lock init\n", x , y , p );
[467]198#endif
[547]199        //////  distributed kernel barrier between all processors
[494]200        _sqt_barrier_init( &_all_procs_barrier );
[467]201
202#if GIET_DEBUG_INIT
[547]203_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes barrier init\n", x , y , p );
[467]204#endif
205
[760]206        ////// get max_pt2 value stored in mapping header
207        mapping_header_t*  header = (mapping_header_t*)SEG_BOOT_MAPPING_BASE;
208        _ptabs_max_pt2 = header->max_pt2;
209
[709]210        //////  TTY fifos initialisation
211        unsigned int tty_id;
212        for ( tty_id = 0 ; tty_id < NB_TTY_CHANNELS ; tty_id++) _tty_init( tty_id );
213
214#if GIET_DEBUG_INIT
215_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes TTY fifos init\n", x , y , p );
216#endif
217
[547]218        ////// _ext_irq_index[isr][channel] initialisation
219        if ( USE_PIC ) _ext_irq_init();
[528]220
[547]221#if GIET_DEBUG_INIT
222_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes ext_irq init\n", x , y , p );
223#endif
[528]224
[547]225        //////  NIC peripheral initialization
226        if ( USE_NIC ) _nic_global_init( 1,      // broadcast accepted
227                                         1,      // bypass activated
228                                         0,      // tdm non activated
229                                         0 );    // tdm period
230#if GIET_DEBUG_INIT
231_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes NIC init\n", x , y , p );
232#endif
[528]233
[568]234        //////  IOC peripheral initialisation
[547]235        if ( USE_IOC_HBA )
236        {
237            _hba_init();
238            _ext_irq_alloc( ISR_HBA , 0 , &unused );
239
[528]240#if GIET_DEBUG_INIT
[547]241_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes HBA init\n", x , y , p );
[528]242#endif
[568]243        }
244        if ( USE_IOC_SDC )
245        {
246            _sdc_init();
247            _ext_irq_alloc( ISR_SDC , 0 , &unused );
[528]248
[568]249#if GIET_DEBUG_INIT
250_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes SDC init\n", x , y , p );
251#endif
252        }
253        if ( USE_IOC_BDV )
254        {
255            _bdv_init();
256            _ext_irq_alloc( ISR_BDV , 0 , &unused );
257
258#if GIET_DEBUG_INIT
259_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes BDV init\n", x , y , p );
260#endif
261        }
262
[547]263        //////  release other processors
[494]264        _kernel_init_done = 1;
[467]265    }
[494]266    else 
267    {
268        while( _kernel_init_done == 0 )  asm volatile ( "nop" );
269    }
[467]270
[528]271    ///////////////////////////////////////////////////////////////////////////
[494]272    // Step 1 : each processor get its scheduler vaddr from CP0_SCHED,
273    //          contributes to _schedulers[] array initialisation,
274    //          and wait completion of array initialisation.
[528]275    ///////////////////////////////////////////////////////////////////////////
[258]276
277    static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
[709]278    unsigned int        threads    = psched->threads;
[258]279
[440]280    _schedulers[x][y][p] = psched;
[258]281
282#if GIET_DEBUG_INIT
[547]283_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises SCHED array\n"
[494]284        " - scheduler vbase = %x\n"
[709]285        " - threads         = %d\n",
286        x, y, p, (unsigned int)psched, threads );
[258]287#endif
288
[528]289    /////////////////////////////////////////
[494]290    _sqt_barrier_wait( &_all_procs_barrier );   
[528]291    /////////////////////////////////////////
[494]292
293    ////////////////////////////////////////////////////////////////////////////
[709]294    // step 2 : each processor that is allocated at least one thread loops
295    //          on its allocated threads:
[760]296    //          - contributes to _ptabs_vaddr & _ptabs_paddr arrays
[709]297    //            initialisation, from values stored in the threads contexts.
[294]298    //          - set CTX_RA slot  with the kernel _ctx_eret() virtual address.
[709]299    //          - set CTX_ENTRY & CTX_EPC slots that must contain the thread
300    //            entry point. The CTX_ENTRY slot contain only at this point
301    //            a pointer on the memory word containing this entry point.
[528]302    ////////////////////////////////////////////////////////////////////////////
[258]303
304    unsigned int ltid;
305
[709]306    for (ltid = 0; ltid < threads; ltid++) 
[258]307    {
[709]308        unsigned int vsid = _get_thread_slot( x, y, p, ltid , CTX_VSID_ID ); 
309        unsigned int ptab = _get_thread_slot( x, y, p, ltid , CTX_PTAB_ID ); 
310        unsigned int ptpr = _get_thread_slot( x, y, p, ltid , CTX_PTPR_ID ); 
[760]311        unsigned int npt2 = _get_thread_slot( x, y, p, ltid , CTX_NPT2_ID ); 
[258]312
[294]313        // initialize PTABS arrays
[760]314        _ptabs_vaddr[vsid][x][y]    = ptab;
315        _ptabs_paddr[vsid][x][y]    = ((unsigned long long)ptpr) << 13;
316        _ptabs_next_pt2[vsid][x][y] = npt2;
[258]317
[648]318        // set the PTPR to use the local page table
[528]319        asm volatile( "mtc2    %0,   $0"
[294]320                      : : "r" (ptpr) );
321
[648]322        // set CTX_RA slot
[258]323        unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
[709]324        _set_thread_slot( x, y, p, ltid, CTX_RA_ID, ctx_ra );
[258]325
[709]326        // set CTX_ENTRY and CTX_EPC slots
327        unsigned int* ptr = (unsigned int*)_get_thread_slot(x , y , p , ltid , CTX_ENTRY_ID);
[648]328        unsigned int ctx_entry = *ptr;
[709]329        _set_thread_slot( x , y , p , ltid , CTX_ENTRY_ID , ctx_entry );
330        _set_thread_slot( x , y , p , ltid , CTX_EPC_ID , ctx_entry );
[258]331
332#if GIET_DEBUG_INIT
[547]333_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises PTABS arrays"
[709]334        " and context for thread %d \n"
[528]335        " - ptabs_vaddr[%d][%d][%d] = %x\n"
336        " - ptabs_paddr[%d][%d][%d] = %l\n"
[648]337        " - ctx_entry            = %x\n"
[528]338        " - ctx_ra               = %x\n",
339        x , y , p , ltid , 
[760]340        vsid , x , y , _ptabs_vaddr[vsid][x][y] ,
341        vsid , x , y , _ptabs_paddr[vsid][x][y] ,
[648]342        ctx_entry, ctx_ra );
[258]343#endif
344
[709]345    }  // end for threads
[258]346
[528]347    /////////////////////////////////////////
[494]348    _sqt_barrier_wait( &_all_procs_barrier );   
[528]349    /////////////////////////////////////////
[258]350
[494]351    ////////////////////////////////////////////////////////////////////////////
[709]352    // step 3 : - Each processor complete idle thread context initialisation.
[656]353    //            Only CTX_SP, CTX_RA, CTX_EPC, CTX_ENTRY slots, because other
354    //            slots have been initialised in boot code)
[528]355    //            The 4 Kbytes idle stack is implemented in the scheduler itself.
[709]356    //          - Each processor starts TICK timer, if at least one thread.
[528]357    //          - P[0,0,0] initialises FAT (not done before, because it must
358    //            be done after the _ptabs_vaddr[v][x][y] array initialisation,
359    //            for V2P translation in _fat_ioc_access() function).
360    ////////////////////////////////////////////////////////////////////////////
[494]361
[648]362    unsigned int sp    = ((unsigned int)psched) + 0x2000;
363    unsigned int ra    = (unsigned int)(&_ctx_eret);
[709]364    unsigned int entry = (unsigned int)(&_idle_thread);
[258]365
[709]366    _set_thread_slot( x , y , p , IDLE_THREAD_INDEX , CTX_SP_ID  , sp    );
367    _set_thread_slot( x , y , p , IDLE_THREAD_INDEX , CTX_RA_ID  , ra    );
368    _set_thread_slot( x , y , p , IDLE_THREAD_INDEX , CTX_EPC_ID , entry );
369    _set_thread_slot( x , y , p , IDLE_THREAD_INDEX , CTX_ENTRY_ID , entry );
[258]370
[709]371    if (threads > 0) _xcu_timer_start( cluster_xy, p, GIET_TICK_VALUE ); 
[294]372
[258]373#if GIET_DEBUG_INIT
[709]374_printf("\n[DEBUG KINIT] P[%d,%d,%d] initializes idle_thread and starts TICK\n", 
[528]375        x, y, p );
[258]376#endif
377
[528]378    if ( gpid == 0 )
[258]379    {
[592]380        _fat_init( 1 );   // kernel mode => Inode-Tree, Fat-Cache and File-Caches
[258]381
382#if GIET_DEBUG_INIT
[547]383_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel FAT init\n",
[494]384        x, y, p );
[258]385#endif
386
[528]387    }
[258]388
[528]389    /////////////////////////////////////////
[494]390    _sqt_barrier_wait( &_all_procs_barrier );   
[528]391    /////////////////////////////////////////
[258]392
[494]393    ////////////////////////////////////////////////////////////////////////////
[709]394    // step 4 : Each processor computes the thread index (ltid), and the values
[648]395    //          to initialize the SP, SR, PTPR, EPC registers.
[709]396    //          It jumps to a runable thread if possible,
397    //          or jumps to IDLE-THREAD if no runable thread.
[528]398    ////////////////////////////////////////////////////////////////////////////
[494]399
[648]400    // default value for ltid
[709]401    ltid = IDLE_THREAD_INDEX;
[528]402
[709]403    // scan allocated threads to find a runable thread
404    unsigned int  thread_id; 
405    for ( thread_id = 0 ; thread_id < threads ; thread_id++ )
[648]406    {
[709]407        if ( _get_thread_slot( x, y, p, thread_id, CTX_NORUN_ID ) == 0 )
[648]408        {
[709]409            ltid = thread_id;
[648]410            break;
411        }
412    }
413
414    // update scheduler
415    psched->current = ltid;
416
[709]417    // get values from selected thread context
418    unsigned int sp_value   = _get_thread_slot( x, y, p, ltid, CTX_SP_ID);
419    unsigned int sr_value   = _get_thread_slot( x, y, p, ltid, CTX_SR_ID);
420    unsigned int ptpr_value = _get_thread_slot( x, y, p, ltid, CTX_PTPR_ID);
421    unsigned int epc_value  = _get_thread_slot( x, y, p, ltid, CTX_ENTRY_ID);
[258]422
[391]423#if GIET_DEBUG_INIT
[648]424_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel_init at cycle %d\n"
[528]425        " ltid = %d / sp = %x / sr = %x / ptpr = %x / epc = %x\n",
426        x , y , p , _get_proctime() ,
427        ltid , sp_value , sr_value , ptpr_value , epc_value );
[391]428#endif
429
[294]430    // set registers and jump to user code
431    asm volatile ( "move  $29,  %0                  \n"   /* SP <= ctx[CTX_SP_ID] */
432                   "mtc0  %1,   $12                 \n"   /* SR <= ctx[CTX_SR_ID] */
433                   "mtc2  %2,   $0                  \n"   /* PTPR <= ctx[CTX_PTPR] */
434                   "mtc0  %3,   $14                 \n"   /* EPC <= ctx[CTX_EPC]  */
435                   "eret                            \n"   /* jump to user code  */
436                   "nop                             \n"
437                   : 
438                   : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value)
[345]439                   : "$29", "memory" );
[294]440
[310]441} // end kernel_init()
[258]442
443
444// Local Variables:
445// tab-width: 4
446// c-basic-offset: 4
447// c-file-offsets:((innamespace . 0)(inline-open . 0))
448// indent-tabs-mode: nil
449// End:
450// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
451
Note: See TracBrowser for help on using the repository browser.