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

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

removing some bugs

File size: 25.3 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] --- ptabs 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] Ptabs 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
249#if INIT_DEBUG_CTX
250_puts("[INIT] --- vobjs initialisation in vspace "); 
251_puts(vspace[vspace_id].name);
252_puts("\n");
253#endif
254        /** Set the current vspace ptpr to initialise the vobjs */
255                _set_ptpr(vspace_id);
256
257        // loop on the vobjs and get the ptpr
258            for(vobj_id= vspace[vspace_id].vobj_offset; 
259                        vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
260                        vobj_id++)
261            {
262            switch( vobj[vobj_id].type )
263            {
264                case VOBJ_TYPE_PTAB:    // initialise page table pointers array
265                {
266                    break;//already handled
267                }
268                case VOBJ_TYPE_MWMR:    // storage capacity is (vobj.length/4 - 5) words
269                        {
270                    mwmr_channel_t* mwmr = (mwmr_channel_t*)(vobj[vobj_id].vaddr);
271                    mwmr->ptw   = 0;
272                    mwmr->ptr   = 0;
273                    mwmr->sts   = 0;
274                    mwmr->depth = ((vobj[vobj_id].length>>2) - 6);//6= number of entry in the strucure
275                    mwmr->width = vobj[vobj_id].init;
276                    mwmr->lock  = 0;
277#if INIT_DEBUG_CTX
278_puts("[INIT]   MWMR channel ");
279_puts( vobj[vobj_id].name);
280_puts(" / depth = ");
281_putw( mwmr->depth );
282_puts("\n");
283#endif
284                    break;
285                }
286                case VOBJ_TYPE_ELF:             // initialisation done by the loader
287                {
288
289#if INIT_DEBUG_CTX
290_puts("[INIT]   ELF section "); 
291_puts( vobj[vobj_id].name);
292_puts(" / length = ");
293_putw( vobj[vobj_id].length ); 
294_puts("\n");
295#endif
296                     break;
297                }
298                case VOBJ_TYPE_BARRIER: // init is the number of participants
299                {
300                    giet_barrier_t* barrier = (giet_barrier_t*)(vobj[vobj_id].vaddr);
301                    barrier->count = 0;
302                    barrier->init  = vobj[vobj_id].init;
303#if INIT_DEBUG_CTX
304_puts("   BARRIER "); 
305_puts( vobj[vobj_id].name);
306_puts(" / init_value = ");
307_putw( barrier->init );
308_puts("\n");
309#endif
310                    break;
311                }
312                case VOBJ_TYPE_LOCK:    // init is "not taken"
313                {
314                    unsigned int* lock = (unsigned int*)(vobj[vobj_id].vaddr);
315                    *lock = 0;
316#if INIT_DEBUG_CTX
317_puts("   LOCK "); 
318_puts( vobj[vobj_id].name);
319_puts("\n");
320#endif
321                    break;
322                }
323                case VOBJ_TYPE_BUFFER:  // nothing to do
324                {
325
326#if INIT_DEBUG_CTX
327_puts("   BUFFER "); 
328_puts( vobj[vobj_id].name);
329_puts(" / length = ");
330_putw( vobj[vobj_id].length ); 
331_puts("\n");
332#endif
333                    break;
334                }
335                default:
336                {
337                    _puts("\n[INIT ERROR] illegal vobj of name ");
338                    _puts(vobj[vobj_id].name);
339                    _puts(" / in vspace = ");
340                    _puts(vobj[vobj_id].name);
341                    _puts("\n ");
342                    _exit();
343                }
344            } // end switch type
345        } // end loop on vobjs
346    } // end loop on vspaces
347
348    _puts("\n[INIT] Vobjs initialisation completed at cycle : ");
349    _putw( _proctime() );
350    _puts("\n");
351
352} // end kernel_vobjs_init()
353
354///////////////////////////////////////////////////////////////////////////////
355// This function maps a given task, defined in a given vspace
356// on the processor allocated in the mapping_info structure,
357// and initialises the task context.
358// There is one scheduler per processor, and processor can be shared
359// by several applications running in different vspaces.
360// There is one private context array handled by each scheduler.
361//
362// The following values must be initialised in all task contexts:
363// - sp     stack pointer = stack_base + stack_length
364// - ra     return address = &_eret
365// - epc    start address = start_vector[task->startid]
366// - sr     status register = OxFF13
367// - tty    TTY terminal index (global index)
368// - fb     FB_DMA channel index (global index)
369// - ptpr   page table base address / 8K
370// - mode   mmu_mode = 0xF (TLBs and caches activated)
371// - ptab   page table virtual address
372////////////////////////////////////////////////////////////////////////////////
373in_kinit void _task_map( unsigned int   task_id,    // global index
374                                         unsigned int   vspace_id,  // global index
375                         unsigned int   tty_id,         // TTY index
376                         unsigned int   fbdma_id )  // FBDMA index
377{
378    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
379
380    mapping_task_t*     task   = _get_task_base(header);
381    mapping_vspace_t*   vspace = _get_vspace_base(header);
382    mapping_vobj_t*     vobj   = _get_vobj_base( header );
383
384    /** Set the current vspace ptpr before acessing the memory */
385    _set_ptpr(vspace_id);
386   
387    // values to be initialised in task context
388    unsigned int                ra   = (unsigned int)&_eret;
389    unsigned int                sr   = 0x0000FF13; 
390    unsigned int                tty  = tty_id; 
391    unsigned int                fb   = fbdma_id;         
392    unsigned int                ptpr = _kernel_ptabs_paddr[vspace_id] >> 13;
393    unsigned int                ptab = _kernel_ptabs_vaddr[vspace_id];
394    unsigned int                mode = 0xF;
395    unsigned int                sp;
396    unsigned int                epc;     
397
398    // EPC : Get the (virtual) base address of the start_vector containing
399    // the start addresses for all tasks defined in a vspace.
400    mapping_vobj_t* vobj_data = &vobj[vspace[vspace_id].vobj_offset + 
401                                      vspace[vspace_id].start_offset]; 
402    unsigned int* start_vector = (unsigned int*)vobj_data->vaddr;
403    epc  = start_vector[task[task_id].startid];
404
405    // SP :  Get the vobj containing the stack
406    unsigned int vobj_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset;
407    sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;
408
409    // compute global processor index
410    unsigned int proc_id = task[task_id].clusterid * NB_PROCS + task[task_id].proclocid;
411
412    // compute and check local task index
413    unsigned int ltid = _scheduler[proc_id].tasks;
414    if ( ltid >= GIET_NB_TASKS_MAX )
415    {
416        _puts("\n[INIT ERROR] : too much tasks allocated to processor ");
417        _putw( proc_id );
418        _puts("\n");
419        _exit();
420    }
421   
422    // update number of tasks allocated to scheduler
423    _scheduler[proc_id].tasks = ltid + 1;
424
425    // initializes the task context
426    _scheduler[proc_id].context[ltid][CTX_SR_ID]    = sr;
427    _scheduler[proc_id].context[ltid][CTX_SP_ID]    = sp;
428    _scheduler[proc_id].context[ltid][CTX_RA_ID]    = ra;
429    _scheduler[proc_id].context[ltid][CTX_EPC_ID]   = epc;
430    _scheduler[proc_id].context[ltid][CTX_PTPR_ID]  = ptpr;
431    _scheduler[proc_id].context[ltid][CTX_MODE_ID]  = mode;
432    _scheduler[proc_id].context[ltid][CTX_TTY_ID]   = tty;
433        _scheduler[proc_id].context[ltid][CTX_FBDMA_ID] = fb;
434    _scheduler[proc_id].context[ltid][CTX_PTAB_ID]  = ptab;
435    _scheduler[proc_id].context[ltid][CTX_TASK_ID]  = task_id;
436   
437#if INIT_DEBUG_CTX
438_puts("Task ");
439_puts( task[task_id].name );
440_puts(" allocated to processor ");
441_putw( proc_id );
442_puts(" / ltid = ");
443_putw( ltid );
444_puts("\n");
445
446_puts("  - SR          = ");
447_putw( sr );
448_puts("  saved at ");
449_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SR_ID] );
450_puts("\n");
451
452_puts("  - RA          = ");
453_putw( ra );
454_puts("  saved at ");
455_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_RA_ID] );
456_puts("\n");
457
458_puts("  - SP          = ");
459_putw( sp );
460_puts("  saved at ");
461_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SP_ID] );
462_puts("\n");
463
464_puts("  - EPC         = ");
465_putw( epc );
466_puts("  saved at ");
467_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_EPC_ID] );
468_puts("\n");
469
470_puts("  - PTPR        = ");
471_putw( ptpr<<13 );
472_puts("  saved at ");
473_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTPR_ID] );
474_puts("\n");
475
476_puts("  - TTY         = ");
477_putw( tty );
478_puts("  saved at ");
479_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_TTY_ID] );
480_puts("\n");
481
482_puts("  - FB          = ");
483_putw( fb );
484_puts("  saved at ");
485_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_FBDMA_ID] );
486_puts("\n");
487
488_puts("  - PTAB        = ");
489_putw( ptab );
490_puts("  saved at ");
491_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTAB_ID] );
492_puts("\n");
493#endif
494
495} // end _task_map()
496
497///////////////////////////////////////////////////////////////////////////////
498// This function initialises all task contexts and processors schedulers.
499// It sets the default values for all schedulers (tasks <= 0, current <= 0).
500// Finally, it scan all tasks in all vspaces to initialise the schedulers,
501// and the tasks contexts, as defined in the mapping_info data structure.
502// A global TTY index and a global FB channel are allocated if required.
503// TTY[0] is reserved for the kernel.
504///////////////////////////////////////////////////////////////////////////////
505in_kinit void _kernel_tasks_init()
506{
507    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
508    mapping_cluster_t*  cluster = _get_cluster_base( header );
509    mapping_vspace_t*   vspace  = _get_vspace_base( header );     
510    mapping_task_t*     task    = _get_task_base( header );
511
512    unsigned int        base_tty_id = 1;     // TTY index allocator
513    unsigned int        base_fb_id  = 0;     // FB channel index allocator
514
515    unsigned int        cluster_id; 
516    unsigned int        proc_id; 
517    unsigned int        vspace_id; 
518    unsigned int        task_id;
519
520    // initialise the schedulers (not done by the compiler)
521    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
522    {
523        for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
524        {
525            if ( proc_id >= NB_PROCS )
526            {
527                _puts("\n[INIT ERROR] The number of processors in cluster ");
528                _putw( cluster_id );
529                _puts(" is larger than NB_PROCS \n");
530                _exit();
531            }
532            _scheduler[cluster_id*NB_PROCS+proc_id].tasks   = 0;
533            _scheduler[cluster_id*NB_PROCS+proc_id].current = 0;
534        }
535    }
536
537    // loop on the virtual spaces
538    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
539    {
540
541#if INIT_DEBUG_CTX
542_puts("\n[INIT] mapping tasks in vspace ");
543_puts(vspace[vspace_id].name);
544_puts("\n");
545#endif
546        // loop on the tasks
547        for ( task_id = vspace[vspace_id].task_offset ; 
548              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
549              task_id++ )
550        {
551            unsigned int        tty_id = 0xFFFFFFFF;
552            unsigned int        fb_id  = 0xFFFFFFFF;
553            if ( task[task_id].use_tty ) 
554            {
555                tty_id = base_tty_id;
556                base_tty_id++;
557            }
558            if ( task[task_id].use_fb  ) 
559            {
560                fb_id = base_fb_id;
561                base_fb_id++;
562            }
563            _task_map( task_id,                         // global task index
564                       vspace_id,                       // vspace index
565                       tty_id,                          // global tty index
566                       fb_id );                         // global fbdma index
567        } // end loop on tasks
568    } // end oop on vspaces
569
570    _puts("\n[INIT] Task Contexts initialisation completed at cycle ");
571    _putw( _proctime() );
572    _puts("\n");
573
574#if INIT_DEBUG_CTX
575for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
576{
577    _puts("\nCluster ");
578    _putw( cluster_id );
579    _puts("\n");
580    for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
581    {
582        unsigned int ltid;              // local task index
583        unsigned int gtid;              // global task index
584        unsigned int pid = cluster_id * NB_PROCS + proc_id;
585       
586        _puts(" - processor ");
587        _putw( pid );
588        _puts("\n");
589        for ( ltid = 0 ; ltid < _scheduler[pid].tasks ; ltid++ )
590        {
591            gtid = _scheduler[pid].context[ltid][CTX_TASK_ID];
592            _puts("    task : ");
593            _puts( task[gtid].name );
594            _puts("\n");
595        }
596    }
597}
598#endif
599
600} // end _kernel_task_init()
601
602////////////////////////////////////////////////////////////////////////////////
603// This function intializes the external periherals such as the IOB component
604// (I/O bridge, containing the IOMMU, the IOC (external disk controller),
605// the NIC (external network controller), the FBDMA (frame buffer controller),
606////////////////////////////////////////////////////////////////////////////////
607in_kinit void _kernel_peripherals_init()
608{
609    /////////////////////
610    // IOC peripheral
611    // we simply activate the IOC interrupts...
612    if ( NB_IOC )
613    {
614        unsigned int*   ioc_address = (unsigned int*)&seg_ioc_base;
615        ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
616    }
617   
618    /////////////////////
619    // FBDMA peripheral
620    // we simply activate the DMA interrupts...
621    if ( NB_DMAS )
622    {
623        unsigned int*   dma_address = (unsigned int*)&seg_dma_base;
624        dma_address[DMA_IRQ_DISABLE] = 0;
625    }
626
627    /////////////////////
628    // IOB peripheral
629    // must be initialised in case of IOMMU
630    if ( GIET_IOMMU_ACTIVE )
631    {
632        unsigned int*   iob_address = (unsigned int*)&seg_iob_base;
633
634        // define IPI address mapping the IOC interrupt ...TODO...
635
636        // set IOMMU page table address
637        iob_address[IOB_IOMMU_PTPR] = (unsigned int)(&_iommu_ptab);   
638
639        // activate IOMMU
640        iob_address[IOB_IOMMU_ACTIVE] = 1;   
641    } 
642
643    _puts("\n[INIT] Peripherals initialisation completed at cycle ");
644    _putw( _proctime() );
645    _puts("\n");
646
647} // end _kernel_peripherals_init()
648
649////////////////////////////////////////////////////////////////////////////////
650// This function intialises the interrupt vector, and initialises
651// the ICU mask registers for all processors in all clusters.
652// It strongly depends on the actual peripheral hardware wiring.
653// In this peculiar version, all clusters are identical,
654// the number of processors per cluster cannot be larger than 8.
655// Processor 0 handle all interrupts corresponding to TTYs, DMAs and IOC
656// (ICU inputs from from IRQ[8] to IRQ[31]). Only the 8 TIMER interrupts
657// (ICU iputs IRQ[0] to IRQ[7]), that are used for context switching
658// are distributed to the 8 processors.
659////////////////////////////////////////////////////////////////////////////////
660in_kinit void _kernel_interrupt_vector_init()
661{
662    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
663    mapping_cluster_t*  cluster = _get_cluster_base( header );
664
665    unsigned int cluster_id;
666    unsigned int proc_id;
667
668    // ICU mask values (up to 8 processors per cluster)
669    unsigned int icu_mask[8] = { 0xFFFFFF01,
670                                 0x00000002,
671                                 0x00000004,
672                                 0x00000008,
673                                 0x00000010,
674                                 0x00000020,
675                                 0x00000040,
676                                 0x00000080 };
677
678    // initialise ICUs for each processor in each cluster
679    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
680    {
681        for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
682        {
683            _icu_write( cluster_id, proc_id, ICU_MASK_SET, icu_mask[proc_id] ); 
684        }
685    }
686
687    // initialize Interrupt vector
688
689    _interrupt_vector[0]   = &_isr_switch;
690    _interrupt_vector[1]   = &_isr_switch;
691    _interrupt_vector[2]   = &_isr_switch;
692    _interrupt_vector[3]   = &_isr_switch;
693    _interrupt_vector[4]   = &_isr_switch;
694    _interrupt_vector[5]   = &_isr_switch;
695    _interrupt_vector[6]   = &_isr_switch;
696    _interrupt_vector[7]   = &_isr_switch;
697
698    _interrupt_vector[8]   = &_isr_dma_0;
699    _interrupt_vector[9]   = &_isr_dma_1;
700    _interrupt_vector[10]  = &_isr_dma_2;
701    _interrupt_vector[11]  = &_isr_dma_3;
702    _interrupt_vector[12]  = &_isr_dma_4;
703    _interrupt_vector[13]  = &_isr_dma_5;
704    _interrupt_vector[14]  = &_isr_dma_6;
705    _interrupt_vector[15]  = &_isr_dma_7;
706
707    _interrupt_vector[16]  = &_isr_tty_get_0;
708    _interrupt_vector[17]  = &_isr_tty_get_1;
709    _interrupt_vector[18]  = &_isr_tty_get_2;
710    _interrupt_vector[19]  = &_isr_tty_get_3;
711    _interrupt_vector[20]  = &_isr_tty_get_4;
712    _interrupt_vector[21]  = &_isr_tty_get_5;
713    _interrupt_vector[22]  = &_isr_tty_get_6;
714    _interrupt_vector[23]  = &_isr_tty_get_7;
715    _interrupt_vector[24]  = &_isr_tty_get_8;
716    _interrupt_vector[25]  = &_isr_tty_get_9;
717    _interrupt_vector[26]  = &_isr_tty_get_10;
718    _interrupt_vector[27]  = &_isr_tty_get_11;
719    _interrupt_vector[28]  = &_isr_tty_get_12;
720    _interrupt_vector[29]  = &_isr_tty_get_13;
721    _interrupt_vector[30]  = &_isr_tty_get_14;
722
723    _interrupt_vector[31]  = &_isr_ioc;
724
725    _puts("\n[INIT] Interrupt vector initialisation completed at cycle ");
726    _putw( _proctime() );
727    _puts("\n");
728
729} // end _kernel_interrup_vector_init()
Note: See TracBrowser for help on using the repository browser.