source: soft/giet_vm/giet_kernel/kernel_init.c

Last change on this file was 760, checked in by alain, 9 years ago
  • Property svn:executable set to *
File size: 16.2 KB
Line 
1////////////////////////////////////////////////////////////////////////////////////
2// File     : kernel_init.c
3// Date     : 26/05/2012
4// Authors  : alain greiner & mohamed karaoui
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////////
7// This kernel_init.c file is part of the GIET-VM nano-kernel.
8////////////////////////////////////////////////////////////////////////////////////
9
10#include <giet_config.h>
11#include <hard_config.h>
12#include <utils.h>
13#include <vmem.h>
14#include <tty0.h>
15#include <kernel_malloc.h>
16#include <kernel_locks.h>
17#include <kernel_barriers.h>
18#include <fat32.h>
19#include <xcu_driver.h>
20#include <nic_driver.h>
21#include <hba_driver.h>
22#include <sdc_driver.h>
23#include <bdv_driver.h>
24#include <mmc_driver.h>
25#include <tty_driver.h>
26#include <ctx_handler.h>
27#include <irq_handler.h>
28#include <sys_handler.h>
29#include <mapping_info.h>
30#include <mips32_registers.h>
31
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
60#if !defined(USE_PIC)
61# error: You must define USE_PIC in the hard_config.h file
62#endif
63
64#if !defined(IDLE_THREAD_INDEX)
65# error: You must define IDLE_THREAD_INDEX in the ctx_handler.h file
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
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
84#if !defined(GIET_ISR_TYPE_MAX)
85# error: You must define GIET_ISR_TYPE_MAX in the giet_config.h file
86#endif
87
88#if !defined(GIET_ISR_CHANNEL_MAX)
89# error: You must define GIET_ISR_CHANNEL_MAX in the giet_config.h file
90#endif
91
92
93////////////////////////////////////////////////////////////////////////////////
94//       Global variables
95////////////////////////////////////////////////////////////////////////////////
96
97// Array of page tables virtual addresses (one per vspace and per cluster)
98__attribute__((section(".kdata")))
99unsigned int        _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 
100
101// Array of page tables physical addresses (one per vspace and per cluster)
102__attribute__((section(".kdata")))
103unsigned long long  _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 
104
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
113// Array of pointers on the schedulers
114__attribute__((section(".kdata")))
115volatile static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
116
117// Synchonisation before entering parallel execution
118__attribute__((section(".kdata")))
119volatile unsigned int _kernel_init_done = 0;
120
121// Kernel uses a sqt_lock to protect TTY0       
122__attribute__((section(".kdata")))
123unsigned int   _tty0_boot_mode = 0;
124
125// Kernel uses a sqt_lock to protect command allocator in HBA       
126__attribute__((section(".kdata")))
127unsigned int   _hba_boot_mode = 0;
128
129// synchronisation barrier for parallel init by all processors     
130__attribute__((section(".kdata")))
131sqt_barrier_t  _all_procs_barrier  __attribute__((aligned(64)));
132
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
138////////////////////////////////////////////////////////////////////////////////
139//      Extern variables
140////////////////////////////////////////////////////////////////////////////////
141
142// this variable is allocated in tty0.c file
143extern sqt_lock_t _tty0_sqt_lock;
144
145// this variable is allocated in mmc_driver.c file
146extern unsigned int _mmc_boot_mode;
147
148// this variable is allocated in sys_handler.c file
149extern unsigned int _tty_channel_alloc[NB_TTY_CHANNELS];
150
151////////////////////////////////////////////////////////////////////////////////
152// This _kernel_init() function completes the kernel initialisation in 5 steps:
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.
156// - step 1 : Each processor initialises scheduler pointers array.
157// - step 2 : Each processor initialises PTAB pointers arrays.
158// - step 3 : Each processor initialise idle thread and starts TICK timer.
159// - step 4 : Each processor set sp, sr, ptpr, epc registers values.
160////////////////////////////////////////////////////////////////////////////////
161__attribute__((section (".kinit"))) void _kernel_init() 
162{
163    // gpid  : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
164    // x,y,p : proc coordinates ( x < X_SIZE / y < Y_SIZE / p < NB_PROCS_MAX )
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);
169    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
170    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
171    unsigned int unused;
172   
173    ////////////////////////////////////////////////////////////////////////////
174    // Step 0 : P[0,0,0] initialises global variables and peripherals
175   ////////////////////////////////////////////////////////////////////////////
176
177    if ( gpid == 0 )
178    {
179        //////  distributed kernel heap initialisation
180        _heap_init();
181       
182#if GIET_DEBUG_INIT
183_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel heap init\n", x, y, p );
184#endif
185        //////  distributed locks for MMC
186        _mmc_boot_mode = 0;
187        _mmc_init_locks();
188
189#if GIET_DEBUG_INIT
190_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes MMC distributed locks init\n", x , y , p );
191#endif
192        //////  distributed lock for TTY0
193        _sqt_lock_init( &_tty0_sqt_lock );
194        _tty_channel_alloc[0] = 1;
195
196#if GIET_DEBUG_INIT
197_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes TTY0 lock init\n", x , y , p );
198#endif
199        //////  distributed kernel barrier between all processors
200        _sqt_barrier_init( &_all_procs_barrier );
201
202#if GIET_DEBUG_INIT
203_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes barrier init\n", x , y , p );
204#endif
205
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
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
218        ////// _ext_irq_index[isr][channel] initialisation
219        if ( USE_PIC ) _ext_irq_init();
220
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
224
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
233
234        //////  IOC peripheral initialisation
235        if ( USE_IOC_HBA )
236        {
237            _hba_init();
238            _ext_irq_alloc( ISR_HBA , 0 , &unused );
239
240#if GIET_DEBUG_INIT
241_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes HBA init\n", x , y , p );
242#endif
243        }
244        if ( USE_IOC_SDC )
245        {
246            _sdc_init();
247            _ext_irq_alloc( ISR_SDC , 0 , &unused );
248
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
263        //////  release other processors
264        _kernel_init_done = 1;
265    }
266    else 
267    {
268        while( _kernel_init_done == 0 )  asm volatile ( "nop" );
269    }
270
271    ///////////////////////////////////////////////////////////////////////////
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.
275    ///////////////////////////////////////////////////////////////////////////
276
277    static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
278    unsigned int        threads    = psched->threads;
279
280    _schedulers[x][y][p] = psched;
281
282#if GIET_DEBUG_INIT
283_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises SCHED array\n"
284        " - scheduler vbase = %x\n"
285        " - threads         = %d\n",
286        x, y, p, (unsigned int)psched, threads );
287#endif
288
289    /////////////////////////////////////////
290    _sqt_barrier_wait( &_all_procs_barrier );   
291    /////////////////////////////////////////
292
293    ////////////////////////////////////////////////////////////////////////////
294    // step 2 : each processor that is allocated at least one thread loops
295    //          on its allocated threads:
296    //          - contributes to _ptabs_vaddr & _ptabs_paddr arrays
297    //            initialisation, from values stored in the threads contexts.
298    //          - set CTX_RA slot  with the kernel _ctx_eret() virtual address.
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.
302    ////////////////////////////////////////////////////////////////////////////
303
304    unsigned int ltid;
305
306    for (ltid = 0; ltid < threads; ltid++) 
307    {
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 ); 
311        unsigned int npt2 = _get_thread_slot( x, y, p, ltid , CTX_NPT2_ID ); 
312
313        // initialize PTABS arrays
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;
317
318        // set the PTPR to use the local page table
319        asm volatile( "mtc2    %0,   $0"
320                      : : "r" (ptpr) );
321
322        // set CTX_RA slot
323        unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
324        _set_thread_slot( x, y, p, ltid, CTX_RA_ID, ctx_ra );
325
326        // set CTX_ENTRY and CTX_EPC slots
327        unsigned int* ptr = (unsigned int*)_get_thread_slot(x , y , p , ltid , CTX_ENTRY_ID);
328        unsigned int ctx_entry = *ptr;
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 );
331
332#if GIET_DEBUG_INIT
333_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises PTABS arrays"
334        " and context for thread %d \n"
335        " - ptabs_vaddr[%d][%d][%d] = %x\n"
336        " - ptabs_paddr[%d][%d][%d] = %l\n"
337        " - ctx_entry            = %x\n"
338        " - ctx_ra               = %x\n",
339        x , y , p , ltid , 
340        vsid , x , y , _ptabs_vaddr[vsid][x][y] ,
341        vsid , x , y , _ptabs_paddr[vsid][x][y] ,
342        ctx_entry, ctx_ra );
343#endif
344
345    }  // end for threads
346
347    /////////////////////////////////////////
348    _sqt_barrier_wait( &_all_procs_barrier );   
349    /////////////////////////////////////////
350
351    ////////////////////////////////////////////////////////////////////////////
352    // step 3 : - Each processor complete idle thread context initialisation.
353    //            Only CTX_SP, CTX_RA, CTX_EPC, CTX_ENTRY slots, because other
354    //            slots have been initialised in boot code)
355    //            The 4 Kbytes idle stack is implemented in the scheduler itself.
356    //          - Each processor starts TICK timer, if at least one thread.
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    ////////////////////////////////////////////////////////////////////////////
361
362    unsigned int sp    = ((unsigned int)psched) + 0x2000;
363    unsigned int ra    = (unsigned int)(&_ctx_eret);
364    unsigned int entry = (unsigned int)(&_idle_thread);
365
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 );
370
371    if (threads > 0) _xcu_timer_start( cluster_xy, p, GIET_TICK_VALUE ); 
372
373#if GIET_DEBUG_INIT
374_printf("\n[DEBUG KINIT] P[%d,%d,%d] initializes idle_thread and starts TICK\n", 
375        x, y, p );
376#endif
377
378    if ( gpid == 0 )
379    {
380        _fat_init( 1 );   // kernel mode => Inode-Tree, Fat-Cache and File-Caches
381
382#if GIET_DEBUG_INIT
383_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel FAT init\n",
384        x, y, p );
385#endif
386
387    }
388
389    /////////////////////////////////////////
390    _sqt_barrier_wait( &_all_procs_barrier );   
391    /////////////////////////////////////////
392
393    ////////////////////////////////////////////////////////////////////////////
394    // step 4 : Each processor computes the thread index (ltid), and the values
395    //          to initialize the SP, SR, PTPR, EPC registers.
396    //          It jumps to a runable thread if possible,
397    //          or jumps to IDLE-THREAD if no runable thread.
398    ////////////////////////////////////////////////////////////////////////////
399
400    // default value for ltid
401    ltid = IDLE_THREAD_INDEX;
402
403    // scan allocated threads to find a runable thread
404    unsigned int  thread_id; 
405    for ( thread_id = 0 ; thread_id < threads ; thread_id++ )
406    {
407        if ( _get_thread_slot( x, y, p, thread_id, CTX_NORUN_ID ) == 0 )
408        {
409            ltid = thread_id;
410            break;
411        }
412    }
413
414    // update scheduler
415    psched->current = ltid;
416
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);
422
423#if GIET_DEBUG_INIT
424_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel_init at cycle %d\n"
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 );
428#endif
429
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)
439                   : "$29", "memory" );
440
441} // end kernel_init()
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.