source: soft/giet_vm/sys/init.c @ 163

Last change on this file since 163 was 163, checked in by karaoui, 12 years ago

changing mover to memo
changing soft.bin to soft.elf
...

File size: 19.1 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : init.c
3// Date     : 26/05/2012
4// Authors  : alain greiner & mohamed karaoui
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////////
7// The init.c files is part of the GIET nano-kernel.
8// This code can be used in the second phase of the boot to inititialise the kernel
9// structures and to launch one or several multi-tasks applications on a many_cores
10// hardware architecture.
11// All procs at this phase should have their MMU activated, this activation is done
12// by the boot phase, wich is responsable of constructing all the pages tables.
13////////////////////////////////////////////////////////////////////////////////////
14
15#include <common.h>
16#include <ctx_handler.h>
17#include <sys_handler.h>
18#include <mapping_info.h>
19#include <giet_config.h>
20#include <mips32_registers.h>
21#include <irq_handler.h>
22#include <hwr_mapping.h>
23#include <mwmr.h>
24
25#define in_kinit __attribute__((section (".kinit")))
26
27unsigned int _ptabs[GIET_NB_VSPACE_MAX];
28
29void _tcg_init();
30void _peri_init(); 
31extern void _task_init();
32
33in_kinit void _init()
34{
35    _puts("\n[INIT] Starting kernel initialisations ");
36    _putw( _proctime() );
37    _puts("\n");
38
39    // building tasks contexts
40    _tcg_init();
41    _puts("\n[INIT] Task Contexts completed at cycle ");
42    _putw( _proctime() );
43    _puts("\n");
44
45    // Initialize peripherals
46    _peri_init();
47    _puts("\n[INIT] Peripherals completed at cycle ");
48    _putw( _proctime() );
49    _puts("\n");
50
51    //wakeup all other processor
52    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
53    header->signature = OUT_MAPPING_SIGNATURE;
54}
55
56////////////////////////////////////////////////////////////////////////////
57//      _eret()
58////////////////////////////////////////////////////////////////////////////
59in_kinit void _eret()
60{
61    asm volatile("eret \n"
62                 "nop");
63}
64
65///////////////////////////////////////////////////////////////////////////////
66// This function initialises the task context for a given vspace.
67// There is a private context array for each vspace, indexed by the
68// (task_id, proc_id) composite index.
69// The following values are written in the task context:
70// - SP     stack pointer = stack_base + stack_length
71// - RA     return address = &_eret
72// - EPC    start address = start_vector[task->startid]
73// - SR     status register = OxFF13
74// - TTY    TTY index = base_tty_id + tty_local_id
75// - PTPR   page table base address / 8K
76// - MODE   mmu_mode = 0xF (TLBs and caches activated)
77// It statically allocates the task to the proper scheduler
78// (one scheduler per processor).
79////////////////////////////////////////////////////////////////////////////////
80in_kinit void _task_map( unsigned int        task_id,        // global index
81                unsigned int        vspace_id,      // global index
82                unsigned int        base_tty_id,
83                unsigned int*       start_vector )
84{
85    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
86
87    mapping_vseg_t*     vseg   = _get_vseg_base(header);
88    mapping_task_t*     task   = _get_task_base(header);
89    mapping_vspace_t*   vspace = _get_vspace_base(header);
90
91    unsigned int        vseg_id;
92    unsigned int        loc_id;
93    unsigned int        proc_id;
94
95    unsigned int        sp;
96    unsigned int        ra   = (unsigned int)&_eret;
97
98#if INIT_DEBUG_CTX
99    _puts("\n[INIT] : task start vector ");
100        _putw((unsigned int)start_vector);
101    _puts("\n[INIT] : task startid ");
102        _putw(task[task_id].startid);
103#endif
104    unsigned int        epc  = start_vector[task[task_id].startid];
105    unsigned int        tty  = base_tty_id + task[task_id].ttylocid; 
106    unsigned int        sr   = 0x0000FF13;
107    unsigned int        mode = 0xF;
108
109        unsigned int            ptpr = ((unsigned int)_ptabs[vspace_id]) >> 13;
110
111    // check values
112    if ( task[task_id].proclocid >= NB_PROCS )
113    {
114        _puts("\n[INIT ERROR] : processor index too large for task ");
115        _puts( task[task_id].name );
116        _puts(" in vspace ");
117        _puts( vspace[vspace_id].name );
118        _puts("\n");
119        _exit();
120    }
121    if ( task[task_id].clusterid >= NB_CLUSTERS )
122    {
123        _puts("\n[INIT ERROR] : cluster index too large for task ");
124        _puts( task[task_id].name );
125        _puts(" in vspace ");
126        _puts( vspace[vspace_id].name );
127        _puts("\n");
128        _exit();
129    }
130    if ( task[task_id].vobjlocid >= vspace->vsegs )
131    {
132        _puts("\n[INIT ERROR] : vseg index too large for task ");
133        _puts( task[task_id].name );
134        _puts(" in vspace ");
135        _puts( vspace[vspace_id].name );
136        _puts("\n");
137        _exit();
138    }
139    if ( task[task_id].startid >= vspace->tasks )
140    {
141        _puts("\n[INIT ERROR] : start index too large for task ");
142        _puts( task[task_id].name );
143        _puts(" in vspace ");
144        _puts( vspace[vspace_id].name );
145        _puts("\n");
146        _exit();
147    }
148    if ( tty >= NB_TTYS )
149    {
150        _puts("\n[INIT ERROR] : TTY index too large for task ");
151        _puts( task[task_id].name );
152        _puts(" in vspace ");
153        _puts( vspace[vspace_id].name );
154        _puts("\n");
155        _exit();
156    }
157
158    // get stack pointer value
159    vseg_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset;
160    sp = vseg[vseg_id].vbase + vseg[vseg_id].length;
161
162    // compute global processor index
163    proc_id = task[task_id].clusterid * NB_PROCS + task[task_id].proclocid;
164
165    // check local task index
166    loc_id = _scheduler[proc_id].tasks;
167    if ( loc_id >= GIET_NB_TASKS_MAX )
168    {
169        _puts("\n[INIT ERROR] : too much tasks allocated to processor ");
170        _putw( proc_id );
171        _puts("\n");
172        _exit();
173    }
174   
175    // update number of tasks allocated to scheduler
176    _scheduler[proc_id].tasks = loc_id + 1;
177
178    // initializes the task context
179    _scheduler[proc_id].context[loc_id][CTX_SR_ID]   = sr;
180    _scheduler[proc_id].context[loc_id][CTX_SP_ID]   = sp;
181    _scheduler[proc_id].context[loc_id][CTX_RA_ID]   = ra;
182    _scheduler[proc_id].context[loc_id][CTX_EPC_ID]  = epc;
183    _scheduler[proc_id].context[loc_id][CTX_TTY_ID]  = tty;
184    _scheduler[proc_id].context[loc_id][CTX_PTPR_ID] = ptpr;
185    _scheduler[proc_id].context[loc_id][CTX_MODE_ID] = mode;
186   
187#if INIT_DEBUG_CTX
188_puts("Task ");
189_puts( task[task_id].name );
190_puts(" allocated to processor ");
191_putw( proc_id );
192_puts(" / loc_id = ");
193_putw( loc_id );
194_puts("\n");
195
196_puts("  - SR          = ");
197_putw( sr );
198_puts("  saved at ");
199_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_SR_ID] );
200_puts("\n");
201
202_puts("  - RA          = ");
203_putw( ra );
204_puts("  saved at ");
205_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_RA_ID] );
206_puts("\n");
207
208_puts("  - SP          = ");
209_putw( sp );
210_puts("  saved at ");
211_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_SP_ID] );
212_puts("\n");
213
214_puts("  - EPC         = ");
215_putw( epc );
216_puts("  saved at ");
217_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_EPC_ID] );
218_puts("\n");
219
220_puts("  - TTY         = ");
221_putw( tty );
222_puts("  saved at ");
223_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_TTY_ID] );
224_puts("\n");
225
226_puts("  - PTPR        = ");
227_putw( ptpr<<13 );
228_puts("  saved at ");
229_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_PTPR_ID] );
230_puts("\n");
231
232_puts("  - MODE        = ");
233_putw( mode );
234_puts("  saved at ");
235_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_MODE_ID] );
236_puts("\n");
237#endif
238
239} // end _task_map()
240
241///////////////////////////////////////////////////////////////////////////
242// Initialise vobjs
243// parm:
244// vobj: the vobj to initialise
245// region_id: the vspace in wich the vobj is located or the global space(-1).
246///////////////////////////////////////////////////////////////////////////
247void initialise_vobj(mapping_vobj_t* vobj, unsigned int region_id)
248{
249    mwmr_channel_t* mwmr;
250    switch(vobj->type)
251    {
252
253        case PTAB:
254            break;
255
256        case MWMR:
257            // initializes MWMR channel if vseg is a MWMR
258            // the channel storage capacity is (vobj->length/4 - 5) words
259            mwmr = (mwmr_channel_t*)(vobj->vaddr);
260            mwmr->ptw   = 0;
261            mwmr->ptr   = 0;
262            mwmr->sts   = 0;
263            mwmr->depth = (vobj->length>>2) - 5;
264            mwmr->lock  = 0;
265
266#if INIT_DEBUG_CTX
267_puts("   MWMR channel name = ");
268_puts( vobj->name);
269_puts("   MWMR channel depth = ");
270_putw( mwmr->depth );
271_puts("\n");
272#endif
273            break;
274        case ELF:
275            break;
276        case PERI:
277            break;
278        case BARRIER:
279        case BUFFER:
280        case LOCK:
281            break;//TODO
282        default:
283            _puts("Unknown Ressource of type: ");
284            _putw(vobj->type);
285            _puts("Unknown Ressource name: ");
286            _puts(vobj->name);
287            _puts("\n ");
288            _exit();
289    } 
290}
291
292
293///////////////////////////////////////////////////////////////////////////////
294//
295///////////////////////////////////////////////////////////////////////////////
296void _set_ptpr(unsigned int vspace_id)
297{
298        unsigned int ptpr = ((unsigned int)_ptabs[vspace_id]) >> 13;
299        asm volatile("mtc2 %0, $0"::"r"(ptpr));
300}
301
302///////////////////////////////////////////////////////////////////////////////
303// This function sets the schedulers default values for all processors
304// (tasks <= 0, and current <= 0).
305// Then it scan all tasks (in all vspaces) to initialise the schedulers,
306// the tasks contexts, as defined in the mapping_info data structure.
307// A global TTY index is allocated to each task, as specified in the mapping.
308// TTY0 is reserved for the kernel.
309///////////////////////////////////////////////////////////////////////////////
310in_kinit void _tcg_init()
311{
312    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
313    mapping_cluster_t*  cluster = _get_cluster_base( header );
314    mapping_vspace_t*   vspace  = _get_vspace_base( header );     
315    mapping_vobj_t*     vobj    = _get_vobj_base( header );
316   
317
318    unsigned int*       start_vector_base;
319
320    unsigned int        base_tty_id = 1;     // TTY allocator
321
322    unsigned int        cluster_id; 
323    unsigned int        proc_id; 
324    unsigned int        vspace_id; 
325    unsigned int        vobj_id;
326    unsigned int        task_id;
327
328_puts("\n SCHEDULLER ");
329_putw((unsigned int)_scheduler);
330_puts("\n");
331
332    // initialise the schedulers (not done by the compiler/loader)
333    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
334    {
335        for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
336        {
337            if ( proc_id >= NB_PROCS )
338            {
339                _puts("\n[INIT ERROR] The number of processors in cluster ");
340                _putw( cluster_id );
341                _puts(" is larger than NB_PROCS \n");
342                _exit();
343            }
344            _scheduler[cluster_id*NB_PROCS+proc_id].tasks   = 0;
345            _scheduler[cluster_id*NB_PROCS+proc_id].current = 0;
346        }
347    }
348
349    // loop on the virtual spaces and set the ptpr
350    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
351    {
352        char found = 0;
353                //initialise all vobjs
354            for(vobj_id= vspace[vspace_id].vobj_offset; 
355                        vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
356                        vobj_id++)
357            {
358            if(vobj[vobj_id].type == PTAB)
359            {
360                found = 1;
361                //ptabs allready buided by the boot
362                _ptabs[vspace_id]        = (unsigned int) vobj[vobj_id].paddr;
363                _puts("ptabs for vspace " ); 
364                _putw(vspace_id);
365                _puts(" address: ") ;
366                _putw(_ptabs[vspace_id]); 
367                _puts("\n");
368            }
369            } 
370
371        if(!found)
372        {
373                _puts("\n[INIT ERROR] Forget to set a PTAB for vspace ");
374                _putw( vspace_id );
375                _puts(" ?\n");
376                _exit();
377        }
378    }
379
380    // main loop on the virtual spaces
381    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
382    {
383                _set_ptpr(vspace_id);
384#if INIT_DEBUG_CTX
385_puts("\n******* mapping tasks and channels in vspace ");
386_puts(vspace[vspace_id].name);
387_puts(" ********\n");
388#endif
389                //initialise all vobjs
390            for(vobj_id= vspace[vspace_id].vobj_offset; 
391                        vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
392                        vobj_id++)
393            {
394                        initialise_vobj(&vobj[vobj_id], vspace_id);
395            } 
396
397
398        // Get the physical address of the start_vector for the vspace.
399        // The start_vector is stored at the beginning of the seg_data segment,
400        // and contains the start addresses for all tasks defined in a vspace.
401        // The seg_data segment must be the first vseg defined in
402        // the mapping_info data structure.
403        mapping_vobj_t* vobj_data = &vobj[vspace[vspace_id].vobj_offset + vspace[vspace_id].funcs_offset]; 
404#if INIT_DEBUG_CTX
405        _puts("\n[INIT] : vobj_data name ");
406        _puts(vobj_data->name);
407        _puts("\n[INIT] : vobj_data vaddrr ");
408                _putw(vobj_data->vaddr);
409        _puts("\n[INIT] : vobj_data addrr ");
410                _putw(vobj_data->paddr);
411#endif
412        start_vector_base = (unsigned int*)vobj_data->vaddr;
413
414        // map tasks
415        for ( task_id = vspace[vspace_id].task_offset ; 
416              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
417              task_id++ )
418        {
419            _task_map( task_id, 
420                           vspace_id,
421                           base_tty_id,
422                           start_vector_base );           
423        }
424
425        // increment TTY allocator
426        base_tty_id = base_tty_id + vspace[vspace_id].ttys;   
427    }
428} // end _tc_init()
429
430////////////////////////////////////////////////////////////////////////////////
431//      _peri_init()
432// This generic function initializes the interrupt vector, the ICU masks,
433// and the timers for the context switch.
434// The hardware parameters are NB_CLUSTERS, NB_PROCS, NB_TIMERS, NB_DMAS
435// CLUSTER_SPAN, seg_icu_base, seg_timer_base.
436// The number of processor per cluster cannot be larger than 8.
437// The total number of TTYs cannot be larger than 15.
438// The NB_TIMERS, NB_DMAS & NB_PROCS parameters must be equal.
439////////////////////////////////////////////////////////////////////////////////
440in_kinit void _peri_init()
441{
442    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
443    mapping_cluster_t* cluster = _get_cluster_base( header );
444
445    unsigned int cluster_id;
446
447    if ( NB_TIMERS != NB_PROCS )
448    {
449        _puts("\n[INIT ERROR] NB_TIMERS != NB_PROCS\n");
450        _exit();
451    }
452    if ( NB_DMAS != NB_PROCS )
453    {
454        _puts("\n[INIT ERROR] NB_DMAS != NB_PROCS\n");
455        _exit();
456    }
457
458    // interrupt vector initialisation
459
460    _interrupt_vector[0]  = &_isr_ioc;
461
462    _interrupt_vector[1]  = &_isr_tty_get_0;
463    _interrupt_vector[2]  = &_isr_tty_get_1;
464    _interrupt_vector[3]  = &_isr_tty_get_2;
465    _interrupt_vector[4]  = &_isr_tty_get_3;
466    _interrupt_vector[5]  = &_isr_tty_get_4;
467    _interrupt_vector[6]  = &_isr_tty_get_5;
468    _interrupt_vector[7]  = &_isr_tty_get_6;
469    _interrupt_vector[8]  = &_isr_tty_get_7;
470    _interrupt_vector[9]  = &_isr_tty_get_8;
471    _interrupt_vector[10] = &_isr_tty_get_9;
472    _interrupt_vector[11] = &_isr_tty_get_10;
473    _interrupt_vector[12] = &_isr_tty_get_11;
474    _interrupt_vector[13] = &_isr_tty_get_12;
475    _interrupt_vector[14] = &_isr_tty_get_13;
476    _interrupt_vector[14] = &_isr_tty_get_14;
477
478
479    _interrupt_vector[16] = &_isr_switch;
480    _interrupt_vector[17] = &_isr_dma;
481    _interrupt_vector[18] = &_isr_switch;
482    _interrupt_vector[19] = &_isr_dma;
483    _interrupt_vector[20] = &_isr_switch;
484    _interrupt_vector[21] = &_isr_dma;
485    _interrupt_vector[22] = &_isr_switch;
486    _interrupt_vector[23] = &_isr_dma;
487    _interrupt_vector[24] = &_isr_switch;
488    _interrupt_vector[25] = &_isr_dma;
489    _interrupt_vector[26] = &_isr_switch;
490    _interrupt_vector[27] = &_isr_dma;
491    _interrupt_vector[28] = &_isr_switch;
492    _interrupt_vector[29] = &_isr_dma;
493    _interrupt_vector[30] = &_isr_switch;
494    _interrupt_vector[31] = &_isr_dma;
495
496
497    // ICU MASKs and TIMERS initialisation
498
499    volatile unsigned int* icu   = (unsigned int*)&seg_icu_base;
500    volatile unsigned int* timer = (unsigned int*)&seg_timer_base;
501   
502    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
503    {
504        if ( cluster[cluster_id].procs == 0 ) break;
505
506        icu[ICU_MASK_SET + 0*ICU_SPAN] = 0x000380FF;    // ICU_MASK for proc 0
507        if ( _scheduler[cluster_id*NB_PROCS + 0].tasks > 1 )
508        {
509           timer[TIMER_PERIOD + 0*TIMER_SPAN] = GIET_TICK_VALUE;
510           timer[TIMER_MODE   + 0*TIMER_SPAN] = 0x3;
511        }
512
513        if ( cluster[cluster_id].procs == 1 ) break;
514
515        icu[ICU_MASK_SET + 1*ICU_SPAN] = 0x000C0000;    // ICU_MASK for proc 1
516        if ( _scheduler[cluster_id*NB_PROCS + 1].tasks > 1 )
517        {
518           timer[TIMER_PERIOD + 1*TIMER_SPAN] = GIET_TICK_VALUE;
519           timer[TIMER_MODE   + 1*TIMER_SPAN] = 0x3;
520        }
521
522        if ( cluster[cluster_id].procs == 2 ) break;
523
524        icu[ICU_MASK_SET + 2*ICU_SPAN] = 0x00300000;    // ICU_MASK for proc 2
525        if ( _scheduler[cluster_id*NB_PROCS + 2].tasks > 1 )
526        {
527           timer[TIMER_PERIOD + 2*TIMER_SPAN] = GIET_TICK_VALUE;
528           timer[TIMER_MODE   + 2*TIMER_SPAN] = 0x3;
529        }
530
531        if ( cluster[cluster_id].procs == 3 ) break;
532
533        icu[ICU_MASK_SET + 3*ICU_SPAN] = 0x00C00000;    // ICU_MASK for proc 3
534        if ( _scheduler[cluster_id*NB_PROCS + 3].tasks > 1 )
535        {
536           timer[TIMER_PERIOD + 3*TIMER_SPAN] = GIET_TICK_VALUE;
537           timer[TIMER_MODE   + 3*TIMER_SPAN] = 0x3;
538        }
539
540        if ( cluster[cluster_id].procs == 4 ) break;
541        icu[ICU_MASK_SET + 4*ICU_SPAN] = 0x03000000;    // ICU_MASK for proc 4
542
543        if ( _scheduler[cluster_id*NB_PROCS + 4].tasks > 1 )
544        {
545           timer[TIMER_PERIOD + 4*TIMER_SPAN] = GIET_TICK_VALUE;
546           timer[TIMER_MODE   + 4*TIMER_SPAN] = 0x3;
547        }
548
549        if ( cluster[cluster_id].procs == 5 ) break;
550
551        icu[ICU_MASK_SET + 5*ICU_SPAN] = 0x0C000000;    // ICU_MASK for proc 5
552        if ( _scheduler[cluster_id*NB_PROCS + 5].tasks > 1 )
553        {
554           timer[TIMER_PERIOD + 5*TIMER_SPAN] = GIET_TICK_VALUE;
555           timer[TIMER_MODE   + 5*TIMER_SPAN] = 0x3;
556        }
557
558        if ( cluster[cluster_id].procs == 6 ) break;
559
560        icu[ICU_MASK_SET + 6*ICU_SPAN] = 0x30000000;    // ICU_MASK for proc 6
561        if ( _scheduler[cluster_id*NB_PROCS + 6].tasks > 1 )
562        {
563           timer[TIMER_PERIOD + 6*TIMER_SPAN] = GIET_TICK_VALUE;
564           timer[TIMER_MODE   + 6*TIMER_SPAN] = 0x3;
565        }
566
567        if ( cluster[cluster_id].procs == 7 ) break;
568
569        icu[ICU_MASK_SET + 7*ICU_SPAN] = 0xC0000000;    // ICU_MASK for proc 7
570        if ( _scheduler[cluster_id*NB_PROCS + 7].tasks > 1 )
571        {
572           timer[TIMER_PERIOD + 7*TIMER_SPAN] = GIET_TICK_VALUE;
573           timer[TIMER_MODE   + 7*TIMER_SPAN] = 0x3;
574        }
575
576        if ( cluster[cluster_id].procs > 8 ) 
577        {
578            _puts("\n[INIT ERROR] The number of processors per cluster\n");
579            _puts("               cannot be larger than 8\n");
580            _exit();
581        }
582        icu   = icu   + (CLUSTER_SPAN>>2);
583        timer = timer + (CLUSTER_SPAN>>2);
584    }
585} // end _peri_init()
Note: See TracBrowser for help on using the repository browser.