Changeset 294


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

Introducing support for IOPIC component.

Location:
soft/giet_vm/giet_kernel
Files:
8 edited

Legend:

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

    r275 r294  
    1 /////////////////////////////////////////////////////////////////////////////////////////
     1//////////////////////////////////////////////////////////////////////////////////
    22// File     : ctx_handler.c
    33// Date     : 01/04/2012
    44// Authors  : alain greiner & joel porquet
    55// Copyright (c) UPMC-LIP6
    6 /////////////////////////////////////////////////////////////////////////////////////////
    7 // The ctx_handler.h and ctx_handler.c files are part of the GIET-VM nano-kernel.
    8 // This code is used to support context switch when several tasks are executing
    9 // in time multiplexing on a single processor.
    10 // The tasks are statically allocated to a processor in the boot phase, and
    11 // there is one private scheduler per processor. Each sheduler occupies 4K bytes,
    12 // and contains up to 14 task contexts (task_id is from 0 to 13).
    13 // The task context [14] is reserved for the "idle" task that does nothing, and
    14 // is launched by the scheduler when there is no other runable task.
    15 /////////////////////////////////////////////////////////////////////////////////////////
     6//////////////////////////////////////////////////////////////////////////////////
    167
    178#include <giet_config.h>
     
    2415#include <sys_handler.h>
    2516
    26 /////////////////////////////////////////////////////////////////////////////////////////
    27 // A task context is an array of 64 words = 256 bytes.
    28 // It contains copies of processor registers (when the task is preempted):
    29 // - GPR[i], generally stored in slot (i). $0, $26 & $27 are not saved.
    30 // - HI & LO registers
    31 // - CP0 registers: EPC, SR, CR, BVAR
    32 // - CP2 registers : PTPR
    33 // It contains some general informations associated to the task:
    34 // - TTY    : TTY channel global index
    35 // - NIC    : NIC channel global index
    36 // - CMA    : CMA channel global index
    37 // - HBA    : HBA channel global index
    38 // - DMA    : DMA channel local index
    39 // - TIM    : TIM channel local index
    40 // - PTAB   : page table virtual base address
    41 // - LTID   : Task local index (in scheduler)
    42 // - VSID   : Virtual space index
    43 // - RUN    : Task state (0 => sleeping / 1 => runnable )
    44 // - TRDID  : Thread ID index (in vspace)
    45 //
    46 // ctx[0]<- ***|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC  |ctx[40]<- TTY
    47 // ctx[1]<- $1 |ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR   |ctx[41]<- DMA
    48 // ctx[2]<- $2 |ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- SR   |ctx[42]<- NIC
    49 // ctx[3]<- $3 |ctx[11]<- $11|ctx[19]<- $19|ctx[27]<- HI |ctx[35]<- BVAR |ctx[43]<- TIM
    50 // ctx[4]<- $4 |ctx[12]<- $12|ctx[20]<- $20|ctx[28]<- $28|ctx[36]<- PTAB |ctx[44]<- HBA
    51 // ctx[5]<- $5 |ctx[13]<- $13|ctx[21]<- $21|ctx[29]<- SP |ctx[37]<- LTID |ctx[45]<- CMA
    52 // ctx[6]<- $6 |ctx[14]<- $14|ctx[22]<- $22|ctx[30]<- $30|ctx[38]<- VSID |ctx[46]<- GTID
    53 // ctx[7]<- $7 |ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- PTPR |ctx[47]<- RUN
    54 //
    55 // ctx[48]<- TRDID
    56 //////////////////////////////////////////////////////////////////////////////////////////
    57 
    5817extern void _task_switch(unsigned int *, unsigned int *);
    5918
    6019/////////////////////////////////////////////////////////////////////////////////
    61 //    _ctx_switch()
    6220// This function performs a context switch between the running task
    6321// and  another task, using a round-robin sheduling policy between all
     
    6624// If the only runable task is the current task, return without context switch.
    6725// If there is no runable task, the scheduler switch to the default "idle" task.
    68 //
     26/////////////////////////////////////////////////////////////////////////////////
    6927// Implementation note
    7028// The return address contained in $31 is saved in the current task context
     
    7432void _ctx_switch()
    7533{
     34    unsigned int gpid       = _get_procid();
     35    unsigned int cluster_xy = gpid / NB_PROCS_MAX;
     36    unsigned int lpid       = gpid % NB_PROCS_MAX;
     37
    7638    // get scheduler address
    7739    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
     
    10567    }
    10668
    107     // no switch if no change
    108     if (curr_task_id != next_task_id)
    109     {
    11069#if GIET_DEBUG_SWITCH
    111 _tty_get_lock( 0 );
    112 _puts("\n[GIET DEBUG] Context switch for processor ");
    113 _putd(_get_procid());
    114 _puts(" at cycle ");
    115 _putd(_get_proctime());
    116 _puts("\n");
    117 _puts(" - tasks        = ");
    118 _putd(tasks);
    119 _puts("\n");
    120 _puts(" - curr_task_id = ");
    121 _putd( curr_task_id );
    122 _puts("\n");
    123 _puts(" - next_task_id = ");
    124 _putd(next_task_id);
    125 _puts("\n");
    126 _tty_release_lock(  0 );
     70unsigned int x = cluster_xy >> Y_WIDTH;
     71unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     72
     73_printf("\n[TASK SWITCH] (%d) -> (%d) on processor[%d,%d,%d] at cycle %d\n",
     74        curr_task_id, next_task_id, x, y , lpid, _get_proctime() );
    12775#endif
    12876
     77    if (curr_task_id != next_task_id)  // actual task switch required
     78    {
    12979        unsigned int* curr_ctx_vaddr = &(psched->context[curr_task_id][0]);
    13080        unsigned int* next_ctx_vaddr = &(psched->context[next_task_id][0]);
    131         unsigned int procid = _get_procid();
    132         unsigned int local_id = procid % NB_PROCS_MAX;
    133         unsigned int cluster_id = procid / NB_PROCS_MAX;
    13481
    135         // reset timer counter
     82        // reset timer counter. In each cluster,
     83        // the NB_PROCS_MAX timers are system timers (TICK)
     84
    13685#if USE_XICU
    137         _xcu_timer_reset_cpt(cluster_id, NB_PROCS_MAX + local_id);
     86        _xcu_timer_reset_cpt( cluster_xy, lpid );
    13887#else
    139         _timer_reset_cpt(cluster_id, NB_PROCS_MAX + local_id);
     88        _timer_reset_cpt( cluster_xy, lpid);
    14089#endif
    14190
     
    153102void _idle_task()
    154103{
    155     unsigned int count = GIET_IDLE_TASK_PERIOD;
    156104    while(1)
    157105    {
    158 #if GIET_IDLE_TASK_VERBOSITY == 1
    159         _tty_get_lock( 0 );
    160         _puts("\n[GIET WARNING] Processor ");
    161         _putd(_get_procid());
    162         _puts(" idle at cycle ");
    163         _putd(_get_proctime());
    164         _puts("\n");
    165         _tty_release_lock( 0 );
    166 #endif
     106        unsigned int count = GIET_IDLE_TASK_PERIOD;
    167107
     108        // decounting loop
    168109        asm volatile(
    169110                "move   $3,   %0              \n"
     
    176117                : "$3" );
    177118
    178          count = GIET_IDLE_TASK_PERIOD;
     119        // warning message
     120        unsigned int gpid       = _get_procid();
     121        unsigned int cluster_xy = gpid / NB_PROCS_MAX;
     122        unsigned int lpid       = gpid % NB_PROCS_MAX;
     123        unsigned int x          = cluster_xy >> Y_WIDTH;
     124        unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     125
     126        _printf("\n[GIET WARNING] Processor[%d,%d,%d] still idle at cycle %d\n",
     127                x, y, lpid, _get_proctime() );
     128
    179129    }
    180130} // end ctx_idle()
     
    182132
    183133/////////////////////////////////////////////////////////////////////////////////
    184 // The address of this functionis used to initialise the return address
     134// The address of this function is used to initialise the return address
    185135// in the "idle" task context.
    186136/////////////////////////////////////////////////////////////////////////////////
  • soft/giet_vm/giet_kernel/ctx_handler.h

    r267 r294  
     1/////////////////////////////////////////////////////////////////////////////////////////
     2// File     : ctx_handler.h
     3// Date     : 01/04/2012
     4// Authors  : alain greiner & joel porquet
     5// Copyright (c) UPMC-LIP6
     6/////////////////////////////////////////////////////////////////////////////////////////
     7// The ctx_handler.h and ctx_handler.c files are part of the GIET-VM nano-kernel.
     8// This code is used to support context switch when several tasks are executing
     9// in time multiplexing on a single processor.
     10// The tasks are statically allocated to a processor in the boot phase, and
     11// there is one private scheduler per processor. Each sheduler occupies 4K bytes,
     12// and contains up to 14 task contexts (task_id is from 0 to 13).
     13// The task context [13] is reserved for the "idle" task that does nothing, and
     14// is launched by the scheduler when there is no other runable task.
     15/////////////////////////////////////////////////////////////////////////////////////////
     16// A task context is an array of 64 words = 256 bytes.
     17// It contains copies of processor registers (when the task is preempted):
     18// - GPR[i], generally stored in slot (i). $0, $26 & $27 are not saved.
     19// - HI & LO registers
     20// - CP0 registers: EPC, SR, CR, BVAR
     21// - CP2 registers : PTPR
     22// It contains some general informations associated to the task:
     23// - TTY    : TTY channel global index
     24// - NIC    : NIC channel global index
     25// - CMA    : CMA channel global index
     26// - HBA    : HBA channel global index
     27// - DMA    : DMA channel local index
     28// - TIM    : TIM channel local index
     29// - PTAB   : page table virtual base address
     30// - LTID   : Task local index (in scheduler)
     31// - VSID   : Virtual space index
     32// - RUN    : Task state (0 => sleeping / 1 => runnable )
     33// - TRDID  : Thread ID index (in vspace)
     34//
     35// ctx[0] <- ***   |ctx[8] <- $8    |ctx[16]<- $16   |ctx[24]<- $24
     36// ctx[1] <- $1    |ctx[9] <- $9    |ctx[17]<- $17   |ctx[25]<- $25
     37// ctx[2] <- $2    |ctx[10]<- $10   |ctx[18]<- $18   |ctx[26]<- LO
     38// ctx[3] <- $3    |ctx[11]<- $11   |ctx[19]<- $19   |ctx[27]<- HI
     39// ctx[4] <- $4    |ctx[12]<- $12   |ctx[20]<- $20   |ctx[28]<- $28
     40// ctx[5] <- $5    |ctx[13]<- $13   |ctx[21]<- $21   |ctx[29]<- SP
     41// ctx[6] <- $6    |ctx[14]<- $14   |ctx[22]<- $22   |ctx[30]<- $30
     42// ctx[7] <- $7    |ctx[15]<- $15   |ctx[23]<- $23   |ctx[31]<- RA
     43//
     44// ctx[32]<- EPC   |ctx[40]<- TTY   |ctx[48]<- TRDID |
     45// ctx[33]<- CR    |ctx[41]<- DMA
     46// ctx[34]<- SR    |ctx[42]<- NIC
     47// ctx[35]<- BVAR  |ctx[43]<- TIM
     48// ctx[36]<- PTAB  |ctx[44]<- HBA
     49// ctx[37]<- LTID  |ctx[45]<- CMA
     50// ctx[38]<- VSID  |ctx[46]<- GTID
     51// ctx[39]<- PTPR  |ctx[47]<- RUN
     52/////////////////////////////////////////////////////////////////////////////////////////
     53
    154#ifndef _CTX_HANDLER_H
    255#define _CTX_HANDLER_H
     
    1063typedef struct static_scheduler_s
    1164{
    12     unsigned int context[15][64];      // at most 15 task contexts
     65    unsigned int context[14][64];      // at most 14 task (including idle_task)
    1366    unsigned int tasks;                // actual number of tasks
    1467    unsigned int current;              // current task index
    15     unsigned int interrupt_vector[32]; // interrupt vector
     68    unsigned int hwi_vector[32];       // hardware interrupt vector
     69    unsigned int pti_vector[32];       // timer    interrupt vector
     70    unsigned int wti_vector[32];       // software interrupt vector
    1671} static_scheduler_t;
    1772
     
    2176/////////////////////////////////////////////////////////////////////////////////
    2277
    23 #define IDLE_TASK_INDEX        14
     78#define IDLE_TASK_INDEX        13
    2479
    2580/////////////////////////////////////////////////////////////////////////////////
     
    2782/////////////////////////////////////////////////////////////////////////////////
    2883
    29 #define CTX_SP_ID        29
    30 #define CTX_RA_ID        31
     84#define CTX_SP_ID        29  // Stack Pointer
     85#define CTX_RA_ID        31  // Return Address
    3186
    3287#define CTX_EPC_ID       32  // Exception Program Counter (CP0)
     
    3489#define CTX_SR_ID        34  // Status Register (CP0)
    3590#define CTX_BVAR_ID      35      // Bad Virtual Address Register (CP0)
    36 
    3791#define CTX_PTAB_ID      36  // Page Table Virtual address
    3892#define CTX_LTID_ID      37  // Local  Task Index (in scheduler)
     
    4094#define CTX_PTPR_ID      39  // Page Table Pointer Register (PADDR>>13)
    4195
    42 #define CTX_TTY_ID       40  // global TTY terminal 
     96#define CTX_TTY_ID       40  // global TTY channel  
    4397#define CTX_DMA_ID       41  // local DMA channel
    4498#define CTX_NIC_ID       42  // global NIC channel
     
    48102#define CTX_GTID_ID      46  // Global Task Index
    49103#define CTX_RUN_ID       47  // Boolean: task runable
     104
    50105#define CTX_TRDID_ID     48  // Thread Index in vspace
    51106
  • soft/giet_vm/giet_kernel/exc_handler.c

    r258 r294  
    6868};
    6969
     70///////////////////////////////////////////////
     71static void _display_cause( unsigned int type )
     72{
     73    unsigned int gpid       = _get_procid();
     74    unsigned int cluster_xy = gpid / NB_PROCS_MAX;
     75    unsigned int lpid       = gpid % NB_PROCS_MAX;
     76    unsigned int x          = cluster_xy >> Y_WIDTH;
     77    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     78    unsigned int task       = _get_context_slot(CTX_LTID_ID);
    7079
    71 static void _display_cause(unsigned int type)
    72 {
    73     _tty_get_lock( 0 );
    74     _puts("\n[GIET] Exception for task ");
    75     _putd(_get_context_slot(CTX_LTID_ID));
    76     _puts(" on processor ");
    77     _putd(_get_procid());
    78     _puts(" at cycle ");
    79     _putd(_get_proctime());
    80     _puts("\n - type      : ");
    81     _puts((char *) exc_type[type]);
    82     _puts("\n - EPC       : ");
    83     _putx(_get_epc());
    84     _puts("\n - BVAR      : ");
    85     _putx(_get_bvar());
    86     _puts("\n");
    87     _puts("...Task desactivated\n");
    88     _tty_release_lock( 0 );
     80    _printf("\n[GIET] Exception for task %d on processor[%d,%d,%d] at cycle %d\n"
     81            " - type      : %s\n"
     82            " - EPC       : %x\n"
     83            " - BVAR      : %x\n"
     84            "...Task desactivated\n",
     85            task, x, y, lpid, _get_proctime(),
     86            exc_type[type], _get_epc(), _get_bvar() );
    8987
    9088    // goes to sleeping state
  • soft/giet_vm/giet_kernel/irq_handler.c

    r281 r294  
    44// Author   : alain greiner
    55// Copyright (c) UPMC-LIP6
    6 ///////////////////////////////////////////////////////////////////////////////////
    7 // The irq_handler.c and irq_handler.h files are part of the GIET-VM nano-kernel.
    8 // They contain the code of the _irq_demux() function that access the XICU or
    9 // ICU component (Interupt Controler Unit), and the various ISRs (Interrupt
    10 // Service Routine) associated to the peripherals.
    116///////////////////////////////////////////////////////////////////////////////////
    127
     
    1914#include <xcu_driver.h>
    2015#include <tty_driver.h>
    21 #include <ioc_driver.h>
     16#include <nic_driver.h>
     17#include <cma_driver.h>
     18#include <bdv_driver.h>
    2219#include <dma_driver.h>
    2320#include <mapping_info.h>
     
    4037// Any value larger than 31 means "no active interrupt", and no ISR is executed.
    4138//
    42 // There is one interrupt vector per processor (stored in the scheduler associated
    43 // to the processor. Each interrupt vector entry contains four bits fields:
    44 // - isr_id     bits[7:0]   : defines the type of ISR to be executed.
    45 // - type_id    bits[15:8]  : IRQ_TYPE_HWI / IRQ_TYPE_SWI / IRQ_TYPE_PTI
     39// There is three interrupt vectors per processor (stored in the processor's
     40// scheduler) for the three HWI, PTI, and WTI interrupts types.
     41// Each interrupt vector entry contains three bits fields:
     42// - isr_id     bits[15:0]  : defines the type of ISR to be executed.
    4643// - channel_id bits[30:16] : defines the channel for multi-channels peripherals.
    4744// - valid      bit 31      : valid interrupt vector entry
    48 // If the peripheral is replicated in clusters (TIMER or DMA), the channel_id is
     45// If the peripheral is replicated in clusters, the channel_id is
    4946// a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id   
    5047///////////////////////////////////////////////////////////////////////////////////
    5148void _irq_demux()
    5249{
    53     unsigned int gpid       = _get_procid();
    54     unsigned int cluster_id = gpid / NB_PROCS_MAX;
    55     unsigned int local_id   = gpid % NB_PROCS_MAX;
     50    unsigned int gpid           = _get_procid();
     51    unsigned int cluster_xy     = gpid / NB_PROCS_MAX;
     52    unsigned int x              = cluster_xy >> Y_WIDTH;
     53    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
     54    unsigned int lpid           = gpid % NB_PROCS_MAX;
    5655    unsigned int irq_id;
    57     unsigned int ko;
     56    unsigned int irq_type;
     57    char*        irq_type_str[] = { "HWI", "WTI", "PTI" };
    5858
    5959    // get the highest priority active IRQ index
    60 
    61     unsigned int icu_out_index = local_id * IRQ_PER_PROCESSOR;
     60    unsigned int icu_out_index = lpid * IRQ_PER_PROCESSOR;
    6261
    6362#if USE_XICU
    64     ko = _xcu_get_index( cluster_id, icu_out_index, &irq_id );
     63    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
    6564#else
    66     ko = _icu_get_index( cluster_id, icu_out_index, &irq_id );
    67 #endif
    68 
    69     if ( ko )
    70     {
    71         _tty_get_lock( 0 );
    72         _puts("\n[GIET ERROR] Wrong _icu_read in _irq_demux()\n");
    73         _tty_release_lock( 0 );
    74     }
    75 
    76     // do nothing if no interrupt active, or
     65    irq_type = IRQ_TYPE_HWI;
     66    _icu_get_index( cluster_xy, icu_out_index, &irq_id );
     67#endif
     68
    7769    if (irq_id < 32)
    7870    {
    79         static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
    80         unsigned int        entry      = psched->interrupt_vector[irq_id];
    81         unsigned int        isr_id     = (entry    ) & 0x000000FF;
    82         unsigned int        type_id    = (entry>> 8) & 0x000000FF;
    83         unsigned int        channel_id = (entry>>16) & 0x00007FFF;
    84 
    85         if(type_id == IRQ_TYPE_HWI)      // HWI
     71        static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
     72        unsigned int        entry;
     73        unsigned int        isr_type;
     74        unsigned int        channel;
     75
     76        if      (irq_type == IRQ_TYPE_HWI) entry = psched->hwi_vector[irq_id];
     77        else if (irq_type == IRQ_TYPE_PTI) entry = psched->pti_vector[irq_id];
     78        else if (irq_type == IRQ_TYPE_WTI) entry = psched->wti_vector[irq_id];
     79        else
    8680        {
    87             if      ( isr_id == ISR_SWITCH) _isr_switch(channel_id);
    88             else if ( isr_id == ISR_IOC   ) _isr_ioc();
    89             else if ( isr_id == ISR_TTY   ) _isr_tty(channel_id);
    90             else if ( isr_id == ISR_TIMER ) _isr_timer(channel_id);
    91             else if ( isr_id == ISR_WAKUP ) _isr_timer(channel_id);
    92             else                            _isr_default( irq_id, isr_id, type_id );
     81            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
     82            _exit();
    9383        }
    94         else if(type_id == IRQ_TYPE_PTI) // PTI
     84
     85        isr_type   = (entry    ) & 0x0000FFFF;
     86        channel    = (entry>>16) & 0x00007FFF;
     87
     88#if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks
     89_puts("\n[IRQS DEBUG] Processor[");
     90_putd(x);
     91_puts(",");
     92_putd(y);
     93_puts(",");
     94_putd(lpid);
     95_puts("] enters _irq_demux() at cycle ");
     96_putd(_get_proctime() );
     97_puts("\n  ");
     98_puts(irq_type_str[irq_type] );
     99_puts(" : irq_id = ");
     100_putd(irq_id);
     101_puts(" / isr_type = ");
     102_putd(isr_type);
     103_puts(" / channel = ");
     104_putd(channel);
     105_puts("\n");
     106#endif
     107
     108        // ISR call
     109        if      ( isr_type == ISR_TICK   ) _isr_tick   ( irq_type, irq_id, channel );
     110        else if ( isr_type == ISR_WAKUP  ) _isr_wakup  ( irq_type, irq_id, channel );
     111        else if ( isr_type == ISR_BDV    ) _bdv_isr    ( irq_type, irq_id, channel );
     112        else if ( isr_type == ISR_CMA    ) _cma_isr    ( irq_type, irq_id, channel );
     113        else if ( isr_type == ISR_TTY_RX ) _tty_rx_isr ( irq_type, irq_id, channel );
     114        else if ( isr_type == ISR_TTY_TX ) _tty_tx_isr ( irq_type, irq_id, channel );
     115        else if ( isr_type == ISR_NIC_RX ) _nic_rx_isr ( irq_type, irq_id, channel );
     116        else if ( isr_type == ISR_NIC_TX ) _nic_tx_isr ( irq_type, irq_id, channel );
     117        else if ( isr_type == ISR_TIMER  ) _timer_isr  ( irq_type, irq_id, channel );
     118        else
    95119        {
    96             if      ( isr_id == ISR_SWITCH) _isr_switch(irq_id);
    97             else if ( isr_id == ISR_TIMER ) _isr_timer(irq_id);
    98             else                            _isr_default( irq_id, isr_id, type_id );
    99         }
    100         else if(type_id == IRQ_TYPE_SWI) // SWI
    101         {
    102             if      ( isr_id == ISR_WAKUP ) return;
    103             else                            _isr_default( irq_id, isr_id, type_id );
     120            // we don't take the TTY lock to avoid deadlock
     121            _puts("\n[GIET ERROR] in _irq_demux() illegal ISR type on processor[");
     122            _putd(x);
     123            _puts(",");
     124            _putd(y);
     125            _puts(",");
     126            _putd(lpid);
     127            _puts("] at cycle ");
     128            _putd(_get_proctime() );
     129            _puts("\n  ");
     130            _puts(irq_type_str[irq_type] );
     131            _puts(" : irq_id = ");
     132            _putd(irq_id);
     133            _puts(" / isr_type = ");
     134            _putd(isr_type);
     135            _puts(" / channel = ");
     136            _putd(channel);
     137            _puts("\n");
     138            _exit();
    104139        }
    105140    }
    106 }
    107 
    108 ///////////////////////////////////////////////////////////////////////////////////
    109 // The default ISR is called when no specific ISR has been installed in the
    110 // interrupt vector. It simply displays an error message on kernel TTY[0].
    111 ///////////////////////////////////////////////////////////////////////////////////
    112 void _isr_default( unsigned int irq_id,
    113                    unsigned int isr_id,
    114                    unsigned int type_id )
    115 {
    116     _tty_get_lock( 0 );
    117     _puts("\n[GIET ERROR] Undefined ISR index = ");
    118     _putd( isr_id );
    119     if(type_id == IRQ_TYPE_HWI) _puts(" / type = HWI ");
    120     if(type_id == IRQ_TYPE_SWI) _puts(" / type = SWI ");
    121     if(type_id == IRQ_TYPE_PTI) _puts(" / type = PTI ");
    122     _puts(" / IRQ index = ");
    123     _putd( irq_id );
    124     _puts(" / processor = ");
    125     _putd( _get_procid() );
    126     _puts("\n");
    127     _tty_release_lock( 0 );
    128     _exit();
    129 }
    130 
    131 
    132 ///////////////////////////////////////////////////////////////////////////////////
    133 // This ISR is executed when a processor wakes up after a SWI interrup.
    134 ///////////////////////////////////////////////////////////////////////////////////
    135 void _isr_wakup()
    136 {
    137     _tty_get_lock( 0 );
    138     _puts("\n  Processor ");
    139     _putd( _get_procid() );
    140     _puts(" wake up\n");
    141     _tty_release_lock( 0 );
    142 }
    143 
    144 ///////////////////////////////////////////////////////////////////////////////////
    145 // There is only one IOC controler shared by all tasks.
    146 // This ISR save the status, acknowledge the IRQ.
    147 // and activates the task waiting on IO transfer.
    148 //
    149 // TODO the _set_task_slot access should be replaced by an atomic LL/SC
    150 //      when the CTX_RUN bool will be replaced by a bit_vector.
    151 ///////////////////////////////////////////////////////////////////////////////////
    152 void _isr_ioc()
    153 {
    154     // save status in _ioc_status variable and reset IRQ
    155     if ( _ioc_get_status(0, &_ioc_status) ) return;
    156 
    157     // reactivate task waiting on IOC
    158     unsigned int gpid = _ioc_gtid>>16;
    159     unsigned int ltid = _ioc_gtid & 0xFFFF;
    160 
    161     _set_task_slot( gpid,        // global processor index
    162                     ltid,        // local task index (on processor)
    163                     CTX_RUN_ID,  // CTX_RUN slot
    164                     1 );         // running
    165 }
    166 
    167 ///////////////////////////////////////////////////////////////////////////////////
    168 // This ISR handles the IRQs generated by the "user" timers (the IRQs generated
    169 // by the "system" timers should be handled by the _isr_switch().
    170 // These timers are distributed in all clusters, and can be implemented
    171 // in a vci_multi_timer component, or in a vci_xicu component.
    172 // The timer_id argument is the user timer local index.
    173 //     timer_globa_id = cluster_id*(NB_TIM_CHANNELS) + timer_id
    174 // The ISR acknowledges the IRQ and registers the event in the proper entry
    175 // of the _timer_event[] array, and a log message is displayed on kernel terminal.
    176 ///////////////////////////////////////////////////////////////////////////////////
    177 void _isr_timer(unsigned int timer_id)
    178 {
    179     // compute cluster_id
    180     unsigned int cluster_id = _get_procid() / NB_PROCS_MAX;
    181 
    182     // aknowledge IRQ
    183     if (_timer_reset_irq( cluster_id, timer_id))
     141    else   // no interrupt active
    184142    {
    185         _tty_get_lock( 0 );
    186         _puts("[GIET ERROR] illegal timer index detected by _isr_timer\n");
    187         _tty_release_lock( 0 );
    188         return;
     143        _isr_default();
     144    }
     145}
     146
     147///////////////////////////////////////////////////////////////////////////////////
     148// The default ISR is called when there is no active IRQ when the interrupt
     149// handler is called. It simply displays a warning message on TTY[0].
     150///////////////////////////////////////////////////////////////////////////////////
     151void _isr_default()
     152{
     153    unsigned int gpid       = _get_procid();
     154    unsigned int cluster_xy = gpid / NB_PROCS_MAX;
     155    unsigned int x          = cluster_xy >> Y_WIDTH;
     156    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     157    unsigned int lpid       = gpid % NB_PROCS_MAX;
     158
     159    // We don't take TTY lock to avoid deadlock
     160    _puts("\n[GIET WARNING] IRQ handler called but no active IRQ on processor[");
     161    _putd( x );
     162    _puts(",");
     163    _putd( y );
     164    _puts(",");
     165    _putd( lpid );
     166    _puts("] at cycle ");
     167    _putd( _get_proctime() );
     168    _puts("\n  ");
     169}
     170
     171
     172///////////////////////////////////////////////////////////////////////////////////
     173// This ISR can only be executed after a WTI (IPI) to force a context switch
     174// on a remote processor. The context switch is only executed if the current task
     175// is the IDLE_TASK, or if the value written in the mailbox is non zero.
     176///////////////////////////////////////////////////////////////////////////////////
     177void _isr_wakup( unsigned int irq_type,   // HWI / WTI / PTI
     178                 unsigned int irq_id,     // index returned by ICU
     179                 unsigned int channel )   // unused
     180{
     181    unsigned int procid     = _get_procid();
     182    unsigned int cluster_xy = procid / NB_PROCS_MAX;
     183    unsigned int x          = cluster_xy >> Y_WIDTH;
     184    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     185    unsigned int lpid       = procid % NB_PROCS_MAX;
     186    unsigned int task       = _get_current_task_id();
     187    unsigned int value;
     188
     189    if ( irq_type != IRQ_TYPE_WTI )
     190    {
     191        // we don't take the TTY lock to avoid deadlocks
     192        _puts("[GIET ERROR] _isr_wakup() not called by a WTI on processor[");
     193        _putd( x );
     194        _puts(",");
     195        _putd( y );
     196        _puts(",");
     197        _putd( lpid );
     198        _puts("] at cycle ");
     199        _putd( _get_proctime() );
     200        _puts("\n");
     201        _exit();
    189202    }
    190203
    191 #if NB_TIM_CHANNELS
    192     // register the event
    193     unsigned int timer_global_id = cluster_id * NB_TIM_CHANNELS + timer_id;
    194     _user_timer_event[timer_global_id] = 1;
    195 #endif
    196 
    197     // display a message on TTY 0
    198     _tty_get_lock( 0 );
    199     _puts("\n[GIET] User Timer IRQ at cycle ");
    200     _putd(_get_proctime());
    201     _puts("\n - cluster_id = ");
    202     _putd(cluster_id);
    203     _puts("\n - timer_id   = ");
    204     _putd(timer_id);
    205     _puts("\n");
    206     _tty_release_lock( 0 );
    207 }
    208 
    209 
    210 ///////////////////////////////////////////////////////////////////////////////////
    211 // This ISR handles the IRQs generated by the multi_tty controler,
    212 // signaling that a character is available.
    213 // There is one single multi_tty component controling all TTYs,
    214 // and the tty_id argument is the global TTY index.
    215 // There is one communication buffer _tty_buf[tty_id] per terminal.
    216 // The sychronisation variable _tty_full[tty_id], is set by the ISR,
    217 // and reset by the OS.
    218 // A character is lost if the buffer is full when the ISR is executed.
    219 ///////////////////////////////////////////////////////////////////////////////////
    220 void _isr_tty(unsigned int tty_id)
    221 {
    222     // read character and reset IRQ in one read access
    223     _tty_get_buf[tty_id] = _tty_read_data( tty_id );
    224 
    225     // signals character available
    226     _tty_get_full[tty_id] = 1;
    227 }
    228 
     204    // get mailbox value and acknowledge WTI
     205    _xcu_get_wti_value( cluster_xy, irq_id, &value );
     206
     207#if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks
     208_puts("\n[IRQS DEBUG] Processor[");
     209_putd( x );
     210_puts(",");
     211_putd( y );
     212_puts(",");
     213_putd( lpid );
     214_puts("] enters _isr_wakup() at cycle ");
     215_putd( _get_proctime() );
     216_puts("\n  WTI / mailbox data = ");
     217_putx( value );
     218_puts(" / current task index = ");
     219_putd( task );
     220_puts("\n  ");
     221#endif
     222
     223    // context swich if required
     224    if ( (task == IDLE_TASK_INDEX) || (value != 0) ) _ctx_switch();
     225}
    229226
    230227/////////////////////////////////////////////////////////////////////////////////////
    231 // This ISR is in charge of context switch, and handle the IRQs generated by
    232 // the "system" timers.
    233 // The IRQs can be generated by the MULTI_TIMER component or by the XICU component,
    234 // that are distributed in all clusters.
    235 // The ISR acknowledges the IRQ and calls the _ctx_switch() function.
     228// This ISR is in charge of context switch, and handles the IRQs generated by
     229// the "system" timers contained in the MULTI_TIMER or in the XICU component.
     230// The ISR acknowledges the IRQ, and calls the _ctx_switch() function.
    236231/////////////////////////////////////////////////////////////////////////////////////
    237 void _isr_switch( unsigned int timer_id)
    238 {
    239     // get cluster index
    240     unsigned int cluster_id = _get_procid() / NB_PROCS_MAX;
    241 
    242     // acknowledge IRQ
    243 
    244 #if USE_XICU
    245     if ( _xcu_timer_reset_irq( cluster_id, timer_id) )
    246     {
    247         _tty_get_lock( 0 );
    248         _puts("[GIET ERROR] illegal proc index detected by _isr_switch\n");
    249         _tty_release_lock( 0 );
    250         return;
    251     }
    252 #else
    253     if (_timer_reset_irq(cluster_id, timer_id))
    254     {
    255         _tty_get_lock( 0 );
    256         _puts("[GIET ERROR] illegal proc index detected by _isr_switch\n");
    257         _tty_release_lock( 0 );
    258         return;
    259     }
    260 #endif
    261 
    262     // performs the context switch
     232void _isr_tick( unsigned int irq_type,   // HWI / WTI / PTI
     233                unsigned int irq_id,     // index returned by ICU
     234                unsigned int channel )   // channel index if HWI
     235{
     236    unsigned int procid     = _get_procid();
     237    unsigned int cluster_xy = procid / NB_PROCS_MAX;
     238
     239    // acknowledge HWI or PTI
     240    if ( irq_type == IRQ_TYPE_HWI ) _timer_reset_irq( cluster_xy, channel );
     241    else                            _xcu_timer_reset_irq( cluster_xy, irq_id );
     242
     243#if GIET_DEBUG_IRQS  // we don't take the lock to avoid deadlock
     244unsigned int x          = cluster_xy >> Y_WIDTH;
     245unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     246unsigned int lpid       = procid % NB_PROCS_MAX;
     247_puts("\n[IRQS DEBUG] Processor[");
     248_putd( x );
     249_puts(",");
     250_putd( y );
     251_puts(",");
     252_putd( lpid );
     253_puts("] enters _isr_tick() at cycle ");
     254_putd( _get_proctime() );
     255_puts("\n  ");
     256#endif
     257
     258    // context switch
    263259    _ctx_switch();
    264260}
  • soft/giet_vm/giet_kernel/irq_handler.h

    r258 r294  
     1///////////////////////////////////////////////////////////////////////////////////
     2// File     : irq_handler.h
     3// Date     : 01/04/2012
     4// Author   : alain greiner
     5// Copyright (c) UPMC-LIP6
     6///////////////////////////////////////////////////////////////////////////////////
     7// The irq_handler.c and irq_handler.h files are part of the GIET-VM nano-kernel.
     8// They contain the code of the _irq_demux() function that access the XICU or
     9// ICU component (Interupt Controler Unit), and the various ISRs (Interrupt
     10// Service Routine) associated to the various ISR types.
     11///////////////////////////////////////////////////////////////////////////////////
     12
    113#ifndef _IRQ_HANDLER_H
    214#define _IRQ_HANDLER_H
     15
     16////////////////////////////////////////////////////////////////////////////////
     17// This enum must be kept consistent with the values defined in the
     18// xml_driver.c and irq_handler.c files (for display)
     19///////////////////////////////////////////////////////////////////////////////
    320
    421enum isr_type_t
    522{
    623    ISR_DEFAULT = 0,
    7     ISR_SWITCH  = 1,
    8     ISR_TTY     = 2,
    9     ISR_DMA     = 3,
    10     ISR_IOC     = 4,
     24    ISR_TICK    = 1,
     25    ISR_TTY_RX  = 2,
     26    ISR_TTY_TX  = 3,
     27    ISR_BDV     = 4,
    1128    ISR_TIMER   = 5,
    1229    ISR_WAKUP   = 6,
     30    ISR_NIC_RX  = 7,
     31    ISR_NIC_TX  = 8,
     32    ISR_CMA     = 9,
    1333};
    14 
    1534
    1635///////////////////////////////////////////////////////////////////////////////
     
    2140
    2241extern void _isr_default();
    23 extern void _isr_ioc();
    24 extern void _isr_timer(unsigned int channel);
    25 extern void _isr_dma(unsigned int channel);
    26 extern void _isr_tty(unsigned int channel);
    27 extern void _isr_switch();
    28 extern void _isr_wakup();
     42
     43extern void _isr_tick( unsigned int irq_type,
     44                       unsigned int irq_id,
     45                       unsigned int channel );
     46
     47extern void _isr_wakup( unsigned int irq_type,
     48                        unsigned int irq_id,
     49                        unsigned int channel );
    2950
    3051#endif
  • 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()
  • soft/giet_vm/giet_kernel/sys_handler.c

    r267 r294  
    3535    &_timer_start,         /* 0x04 */
    3636    &_timer_stop,          /* 0x05 */
    37     &_sys_ukn,             /* 0x06 */
    38     &_sys_ukn,             /* 0x07 */
     37    &_tty_get_lock,        /* 0x06 */
     38    &_tty_release_lock,    /* 0x07 */
    3939    &_heap_info,           /* 0x08 */
    4040    &_local_task_id,       /* 0x09 */
     
    4949    &_fb_sync_read,        /* 0x11 */
    5050    &_thread_id,           /* 0x12 */
    51     &_tty_get_release_lock,/* 0x13 */
     51    &_sys_ukn,             /* 0x13 */
    5252    &_sys_ukn,             /* 0x14 */
    5353    &_sys_ukn,             /* 0x15 */
     
    103103void _sys_ukn()
    104104{
    105     unsigned int epc;
    106     asm volatile("mfc0 %0, $14" : "=r" (epc));
    107 
    108     _tty_get_lock( 0 );
    109     _puts("\n\n!!! Undefined System Call !!!\n");
    110     _puts("\nEPC = ");
    111     _putx(epc);
    112     _tty_release_lock( 0 );
     105    _printf("\n\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
    113106    _exit();
    114107}
    115108
    116109////////////////////////////////////////////////////////////////////////////
    117 // _exit()
    118110// Task suicide... after printing a death message.
    119111////////////////////////////////////////////////////////////////////////////
    120 void _task_exit()
    121 {
    122     unsigned int date    = _get_proctime();
    123     unsigned int proc_id = _get_procid();
    124     unsigned int task_id = _get_context_slot(CTX_LTID_ID);
     112void _task_exit( char* string )
     113{
     114    unsigned int date       = _get_proctime();
     115    unsigned int proc_id    = _get_procid();
     116    unsigned int cluster_xy = proc_id / NB_PROCS_MAX;
     117    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     118    unsigned int x          = cluster_xy >> Y_WIDTH;
     119    unsigned int lpid       = proc_id % NB_PROCS_MAX;
     120    unsigned int task_id    = _get_context_slot(CTX_LTID_ID);
    125121
    126122    // print death message
    127     _tty_get_lock( 0 );
    128     _puts("\n[GIET] Exit task ");
    129     _putd(task_id);
    130     _puts(" on processor ");
    131     _putd(proc_id);
    132     _puts(" at cycle ");
    133     _putd(date);
    134     _puts("\n\n");
    135     _tty_release_lock( 0 );
     123    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
     124            "\n       Cause : %s\n\n",
     125            task_id, x, y, lpid, date, string );
    136126
    137127    // goes to sleeping state
     
    143133
    144134//////////////////////////////////////////////////////////////////////////////
    145 // _procnumber()
    146135// returns in buffer argument the number of processors in the cluster
    147136// specified by the cluster_id argument.
     
    165154
    166155/////////////////////////////////////////////////////////////////////////////
    167 // _local_task_id()
    168156// Returns current task local index.
    169157/////////////////////////////////////////////////////////////////////////////
     
    174162
    175163/////////////////////////////////////////////////////////////////////////////
    176 // _global_task_id()
    177164// Returns current task global index.
    178165/////////////////////////////////////////////////////////////////////////////
     
    183170
    184171/////////////////////////////////////////////////////////////////////////////
    185 // _thread_id()
    186172// Returns current thread index.
    187173/////////////////////////////////////////////////////////////////////////////
     
    192178
    193179/////////////////////////////////////////////////////////////////////////////
    194 // _tty_get_release_lock(int val)
    195 // Get or release the hardware TTY lock depending on val (0: get,1: release)
    196 /////////////////////////////////////////////////////////////////////////////
    197 int _tty_get_release_lock(unsigned int val)
    198 {
    199     unsigned int channel = _get_context_slot(CTX_TTY_ID);
    200 
    201     if      ( val == 0 ) _tty_get_lock(channel);
    202     else if ( val == 1 ) _tty_release_lock(channel);
    203     else return -1; // Wrong action
    204 
    205     return 0;
    206 }
    207 
    208 /////////////////////////////////////////////////////////////////////////////
    209 // _get_vobj()
    210180// This function writes in res_vobj a pointer on a vobj
    211181// identified by the (vspace_name / vobj_name ) couple.
    212 // The vobj_type argument is here only for the purpose of checking .
    213 // returns 0: success, else: failed.
     182// returns 0 if success, >0 if not found
    214183/////////////////////////////////////////////////////////////////////////////
    215184int _get_vobj( char*             vspace_name,
    216185               char*             vobj_name,
    217                unsigned int      vobj_type,
    218186               mapping_vobj_t**  res_vobj )
    219187{
     
    237205                if (_strncmp(vobj[vobj_id].name, vobj_name, 31) == 0)
    238206                {
    239                     if (vobj[vobj_id].type != vobj_type)
    240                     {
    241                         _tty_get_lock( 0 );
    242                         _puts("*** Error in _get_obj: wrong type\n");
    243                         _tty_release_lock( 0 );
    244                         return -1; // wrong type
    245                     }
    246207                    *res_vobj = &vobj[vobj_id];
    247208                    return 0;
     
    250211        }
    251212    }
    252     _tty_get_lock( 0 );
    253     _puts("*** Error in _get_obj: object not found\n");
    254     _tty_release_lock( 0 );
    255 
    256     return -2; //not found
    257 }
    258 
    259 /////////////////////////////////////////////////////////////////////////////
    260 // _vobj_get_vbase()
     213    return 1;    //not found
     214}
     215
     216/////////////////////////////////////////////////////////////////////////////
    261217// This function writes in vobj_vaddr the virtual base address of a vobj
    262218// identified by the (vspace_name / vobj_name ) couple.
    263 // The vobj_type argument is here only for the purpose of checking .
    264 // returns 0: success, else: failed.
     219// returns 0 if success, >0 if not found
    265220/////////////////////////////////////////////////////////////////////////////
    266221unsigned int _vobj_get_vbase( char*         vspace_name,
    267222                              char*         vobj_name,
    268                               unsigned int  vobj_type,
    269                               unsigned int* vobj_vaddr )
     223                              unsigned int* vobj_vbase )
    270224{
    271225    mapping_vobj_t* res_vobj;
    272226    unsigned int    ret;
    273     if ((ret = _get_vobj(vspace_name, vobj_name, vobj_type, &res_vobj)))
     227    if ((ret = _get_vobj(vspace_name, vobj_name, &res_vobj)))
    274228    {
    275229        return ret;
    276230    }
    277     *vobj_vaddr = res_vobj->vaddr;
     231    *vobj_vbase = res_vobj->vaddr;
    278232    return 0;
    279233}
    280234
    281235/////////////////////////////////////////////////////////////////////////////
    282 // _vobj_get_length()
    283 // This function writes in vobj_length the virtual base address of a vobj
     236// This function writes in vobj_length the length of a vobj
    284237// identified by the (vspace_name / vobj_name ) couple.
    285 // The vobj_type argument is here only for the purpose of checking .
    286 // returns 0: success, else: failed.
     238// returns 0 if success, >0 if not found
    287239/////////////////////////////////////////////////////////////////////////////
    288240unsigned int _vobj_get_length( char*         vspace_name,
    289241                               char*         vobj_name,
    290                                unsigned int  vobj_type,
    291242                               unsigned int* vobj_length )
    292243{
    293244    mapping_vobj_t * res_vobj;
    294245    unsigned int ret;
    295     if ((ret = _get_vobj(vspace_name, vobj_name, vobj_type, &res_vobj)))
     246    if ((ret = _get_vobj(vspace_name, vobj_name, &res_vobj)))
    296247    {
    297248        return ret;
     
    301252}
    302253
    303 
    304 ////////////////////////////////////////////////////////////////
    305 // _context_switch()
    306 // This functions masks interruptions before calling _ctx_switch
    307 // (They are usually masked when we receive a isr_switch interrupt
    308 // because we execute ISRs with interrupt masked)
    309 ////////////////////////////////////////////////////////////////
     254////////////////////////////////////////////////////////////////////////////
     255// This sysrem function deschedule the requestint task.
     256// It mask interrupts before calling the _ctx_switch, and restore it
     257// when the task is rescheduled.
     258////////////////////////////////////////////////////////////////////////////
    310259void _context_switch()
    311260{
    312     _it_disable();
     261    unsigned int save_sr;
     262
     263    _it_disable( &save_sr );
    313264    _ctx_switch();
    314 }
    315 
     265    _it_restore( &save_sr );
     266}
    316267
    317268// Local Variables:
  • soft/giet_vm/giet_kernel/sys_handler.h

    r267 r294  
    2020
    2121void         _sys_ukn();
     22
    2223void         _task_exit();
     24
    2325void         _context_switch();
     26
    2427unsigned int _local_task_id();
     28
    2529unsigned int _global_task_id();
     30
    2631unsigned int _thread_id();
    27 
    28 int          _tty_get_release_lock(unsigned int val);
    2932
    3033unsigned int _procs_number( unsigned int  cluster_id,
     
    3336unsigned int _vobj_get_vbase( char*         vspace_name,
    3437                              char*         vobj_name,
    35                               unsigned      vobj_type,
    36                               unsigned int* vobj_buffer);
     38                              unsigned int* vobj_vbase );
     39
     40unsigned int _vobj_get_length( char*         vspace_name,
     41                               char*         vobj_name,
     42                               unsigned int* vobj_length );
    3743
    3844#endif
Note: See TracChangeset for help on using the changeset viewer.