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

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

Move the peripheral initialisation from the boot.c to the kernel_init.c

  • Property svn:executable set to *
File size: 13.6 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>
[478]22#include <mmc_driver.h>
[258]23#include <ctx_handler.h>
24#include <irq_handler.h>
25#include <mapping_info.h>
26#include <mips32_registers.h>
27
[322]28#if !defined(X_SIZE)
29# error: You must define X_SIZE in the hard_config.h file
30#endif
31
32#if !defined(Y_SIZE)
33# error: You must define Y_SIZE in the hard_config.h file
34#endif
35
36#if !defined(Y_WIDTH)
37# error: You must define Y_WIDTH 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(NB_PROCS_MAX)
45# error: You must define NB_PROCS_MAX in the hard_config.h file
46#endif
47
48#if !defined(NB_TOTAL_PROCS)
49# error: You must define NB_TOTAL_PROCS in the hard_config.h file
50#endif
51
52#if !defined(USE_XCU)
53# error: You must define USE_XCU in the hard_config.h file
54#endif
55
[528]56#if !defined(USE_PIC)
57# error: You must define USE_PIC in the hard_config.h file
58#endif
59
[322]60#if !defined(IDLE_TASK_INDEX)
[391]61# error: You must define IDLE_TASK_INDEX in the ctx_handler.h file
[322]62#endif
63
64#if !defined(GIET_TICK_VALUE)
65# error: You must define GIET_TICK_VALUE in the giet_config.h file
66#endif
67
68#if !defined(GIET_NB_VSPACE_MAX)
69# error: You must define GIET_NB_VSPACE_MAX in the giet_config.h file
70#endif
71
[467]72#if !defined(NB_TTY_CHANNELS)
73# error: You must define NB_TTY_CHANNELS in the hard_config.h file
74#endif
75
76#if (NB_TTY_CHANNELS < 1)
77# error: NB_TTY_CHANNELS cannot be smaller than 1
78#endif
79
[528]80#if !defined(GIET_ISR_TYPE_MAX)
81# error: You must define GIET_ISR_TYPE_MAX in the giet_config.h file
82#endif
[467]83
[528]84#if !defined(GIET_ISR_CHANNEL_MAX)
85# error: You must define GIET_ISR_CHANNEL_MAX in the giet_config.h file
86#endif
[467]87
88
[528]89////////////////////////////////////////////////////////////////////////////////
90//       Global variables
91////////////////////////////////////////////////////////////////////////////////
92
[410]93// FAT internal representation for kernel code
[494]94__attribute__((section(".kdata")))
[528]95fat32_fs_t     _fat      __attribute__((aligned(512)));
[410]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
[494]113// Kernel uses sqt_lock to protect TTY0       
114__attribute__((section(".kdata")))
115unsigned int   _tty0_boot_mode = 0;
[294]116
[528]117// synchronisation barrier for parallel init by all processors     
[494]118__attribute__((section(".kdata")))
119sqt_barrier_t  _all_procs_barrier  __attribute__((aligned(64)));
[467]120
[528]121////////////////////////////////////////////////////////////////////////////////
122//      Extern variables
123////////////////////////////////////////////////////////////////////////////////
[467]124
[494]125// this variable is defined in tty0.c file
126extern sqt_lock_t _tty0_sqt_lock;
[467]127
[528]128////////////////////////////////////////////////////////////////////////////////
129// This kernel_init() function completes the kernel initialisation in 6 steps:
130// Step 0 is done by processor[0,0,0]. Steps 1 to 4 are executed in parallel
131// by all processors.
132// - step 0 : P[0,0,0] Initialise various global variables.
[494]133// - step 1 : Each processor initialises scheduler pointers array.
134// - step 2 : Each processor initialises PTAB pointers arrays.
[528]135// - step 3 : Each processor initialise idle task and starts TICK timer.
136// - step 4 : Each processor set sp, sr, ptpr, epc registers values.
137////////////////////////////////////////////////////////////////////////////////
[310]138__attribute__((section (".kinit"))) void kernel_init() 
[258]139{
[494]140    // gpid  : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
[528]141    // x,y,p : proc coordinates ( x < X_SIZE / y < Y_SIZE / p < NB_PROCS_MAX )
[428]142
143    unsigned int gpid       = _get_procid();
144    unsigned int cluster_xy = gpid >> P_WIDTH;
145    unsigned int x          = cluster_xy >> Y_WIDTH & ((1<<X_WIDTH)-1);
[294]146    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[440]147    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[547]148    unsigned int unused;
149   
[494]150    ////////////////////////////////////////////////////////////////////////////
[547]151    // Step 0 : P[0,0,0] initialises global variables and peripherals
152   ////////////////////////////////////////////////////////////////////////////
[428]153
[467]154    if ( gpid == 0 )
155    {
[547]156        //////  distributed kernel heap initialisation
[467]157        _heap_init();
158       
159#if GIET_DEBUG_INIT
[547]160_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel heap init\n", x, y, p );
[467]161#endif
[547]162        //////  distributed lock for TTY0
[494]163        _sqt_lock_init( &_tty0_sqt_lock );
[459]164
[467]165#if GIET_DEBUG_INIT
[547]166_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes TTY0 lock init\n", x , y , p );
[467]167#endif
[547]168        //////  distributed kernel barrier between all processors
[494]169        _sqt_barrier_init( &_all_procs_barrier );
[467]170
171#if GIET_DEBUG_INIT
[547]172_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes barrier init\n", x , y , p );
[467]173#endif
174
[547]175        ////// _ext_irq_index[isr][channel] initialisation
176        if ( USE_PIC ) _ext_irq_init();
[528]177
[547]178#if GIET_DEBUG_INIT
179_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes ext_irq init\n", x , y , p );
180#endif
[528]181
[547]182        //////  NIC peripheral initialization
183        if ( USE_NIC ) _nic_global_init( 1,      // broadcast accepted
184                                         1,      // bypass activated
185                                         0,      // tdm non activated
186                                         0 );    // tdm period
187#if GIET_DEBUG_INIT
188_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes NIC init\n", x , y , p );
189#endif
[528]190
[547]191        //////  HBA peripheral initialisation
192        if ( USE_IOC_HBA )
193        {
194            _hba_init();
195
196            // routing HBA IRQ to proc[0,0,0]
197            _ext_irq_alloc( ISR_HBA , 0 , &unused );
198        }
199
[528]200#if GIET_DEBUG_INIT
[547]201_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes HBA init\n", x , y , p );
[528]202#endif
203
[547]204        //////  release other processors
[494]205        _kernel_init_done = 1;
[467]206    }
[494]207    else 
208    {
209        while( _kernel_init_done == 0 )  asm volatile ( "nop" );
210    }
[467]211
[528]212    ///////////////////////////////////////////////////////////////////////////
[494]213    // Step 1 : each processor get its scheduler vaddr from CP0_SCHED,
214    //          contributes to _schedulers[] array initialisation,
215    //          and wait completion of array initialisation.
[528]216    ///////////////////////////////////////////////////////////////////////////
[258]217
218    static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
219    unsigned int        tasks      = psched->tasks;
220
[440]221    _schedulers[x][y][p] = psched;
[258]222
223#if GIET_DEBUG_INIT
[547]224_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises SCHED array\n"
[494]225        " - scheduler vbase = %x\n"
226        " - tasks           = %d\n",
227        x, y, p, (unsigned int)psched, tasks );
[258]228#endif
229
[528]230    /////////////////////////////////////////
[494]231    _sqt_barrier_wait( &_all_procs_barrier );   
[528]232    /////////////////////////////////////////
[494]233
234    ////////////////////////////////////////////////////////////////////////////
[294]235    // step 2 : each processor that is allocated at least one task loops
[528]236    //          on its allocated tasks:
237    //          - contributes to _ptabs_vaddr[][][] & _ptabs_ptprs[][][]
238    //            initialisation, from values stored in the tasks contexts.
[294]239    //          - set CTX_RA slot  with the kernel _ctx_eret() virtual address.
240    //          - set CTX_EPC slot that must contain the task entry point,
[528]241    //            and contain only at this point the virtual address of the
242    //            memory slot containing this entry point.
243    ////////////////////////////////////////////////////////////////////////////
[258]244
245    unsigned int ltid;
246
247    for (ltid = 0; ltid < tasks; ltid++) 
248    {
[440]249        unsigned int vsid = _get_task_slot( x, y, p, ltid , CTX_VSID_ID ); 
250        unsigned int ptab = _get_task_slot( x, y, p, ltid , CTX_PTAB_ID ); 
251        unsigned int ptpr = _get_task_slot( x, y, p, ltid , CTX_PTPR_ID ); 
[258]252
[294]253        // initialize PTABS arrays
[528]254        _ptabs_vaddr[vsid][x][y] = ptab;
255        _ptabs_ptprs[vsid][x][y] = ptpr;
[258]256
[528]257        // set the ptpr to use the local page table
258        asm volatile( "mtc2    %0,   $0"
[294]259                      : : "r" (ptpr) );
260
261        // compute ctx_ra
[258]262        unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
[440]263        _set_task_slot( x, y, p, ltid, CTX_RA_ID, ctx_ra );
[258]264
[294]265        // compute ctx_epc
[528]266        unsigned int* ptr = (unsigned int*)_get_task_slot(x,y,p,ltid,CTX_EPC_ID);
267        _set_task_slot(x,y,p,ltid,CTX_EPC_ID,*ptr);
[258]268
269#if GIET_DEBUG_INIT
[547]270_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises PTABS arrays"
[528]271        " and context for task %d \n"
272        " - ptabs_vaddr[%d][%d][%d] = %x\n"
273        " - ptabs_paddr[%d][%d][%d] = %l\n"
274        " - ctx_epc              = %x\n"
275        " - ctx_ra               = %x\n",
276        x , y , p , ltid , 
277        vsid , x , y , ptab ,
278        vsid , x , y , ((unsigned long long)ptpr)<<13 ,
[494]279        _get_task_slot( x, y, p, ltid, CTX_EPC_ID ),
280        _get_task_slot( x, y, p, ltid, CTX_RA_ID ) );
[258]281#endif
282
[294]283    }  // end for tasks
[258]284
[528]285    /////////////////////////////////////////
[494]286    _sqt_barrier_wait( &_all_procs_barrier );   
[528]287    /////////////////////////////////////////
[258]288
[494]289    ////////////////////////////////////////////////////////////////////////////
[528]290    // step 3 : - Each processor complete idle task context initialisation,
291    //            (only the CTX_SP, CTX_RA, CTX_EPC slot, because the CTX_PTPR
292    //            and CTX_PTAB slots have been initialised in boot code)
293    //            The 4 Kbytes idle stack is implemented in the scheduler itself.
294    //          - Each processor starts TICK timer, as soon as at least one task
295    //            is allocated.
296    //          - P[0,0,0] initialises FAT (not done before, because it must
297    //            be done after the _ptabs_vaddr[v][x][y] array initialisation,
298    //            for V2P translation in _fat_ioc_access() function).
299    ////////////////////////////////////////////////////////////////////////////
[494]300
[528]301    unsigned int sp  = ((unsigned int)psched) + 0x2000;
302    unsigned int ra  = (unsigned int)(&_ctx_eret);
303    unsigned int epc = (unsigned int)(&_idle_task);
[258]304
[528]305    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_SP_ID  , sp  );
306    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_RA_ID  , ra  );
307    _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_EPC_ID , epc );
[258]308
[528]309    if (tasks > 0) _xcu_timer_start( cluster_xy, p, GIET_TICK_VALUE ); 
[294]310
[258]311#if GIET_DEBUG_INIT
[547]312_printf("\n[DEBUG KINIT] P[%d,%d,%d] initializes idle_task and starts TICK\n", 
[528]313        x, y, p );
[258]314#endif
315
[528]316    if ( gpid == 0 )
[258]317    {
[528]318         _fat_init( 0 );   // no IRQ
[258]319
320#if GIET_DEBUG_INIT
[547]321_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel FAT init\n",
[494]322        x, y, p );
[258]323#endif
324
[528]325    }
[258]326
[528]327    /////////////////////////////////////////
[494]328    _sqt_barrier_wait( &_all_procs_barrier );   
[528]329    /////////////////////////////////////////
[258]330
[494]331    ////////////////////////////////////////////////////////////////////////////
[528]332    // step 4 : Each processor compute values for registers SP, SR, PTPR, EPC,
[494]333    //          corresponding to the first allocated task (can be idle task)
[528]334    //          and jumps to user code.
335    ////////////////////////////////////////////////////////////////////////////
[494]336
[528]337    if (tasks == 0) _printf("\n[GIET WARNING] No task allocated to P[%d,%d,%d]\n",
338                            x, y, p );
[258]339
[528]340    if (tasks == 0) ltid = IDLE_TASK_INDEX;
341    else            ltid = 0;
342
[440]343    unsigned int sp_value   = _get_task_slot( x, y, p, ltid, CTX_SP_ID);
344    unsigned int sr_value   = _get_task_slot( x, y, p, ltid, CTX_SR_ID);
345    unsigned int ptpr_value = _get_task_slot( x, y, p, ltid, CTX_PTPR_ID);
346    unsigned int epc_value  = _get_task_slot( x, y, p, ltid, CTX_EPC_ID);
[258]347
[391]348#if GIET_DEBUG_INIT
[547]349_printf("\n[DEBUG KINIT] P[%d,%d,%d] jumps to user code at cycle %d\n"
[528]350        " ltid = %d / sp = %x / sr = %x / ptpr = %x / epc = %x\n",
351        x , y , p , _get_proctime() ,
352        ltid , sp_value , sr_value , ptpr_value , epc_value );
[391]353#endif
354
[294]355    // set registers and jump to user code
356    asm volatile ( "move  $29,  %0                  \n"   /* SP <= ctx[CTX_SP_ID] */
357                   "mtc0  %1,   $12                 \n"   /* SR <= ctx[CTX_SR_ID] */
358                   "mtc2  %2,   $0                  \n"   /* PTPR <= ctx[CTX_PTPR] */
359                   "mtc0  %3,   $14                 \n"   /* EPC <= ctx[CTX_EPC]  */
360                   "eret                            \n"   /* jump to user code  */
361                   "nop                             \n"
362                   : 
363                   : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value)
[345]364                   : "$29", "memory" );
[294]365
[310]366} // end kernel_init()
[258]367
368
369// Local Variables:
370// tab-width: 4
371// c-basic-offset: 4
372// c-file-offsets:((innamespace . 0)(inline-open . 0))
373// indent-tabs-mode: nil
374// End:
375// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
376
Note: See TracBrowser for help on using the repository browser.