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

Last change on this file since 722 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
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
98__attribute__((section(".kdata")))
99volatile unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 
100
101// array of page tables PTPR values (physical addresses >> 13)
102__attribute__((section(".kdata")))
103volatile unsigned int _ptabs_ptprs[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 
104
105// Array of pointers on the schedulers
106__attribute__((section(".kdata")))
107volatile static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
108
109// Synchonisation before entering parallel execution
110__attribute__((section(".kdata")))
111volatile unsigned int _kernel_init_done = 0;
112
113// Kernel uses a sqt_lock to protect TTY0       
114__attribute__((section(".kdata")))
115unsigned int   _tty0_boot_mode = 0;
116
117// Kernel uses a sqt_lock to protect command allocator in HBA       
118__attribute__((section(".kdata")))
119unsigned int   _hba_boot_mode = 0;
120
121// synchronisation barrier for parallel init by all processors     
122__attribute__((section(".kdata")))
123sqt_barrier_t  _all_procs_barrier  __attribute__((aligned(64)));
124
125////////////////////////////////////////////////////////////////////////////////
126//      Extern variables
127////////////////////////////////////////////////////////////////////////////////
128
129// this variable is allocated in tty0.c file
130extern sqt_lock_t _tty0_sqt_lock;
131
132// this variable is allocated in mmc_driver.c file
133extern unsigned int _mmc_boot_mode;
134
135// this variable is allocated in sys_handler.c file
136extern unsigned int _tty_channel_alloc[NB_TTY_CHANNELS];
137
138////////////////////////////////////////////////////////////////////////////////
139// This kernel_init() function completes the kernel initialisation in 5 steps:
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.
143// - step 1 : Each processor initialises scheduler pointers array.
144// - step 2 : Each processor initialises PTAB pointers arrays.
145// - step 3 : Each processor initialise idle thread and starts TICK timer.
146// - step 4 : Each processor set sp, sr, ptpr, epc registers values.
147////////////////////////////////////////////////////////////////////////////////
148__attribute__((section (".kinit"))) void kernel_init() 
149{
150    // gpid  : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
151    // x,y,p : proc coordinates ( x < X_SIZE / y < Y_SIZE / p < NB_PROCS_MAX )
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);
156    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
157    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
158    unsigned int unused;
159   
160    ////////////////////////////////////////////////////////////////////////////
161    // Step 0 : P[0,0,0] initialises global variables and peripherals
162   ////////////////////////////////////////////////////////////////////////////
163
164    if ( gpid == 0 )
165    {
166        //////  distributed kernel heap initialisation
167        _heap_init();
168       
169#if GIET_DEBUG_INIT
170_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel heap init\n", x, y, p );
171#endif
172        //////  distributed locks for MMC
173        _mmc_boot_mode = 0;
174        _mmc_init_locks();
175
176#if GIET_DEBUG_INIT
177_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes MMC distributed locks init\n", x , y , p );
178#endif
179        //////  distributed lock for TTY0
180        _sqt_lock_init( &_tty0_sqt_lock );
181        _tty_channel_alloc[0] = 1;
182
183#if GIET_DEBUG_INIT
184_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes TTY0 lock init\n", x , y , p );
185#endif
186        //////  distributed kernel barrier between all processors
187        _sqt_barrier_init( &_all_procs_barrier );
188
189#if GIET_DEBUG_INIT
190_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes barrier init\n", x , y , p );
191#endif
192
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
201        ////// _ext_irq_index[isr][channel] initialisation
202        if ( USE_PIC ) _ext_irq_init();
203
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
207
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
216
217        //////  IOC peripheral initialisation
218        if ( USE_IOC_HBA )
219        {
220            _hba_init();
221            _ext_irq_alloc( ISR_HBA , 0 , &unused );
222
223#if GIET_DEBUG_INIT
224_nolock_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes HBA init\n", x , y , p );
225#endif
226        }
227        if ( USE_IOC_SDC )
228        {
229            _sdc_init();
230            _ext_irq_alloc( ISR_SDC , 0 , &unused );
231
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
246        //////  release other processors
247        _kernel_init_done = 1;
248    }
249    else 
250    {
251        while( _kernel_init_done == 0 )  asm volatile ( "nop" );
252    }
253
254    ///////////////////////////////////////////////////////////////////////////
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.
258    ///////////////////////////////////////////////////////////////////////////
259
260    static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
261    unsigned int        threads    = psched->threads;
262
263    _schedulers[x][y][p] = psched;
264
265#if GIET_DEBUG_INIT
266_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises SCHED array\n"
267        " - scheduler vbase = %x\n"
268        " - threads         = %d\n",
269        x, y, p, (unsigned int)psched, threads );
270#endif
271
272    /////////////////////////////////////////
273    _sqt_barrier_wait( &_all_procs_barrier );   
274    /////////////////////////////////////////
275
276    ////////////////////////////////////////////////////////////////////////////
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.
281    //          - set CTX_RA slot  with the kernel _ctx_eret() virtual address.
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.
285    ////////////////////////////////////////////////////////////////////////////
286
287    unsigned int ltid;
288
289    for (ltid = 0; ltid < threads; ltid++) 
290    {
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 ); 
294
295        // initialize PTABS arrays
296        _ptabs_vaddr[vsid][x][y] = ptab;
297        _ptabs_ptprs[vsid][x][y] = ptpr;
298
299        // set the PTPR to use the local page table
300        asm volatile( "mtc2    %0,   $0"
301                      : : "r" (ptpr) );
302
303        // set CTX_RA slot
304        unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
305        _set_thread_slot( x, y, p, ltid, CTX_RA_ID, ctx_ra );
306
307        // set CTX_ENTRY and CTX_EPC slots
308        unsigned int* ptr = (unsigned int*)_get_thread_slot(x , y , p , ltid , CTX_ENTRY_ID);
309        unsigned int ctx_entry = *ptr;
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 );
312
313#if GIET_DEBUG_INIT
314_printf("\n[DEBUG KINIT] P[%d,%d,%d] initialises PTABS arrays"
315        " and context for thread %d \n"
316        " - ptabs_vaddr[%d][%d][%d] = %x\n"
317        " - ptabs_paddr[%d][%d][%d] = %l\n"
318        " - ctx_entry            = %x\n"
319        " - ctx_ra               = %x\n",
320        x , y , p , ltid , 
321        vsid , x , y , ptab ,
322        vsid , x , y , ((unsigned long long)ptpr)<<13 ,
323        ctx_entry, ctx_ra );
324#endif
325
326    }  // end for threads
327
328    /////////////////////////////////////////
329    _sqt_barrier_wait( &_all_procs_barrier );   
330    /////////////////////////////////////////
331
332    ////////////////////////////////////////////////////////////////////////////
333    // step 3 : - Each processor complete idle thread context initialisation.
334    //            Only CTX_SP, CTX_RA, CTX_EPC, CTX_ENTRY slots, because other
335    //            slots have been initialised in boot code)
336    //            The 4 Kbytes idle stack is implemented in the scheduler itself.
337    //          - Each processor starts TICK timer, if at least one thread.
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    ////////////////////////////////////////////////////////////////////////////
342
343    unsigned int sp    = ((unsigned int)psched) + 0x2000;
344    unsigned int ra    = (unsigned int)(&_ctx_eret);
345    unsigned int entry = (unsigned int)(&_idle_thread);
346
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 );
351
352    if (threads > 0) _xcu_timer_start( cluster_xy, p, GIET_TICK_VALUE ); 
353
354#if GIET_DEBUG_INIT
355_printf("\n[DEBUG KINIT] P[%d,%d,%d] initializes idle_thread and starts TICK\n", 
356        x, y, p );
357#endif
358
359    if ( gpid == 0 )
360    {
361        _fat_init( 1 );   // kernel mode => Inode-Tree, Fat-Cache and File-Caches
362
363#if GIET_DEBUG_INIT
364_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel FAT init\n",
365        x, y, p );
366#endif
367
368    }
369
370    /////////////////////////////////////////
371    _sqt_barrier_wait( &_all_procs_barrier );   
372    /////////////////////////////////////////
373
374    ////////////////////////////////////////////////////////////////////////////
375    // step 4 : Each processor computes the thread index (ltid), and the values
376    //          to initialize the SP, SR, PTPR, EPC registers.
377    //          It jumps to a runable thread if possible,
378    //          or jumps to IDLE-THREAD if no runable thread.
379    ////////////////////////////////////////////////////////////////////////////
380
381    if (threads == 0) _printf("\n[GIET WARNING] No thread allocated to P[%d,%d,%d]\n",
382                            x, y, p );
383
384    // default value for ltid
385    ltid = IDLE_THREAD_INDEX;
386
387    // scan allocated threads to find a runable thread
388    unsigned int  thread_id; 
389    for ( thread_id = 0 ; thread_id < threads ; thread_id++ )
390    {
391        if ( _get_thread_slot( x, y, p, thread_id, CTX_NORUN_ID ) == 0 )
392        {
393            ltid = thread_id;
394            break;
395        }
396    }
397
398    // update scheduler
399    psched->current = ltid;
400
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);
406
407#if GIET_DEBUG_INIT
408_printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel_init at cycle %d\n"
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 );
412#endif
413
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)
423                   : "$29", "memory" );
424
425} // end kernel_init()
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.