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

Last change on this file since 715 was 709, checked in by alain, 9 years ago

Major release: Change the task model to implement the POSIX threads API.

  • The shell "exec" and "kill" commands can be used to activate/de-activate the applications.
  • The "pause", "resume", and "context" commands can be used to stop, restart, a single thtead or to display the thread context.

This version has been tested on the following multi-threaded applications,
that have been modified to use the POSIX threads:

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