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

Last change on this file since 776 was 709, checked in by alain, 9 years ago

Major release: Change the task model to implement the POSIX threads API.

  • The shell "exec" and "kill" commands can be used to activate/de-activate the applications.
  • The "pause", "resume", and "context" commands can be used to stop, restart, a single thtead or to display the thread context.

This version has been tested on the following multi-threaded applications,
that have been modified to use the POSIX threads:

  • classif
  • convol
  • transpose
  • gameoflife
  • raycast
  • Property svn:executable set to *
File size: 17.9 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    unsigned int wti_id;        // allocated WTI mailbox index in XCU
155    unsigned int irq_id;        // external IRQ index in PIC (input)
156    unsigned int wti_addr;      // WTI mailbox physical address (32 lsb bits)
157
158    unsigned int count = MAX_RETRY;
159
160    // check input arguments
161    if ( isr_type >= GIET_ISR_TYPE_MAX )
162    {
163        _printf("\n[GIET ERROR] in _ext_irq_alloc() : illegal ISR type\n");
164        _exit();
165    }
166    if ( isr_channel >= GIET_ISR_CHANNEL_MAX )
167    {
168        _printf("\n[GIET ERROR] in _ext_irq_alloc() : illegal ISR channel\n");
169        _exit();
170    }
171
172    // get processor coordinates [x,y,p]
173    unsigned int gpid           = _get_procid();
174    unsigned int cluster_xy     = gpid >> P_WIDTH;
175    unsigned int x              = cluster_xy >> Y_WIDTH;
176    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
177    unsigned int p              = gpid & ((1<<P_WIDTH)-1);
178
179    // allocate a WTI mailbox to proc[x,y,p] (blocking until success)
180   
181    while ( 1 )
182    {
183        if ( count == 0 )
184        {
185            unsigned int trdid = _get_context_slot( CTX_TRDID_ID );
186            unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
187            _printf("\n[GIET WARNING] thread %x in vspace %d "
188                    "running on P[%d,%d,%d] still waiting in _ext_irq_alloc()\n",
189                    trdid, vsid, x, y, p );
190            count = MAX_RETRY;
191        }
192
193        if ( _wti_alloc_one[x][y][p] == 0 )
194        {
195            _wti_alloc_one[x][y][p] = 1;
196            wti_id = p + NB_PROCS_MAX;
197            break;
198        }
199        if ( _wti_alloc_two[x][y][p] == 0 )
200        {
201            _wti_alloc_two[x][y][p] = 1;
202            wti_id = p + 2*NB_PROCS_MAX;
203            break;
204        }
205        if ( _wti_alloc_ter[x][y][p] == 0 )
206        {
207            _wti_alloc_ter[x][y][p] = 1;
208            wti_id = p + 3*NB_PROCS_MAX;
209            break;
210        }
211        count--;
212    }   
213
214    *wti_index = wti_id;
215
216    // register the mailbox physical address in IOPIC
217    irq_id   = _ext_irq_index[isr_type][isr_channel];
218    _xcu_get_wti_address( wti_id , &wti_addr );
219    _pic_init( irq_id , wti_addr, cluster_xy );
220   
221    // initializes the WTI interrupt vector entry for target XCU
222    static_scheduler_t*  psched = (static_scheduler_t*)_get_sched();
223    psched->wti_vector[wti_id] = isr_channel<<16 | isr_type;
224
225#if GIET_DEBUG_IRQS
226if ( _get_proctime() > GIET_DEBUG_IRQS )
227_printf("\n[DEBUG IRQS] _ext_irq_alloc() for P[%d,%d,%d] at cycle %d\n"
228        "  wti_id = %d / isr_type = %s / channel = %d / pic_input = %d\n",
229        x , y , p , _get_proctime() ,
230        wti_id , _isr_type_str[isr_type] , isr_channel , irq_id );
231#endif
232
233}  // end ext_irq_alloc()
234
235////////////////////////////////////////////////
236void _ext_irq_release( unsigned int isr_type,
237                       unsigned int channel )
238{
239    // check input arguments
240    if ( isr_type >= GIET_ISR_TYPE_MAX )
241    {
242        _printf("\n[GIET ERROR] in _ext_irq_release() : "
243                "illegal ISR type %d\n", isr_type );
244        _exit();
245    }
246    if ( channel >= GIET_ISR_CHANNEL_MAX )
247    {
248        _printf("\n[GIET ERROR] in _ext_irq_release() : "
249                "illegal ISR channel %d\n", channel );
250        _exit();
251    }
252
253    // analyse ISR type to get WTI index (wti), and coordinates
254    // of processor (x,y,p) that has been allocated the external IRQ
255    unsigned int wti    = 0;
256    unsigned int x      = 0;
257    unsigned int y      = 0;
258    unsigned int p      = 0;
259
260    if      ( (isr_type == ISR_TTY_RX) || (isr_type == ISR_TTY_TX) )
261    {
262        x       = (_tty_channel_wti[channel]>>24) & 0xFF;
263        y       = (_tty_channel_wti[channel]>>16) & 0xFF;
264        p       = (_tty_channel_wti[channel]>> 8) & 0xFF;
265        wti     = (_tty_channel_wti[channel]    ) & 0xFF;
266    }
267#if NB_TIM_CHANNELS
268    else if ( isr_type == ISR_TIMER )
269    {
270        x       = (_tim_channel_wti[channel]>>24) & 0xFF;
271        y       = (_tim_channel_wti[channel]>>16) & 0xFF;
272        p       = (_tim_channel_wti[channel]>> 8) & 0xFF;
273        wti     = (_tim_channel_wti[channel]    ) & 0xFF;
274    }
275#endif
276#if NB_CMA_CHANNELS
277    else if ( isr_type == ISR_CMA )
278    {
279        x       = (_cma_channel_wti[channel]>>24) & 0xFF;
280        y       = (_cma_channel_wti[channel]>>16) & 0xFF;
281        p       = (_cma_channel_wti[channel]>> 8) & 0xFF;
282        wti     = (_cma_channel_wti[channel]    ) & 0xFF;
283    }
284#endif
285#if NB_NIC_CHANNELS
286    else if ( isr_type == ISR_NIC_RX )
287    {
288        x       = (_nic_rx_channel_wti[channel]>>24) & 0xFF;
289        y       = (_nic_rx_channel_wti[channel]>>16) & 0xFF;
290        p       = (_nic_rx_channel_wti[channel]>> 8) & 0xFF;
291        wti     = (_nic_rx_channel_wti[channel]    ) & 0xFF;
292    }
293    else if ( isr_type == ISR_NIC_TX )
294    {
295        x       = (_nic_tx_channel_wti[channel]>>24) & 0xFF;
296        y       = (_nic_tx_channel_wti[channel]>>16) & 0xFF;
297        p       = (_nic_tx_channel_wti[channel]>> 8) & 0xFF;
298        wti     = (_nic_tx_channel_wti[channel]    ) & 0xFF;
299    }
300#endif
301    else 
302    {
303        _printf("\n[GIET ERROR] in _ext_irq_release() : "
304                "ISR type %s not supported / thread = %x\n", 
305                _isr_type_str[isr_type] , _get_thread_trdid() );
306        _exit();
307    }
308   
309    // desactivates dynamically allocated PIC entry
310    unsigned int irq_id = _ext_irq_index[isr_type][channel];
311    _pic_set_register( irq_id , IOPIC_MASK , 0 );
312
313    // releases dynamically allocated WTI mailbox
314    if      ( wti == p +   NB_PROCS_MAX ) _wti_alloc_one[x][y][p] = 0;
315    else if ( wti == p + 2*NB_PROCS_MAX ) _wti_alloc_two[x][y][p] = 0;
316    else if ( wti == p + 3*NB_PROCS_MAX ) _wti_alloc_ter[x][y][p] = 0;
317    else
318    {
319        _printf("\n[GIET ERROR] in _ext_irq_release() : "
320                "WTI = %d / X = %d / Y = %d / P = %d\n", wti , x, y , p );
321        _exit();
322    }
323}  // end ext_irq_release()
324
325/////////////////
326void _irq_demux() 
327{
328    unsigned int gpid           = _get_procid();
329    unsigned int cluster_xy     = gpid >> P_WIDTH;
330    unsigned int x              = cluster_xy >> Y_WIDTH;
331    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
332    unsigned int p              = gpid & ((1<<P_WIDTH)-1);
333    unsigned int irq_id;
334    unsigned int irq_type;
335
336    // get the highest priority active IRQ index
337    unsigned int icu_out_index = p * IRQ_PER_PROCESSOR;
338
339    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
340
341    if (irq_id < 32) 
342    {
343        static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
344        unsigned int        entry = 0;
345        unsigned int        isr_type;
346        unsigned int        channel;
347
348        if      (irq_type == IRQ_TYPE_HWI) entry = psched->hwi_vector[irq_id];
349        else if (irq_type == IRQ_TYPE_PTI) entry = psched->pti_vector[irq_id];
350        else if (irq_type == IRQ_TYPE_WTI) entry = psched->wti_vector[irq_id];
351        else
352        {
353            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
354            _exit();
355        }
356
357        isr_type   = (entry    ) & 0x0000FFFF;
358        channel    = (entry>>16) & 0x00007FFF;
359
360#if GIET_DEBUG_IRQS    // we don't take the TTY lock to avoid deadlocks
361if ( _get_proctime() > GIET_DEBUG_IRQS )
362_nolock_printf("\n[DEBUG IRQS] _irq_demux() Processor[%d,%d,%d] enters at cycle %d\n"
363               " irq_type = %s / irq_id = %d / isr_type = %s / channel = %d\n",
364               x , y , p , _get_proctime() ,
365               _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] , channel );   
366#endif
367
368        // ISR call
369        if      ( isr_type == ISR_TICK   ) _isr_tick   ( irq_type, irq_id, channel );
370        else if ( isr_type == ISR_TTY_RX ) _tty_rx_isr ( irq_type, irq_id, channel );
371        else if ( isr_type == ISR_TTY_TX ) _tty_tx_isr ( irq_type, irq_id, channel );
372        else if ( isr_type == ISR_BDV    ) _bdv_isr    ( irq_type, irq_id, channel );
373        else if ( isr_type == ISR_TIMER  ) _timer_isr  ( irq_type, irq_id, channel );
374        else if ( isr_type == ISR_WAKUP  ) _isr_wakup  ( irq_type, irq_id, channel );
375        else if ( isr_type == ISR_NIC_RX ) _nic_rx_isr ( irq_type, irq_id, channel );
376        else if ( isr_type == ISR_NIC_TX ) _nic_tx_isr ( irq_type, irq_id, channel );
377        else if ( isr_type == ISR_CMA    ) _cma_isr    ( irq_type, irq_id, channel );
378        else if ( isr_type == ISR_MMC    ) _mmc_isr    ( irq_type, irq_id, channel );
379        else if ( isr_type == ISR_DMA    ) _dma_isr    ( irq_type, irq_id, channel );
380        else if ( isr_type == ISR_SDC    ) _sdc_isr    ( irq_type, irq_id, channel );
381        else if ( isr_type == ISR_MWR    ) _mwr_isr    ( irq_type, irq_id, channel );
382        else if ( isr_type == ISR_HBA    ) _hba_isr    ( irq_type, irq_id, channel );
383        else
384        {
385            _printf("\n[GIET ERROR] in _irq_demux() :"
386                    " illegal ISR type on processor[%d,%d,%d] at cycle %d\n"
387                    " - irq_type = %s\n"
388                    " - irq_id   = %d\n"
389                    " - isr_type = %s\n",
390                    x, y, p, _get_proctime(), 
391                    _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] );   
392            _exit();
393        }
394    }
395    else   // no interrupt active
396    {
397        _isr_default();
398    } 
399}
400
401///////////////////
402void _isr_default()
403{
404    unsigned int gpid       = _get_procid();
405    unsigned int cluster_xy = gpid >> P_WIDTH;
406    unsigned int x          = cluster_xy >> Y_WIDTH;
407    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
408    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
409
410    _printf("\n[GIET WARNING] IRQ handler called but no active IRQ "
411            "on processor[%d,%d,%d] at cycle %d\n",
412            x, y, p, _get_proctime() );
413}
414
415
416////////////////////////////////////////////////////////////
417void _isr_wakup( unsigned int irq_type,   // HWI / WTI / PTI
418                 unsigned int irq_id,     // index returned by ICU
419                 unsigned int channel )   // unused
420{
421    unsigned int gpid       = _get_procid();
422    unsigned int cluster_xy = gpid >> P_WIDTH;
423    unsigned int x          = cluster_xy >> Y_WIDTH;
424    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
425    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
426
427    unsigned int value;     // WTI mailbox value
428    unsigned int save_sr;   // save SR value in pre-empted thread stack
429
430    unsigned int ltid       = _get_thread_ltid();
431
432    if ( irq_type != IRQ_TYPE_WTI )
433    {
434        _printf("[GIET ERROR] P[%d,%d,%d] enters _isr_wakup() at cycle %d\n"
435                " but not called by a WTI interrupt\n",
436                x , y , p , _get_proctime() );
437        _exit();
438    }
439
440    // get mailbox value and acknowledge WTI
441    _xcu_get_wti_value( cluster_xy, irq_id, &value );
442
443#if GIET_DEBUG_IRQS
444if ( _get_proctime() > GIET_DEBUG_IRQS )
445_printf("\n[DEBUG IRQS] P[%d,%d,%d] enters _isr_wakup() at cycle %d\n"
446        "  WTI index = %d / current ltid = %d / mailbox value = %x\n",
447        x , y , p , _get_proctime() , irq_id , ltid , value );
448#endif
449
450    // enter critical section and swich context (if required)
451    if ( (ltid == IDLE_THREAD_INDEX) || (value != 0) )
452    {
453        _it_disable( &save_sr );
454        _ctx_switch();
455        _it_restore( &save_sr );
456    }
457
458} // end _isr_wakup
459
460///////////////////////////////////////////////////////////
461void _isr_tick( unsigned int irq_type,   // HWI / WTI / PTI
462                unsigned int irq_id,     // index returned by ICU
463                unsigned int channel )   // channel index if HWI
464{
465    unsigned int gpid       = _get_procid();
466    unsigned int cluster_xy = gpid >> P_WIDTH;
467    unsigned int x          = cluster_xy >> Y_WIDTH;
468    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
469    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
470
471    unsigned int save_sr;   // save SR value in pre-empted thread stack
472
473    if ( irq_type != IRQ_TYPE_PTI )
474    {
475        _printf("[GIET ERROR] P[%d,%d,%d] enters _isr_tick() at cycle %d\n"
476                " but not called by a PTI interrupt\n",
477                x , y , p , _get_proctime() );
478        _exit();
479    }
480
481    // acknowledge PTI
482    _xcu_timer_reset_irq( cluster_xy, irq_id );
483
484#if GIET_DEBUG_IRQS
485unsigned int ltid  = _get_thread_ltid();
486if ( _get_proctime() > GIET_DEBUG_IRQS )
487_printf("\n[DEBUG IRQS] P[%d,%d,%d] enters _isr_tick() at cycle %d\n"
488        "  WTI index = %d / current ltid = %d\n",
489        x , y , p , _get_proctime() , irq_id , ltid );
490#endif
491
492    // enter critical section and switch context
493    _it_disable( &save_sr );
494    _ctx_switch();
495    _it_restore( &save_sr );
496
497}  // end _isr_tick
498
499
500// Local Variables:
501// tab-width: 4
502// c-basic-offset: 4
503// c-file-offsets:((innamespace . 0)(inline-open . 0))
504// indent-tabs-mode: nil
505// End:
506// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
507
Note: See TracBrowser for help on using the repository browser.