Ignore:
Timestamp:
Mar 26, 2014, 6:10:01 PM (10 years ago)
Author:
alain
Message:

Introducing support for IOPIC component.

File:
1 edited

Legend:

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

    r293 r294  
    6161
    6262__attribute__((section (".kdata")))
    63 static_scheduler_t* _schedulers[NB_PROCS_MAX<<(X_WIDTH+Y_WIDTH)];   // virtual addresses
     63static_scheduler_t* _schedulers[NB_PROCS_MAX<<(X_WIDTH+Y_WIDTH)]; // virtual addresses
    6464
    6565////////////////////////////////////////////////////////////////////////////////////
     
    6969__attribute__((section (".kdata")))
    7070unsigned int _idle_stack[X_SIZE * Y_SIZE * NB_PROCS_MAX * 128 ];
     71
     72////////////////////////////////////////////////////////////////////////////////////
     73// Synchonisation Barrier before jumping to user code
     74////////////////////////////////////////////////////////////////////////////////////
     75
     76__attribute__((section (".kdata")))
     77unsigned int _init_barrier = 0;
    7178
    7279////////////////////////////////////////////////////////////////////////////////////
     
    99106// 1/ contribute to _schedulers_paddr[] array initialisation.
    100107// 2/ contribute to _ptabs_paddr[] and _ptabs_vaddr arrays initialisation
    101 // 3/ compute and set the ICU mask for its private ICU channel
    102 // 4/ initialise its private TICK timer (if tasks > 0)
    103 // 5/ initialise the "idle" task context in its private scheduler
    104 // 6/ initialise the SP, SR, PTPR, EPC registers
    105 // 7/ jump to the user code with an eret.
     108// 3/ completes task context initialisation for ech allocated task
     109// 4/ compute and set the ICU mask for its private ICU channel
     110// 5/ initialise its private TICK timer (if tasks > 0)
     111// 6/ initialise the "idle" task context in its private scheduler
     112// 7/ initialise SP, SR, PTPR, EPC registers and jump to user code with an eret.
    106113////////////////////////////////////////////////////////////////////////////////////
    107114__attribute__((section (".kinit"))) void kernel_parallel_init()
     
    109116    unsigned int global_pid = _get_procid();
    110117    unsigned int cluster_xy = global_pid / NB_PROCS_MAX;
    111     unsigned int local_pid  = global_pid % NB_PROCS_MAX;
    112 
    113 #if 0
    114 ////////////// Debug : we can kill all processors but one
    115 if ( global_pid != 0 )
    116 {
    117     _tty_get_lock( 0 );
    118     _puts("\n[GIET] Processor[");
    119     _putd( cluster_xy >> Y_WIDTH );
    120     _puts(",");
    121     _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
    122     _puts(",");
    123     _putd( local_pid );
    124     _puts("] suicide...\n");
    125     _tty_release_lock( 0 );
    126     _exit();
    127 }
    128 #endif
     118    unsigned int x          = cluster_xy >> Y_WIDTH;
     119    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     120    unsigned int lpid       = global_pid % NB_PROCS_MAX;
    129121
    130122    // Step 1 : each processor get its scheduler virtual address
     
    137129
    138130#if GIET_DEBUG_INIT
    139 _tty_get_lock( 0 );
    140 _puts("\n[GIET DEBUG] Parallel init : step 1 for processor[");
    141 _putd( cluster_xy >> Y_WIDTH );
    142 _puts(",");
    143 _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
    144 _puts(",");
    145 _putd( local_pid );
    146 _puts("]\n - scheduler vbase = ");
    147 _putx((unsigned int) psched);
    148 _puts("\n - tasks           = ");
    149 _putd(tasks);
    150 _puts("\n");
    151 _tty_release_lock( 0 );
    152 #endif
    153 
    154     // step 2 : each processor that is allocated at least one task
    155     //          completes its private scheduler initialisation, and
    156     //          contribute to _ptabs_vaddr[] and _ptabs_ptprs[] arrays initialisation.
    157     //          - set the CTX_RA slot vith the virtual address
    158     //            of the _ctx_eret() function (for context switch).
    159     //          - set the CTX_EPC slot that must contain the task
    160     //            entry point, and contain only the address of the
    161     //            memory location containing this entry point.
     131_printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d]\n"
     132        " - scheduler vbase = %x\n"
     133        " - tasks           = %d\n",
     134        x, y, lpid, (unsigned int)psched, tasks );
     135#endif
     136
     137    // step 2 : each processor that is allocated at least one task loops
     138    //          on all allocated tasks:
     139    //          - contributes to _ptabs_vaddr[] & _ptabs_ptprs[] initialisation.
     140    //          - set CTX_RA slot  with the kernel _ctx_eret() virtual address.
     141    //          - set CTX_EPC slot that must contain the task entry point,
     142    //            and contain only at this point the virtual address of the memory
     143    //            location containing this entry point. We must switch the PTPR
     144    //            to use the page table corresponding to the task.
    162145
    163146    unsigned int ltid;
    164147
    165     // loop on all allocated tasks
    166148    for (ltid = 0; ltid < tasks; ltid++)
    167149    {
     
    170152        unsigned int ptpr = _get_task_slot( global_pid, ltid , CTX_PTPR_ID );
    171153
     154        // initialize PTABS arrays
    172155        _ptabs_vaddr[vsid] = ptab;
    173156        _ptabs_ptprs[vsid] = ptpr;
    174157
     158#if GIET_DEBUG_INIT
     159_printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] contibutes to PTABS arrays\n"
     160        " - ptabs_vaddr[%d] = %x / ptpr_paddr[%d] = %l\n",
     161        x, y, lpid, 
     162        vsid, ptab, vsid, ((unsigned long long)ptpr)<<13 );
     163#endif
     164
     165        // set the ptpr to use the task page table
     166        asm volatile( "mtc2    %0,   $0   \n"
     167                      : : "r" (ptpr) );
     168
     169        // compute ctx_ra
    175170        unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
    176171        _set_task_slot( global_pid, ltid, CTX_RA_ID, ctx_ra );
    177172
     173        // compute ctx_epc
    178174        unsigned int* ptr = (unsigned int*)_get_task_slot( global_pid, ltid, CTX_EPC_ID );
    179175        _set_task_slot( global_pid, ltid, CTX_EPC_ID, *ptr );
    180176
    181177#if GIET_DEBUG_INIT
    182 _tty_get_lock( 0 );
    183 _puts("\n[GIET DEBUG] Parallel init : step 2 for processor[");
    184 _putd( cluster_xy >> Y_WIDTH );
    185 _puts(",");
    186 _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
    187 _puts(",");
    188 _putd( local_pid );
    189 _puts("] / task ");
    190 _putd( ltid );
    191 _puts("\n - ctx_vsid  = ");
    192 _putd( _get_task_slot( global_pid, ltid, CTX_VSID_ID ) );
    193 _puts("\n - ctx_ptpr  = ");
    194 _putx( _get_task_slot( global_pid, ltid, CTX_PTPR_ID ) );
    195 _puts("\n - ctx_ptab  = ");
    196 _putx( _get_task_slot( global_pid, ltid, CTX_PTAB_ID ) );
    197 _puts("\n - ctx_ltid  = ");
    198 _putd( _get_task_slot( global_pid, ltid, CTX_LTID_ID ) );
    199 _puts("\n - ctx_epc   = ");
    200 _putx( _get_task_slot( global_pid, ltid, CTX_EPC_ID ) );
    201 _puts("\n - ctx_ra    = ");
    202 _putx( _get_task_slot( global_pid, ltid, CTX_RA_ID ) );
    203 _puts("\n - ctx_gtid  = ");
    204 _putd( _get_task_slot( global_pid, ltid, CTX_GTID_ID ) );
    205 _puts("\n - ctx_tty   = ");
    206 _putd( _get_task_slot( global_pid, ltid, CTX_TTY_ID ) );
    207 _puts("\n");
    208 _tty_release_lock( 0 );
    209 #endif
    210 
     178_printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] set scheduler for task %d\n"
     179        " - ctx_epc   = %x\n"
     180        " - ctx_ra    = %x\n",
     181        x, y, lpid, ltid,
     182        _get_task_slot( global_pid, ltid, CTX_EPC_ID ),
     183        _get_task_slot( global_pid, ltid, CTX_RA_ID ) );
     184#endif
     185
     186    }  // end for tasks
     187
     188    // step 4 : compute and set ICU or XCU masks
     189
     190    unsigned int isr_switch_index = 0xFFFFFFFF;
     191    unsigned int hwi_mask = 0;
     192    unsigned int pti_mask = 0;
     193    unsigned int wti_mask = 0;
     194    unsigned int irq_id;            // IN_IRQ index
     195    unsigned int entry;             // interrupt vector entry
     196
     197    for (irq_id = 0; irq_id < 32; irq_id++)
     198    {
     199        entry = psched->hwi_vector[irq_id];
     200        if ( entry & 0x80000000 ) hwi_mask = hwi_mask | (1<<irq_id);
     201        if ( (entry & 0x0000FFFF) == ISR_TICK ) isr_switch_index = irq_id;
     202
     203        entry = psched->pti_vector[irq_id];
     204        if ( entry & 0x80000000 ) pti_mask = pti_mask | (1<<irq_id);
     205        if ( (entry & 0x0000FFFF) == ISR_TICK ) isr_switch_index = irq_id;
     206
     207        entry = psched->wti_vector[irq_id];
     208        if ( entry & 0x80000000 ) wti_mask = wti_mask | (1<<irq_id);
     209        if ( (entry & 0x0000FFFF) == ISR_TICK ) isr_switch_index = irq_id;
    211210    }
    212211
    213     // step 3 : compute and set ICU or XICU masks
    214     //          there is at most 32 interrupts per processor
    215 
    216     unsigned int isr_switch_index = 0xFFFFFFFF;
    217     unsigned int irq_id;            // IN_IRQ index
    218     unsigned int hwi_mask = 0;
    219     unsigned int swi_mask = 0;
    220     unsigned int pti_mask = 0;
    221 
    222     for (irq_id = 0; irq_id < 32; irq_id++)
    223     {
    224         unsigned int entry = psched->interrupt_vector[irq_id];
    225         unsigned int isr   = (entry & 0x000000FF);
    226         unsigned int type  = (entry & 0x0000FF00) >> 8;
    227         unsigned int valid = (entry & 0x80000000);
    228 
    229         if      ((type == IRQ_TYPE_HWI) && valid ) hwi_mask = hwi_mask | (1<<irq_id);
    230         else if ((type == IRQ_TYPE_SWI) && valid ) swi_mask = swi_mask | (1<<irq_id);
    231         else if ((type == IRQ_TYPE_PTI) && valid ) pti_mask = pti_mask | (1<<irq_id);
    232         else if ( valid )
     212#if GIET_DEBUG_INIT
     213_printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] set XCU masks\n"
     214        " - ICU HWI_MASK = %x\n"
     215        " - ICU WTI_MASK = %x\n"
     216        " - ICU PTI_MASK = %x\n",
     217        x, y, lpid, hwi_mask, wti_mask, pti_mask );
     218#endif
     219
     220    unsigned int channel = lpid * IRQ_PER_PROCESSOR;
     221
     222#if USE_XICU
     223    _xcu_set_mask( cluster_xy, channel, hwi_mask, IRQ_TYPE_HWI );
     224    _xcu_set_mask( cluster_xy, channel, wti_mask, IRQ_TYPE_WTI );
     225    _xcu_set_mask( cluster_xy, channel, pti_mask, IRQ_TYPE_PTI );
     226#else
     227    _icu_set_mask( cluster_xy, channel, hwi_mask );   
     228#endif
     229
     230    // step 5 : start TICK timer if at least one task
     231    if (tasks > 0)
     232    {
     233        // one ISR_TICK must be defined for each proc
     234        if (isr_switch_index == 0xFFFFFFFF)
    233235        {
    234             _puts("\n[GIET ERROR] _kernel_parallel_start() : illegal IRQ type\n");
    235             _puts(" irq_id = ");
    236             _putx( irq_id );
    237             _puts(" / entry = ");
    238             _putx( entry );
    239             _puts("\n");
     236            _printf("\n[GIET ERROR] ISR_TICK not found for processor[%d,%d,%d]\n",
     237                    x, y, lpid );
    240238            _exit();
    241239        }
    242         if (isr == ISR_SWITCH) isr_switch_index = irq_id;
     240
     241        // start system timer
     242
     243#if USE_XICU
     244        _xcu_timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE );
     245#else
     246        _timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE );
     247#endif
     248
    243249    }
    244250
    245251#if GIET_DEBUG_INIT
    246 _tty_get_lock( 0 );
    247 _puts("\n[GIET DEBUG] Parallel init : step 3 for processor[");
    248 _putd( cluster_xy >> Y_WIDTH );
    249 _puts(",");
    250 _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
    251 _puts(",");
    252 _putd( local_pid );
    253 _puts("]\n - ICU HWI_MASK = ");
    254 _putx(hwi_mask);
    255 _puts("\n - ICU SWI_MASK = ");
    256 _putx(swi_mask);
    257 _puts("\n - ICU PTI_MASK = ");
    258 _putx(pti_mask);
    259 _puts("\n");
    260 _tty_release_lock( 0 );
    261 #endif
    262 
    263     // GIET-VM constraint : only one IRQ type per irq_id
    264     if ( hwi_mask & swi_mask & pti_mask )
    265     {
    266         _puts("[GIET ERROR] _kernel_parallel_start : conflicting IRQs\n");
    267         _exit();
    268     }
    269 
    270 
    271     // The ICU output index is computed as the local processor id multiplied by
    272     // the number of ICU outputs connected to each processor.
    273     int icu_out_index = local_pid * IRQ_PER_PROCESSOR;
    274 
    275 #if USE_XICU
    276     _xcu_set_mask(cluster_xy, icu_out_index, hwi_mask, IRQ_TYPE_HWI); // set HWI_MASK
    277     _xcu_set_mask(cluster_xy, icu_out_index, swi_mask, IRQ_TYPE_SWI); // set SWI_MASK
    278     _xcu_set_mask(cluster_xy, icu_out_index, pti_mask, IRQ_TYPE_PTI); // set PTI_MASK
    279 #else
    280     _icu_set_mask(cluster_xy, icu_out_index, (hwi_mask | pti_mask | swi_mask) );   
    281 #endif
    282 
    283     // step 4 : start TICK timer if at least one task
    284     if (tasks > 0)
    285     {
    286         // one ISR_SWITCH must be defined for each proc
    287         if (isr_switch_index == 0xFFFFFFFF)
    288         {
    289             _tty_get_lock( 0 );
    290             _puts("\n[GIET ERROR] ISR_SWITCH not found for processor ");
    291             _putx(global_pid);
    292             _puts("\n");
    293             _tty_release_lock( 0 );
    294             _exit();
    295         }
    296 
    297         // the ISR_SWITCH irq index must be NB_PROCS_MAX + local_pid because
    298         // the first NB_PROCS_MAX irqs are used by the WAKEUP ones
    299         if (isr_switch_index != (NB_PROCS_MAX + local_pid))
    300         {
    301             _tty_get_lock( 0 );
    302             _puts("\n[GIET ERROR] ISR_SWITCH wrong index for processor ");
    303             _putx(global_pid);
    304             _puts("\n. It should be NB_PROCS_MAX + local_pid =");
    305             _putd(NB_PROCS_MAX + local_pid);
    306             _puts("\n");
    307             _tty_release_lock( 0 );
    308             _exit();
    309         }
    310 
    311         // start system timer
    312         unsigned int ko;
    313 #if USE_XICU
    314         ko = _xcu_timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE );
    315 #else
    316         ko = _timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE );
    317 #endif
    318         if ( ko )
    319         {
    320             _tty_get_lock( 0 );
    321             _puts("\n[GIET ERROR] cannot start timer for processor ");
    322             _putd(local_pid);
    323             _puts("\n");
    324             _tty_release_lock( 0 );
    325             _exit();
    326         }
    327     }
    328 
    329 #if GIET_DEBUG_INIT
    330 _tty_get_lock( 0 );
    331 _puts("\n[GIET DEBUG] Parallel init : step 4 for processor[");
    332 _putd( cluster_xy >> Y_WIDTH );
    333 _puts(",");
    334 _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
    335 _puts(",");
    336 _putd( local_pid );
    337 _puts("]");
    338 if ( tasks > 1 ) _puts("\n  context switch activated\n");
    339 else             _puts("\n  context switch  not activated\n");
    340 _tty_release_lock( 0 );
    341 #endif
    342 
    343     // step 5 : each processor updates the idle_task context:
     252_printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] start TICK timer\n",
     253        x, y, lpid );
     254#endif
     255
     256    // step 6 : each processor updates the idle_task context:
    344257    //          (only CTX_SP, CTX_RA, CTX_EPC).
    345258    //          The stack size is 512 bytes, reserved in seg_kdata.
     
    347260    //          have been initialised in boot code.
    348261
    349     unsigned int x = cluster_xy >> Y_WIDTH;
    350     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    351     unsigned int p = ((x * Y_SIZE) + y) * NB_PROCS_MAX + local_pid;
     262    unsigned int p = ((x * Y_SIZE) + y) * NB_PROCS_MAX + lpid;
    352263
    353264    unsigned int stack = (unsigned int)_idle_stack + ((p + 1)<<9);
     
    358269
    359270#if GIET_DEBUG_INIT
    360 _tty_get_lock( 0 );
    361 _puts("\n[GIET DEBUG] Parallel init : step 5 for processor[");
    362 _putd( cluster_xy >> Y_WIDTH );
    363 _puts(",");
    364 _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
    365 _puts(",");
    366 _putd( local_pid );
    367 _puts("] : idle task context set\n");
    368 _tty_release_lock( 0 );
    369 #endif
    370 
    371     // step 6 : each processor initialises SP, SR, PTPR, EPC, registers
     271_printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] initialize IDLE task\n",
     272        x, y, lpid );
     273#endif
     274
     275    // step 7 : when all processors reach the synchronisation barrier,
     276    //          each processor set registers SP, SR, PTPR, EPC,
    372277    //          with the values corresponding to the first allocated task,
    373     //          or to the idle_task if there is no task allocated.
    374 
    375     ltid = 0;
     278    //          or to the idle_task if there is no task allocated,
     279    //          and jump to user code
    376280
    377281    if (tasks == 0)
     
    379283        ltid = IDLE_TASK_INDEX;
    380284
    381         _tty_get_lock( 0 );
    382         _puts("\n[GIET WARNING] No task allocated to processor ");
    383         _putx(global_pid);
    384         _puts(" => idle\n");
    385         _tty_release_lock ( 0 );
     285        _printf("\n[GIET WARNING] No task allocated to processor[%d,%d,%d]\n",
     286                x, y, lpid );
     287    }
     288    else
     289    {
     290        ltid = 0;
    386291    }
    387292
     
    392297
    393298#if GIET_DEBUG_INIT
    394 _tty_get_lock( 0 );
    395 _puts("\n[GIET DEBUG] Parallel init : step 6 for processor[");
    396 _putd( cluster_xy >> Y_WIDTH );
    397 _puts(",");
    398 _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
    399 _puts(",");
    400 _putd( local_pid );
    401 _puts("]\n - sp   = ");
    402 _putx(sp_value);
    403 _puts("\n - sr   = ");
    404 _putx(sr_value);
    405 _puts("\n - ptpr = ");
    406 _putx(ptpr_value);
    407 _puts("\n - epc  = ");
    408 _putx(epc_value);
    409 _puts("\n");
    410 
    411 _puts("\n[GIET DEBUG] Processor[");
    412 _putd( cluster_xy >> Y_WIDTH );
    413 _puts(",");
    414 _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
    415 _puts(",");
    416 _putd( local_pid );
    417 _puts("] completes kernel init at cycle ");
    418 _putd( _get_proctime() );
    419 _puts(" / task_entry_point = ");
    420 _putx( epc_value );
    421 _puts("\n");
    422 _tty_release_lock( 0 );
    423 #endif
    424 
    425     // Step 7 : set  registers and jump to user code
    426     asm volatile (
    427             "move    $29,       %0    \n"        /* SP <= ctx[CTX_SP_ID] */
    428             "mtc0    %1,        $12   \n"        /* SR <= ctx[CTX_SR_ID] */
    429             "mtc2    %2,        $0    \n"        /* PTPR <= ctx[CTX_PTPR_ID] */
    430             "mtc0    %3,        $14   \n"        /* EPC <= ctx[CTX_EPC_ID] */
    431             "eret                     \n"        /* jump to user code */
    432             "nop                      \n"
    433             :
    434             : "r" (sp_value), "r" (sr_value), "r" (ptpr_value), "r" (epc_value));
     299_printf("\n[GIET DEBUG INIT] Processor[%d,%d,%d] reach barrier at cycle %d\n"
     300        " - sp   = %x\n"
     301        " - sr   = %x\n"
     302        " - ptpr = %x\n"
     303        " - epc  = %x\n",
     304        x, y, lpid, _get_proctime(),
     305        sp_value, sr_value, ptpr_value, epc_value );
     306#endif
     307
     308    unsigned int*  pcount = &_init_barrier;
     309    unsigned int   nprocs = X_SIZE*(Y_SIZE-1)*NB_PROCS_MAX;
     310    unsigned int   count;
     311
     312    // increment barrier counter with atomic LL/SC
     313    asm volatile ( "_init_barrier_loop:             \n"
     314                   "ll    %0,   0(%1)               \n"   /* count <= *pcount  */
     315                   "addi  $3,   %0,   1             \n"   /* $3 <= count + 1  */
     316                   "sc    $3,   0(%1)               \n"   /* *pcount <= $3  */
     317                   "beqz  $3,   _init_barrier_loop  \n"   /* retry if failure */
     318                   "nop                             \n"
     319                   : "=&r"(count)
     320                   : "r"(pcount)
     321                   : "$3" );
     322   
     323    // busy waiting until all processors synchronized
     324    while ( *pcount != nprocs ) asm volatile ("nop");
     325
     326    _printf("\n[GIET] Processor[%d,%d,%d] jumps to user code at cycle %d\n",
     327            x, y, lpid, _get_proctime() );
     328       
     329    // set registers and jump to user code
     330    asm volatile ( "move  $29,  %0                  \n"   /* SP <= ctx[CTX_SP_ID] */
     331                   "mtc0  %1,   $12                 \n"   /* SR <= ctx[CTX_SR_ID] */
     332                   "mtc2  %2,   $0                  \n"   /* PTPR <= ctx[CTX_PTPR] */
     333                   "mtc0  %3,   $14                 \n"   /* EPC <= ctx[CTX_EPC]  */
     334                   "eret                            \n"   /* jump to user code  */
     335                   "nop                             \n"
     336                   :
     337                   : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value)
     338                   : "$29" );
    435339
    436340} // end kernel_parallel_init()
Note: See TracChangeset for help on using the changeset viewer.