source: soft/giet_vm/sys/kernel_init.c @ 179

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

reverting modification in kernel_init: mwmr depth

File size: 26.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// FIXME
8// The kernel_init.c files is part of the GIET-VM nano-kernel.
9// It contains the kernel entry point for the second phase of system initialisation:
10// all processors are jumping to _kernel_init, but P[0] is first because other
11// processors are blocked until P[0] complete initilisation of task contexts,
12// vobjs and peripherals.
13// All procs in this phase have their MMU activated, because each processor P[i]
14// must initialise registers SP, SR, PTPR and EPC with informations stored
15// in _scheduler[i].
16////////////////////////////////////////////////////////////////////////////////////
17
18#include <common.h>
19#include <ctx_handler.h>
20#include <sys_handler.h>
21#include <mapping_info.h>
22#include <giet_config.h>
23#include <mips32_registers.h>
24#include <irq_handler.h>
25#include <vm_handler.h>
26#include <hwr_mapping.h>
27#include <mwmr_channel.h>
28#include <barrier.h>
29#include <drivers.h>
30
31#define in_kinit __attribute__((section (".kinit")))
32 
33///////////////////////////////////////////////////////////////////////////////////
34// array of pointers on the page tables
35// (both physical and virtual addresses)
36///////////////////////////////////////////////////////////////////////////////////
37
38__attribute__((section (".kdata"))) unsigned int _kernel_ptabs_paddr[GIET_NB_VSPACE_MAX]; 
39__attribute__((section (".kdata"))) unsigned int _kernel_ptabs_vaddr[GIET_NB_VSPACE_MAX]; 
40
41///////////////////////////////////////////////////////////////////////////////////
42// declarations required to avoid forward references
43///////////////////////////////////////////////////////////////////////////////////
44
45void    _kernel_ptabs_init(void);
46void    _kernel_vobjs_init(void);
47void    _kernel_tasks_init(void);
48void    _kernel_peripherals_init(void);
49void    _kernel_interrupt_vector_init(void);
50void    _kernel_start_all_procs(void);
51
52//////////////////////////////////////////////////////////////////////////////////
53// This function is the entry point for the second step of the boot sequence.
54//////////////////////////////////////////////////////////////////////////////////
55in_kinit void _kernel_init()
56{
57    // values to be written in registers
58    unsigned int        sp_value;
59    unsigned int        sr_value;
60    unsigned int        ptpr_value;
61    unsigned int        epc_value;
62
63    unsigned int        pid =   _procid();
64
65    // only processor 0 executes system initialisation
66    if ( pid == 0 )
67    {
68        _kernel_ptabs_init();
69        /* must be called after the initialisation of ptabs */
70        _kernel_vobjs_init();
71        _kernel_tasks_init();
72        _kernel_interrupt_vector_init();
73        _kernel_peripherals_init();
74        _kernel_start_all_procs();
75    }
76
77    // each processor initialises it's SP, SR, PTPR, and EPC registers
78    // from values defined in _scheduler[pid], starts it's private
79    // context switch timer (if there is more than one task allocated)
80    // and jumps to user code.
81    // It does nothing, and keep idle if no task allocated.
82
83    static_scheduler_t*  sched = &_scheduler[pid];
84
85    if ( sched->tasks )         // at leat one task allocated
86    {
87        // initialise registers
88        sp_value   = sched->context[0][CTX_SP_ID];
89        sr_value   = sched->context[0][CTX_SR_ID];
90        ptpr_value = sched->context[0][CTX_PTPR_ID];
91        epc_value  = sched->context[0][CTX_EPC_ID];
92
93        // start TICK timer
94        if ( sched->tasks > 1 )
95        {
96            unsigned int cluster_id = pid / NB_PROCS;
97            unsigned int proc_id    = pid % NB_PROCS;
98           _timer_write( cluster_id, proc_id, TIMER_PERIOD, GIET_TICK_VALUE );
99           _timer_write( cluster_id, proc_id, TIMER_MODE  , 0x3 );
100        }
101    }
102    else                                        // no task allocated
103    {
104        _get_lock( &_tty_put_lock );
105        _puts("\n No task allocated to processor ");
106        _putw( pid );
107        _puts(" => keep idle\n");
108        _release_lock ( &_tty_put_lock );
109
110        // enable interrupts in kernel mode
111        asm volatile ( "li         $26, 0xFF01  \n"
112                       "mtc0   $26, $12     \n" 
113                       ::: "$26" );
114
115                // infinite loop in kernel mode
116        while (1) asm volatile("nop");
117    }
118
119    asm volatile (
120       "move    $29,    %0              \n"             /* SP <= ctx[CTX_SP_ID] */
121       "mtc0    %1,             $12             \n"             /* SR <= ctx[CTX_SR_ID] */
122       "mtc2    %2,             $0              \n"             /* PTPR <= ctx[CTX_PTPR_ID] */
123       "mtc0    %3,             $14             \n"             /* EPC <= ctx[CTX_EPC_ID] */
124       "eret                                    \n"             /* jump to user code */
125       "nop                                             \n"
126       :
127       : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value) );
128
129} // end _kernel_init()
130
131//////////////////////////////////////////////////////////////////////////////////
132// This function wakeup all processors.
133// It should be executed by P[0] when the kernel initialisation is done.
134//////////////////////////////////////////////////////////////////////////////////
135in_kinit void _kernel_start_all_procs()
136{
137    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
138
139    _puts("\n[INIT] Starting parallel execution at cycle : ");
140    _putw( _proctime() );
141    _puts("\n");
142
143    header->signature = OUT_MAPPING_SIGNATURE;
144}
145
146//////////////////////////////////////////////////////////////////////////////////
147// _eret()
148// The address of this function is used to initialise the return address (RA)
149// in all task contexts (when the task has never been executed.
150//////////////////////////////////////////////////////////////////////////////////
151in_kinit void _eret()
152{
153    asm volatile("eret \n"
154                 "nop");
155}
156
157///////////////////////////////////////////////////////////////////////////////
158// used to access user space
159///////////////////////////////////////////////////////////////////////////////
160void _set_ptpr(unsigned int vspace_id)
161{
162        unsigned int ptpr = ((unsigned int)_kernel_ptabs_paddr[vspace_id]) >> 13;
163        asm volatile("mtc2 %0, $0"::"r"(ptpr));
164}
165
166///////////////////////////////////////////////////////////////////////////////
167// This function initialises the _kernel_ptabs_paddr[] array indexed by the vspace_id,
168// and containing the base addresses of all page tables.
169// This _kernel_ptabs_paddr[] array is used to initialise the task contexts.
170///////////////////////////////////////////////////////////////////////////////
171in_kinit void _kernel_ptabs_init()
172{
173    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
174    mapping_vspace_t*   vspace  = _get_vspace_base( header );     
175    mapping_vobj_t*     vobj    = _get_vobj_base( header );
176
177    unsigned int        vspace_id; 
178    unsigned int        vobj_id;
179
180    // loop on the vspaces
181    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
182    {
183        char ptab_found = 0;
184
185#if INIT_DEBUG_CTX
186_puts("[INIT] --- vobjs initialisation in vspace "); 
187_puts(vspace[vspace_id].name);
188_puts("\n");
189#endif
190        // loop on the vobjs and get the ptpr
191            for(vobj_id= vspace[vspace_id].vobj_offset; 
192                        vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
193                        vobj_id++)
194            {
195            if(vobj[vobj_id].type == VOBJ_TYPE_PTAB)
196            {
197                if( ptab_found )
198                {
199                    _puts("\n[INIT ERROR] Only one PTAB for by vspace ");
200                    _putw( vspace_id );
201                    _exit();
202                }
203
204                ptab_found = 1;
205                _kernel_ptabs_paddr[vspace_id] = vobj[vobj_id].paddr;
206                _kernel_ptabs_vaddr[vspace_id] = vobj[vobj_id].vaddr;
207
208#if INIT_DEBUG_CTX
209_puts("[INIT]   PTAB address = "); 
210_putw(_kernel_ptabs_paddr[vspace_id]); 
211_puts("\n");
212#endif
213            }
214
215        }
216
217        if( !ptab_found )
218        {
219            _puts("\n[INIT ERROR] Missing PTAB for vspace ");
220            _putw( vspace_id );
221            _exit();
222        }
223    }
224       
225    _puts("\n[INIT] Ptabss initialisation completed at cycle : ");
226    _putw( _proctime() );
227    _puts("\n");
228
229} // end kernel_ptabs_init()
230
231///////////////////////////////////////////////////////////////////////////////
232// This function initializes all private vobjs defined in the vspaces,
233// such as mwmr channels, barriers and locks, depending on the vobj type.
234// (Most of the vobjs are not known, and not initialised by the compiler).
235///////////////////////////////////////////////////////////////////////////////
236in_kinit void _kernel_vobjs_init()
237{
238    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
239    mapping_vspace_t*   vspace  = _get_vspace_base( header );     
240    mapping_vobj_t*     vobj    = _get_vobj_base( header );
241
242    unsigned int        vspace_id; 
243    unsigned int        vobj_id;
244
245    // loop on the vspaces
246    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
247    {
248        char ptab_found = 0;
249
250#if INIT_DEBUG_CTX
251_puts("[INIT] --- vobjs initialisation in vspace "); 
252_puts(vspace[vspace_id].name);
253_puts("\n");
254#endif
255        // loop on the vobjs and get the ptpr
256            for(vobj_id= vspace[vspace_id].vobj_offset; 
257                        vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
258                        vobj_id++)
259            {
260            if(vobj[vobj_id].type == VOBJ_TYPE_PTAB)
261            {
262                if( ptab_found )
263                {
264                    _puts("\n[INIT ERROR] Only one PTAB for by vspace ");
265                    _putw( vspace_id );
266                    _exit();
267                }
268
269                ptab_found = 1;
270                _kernel_ptabs_paddr[vspace_id] = vobj[vobj_id].paddr;
271                _kernel_ptabs_vaddr[vspace_id] = vobj[vobj_id].vaddr;
272
273#if INIT_DEBUG_CTX
274_puts("[INIT]   PTAB address = "); 
275_putw(_kernel_ptabs_paddr[vspace_id]); 
276_puts("\n");
277#endif
278            }
279
280        }
281
282        if( !ptab_found )
283        {
284            _puts("\n[INIT ERROR] Missing PTAB for vspace ");
285            _putw( vspace_id );
286            _exit();
287        }
288       
289        /** Set the current vspace ptpr to initialise the vobjs */
290                _set_ptpr(vspace_id);
291
292        // loop on the vobjs and get the ptpr
293            for(vobj_id= vspace[vspace_id].vobj_offset; 
294                        vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
295                        vobj_id++)
296            {
297            switch( vobj[vobj_id].type )
298            {
299                case VOBJ_TYPE_PTAB:    // initialise page table pointers array
300                {
301                    break;//already handled
302                }
303                case VOBJ_TYPE_MWMR:    // storage capacity is (vobj.length/4 - 5) words
304                        {
305                    mwmr_channel_t* mwmr = (mwmr_channel_t*)(vobj[vobj_id].vaddr);
306                    mwmr->ptw   = 0;
307                    mwmr->ptr   = 0;
308                    mwmr->sts   = 0;
309                    mwmr->depth = ((vobj[vobj_id].length>>2) - 6);//6= number of entry in the strucure
310                    mwmr->width = vobj[vobj_id].init;
311                    mwmr->lock  = 0;
312#if INIT_DEBUG_CTX
313_puts("[INIT]   MWMR channel ");
314_puts( vobj->name);
315_puts(" / depth = ");
316_putw( mwmr->depth );
317_puts("\n");
318#endif
319                    break;
320                }
321                case VOBJ_TYPE_ELF:             // initialisation done by the loader
322                {
323
324#if INIT_DEBUG_CTX
325_puts("[INIT]   ELF section "); 
326_puts( vobj->name);
327_puts(" / length = ");
328_putw( vobj->length ); 
329_puts("\n");
330#endif
331                     break;
332                }
333                case VOBJ_TYPE_BARRIER: // init is the number of participants
334                {
335                    giet_barrier_t* barrier = (giet_barrier_t*)(vobj[vobj_id].vaddr);
336                    barrier->count = 0;
337                    barrier->init  = vobj[vobj_id].init;
338#if INIT_DEBUG_CTX
339_puts("   BARRIER "); 
340_puts( vobj->name);
341_puts(" / init_value = ");
342_putw( barrier->init );
343_puts("\n");
344#endif
345                    break;
346                }
347                case VOBJ_TYPE_LOCK:    // init is "not taken"
348                {
349                    unsigned int* lock = (unsigned int*)(vobj[vobj_id].vaddr);
350                    *lock = 0;
351#if INIT_DEBUG_CTX
352_puts("   LOCK "); 
353_puts( vobj->name);
354_puts("\n");
355#endif
356                    break;
357                }
358                case VOBJ_TYPE_BUFFER:  // nothing to do
359                {
360
361#if INIT_DEBUG_CTX
362_puts("   BUFFER "); 
363_puts( vobj->name);
364_puts(" / length = ");
365_putw( vobj->length ); 
366_puts("\n");
367#endif
368                    break;
369                }
370                default:
371                {
372                    _puts("\n[INIT ERROR] illegal vobj of name ");
373                    _puts(vobj->name);
374                    _puts(" / in vspace = ");
375                    _puts(vobj->name);
376                    _puts("\n ");
377                    _exit();
378                }
379            } // end switch type
380        } // end loop on vobjs
381    } // end loop on vspaces
382
383    _puts("\n[INIT] Vobjs initialisation completed at cycle : ");
384    _putw( _proctime() );
385    _puts("\n");
386
387} // end kernel_vobjs_init()
388
389///////////////////////////////////////////////////////////////////////////////
390// This function maps a given task, defined in a given vspace
391// on the processor allocated in the mapping_info structure,
392// and initialises the task context.
393// There is one scheduler per processor, and processor can be shared
394// by several applications running in different vspaces.
395// There is one private context array handled by each scheduler.
396//
397// The following values must be initialised in all task contexts:
398// - sp     stack pointer = stack_base + stack_length
399// - ra     return address = &_eret
400// - epc    start address = start_vector[task->startid]
401// - sr     status register = OxFF13
402// - tty    TTY terminal index (global index)
403// - fb     FB_DMA channel index (global index)
404// - ptpr   page table base address / 8K
405// - mode   mmu_mode = 0xF (TLBs and caches activated)
406// - ptab   page table virtual address
407////////////////////////////////////////////////////////////////////////////////
408in_kinit void _task_map( unsigned int   task_id,    // global index
409                                         unsigned int   vspace_id,  // global index
410                         unsigned int   tty_id,         // TTY index
411                         unsigned int   fbdma_id )  // FBDMA index
412{
413    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
414
415    mapping_task_t*     task   = _get_task_base(header);
416    mapping_vspace_t*   vspace = _get_vspace_base(header);
417    mapping_vobj_t*     vobj   = _get_vobj_base( header );
418
419    /** Set the current vspace ptpr before acessing the memory */
420    _set_ptpr(vspace_id);
421   
422    // values to be initialised in task context
423    unsigned int                ra   = (unsigned int)&_eret;
424    unsigned int                sr   = 0x0000FF13; 
425    unsigned int                tty  = tty_id; 
426    unsigned int                fb   = fbdma_id;         
427    unsigned int                ptpr = _kernel_ptabs_paddr[vspace_id] >> 13;
428    unsigned int                ptab = _kernel_ptabs_vaddr[vspace_id];
429    unsigned int                mode = 0xF;
430    unsigned int                sp;
431    unsigned int                epc;     
432
433    // EPC : Get the (virtual) base address of the start_vector containing
434    // the start addresses for all tasks defined in a vspace.
435    mapping_vobj_t* vobj_data = &vobj[vspace[vspace_id].vobj_offset + 
436                                      vspace[vspace_id].start_offset]; 
437    unsigned int* start_vector = (unsigned int*)vobj_data->vaddr;
438    epc  = start_vector[task[task_id].startid];
439
440    // SP :  Get the vobj containing the stack
441    unsigned int vobj_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset;
442    sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;
443
444    // compute global processor index
445    unsigned int proc_id = task[task_id].clusterid * NB_PROCS + task[task_id].proclocid;
446
447    // compute and check local task index
448    unsigned int ltid = _scheduler[proc_id].tasks;
449    if ( ltid >= GIET_NB_TASKS_MAX )
450    {
451        _puts("\n[INIT ERROR] : too much tasks allocated to processor ");
452        _putw( proc_id );
453        _puts("\n");
454        _exit();
455    }
456   
457    // update number of tasks allocated to scheduler
458    _scheduler[proc_id].tasks = ltid + 1;
459
460    // initializes the task context
461    _scheduler[proc_id].context[ltid][CTX_SR_ID]    = sr;
462    _scheduler[proc_id].context[ltid][CTX_SP_ID]    = sp;
463    _scheduler[proc_id].context[ltid][CTX_RA_ID]    = ra;
464    _scheduler[proc_id].context[ltid][CTX_EPC_ID]   = epc;
465    _scheduler[proc_id].context[ltid][CTX_PTPR_ID]  = ptpr;
466    _scheduler[proc_id].context[ltid][CTX_MODE_ID]  = mode;
467    _scheduler[proc_id].context[ltid][CTX_TTY_ID]   = tty;
468        _scheduler[proc_id].context[ltid][CTX_FBDMA_ID] = fb;
469    _scheduler[proc_id].context[ltid][CTX_PTAB_ID]  = ptab;
470    _scheduler[proc_id].context[ltid][CTX_TASK_ID]  = task_id;
471   
472#if INIT_DEBUG_CTX
473_puts("Task ");
474_puts( task[task_id].name );
475_puts(" allocated to processor ");
476_putw( proc_id );
477_puts(" / ltid = ");
478_putw( ltid );
479_puts("\n");
480
481_puts("  - SR          = ");
482_putw( sr );
483_puts("  saved at ");
484_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SR_ID] );
485_puts("\n");
486
487_puts("  - RA          = ");
488_putw( ra );
489_puts("  saved at ");
490_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_RA_ID] );
491_puts("\n");
492
493_puts("  - SP          = ");
494_putw( sp );
495_puts("  saved at ");
496_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SP_ID] );
497_puts("\n");
498
499_puts("  - EPC         = ");
500_putw( epc );
501_puts("  saved at ");
502_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_EPC_ID] );
503_puts("\n");
504
505_puts("  - PTPR        = ");
506_putw( ptpr<<13 );
507_puts("  saved at ");
508_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTPR_ID] );
509_puts("\n");
510
511_puts("  - TTY         = ");
512_putw( tty );
513_puts("  saved at ");
514_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_TTY_ID] );
515_puts("\n");
516
517_puts("  - FB          = ");
518_putw( fb );
519_puts("  saved at ");
520_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_FBDMA_ID] );
521_puts("\n");
522
523_puts("  - PTAB        = ");
524_putw( ptab );
525_puts("  saved at ");
526_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTAB_ID] );
527_puts("\n");
528#endif
529
530} // end _task_map()
531
532///////////////////////////////////////////////////////////////////////////////
533// This function initialises all task contexts and processors schedulers.
534// It sets the default values for all schedulers (tasks <= 0, current <= 0).
535// Finally, it scan all tasks in all vspaces to initialise the schedulers,
536// and the tasks contexts, as defined in the mapping_info data structure.
537// A global TTY index and a global FB channel are allocated if required.
538// TTY[0] is reserved for the kernel.
539///////////////////////////////////////////////////////////////////////////////
540in_kinit void _kernel_tasks_init()
541{
542    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
543    mapping_cluster_t*  cluster = _get_cluster_base( header );
544    mapping_vspace_t*   vspace  = _get_vspace_base( header );     
545    mapping_task_t*     task    = _get_task_base( header );
546
547    unsigned int        base_tty_id = 1;     // TTY index allocator
548    unsigned int        base_fb_id  = 0;     // FB channel index allocator
549
550    unsigned int        cluster_id; 
551    unsigned int        proc_id; 
552    unsigned int        vspace_id; 
553    unsigned int        task_id;
554
555    // initialise the schedulers (not done by the compiler)
556    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
557    {
558        for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
559        {
560            if ( proc_id >= NB_PROCS )
561            {
562                _puts("\n[INIT ERROR] The number of processors in cluster ");
563                _putw( cluster_id );
564                _puts(" is larger than NB_PROCS \n");
565                _exit();
566            }
567            _scheduler[cluster_id*NB_PROCS+proc_id].tasks   = 0;
568            _scheduler[cluster_id*NB_PROCS+proc_id].current = 0;
569        }
570    }
571
572    // loop on the virtual spaces
573    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
574    {
575
576#if INIT_DEBUG_CTX
577_puts("\n[INIT] mapping tasks in vspace ");
578_puts(vspace[vspace_id].name);
579_puts("\n");
580#endif
581        // loop on the tasks
582        for ( task_id = vspace[vspace_id].task_offset ; 
583              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
584              task_id++ )
585        {
586            unsigned int        tty_id = 0xFFFFFFFF;
587            unsigned int        fb_id  = 0xFFFFFFFF;
588            if ( task[task_id].use_tty ) 
589            {
590                tty_id = base_tty_id;
591                base_tty_id++;
592            }
593            if ( task[task_id].use_fb  ) 
594            {
595                fb_id = base_fb_id;
596                base_fb_id++;
597            }
598            _task_map( task_id,                         // global task index
599                       vspace_id,                       // vspace index
600                       tty_id,                          // global tty index
601                       fb_id );                         // global fbdma index
602        } // end loop on tasks
603    } // end oop on vspaces
604
605    _puts("\n[INIT] Task Contexts initialisation completed at cycle ");
606    _putw( _proctime() );
607    _puts("\n");
608
609#if INIT_DEBUG_CTX
610for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
611{
612    _puts("\nCluster ");
613    _putw( cluster_id );
614    _puts("\n");
615    for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
616    {
617        unsigned int ltid;              // local task index
618        unsigned int gtid;              // global task index
619        unsigned int pid = cluster_id * NB_PROCS + proc_id;
620       
621        _puts(" - processor ");
622        _putw( pid );
623        _puts("\n");
624        for ( ltid = 0 ; ltid < _scheduler[pid].tasks ; ltid++ )
625        {
626            gtid = _scheduler[pid].context[ltid][CTX_TASK_ID];
627            _puts("    task : ");
628            _puts( task[gtid].name );
629            _puts("\n");
630        }
631    }
632}
633#endif
634
635} // end _kernel_task_init()
636
637////////////////////////////////////////////////////////////////////////////////
638// This function intializes the external periherals such as the IOB component
639// (I/O bridge, containing the IOMMU, the IOC (external disk controller),
640// the NIC (external network controller), the FBDMA (frame buffer controller),
641////////////////////////////////////////////////////////////////////////////////
642in_kinit void _kernel_peripherals_init()
643{
644    /////////////////////
645    // IOC peripheral
646    // we simply activate the IOC interrupts...
647    if ( NB_IOC )
648    {
649        unsigned int*   ioc_address = (unsigned int*)&seg_ioc_base;
650        ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
651    }
652   
653    /////////////////////
654    // FBDMA peripheral
655    // we simply activate the DMA interrupts...
656    if ( NB_DMAS )
657    {
658        unsigned int*   dma_address = (unsigned int*)&seg_dma_base;
659        dma_address[DMA_IRQ_DISABLE] = 0;
660    }
661
662    /////////////////////
663    // IOB peripheral
664    // must be initialised in case of IOMMU
665    if ( GIET_IOMMU_ACTIVE )
666    {
667        unsigned int*   iob_address = (unsigned int*)&seg_iob_base;
668
669        // define IPI address mapping the IOC interrupt ...TODO...
670
671        // set IOMMU page table address
672        iob_address[IOB_IOMMU_PTPR] = (unsigned int)(&_iommu_ptab);   
673
674        // activate IOMMU
675        iob_address[IOB_IOMMU_ACTIVE] = 1;   
676    } 
677
678    _puts("\n[INIT] Peripherals initialisation completed at cycle ");
679    _putw( _proctime() );
680    _puts("\n");
681
682} // end _kernel_peripherals_init()
683
684////////////////////////////////////////////////////////////////////////////////
685// This function intialises the interrupt vector, and initialises
686// the ICU mask registers for all processors in all clusters.
687// It strongly depends on the actual peripheral hardware wiring.
688// In this peculiar version, all clusters are identical,
689// the number of processors per cluster cannot be larger than 8.
690// Processor 0 handle all interrupts corresponding to TTYs, DMAs and IOC
691// (ICU inputs from from IRQ[8] to IRQ[31]). Only the 8 TIMER interrupts
692// (ICU iputs IRQ[0] to IRQ[7]), that are used for context switching
693// are distributed to the 8 processors.
694////////////////////////////////////////////////////////////////////////////////
695in_kinit void _kernel_interrupt_vector_init()
696{
697    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
698    mapping_cluster_t*  cluster = _get_cluster_base( header );
699
700    unsigned int cluster_id;
701    unsigned int proc_id;
702
703    // ICU mask values (up to 8 processors per cluster)
704    unsigned int icu_mask[8] = { 0xFFFFFF01,
705                                 0x00000002,
706                                 0x00000004,
707                                 0x00000008,
708                                 0x00000010,
709                                 0x00000020,
710                                 0x00000040,
711                                 0x00000080 };
712
713    // initialise ICUs for each processor in each cluster
714    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
715    {
716        for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
717        {
718            _icu_write( cluster_id, proc_id, ICU_MASK_SET, icu_mask[proc_id] ); 
719        }
720    }
721
722    // initialize Interrupt vector
723
724    _interrupt_vector[0]   = &_isr_switch;
725    _interrupt_vector[1]   = &_isr_switch;
726    _interrupt_vector[2]   = &_isr_switch;
727    _interrupt_vector[3]   = &_isr_switch;
728    _interrupt_vector[4]   = &_isr_switch;
729    _interrupt_vector[5]   = &_isr_switch;
730    _interrupt_vector[6]   = &_isr_switch;
731    _interrupt_vector[7]   = &_isr_switch;
732
733    _interrupt_vector[8]   = &_isr_dma_0;
734    _interrupt_vector[9]   = &_isr_dma_1;
735    _interrupt_vector[10]  = &_isr_dma_2;
736    _interrupt_vector[11]  = &_isr_dma_3;
737    _interrupt_vector[12]  = &_isr_dma_4;
738    _interrupt_vector[13]  = &_isr_dma_5;
739    _interrupt_vector[14]  = &_isr_dma_6;
740    _interrupt_vector[15]  = &_isr_dma_7;
741
742    _interrupt_vector[16]  = &_isr_tty_get_0;
743    _interrupt_vector[17]  = &_isr_tty_get_1;
744    _interrupt_vector[18]  = &_isr_tty_get_2;
745    _interrupt_vector[19]  = &_isr_tty_get_3;
746    _interrupt_vector[20]  = &_isr_tty_get_4;
747    _interrupt_vector[21]  = &_isr_tty_get_5;
748    _interrupt_vector[22]  = &_isr_tty_get_6;
749    _interrupt_vector[23]  = &_isr_tty_get_7;
750    _interrupt_vector[24]  = &_isr_tty_get_8;
751    _interrupt_vector[25]  = &_isr_tty_get_9;
752    _interrupt_vector[26]  = &_isr_tty_get_10;
753    _interrupt_vector[27]  = &_isr_tty_get_11;
754    _interrupt_vector[28]  = &_isr_tty_get_12;
755    _interrupt_vector[29]  = &_isr_tty_get_13;
756    _interrupt_vector[30]  = &_isr_tty_get_14;
757
758    _interrupt_vector[31]  = &_isr_ioc;
759
760    _puts("\n[INIT] Interrupt vector initialisation completed at cycle ");
761    _putw( _proctime() );
762    _puts("\n");
763
764} // end _kernel_interrup_vector_init()
Note: See TracBrowser for help on using the repository browser.