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

Last change on this file since 294 was 294, checked in by alain, 10 years ago

Introducing support for IOPIC component.

  • Property svn:executable set to *
File size: 9.4 KB
Line 
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>
16#include <nic_driver.h>
17#include <cma_driver.h>
18#include <bdv_driver.h>
19#include <dma_driver.h>
20#include <mapping_info.h>
21#include <utils.h>
22
23#if !defined( USE_XICU )
24# error: You must define USE_XICU in the hard_config.h file
25#endif
26
27#if NB_TIM_CHANNELS
28extern volatile unsigned char _user_timer_event[X_SIZE*Y_SIZE*NB_TIM_CHANNELS] ;
29#endif
30
31///////////////////////////////////////////////////////////////////////////////////
32// This function uses the ICU or XICU component (Interrupt Controler Unit)
33// to get the interrupt vector entry. There is one ICU or XICU component per
34// cluster, and this component can support up to NB_PROCS_MAX output IRQs.
35// It returns the highest priority active interrupt index (smaller
36// indexes have the highest priority).
37// Any value larger than 31 means "no active interrupt", and no ISR is executed.
38//
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.
43// - channel_id bits[30:16] : defines the channel for multi-channels peripherals.
44// - valid      bit 31      : valid interrupt vector entry
45// If the peripheral is replicated in clusters, the channel_id is
46// a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id   
47///////////////////////////////////////////////////////////////////////////////////
48void _irq_demux() 
49{
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;
55    unsigned int irq_id;
56    unsigned int irq_type;
57    char*        irq_type_str[] = { "HWI", "WTI", "PTI" }; 
58
59    // get the highest priority active IRQ index
60    unsigned int icu_out_index = lpid * IRQ_PER_PROCESSOR;
61
62#if USE_XICU
63    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
64#else
65    irq_type = IRQ_TYPE_HWI;
66    _icu_get_index( cluster_xy, icu_out_index, &irq_id );
67#endif
68
69    if (irq_id < 32) 
70    {
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
80        {
81            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
82            _exit();
83        }
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
119        {
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();
139        }
140    }
141    else   // no interrupt active
142    {
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();
202    }
203
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}
226
227/////////////////////////////////////////////////////////////////////////////////////
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.
231/////////////////////////////////////////////////////////////////////////////////////
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
259    _ctx_switch();
260}
261
262
263// Local Variables:
264// tab-width: 4
265// c-basic-offset: 4
266// c-file-offsets:((innamespace . 0)(inline-open . 0))
267// indent-tabs-mode: nil
268// End:
269// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
270
Note: See TracBrowser for help on using the repository browser.