source: soft/giet_vm/giet_kernel/irq_handler.c @ 315

Last change on this file since 315 was 310, checked in by alain, 11 years ago

Reducing the number of log messages.

  • Property svn:executable set to *
File size: 9.2 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : irq_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <giet_config.h>
9#include <irq_handler.h>
10#include <sys_handler.h>
11#include <ctx_handler.h>
12#include <tim_driver.h>
13#include <icu_driver.h>
14#include <xcu_driver.h>
15#include <tty_driver.h>
[294]16#include <nic_driver.h>
17#include <cma_driver.h>
[297]18#include <mmc_driver.h>
[294]19#include <bdv_driver.h>
[258]20#include <dma_driver.h>
[281]21#include <mapping_info.h>
[258]22#include <utils.h>
23
24#if !defined( USE_XICU )
25# error: You must define USE_XICU in the hard_config.h file
26#endif
27
28#if NB_TIM_CHANNELS
[263]29extern volatile unsigned char _user_timer_event[X_SIZE*Y_SIZE*NB_TIM_CHANNELS] ;
[258]30#endif
31
32///////////////////////////////////////////////////////////////////////////////////
33// This function uses the ICU or XICU component (Interrupt Controler Unit)
34// to get the interrupt vector entry. There is one ICU or XICU component per
35// cluster, and this component can support up to NB_PROCS_MAX output IRQs.
36// It returns the highest priority active interrupt index (smaller
37// indexes have the highest priority).
38// Any value larger than 31 means "no active interrupt", and no ISR is executed.
39//
[294]40// There is three interrupt vectors per processor (stored in the processor's
41// scheduler) for the three HWI, PTI, and WTI interrupts types.
42// Each interrupt vector entry contains three bits fields:
43// - isr_id     bits[15:0]  : defines the type of ISR to be executed.
[258]44// - channel_id bits[30:16] : defines the channel for multi-channels peripherals.
45// - valid      bit 31      : valid interrupt vector entry
[294]46// If the peripheral is replicated in clusters, the channel_id is
[258]47// a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id   
48///////////////////////////////////////////////////////////////////////////////////
49void _irq_demux() 
50{
[294]51    unsigned int gpid           = _get_procid();
52    unsigned int cluster_xy     = gpid / NB_PROCS_MAX;
53    unsigned int x              = cluster_xy >> Y_WIDTH;
54    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
55    unsigned int lpid           = gpid % NB_PROCS_MAX;
[258]56    unsigned int irq_id;
[294]57    unsigned int irq_type;
[258]58
59    // get the highest priority active IRQ index
[294]60    unsigned int icu_out_index = lpid * IRQ_PER_PROCESSOR;
[258]61
62#if USE_XICU
[294]63    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
[258]64#else
[294]65    irq_type = IRQ_TYPE_HWI;
66    _icu_get_index( cluster_xy, icu_out_index, &irq_id );
[258]67#endif
68
69    if (irq_id < 32) 
70    {
[294]71        static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
72        unsigned int        entry;
73        unsigned int        isr_type;
74        unsigned int        channel;
[258]75
[294]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
[258]80        {
[294]81            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
82            _exit();
[258]83        }
[294]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
[310]89char* irq_type_str[] = { "HWI", "WTI", "PTI" }; 
[294]90_puts("\n[IRQS DEBUG] Processor[");
91_putd(x);
92_puts(",");
93_putd(y);
94_puts(",");
95_putd(lpid);
96_puts("] enters _irq_demux() at cycle ");
97_putd(_get_proctime() );
98_puts("\n  ");
99_puts(irq_type_str[irq_type] );
100_puts(" : irq_id = ");
101_putd(irq_id);
102_puts(" / isr_type = ");
103_putd(isr_type);
104_puts(" / channel = ");
105_putd(channel);
106_puts("\n");
107#endif
108
109        // ISR call
110        if      ( isr_type == ISR_TICK   ) _isr_tick   ( irq_type, irq_id, channel );
111        else if ( isr_type == ISR_WAKUP  ) _isr_wakup  ( irq_type, irq_id, channel );
112        else if ( isr_type == ISR_BDV    ) _bdv_isr    ( irq_type, irq_id, channel );
113        else if ( isr_type == ISR_CMA    ) _cma_isr    ( irq_type, irq_id, channel );
114        else if ( isr_type == ISR_TTY_RX ) _tty_rx_isr ( irq_type, irq_id, channel );
115        else if ( isr_type == ISR_TTY_TX ) _tty_tx_isr ( irq_type, irq_id, channel );
116        else if ( isr_type == ISR_NIC_RX ) _nic_rx_isr ( irq_type, irq_id, channel );
117        else if ( isr_type == ISR_NIC_TX ) _nic_tx_isr ( irq_type, irq_id, channel );
118        else if ( isr_type == ISR_TIMER  ) _timer_isr  ( irq_type, irq_id, channel );
[297]119        else if ( isr_type == ISR_MMC    ) _mmc_isr    ( irq_type, irq_id, channel );
[294]120        else
[258]121        {
[310]122            _printf("\n[GIET ERROR] in _irq_demux() :"
123                    " illegal ISR type on processor[%d,%d,%d] at cycle %d\n"
124                    " - irq_type = %d\n"
125                    " - irq_id   = %d\n"
126                    " - isr_type = %x\n",
127                    x, y, lpid, _get_proctime(), irq_type, irq_id, isr_type );
[258]128        }
129    }
[294]130    else   // no interrupt active
131    {
132        _isr_default();
133    } 
[258]134}
135
136///////////////////////////////////////////////////////////////////////////////////
[294]137// The default ISR is called when there is no active IRQ when the interrupt
138// handler is called. It simply displays a warning message on TTY[0].
[258]139///////////////////////////////////////////////////////////////////////////////////
[294]140void _isr_default()
[258]141{
[294]142    unsigned int gpid       = _get_procid();
143    unsigned int cluster_xy = gpid / NB_PROCS_MAX;
144    unsigned int x          = cluster_xy >> Y_WIDTH;
145    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
146    unsigned int lpid       = gpid % NB_PROCS_MAX;
[258]147
[294]148    // We don't take TTY lock to avoid deadlock
149    _puts("\n[GIET WARNING] IRQ handler called but no active IRQ on processor[");
150    _putd( x );
151    _puts(",");
152    _putd( y );
153    _puts(",");
154    _putd( lpid );
155    _puts("] at cycle ");
156    _putd( _get_proctime() );
157    _puts("\n  ");
[258]158}
159
160
161///////////////////////////////////////////////////////////////////////////////////
[294]162// This ISR can only be executed after a WTI (IPI) to force a context switch
163// on a remote processor. The context switch is only executed if the current task
164// is the IDLE_TASK, or if the value written in the mailbox is non zero.
[258]165///////////////////////////////////////////////////////////////////////////////////
[294]166void _isr_wakup( unsigned int irq_type,   // HWI / WTI / PTI
167                 unsigned int irq_id,     // index returned by ICU
168                 unsigned int channel )   // unused
[258]169{
[294]170    unsigned int procid     = _get_procid();
171    unsigned int cluster_xy = procid / NB_PROCS_MAX;
172    unsigned int x          = cluster_xy >> Y_WIDTH;
173    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
174    unsigned int lpid       = procid % NB_PROCS_MAX;
175    unsigned int task       = _get_current_task_id();
176    unsigned int value;
[258]177
[294]178    if ( irq_type != IRQ_TYPE_WTI )
[258]179    {
[294]180        // we don't take the TTY lock to avoid deadlocks
181        _puts("[GIET ERROR] _isr_wakup() not called by a WTI on processor[");
182        _putd( x );
183        _puts(",");
184        _putd( y );
185        _puts(",");
186        _putd( lpid );
187        _puts("] at cycle ");
188        _putd( _get_proctime() );
189        _puts("\n");
190        _exit();
[258]191    }
192
[294]193    // get mailbox value and acknowledge WTI
194    _xcu_get_wti_value( cluster_xy, irq_id, &value );
195
196#if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks
197_puts("\n[IRQS DEBUG] Processor[");
198_putd( x );
199_puts(",");
200_putd( y );
201_puts(",");
202_putd( lpid );
203_puts("] enters _isr_wakup() at cycle ");
204_putd( _get_proctime() );
205_puts("\n  WTI / mailbox data = ");
206_putx( value );
207_puts(" / current task index = ");
208_putd( task );
209_puts("\n  ");
[258]210#endif
211
[294]212    // context swich if required
213    if ( (task == IDLE_TASK_INDEX) || (value != 0) ) _ctx_switch();
[258]214}
215
216/////////////////////////////////////////////////////////////////////////////////////
[294]217// This ISR is in charge of context switch, and handles the IRQs generated by
218// the "system" timers contained in the MULTI_TIMER or in the XICU component.
219// The ISR acknowledges the IRQ, and calls the _ctx_switch() function.
[258]220/////////////////////////////////////////////////////////////////////////////////////
[294]221void _isr_tick( unsigned int irq_type,   // HWI / WTI / PTI
222                unsigned int irq_id,     // index returned by ICU
223                unsigned int channel )   // channel index if HWI
[258]224{
[294]225    unsigned int procid     = _get_procid();
226    unsigned int cluster_xy = procid / NB_PROCS_MAX;
[258]227
[294]228    // acknowledge HWI or PTI
229    if ( irq_type == IRQ_TYPE_HWI ) _timer_reset_irq( cluster_xy, channel );
230    else                            _xcu_timer_reset_irq( cluster_xy, irq_id );
[258]231
[294]232#if GIET_DEBUG_IRQS  // we don't take the lock to avoid deadlock
233unsigned int x          = cluster_xy >> Y_WIDTH;
234unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
235unsigned int lpid       = procid % NB_PROCS_MAX;
236_puts("\n[IRQS DEBUG] Processor[");
237_putd( x );
238_puts(",");
239_putd( y );
240_puts(",");
241_putd( lpid );
242_puts("] enters _isr_tick() at cycle ");
243_putd( _get_proctime() );
244_puts("\n  ");
[258]245#endif
246
[294]247    // context switch
[258]248    _ctx_switch();
249}
250
251
252// Local Variables:
253// tab-width: 4
254// c-basic-offset: 4
255// c-file-offsets:((innamespace . 0)(inline-open . 0))
256// indent-tabs-mode: nil
257// End:
258// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
259
Note: See TracBrowser for help on using the repository browser.