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

Last change on this file since 817 was 811, checked in by bouyer, 9 years ago

Do not try to allocate a WTI and write it to the PIC if we don't have a PIC.

  • Property svn:executable set to *
File size: 18.0 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 <xcu_driver.h>
14#include <pic_driver.h>
15#include <tty_driver.h>
16#include <nic_driver.h>
17#include <cma_driver.h>
18#include <mmc_driver.h>
19#include <bdv_driver.h>
20#include <hba_driver.h>
21#include <dma_driver.h>
22#include <sdc_driver.h>
23#include <mwr_driver.h>
24#include <mapping_info.h>
25#include <utils.h>
26#include <tty0.h>
27
28////////////////////////////////////////////////////////////////////////////
29//        Extern variables
30////////////////////////////////////////////////////////////////////////////
31
32// allocated in sys_handler.c file
33extern unsigned int _tty_channel_wti[NB_TTY_CHANNELS];
34extern unsigned int _tim_channel_wti[NB_TIM_CHANNELS];
35extern unsigned int _cma_channel_wti[NB_CMA_CHANNELS];
36extern unsigned int _nic_rx_channel_wti[NB_NIC_CHANNELS];
37extern unsigned int _nic_tx_channel_wti[NB_NIC_CHANNELS];
38
39/////////////////////////////////////////////////////////////////////////
40//       Global variables
41/////////////////////////////////////////////////////////////////////////
42
43// array of external IRQ indexes for each (isr/channel) couple
44__attribute__((section(".kdata")))
45unsigned char _ext_irq_index[GIET_ISR_TYPE_MAX][GIET_ISR_CHANNEL_MAX];
46
47// WTI mailbox allocators for external IRQ routing (3 allocators per proc)
48__attribute__((section(".kdata")))
49unsigned char _wti_alloc_one[X_SIZE][Y_SIZE][NB_PROCS_MAX];
50__attribute__((section(".kdata")))
51unsigned char _wti_alloc_two[X_SIZE][Y_SIZE][NB_PROCS_MAX];
52__attribute__((section(".kdata")))
53unsigned char _wti_alloc_ter[X_SIZE][Y_SIZE][NB_PROCS_MAX];
54
55#define MAX_RETRY   10000
56
57/////////////////////////////////////////////////////////////////////////
58// this array is allocated in the boot.c or kernel_init.c
59/////////////////////////////////////////////////////////////////////////
60
61extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
62
63/////////////////////////////////////////////////////////////////////////
64// These ISR_TYPE names for display must be consistent with values in
65// irq_handler.h / mapping.py / xml_driver.c
66/////////////////////////////////////////////////////////////////////////
67
68__attribute__((section(".kdata")))
69char* _isr_type_str[] = { "DEFAULT",
70                          "TICK"   ,
71                          "TTY_RX" ,
72                          "TTY_TX" ,
73                          "BDV"    ,
74                          "TIMER"  ,
75                          "WAKUP"  ,
76                          "NIC_RX" ,
77                          "NIC_TX" ,
78                          "CMA"    ,
79                          "MMC"    ,
80                          "DMA"    ,
81                          "SPI"    ,
82                          "MWR"    ,
83                          "HBA"    };
84
85__attribute__((section(".kdata")))
86char* _irq_type_str[] = { "HWI", 
87                          "WTI", 
88                          "PTI" }; 
89
90////////////////////
91void _ext_irq_init()
92{
93    mapping_header_t*    header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
94    mapping_cluster_t*   cluster = _get_cluster_base(header);
95    mapping_periph_t*    periph  = _get_periph_base(header);
96    mapping_irq_t*       irq     = _get_irq_base(header);
97    unsigned int         periph_id;   // peripheral index in mapping_info
98    unsigned int         irq_id;      // irq index in mapping_info
99
100    // get cluster_io index in mapping
101    unsigned int         x_io       = header->x_io; 
102    unsigned int         y_io       = header->y_io; 
103    unsigned int         cluster_io = (x_io * Y_SIZE) + y_io; 
104    mapping_periph_t*    pic        = NULL;
105
106    // scan external peripherals to find PIC
107    unsigned int min = cluster[cluster_io].periph_offset ;
108    unsigned int max = min + cluster[cluster_io].periphs ;
109   
110    for ( periph_id = min ; periph_id < max ; periph_id++ )
111    {
112        if ( periph[periph_id].type == PERIPH_TYPE_PIC ) 
113        {
114            pic = &periph[periph_id];
115            break;
116        }
117    } 
118
119    if ( pic == NULL )
120    {
121        _printf("\n[GIET ERROR] in _ext_irq_init() : No PIC component found\n");
122        _exit();
123    }
124
125    // scan PIC IRQS defined in mapping
126    for ( irq_id = pic->irq_offset ;
127          irq_id < pic->irq_offset + pic->irqs ;
128          irq_id++ )
129    {
130        unsigned int type    = irq[irq_id].srctype;
131        unsigned int srcid   = irq[irq_id].srcid;
132        unsigned int isr     = irq[irq_id].isr;
133        unsigned int channel = irq[irq_id].channel;
134
135        if ( (type != IRQ_TYPE_HWI)            || 
136             (srcid > 31)                      || 
137             (isr >= GIET_ISR_TYPE_MAX)        ||
138             (channel >= GIET_ISR_CHANNEL_MAX) )
139        {
140            _printf("\n[GIET ERROR] in _ext_irq_init() : Bad PIC IRQ\n"
141                    "  type = %d / srcid = %d / isr = %d / channel = %d\n",
142                    type , srcid , isr , channel );
143            _exit();
144        }
145        _ext_irq_index[isr][channel] = srcid;
146    }
147}  // end _ext_irq_init()
148
149/////////////////////////////////////////////
150void _ext_irq_alloc( unsigned int   isr_type,
151                     unsigned int   isr_channel,
152                     unsigned int*  wti_index )
153{
154#if USE_PIC
155    unsigned int wti_id;        // allocated WTI mailbox index in XCU
156    unsigned int irq_id;        // external IRQ index in PIC (input)
157    unsigned int wti_addr;      // WTI mailbox physical address (32 lsb bits)
158
159    unsigned int count = MAX_RETRY;
160
161    // check input arguments
162    if ( isr_type >= GIET_ISR_TYPE_MAX )
163    {
164        _printf("\n[GIET ERROR] in _ext_irq_alloc() : illegal ISR type\n");
165        _exit();
166    }
167    if ( isr_channel >= GIET_ISR_CHANNEL_MAX )
168    {
169        _printf("\n[GIET ERROR] in _ext_irq_alloc() : illegal ISR channel\n");
170        _exit();
171    }
172
173    // get processor coordinates [x,y,p]
174    unsigned int gpid           = _get_procid();
175    unsigned int cluster_xy     = gpid >> P_WIDTH;
176    unsigned int x              = cluster_xy >> Y_WIDTH;
177    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
178    unsigned int p              = gpid & ((1<<P_WIDTH)-1);
179
180    // allocate a WTI mailbox to proc[x,y,p] (blocking until success)
181   
182    while ( 1 )
183    {
184        if ( count == 0 )
185        {
186            unsigned int trdid = _get_context_slot( CTX_TRDID_ID );
187            unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
188            _printf("\n[GIET WARNING] thread %x in vspace %d "
189                    "running on P[%d,%d,%d] still waiting in _ext_irq_alloc()\n",
190                    trdid, vsid, x, y, p );
191            count = MAX_RETRY;
192        }
193
194        if ( _wti_alloc_one[x][y][p] == 0 )
195        {
196            _wti_alloc_one[x][y][p] = 1;
197            wti_id = p + NB_PROCS_MAX;
198            break;
199        }
200        if ( _wti_alloc_two[x][y][p] == 0 )
201        {
202            _wti_alloc_two[x][y][p] = 1;
203            wti_id = p + 2*NB_PROCS_MAX;
204            break;
205        }
206        if ( _wti_alloc_ter[x][y][p] == 0 )
207        {
208            _wti_alloc_ter[x][y][p] = 1;
209            wti_id = p + 3*NB_PROCS_MAX;
210            break;
211        }
212        count--;
213    }   
214
215    *wti_index = wti_id;
216
217    // register the mailbox physical address in IOPIC
218    irq_id   = _ext_irq_index[isr_type][isr_channel];
219    _xcu_get_wti_address( wti_id , &wti_addr );
220    _pic_init( irq_id , wti_addr, cluster_xy );
221   
222    // initializes the WTI interrupt vector entry for target XCU
223    static_scheduler_t*  psched = (static_scheduler_t*)_get_sched();
224    psched->wti_vector[wti_id] = isr_channel<<16 | isr_type;
225
226#if GIET_DEBUG_IRQS
227if ( _get_proctime() > GIET_DEBUG_IRQS )
228_printf("\n[DEBUG IRQS] _ext_irq_alloc() for P[%d,%d,%d] at cycle %d\n"
229        "  wti_id = %d / isr_type = %s / channel = %d / pic_input = %d\n",
230        x , y , p , _get_proctime() ,
231        wti_id , _isr_type_str[isr_type] , isr_channel , irq_id );
232#endif
233#endif // USE_PIC
234}  // end ext_irq_alloc()
235
236////////////////////////////////////////////////
237void _ext_irq_release( unsigned int isr_type,
238                       unsigned int channel )
239{
240    // check input arguments
241    if ( isr_type >= GIET_ISR_TYPE_MAX )
242    {
243        _printf("\n[GIET ERROR] in _ext_irq_release() : "
244                "illegal ISR type %d\n", isr_type );
245        _exit();
246    }
247    if ( channel >= GIET_ISR_CHANNEL_MAX )
248    {
249        _printf("\n[GIET ERROR] in _ext_irq_release() : "
250                "illegal ISR channel %d\n", channel );
251        _exit();
252    }
253
254    // analyse ISR type to get WTI index (wti), and coordinates
255    // of processor (x,y,p) that has been allocated the external IRQ
256    unsigned int wti    = 0;
257    unsigned int x      = 0;
258    unsigned int y      = 0;
259    unsigned int p      = 0;
260
261    if      ( (isr_type == ISR_TTY_RX) || (isr_type == ISR_TTY_TX) )
262    {
263        x       = (_tty_channel_wti[channel]>>24) & 0xFF;
264        y       = (_tty_channel_wti[channel]>>16) & 0xFF;
265        p       = (_tty_channel_wti[channel]>> 8) & 0xFF;
266        wti     = (_tty_channel_wti[channel]    ) & 0xFF;
267    }
268#if NB_TIM_CHANNELS
269    else if ( isr_type == ISR_TIMER )
270    {
271        x       = (_tim_channel_wti[channel]>>24) & 0xFF;
272        y       = (_tim_channel_wti[channel]>>16) & 0xFF;
273        p       = (_tim_channel_wti[channel]>> 8) & 0xFF;
274        wti     = (_tim_channel_wti[channel]    ) & 0xFF;
275    }
276#endif
277#if NB_CMA_CHANNELS
278    else if ( isr_type == ISR_CMA )
279    {
280        x       = (_cma_channel_wti[channel]>>24) & 0xFF;
281        y       = (_cma_channel_wti[channel]>>16) & 0xFF;
282        p       = (_cma_channel_wti[channel]>> 8) & 0xFF;
283        wti     = (_cma_channel_wti[channel]    ) & 0xFF;
284    }
285#endif
286#if NB_NIC_CHANNELS
287    else if ( isr_type == ISR_NIC_RX )
288    {
289        x       = (_nic_rx_channel_wti[channel]>>24) & 0xFF;
290        y       = (_nic_rx_channel_wti[channel]>>16) & 0xFF;
291        p       = (_nic_rx_channel_wti[channel]>> 8) & 0xFF;
292        wti     = (_nic_rx_channel_wti[channel]    ) & 0xFF;
293    }
294    else if ( isr_type == ISR_NIC_TX )
295    {
296        x       = (_nic_tx_channel_wti[channel]>>24) & 0xFF;
297        y       = (_nic_tx_channel_wti[channel]>>16) & 0xFF;
298        p       = (_nic_tx_channel_wti[channel]>> 8) & 0xFF;
299        wti     = (_nic_tx_channel_wti[channel]    ) & 0xFF;
300    }
301#endif
302    else 
303    {
304        _printf("\n[GIET ERROR] in _ext_irq_release() : "
305                "ISR type %s not supported / thread = %x\n", 
306                _isr_type_str[isr_type] , _get_thread_trdid() );
307        _exit();
308    }
309   
310    // desactivates dynamically allocated PIC entry
311    unsigned int irq_id = _ext_irq_index[isr_type][channel];
312    _pic_set_register( irq_id , IOPIC_MASK , 0 );
313
314    // releases dynamically allocated WTI mailbox
315    if      ( wti == p +   NB_PROCS_MAX ) _wti_alloc_one[x][y][p] = 0;
316    else if ( wti == p + 2*NB_PROCS_MAX ) _wti_alloc_two[x][y][p] = 0;
317    else if ( wti == p + 3*NB_PROCS_MAX ) _wti_alloc_ter[x][y][p] = 0;
318    else
319    {
320        _printf("\n[GIET ERROR] in _ext_irq_release() : "
321                "WTI = %d / X = %d / Y = %d / P = %d\n", wti , x, y , p );
322        _exit();
323    }
324}  // end ext_irq_release()
325
326/////////////////
327void _irq_demux() 
328{
329    unsigned int gpid           = _get_procid();
330    unsigned int cluster_xy     = gpid >> P_WIDTH;
331    unsigned int x              = cluster_xy >> Y_WIDTH;
332    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
333    unsigned int p              = gpid & ((1<<P_WIDTH)-1);
334    unsigned int irq_id;
335    unsigned int irq_type;
336
337    // get the highest priority active IRQ index
338    unsigned int icu_out_index = p * IRQ_PER_PROCESSOR;
339
340    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
341
342    if (irq_id < 32) 
343    {
344        static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
345        unsigned int        entry = 0;
346        unsigned int        isr_type;
347        unsigned int        channel;
348
349        if      (irq_type == IRQ_TYPE_HWI) entry = psched->hwi_vector[irq_id];
350        else if (irq_type == IRQ_TYPE_PTI) entry = psched->pti_vector[irq_id];
351        else if (irq_type == IRQ_TYPE_WTI) entry = psched->wti_vector[irq_id];
352        else
353        {
354            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
355            _exit();
356        }
357
358        isr_type   = (entry    ) & 0x0000FFFF;
359        channel    = (entry>>16) & 0x00007FFF;
360
361#if GIET_DEBUG_IRQS    // we don't take the TTY lock to avoid deadlocks
362if ( _get_proctime() > GIET_DEBUG_IRQS )
363_nolock_printf("\n[DEBUG IRQS] _irq_demux() Processor[%d,%d,%d] enters at cycle %d\n"
364               " irq_type = %s / irq_id = %d / isr_type = %s / channel = %d\n",
365               x , y , p , _get_proctime() ,
366               _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] , channel );   
367#endif
368
369        // ISR call
370        if      ( isr_type == ISR_TICK   ) _isr_tick   ( irq_type, irq_id, channel );
371        else if ( isr_type == ISR_TTY_RX ) _tty_rx_isr ( irq_type, irq_id, channel );
372        else if ( isr_type == ISR_TTY_TX ) _tty_tx_isr ( irq_type, irq_id, channel );
373        else if ( isr_type == ISR_BDV    ) _bdv_isr    ( irq_type, irq_id, channel );
374        else if ( isr_type == ISR_TIMER  ) _timer_isr  ( irq_type, irq_id, channel );
375        else if ( isr_type == ISR_WAKUP  ) _isr_wakup  ( irq_type, irq_id, channel );
376        else if ( isr_type == ISR_NIC_RX ) _nic_rx_isr ( irq_type, irq_id, channel );
377        else if ( isr_type == ISR_NIC_TX ) _nic_tx_isr ( irq_type, irq_id, channel );
378        else if ( isr_type == ISR_CMA    ) _cma_isr    ( irq_type, irq_id, channel );
379        else if ( isr_type == ISR_MMC    ) _mmc_isr    ( irq_type, irq_id, channel );
380        else if ( isr_type == ISR_DMA    ) _dma_isr    ( irq_type, irq_id, channel );
381        else if ( isr_type == ISR_SDC    ) _sdc_isr    ( irq_type, irq_id, channel );
382        else if ( isr_type == ISR_MWR    ) _mwr_isr    ( irq_type, irq_id, channel );
383        else if ( isr_type == ISR_HBA    ) _hba_isr    ( irq_type, irq_id, channel );
384        else
385        {
386            _printf("\n[GIET ERROR] in _irq_demux() :"
387                    " illegal ISR type on processor[%d,%d,%d] at cycle %d\n"
388                    " - irq_type = %s\n"
389                    " - irq_id   = %d\n"
390                    " - isr_type = %s\n",
391                    x, y, p, _get_proctime(), 
392                    _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] );   
393            _exit();
394        }
395    }
396    else   // no interrupt active
397    {
398        _isr_default();
399    } 
400}
401
402///////////////////
403void _isr_default()
404{
405    unsigned int gpid       = _get_procid();
406    unsigned int cluster_xy = gpid >> P_WIDTH;
407    unsigned int x          = cluster_xy >> Y_WIDTH;
408    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
409    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
410
411    _printf("\n[GIET WARNING] IRQ handler called but no active IRQ "
412            "on processor[%d,%d,%d] at cycle %d\n",
413            x, y, p, _get_proctime() );
414}
415
416
417////////////////////////////////////////////////////////////
418void _isr_wakup( unsigned int irq_type,   // HWI / WTI / PTI
419                 unsigned int irq_id,     // index returned by ICU
420                 unsigned int channel )   // unused
421{
422    unsigned int gpid       = _get_procid();
423    unsigned int cluster_xy = gpid >> P_WIDTH;
424    unsigned int x          = cluster_xy >> Y_WIDTH;
425    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
426    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
427
428    unsigned int value;     // WTI mailbox value
429    unsigned int save_sr;   // save SR value in pre-empted thread stack
430
431    unsigned int ltid       = _get_thread_ltid();
432
433    if ( irq_type != IRQ_TYPE_WTI )
434    {
435        _printf("[GIET ERROR] P[%d,%d,%d] enters _isr_wakup() at cycle %d\n"
436                " but not called by a WTI interrupt\n",
437                x , y , p , _get_proctime() );
438        _exit();
439    }
440
441    // get mailbox value and acknowledge WTI
442    _xcu_get_wti_value( cluster_xy, irq_id, &value );
443
444#if GIET_DEBUG_IRQS
445if ( _get_proctime() > GIET_DEBUG_IRQS )
446_printf("\n[DEBUG IRQS] P[%d,%d,%d] enters _isr_wakup() at cycle %d\n"
447        "  WTI index = %d / current ltid = %d / mailbox value = %x\n",
448        x , y , p , _get_proctime() , irq_id , ltid , value );
449#endif
450
451    // enter critical section and swich context (if required)
452    if ( (ltid == IDLE_THREAD_INDEX) || (value != 0) )
453    {
454        _it_disable( &save_sr );
455        _ctx_switch();
456        _it_restore( &save_sr );
457    }
458
459} // end _isr_wakup
460
461///////////////////////////////////////////////////////////
462void _isr_tick( unsigned int irq_type,   // HWI / WTI / PTI
463                unsigned int irq_id,     // index returned by ICU
464                unsigned int channel )   // channel index if HWI
465{
466    unsigned int gpid       = _get_procid();
467    unsigned int cluster_xy = gpid >> P_WIDTH;
468    unsigned int x          = cluster_xy >> Y_WIDTH;
469    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
470    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
471
472    unsigned int save_sr;   // save SR value in pre-empted thread stack
473
474    if ( irq_type != IRQ_TYPE_PTI )
475    {
476        _printf("[GIET ERROR] P[%d,%d,%d] enters _isr_tick() at cycle %d\n"
477                " but not called by a PTI interrupt\n",
478                x , y , p , _get_proctime() );
479        _exit();
480    }
481
482    // acknowledge PTI
483    _xcu_timer_reset_irq( cluster_xy, irq_id );
484
485#if GIET_DEBUG_IRQS
486unsigned int ltid  = _get_thread_ltid();
487if ( _get_proctime() > GIET_DEBUG_IRQS )
488_printf("\n[DEBUG IRQS] P[%d,%d,%d] enters _isr_tick() at cycle %d\n"
489        "  WTI index = %d / current ltid = %d\n",
490        x , y , p , _get_proctime() , irq_id , ltid );
491#endif
492
493    // enter critical section and switch context
494    _it_disable( &save_sr );
495    _ctx_switch();
496    _it_restore( &save_sr );
497
498}  // end _isr_tick
499
500
501// Local Variables:
502// tab-width: 4
503// c-basic-offset: 4
504// c-file-offsets:((innamespace . 0)(inline-open . 0))
505// indent-tabs-mode: nil
506// End:
507// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
508
Note: See TracBrowser for help on using the repository browser.