Ignore:
Timestamp:
Aug 7, 2012, 6:37:49 PM (12 years ago)
Author:
alain
Message:

Introducing a new release where all initialisation
is done in the boot code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/sys/kernel_init.c

    r185 r189  
    55// Copyright (c) UPMC-LIP6
    66////////////////////////////////////////////////////////////////////////////////////
    7 // FIXME
    87// 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].
     8// It contains the kernel entry point for the last step of system initialisation.
     9// All procs in this phase have their MMU activated, and are running in parallel.
     10// - each processor updates its own scheduler, to replace the ISR index
     11//   by the actual ISR virtual address, and set its own entry in the
     12//   kernel _schedulers_paddr[] array.
     13// - each processor initialises the SP, SR, PTPR, EPC registers, and starts
     14//   its private Timer, before jumping to the user code with an eret.
    1615////////////////////////////////////////////////////////////////////////////////////
    1716
    1817#include <common.h>
     18#include <irq_handler.h>
    1919#include <ctx_handler.h>
    2020#include <sys_handler.h>
     
    2929#include <drivers.h>
    3030
    31 #define in_kinit __attribute__((section (".kinit")))
    32  
    3331///////////////////////////////////////////////////////////////////////////////////
    34 // array of pointers on the page tables
    35 // (both physical and virtual addresses)
     32// Kernel Global variables
    3633///////////////////////////////////////////////////////////////////////////////////
    3734
    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];
     35__attribute__((section (".kdata")))
     36page_table_t* _ptabs_paddr[GIET_NB_VSPACE_MAX];
    4037
    41 ///////////////////////////////////////////////////////////////////////////////////
    42 // declarations required to avoid forward references
    43 ///////////////////////////////////////////////////////////////////////////////////
     38__attribute__((section (".kdata")))
     39page_table_t* _ptabs_vaddr[GIET_NB_VSPACE_MAX];
    4440
    45 void    _kernel_ptabs_init(void);
    46 void    _kernel_vobjs_init(void);
    47 void    _kernel_tasks_init(void);
    48 void    _kernel_peripherals_init(void);
    49 void    _kernel_interrupt_vector_init(void);
    50 void    _kernel_start_all_procs(void);
     41__attribute__((section (".kdata")))
     42static_scheduler_t*     _schedulers_paddr[NB_CLUSTERS*NB_PROCS_MAX];
    5143
    5244//////////////////////////////////////////////////////////////////////////////////
    53 // This function is the entry point for the second step of the boot sequence.
     45// This function is the entry point for the last step of the boot sequence.
    5446//////////////////////////////////////////////////////////////////////////////////
    55 in_kinit void _kernel_init()
     47__attribute__((section (".kinit"))) void _kernel_init()
    5648{
    5749    // values to be written in registers
     
    6153    unsigned int        epc_value;
    6254
    63     unsigned int        pid =   _procid();
     55    unsigned int        proc_id    = _procid();
     56    unsigned int    cluster_id = proc_id / NB_PROCS_MAX;
     57    unsigned int    lpid       = proc_id % NB_PROCS_MAX;
    6458
    65     // only processor 0 executes system initialisation
    66     if ( pid == 0 )
     59    // step 1 : Initialise scheduler physical addresses array
     60
     61    // get scheduler physical address from register
     62    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
     63    _schedulers_paddr[proc_id]     = psched;
     64
     65#if GIET_DEBUG_INIT
     66_get_lock(&_tty_put_lock);
     67_puts("\n[GIET DEBUG] step 1 for processor ");
     68_putw( proc_id );
     69_puts("\n");
     70_puts("- scheduler pbase = ");
     71_putw( (unsigned int)psched );
     72_puts("\n");
     73_release_lock(&_tty_put_lock);
     74#endif
     75
     76    // step 2 : compute and set ICU mask
     77    unsigned int irq_id;
     78    unsigned int mask = 0;
     79    for ( irq_id = 0 ; irq_id < 32 ; irq_id++ )
    6780    {
    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();
     81        unsigned int entry   = _get_interrupt_vector_entry(irq_id);
     82        if ( entry ) mask = mask | 0x1<< irq_id;
    7583    }
     84    _icu_write( cluster_id,
     85                lpid,
     86                ICU_MASK_SET,
     87                mask );
     88   
     89#if GIET_DEBUG_INIT
     90_get_lock(&_tty_put_lock);
     91_puts("\n[GIET DEBUG] step 2 for processor ");
     92_putw( proc_id );
     93_puts("\n");
     94_puts("- ICU mask = ");
     95_putw( mask );
     96_puts("\n");
     97_release_lock(&_tty_put_lock);
     98#endif
    7699
    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.
    82100
    83     static_scheduler_t*  sched = &_scheduler[pid];
     101    // step 3 : TODO initialise page table addresse arrays
    84102
    85     if ( sched->tasks )         // at leat one task allocated
     103
     104    // step 4 : start TICK timer if more than one task
     105    unsigned int tasks = _get_tasks_number();
     106    if ( tasks > 1 )
     107    {
     108        unsigned int period     = GIET_TICK_VALUE;
     109        unsigned int mode       = 0x3;
     110        _timer_access( 0,                       // write access
     111                       cluster_id,
     112                       proc_id,
     113                       TIMER_PERIOD,
     114                       &period );
     115        _timer_access( 0,                       // write access
     116                       cluster_id,
     117                       proc_id,
     118                       TIMER_MODE,
     119                       &mode );
     120       
     121#if GIET_DEBUG_INIT
     122_get_lock(&_tty_put_lock);
     123_puts("\n[GIET DEBUG] Step 4 for processor ");
     124_putw( proc_id );
     125_puts("\n");
     126_puts("- TICK period = ");
     127_putd( period );
     128_puts("\n");
     129_release_lock(&_tty_put_lock);
     130#endif
     131   
     132    }
     133
     134    // step 5 : each processor initialises SP, SR, PTPR, EPC, registers
     135    //          with the values corresponding to the first allocated task,
     136    //          It does nothing, and keep idle if no task allocated.
     137
     138    if ( tasks )                // at leat one task allocated
    86139    {
    87140        // 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];
     141        sp_value   = _get_current_context_slot(CTX_SP_ID);
     142        sr_value   = _get_current_context_slot(CTX_SR_ID);
     143        ptpr_value = _get_current_context_slot(CTX_PTPR_ID);
     144        epc_value  = _get_current_context_slot(CTX_EPC_ID);
    92145
    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         }
     146#if GIET_DEBUG_INIT
     147_get_lock(&_tty_put_lock);
     148_puts("\n[GIET DEBUG] step 5 for processor ");
     149_putw( proc_id );
     150_puts("\n");
     151_puts("- sp   = ");
     152_putw( sp_value );
     153_puts("\n");
     154_puts("- sr   = ");
     155_putw( sr_value );
     156_puts("\n");
     157_puts("- ptpr = ");
     158_putw( ptpr_value<<13 );
     159_puts("\n");
     160_puts("- epc  = ");
     161_putw( epc_value );
     162_puts("\n");
     163_release_lock(&_tty_put_lock);
     164#endif
    101165    }
    102166    else                                        // no task allocated
     
    104168        _get_lock( &_tty_put_lock );
    105169        _puts("\n No task allocated to processor ");
    106         _putw( pid );
     170        _putw( proc_id );
    107171        _puts(" => keep idle\n");
    108172        _release_lock ( &_tty_put_lock );
     
    117181    }
    118182
     183    // set critical registers and jump to user code
    119184    asm volatile (
    120185       "move    $29,    %0              \n"             /* SP <= ctx[CTX_SP_ID] */
     
    128193
    129194} // 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 //////////////////////////////////////////////////////////////////////////////////
    135 in_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 //////////////////////////////////////////////////////////////////////////////////
    151 in_kinit void _eret()
    152 {
    153     asm volatile("eret \n"
    154                  "nop");
    155 }
    156 
    157 ///////////////////////////////////////////////////////////////////////////////
    158 // used to access user space
    159 ///////////////////////////////////////////////////////////////////////////////
    160 void _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 ///////////////////////////////////////////////////////////////////////////////
    171 in_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 ///////////////////////////////////////////////////////////////////////////////
    236 in_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 ////////////////////////////////////////////////////////////////////////////////
    373 in_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 ///////////////////////////////////////////////////////////////////////////////
    505 in_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
    575 for ( 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 ////////////////////////////////////////////////////////////////////////////////
    607 in_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 ////////////////////////////////////////////////////////////////////////////////
    660 in_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 TracChangeset for help on using the changeset viewer.