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

Last change on this file since 812 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
RevLine 
[528]1///////////////////////////////////////////////////////////////////////////
[258]2// File     : irq_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
[528]6///////////////////////////////////////////////////////////////////////////
[258]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>
[528]14#include <pic_driver.h>
[258]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>
[547]20#include <hba_driver.h>
[258]21#include <dma_driver.h>
[547]22#include <sdc_driver.h>
[528]23#include <mwr_driver.h>
[281]24#include <mapping_info.h>
[258]25#include <utils.h>
[459]26#include <tty0.h>
[258]27
[709]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
[528]39/////////////////////////////////////////////////////////////////////////
40//       Global variables
41/////////////////////////////////////////////////////////////////////////
[258]42
[528]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
[709]55#define MAX_RETRY   10000
56
[519]57/////////////////////////////////////////////////////////////////////////
[528]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/////////////////////////////////////////////////////////////////////////
[519]64// These ISR_TYPE names for display must be consistent with values in
65// irq_handler.h / mapping.py / xml_driver.c
66/////////////////////////////////////////////////////////////////////////
[547]67
[494]68__attribute__((section(".kdata")))
[547]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"    };
[528]84
[547]85__attribute__((section(".kdata")))
86char* _irq_type_str[] = { "HWI", 
87                          "WTI", 
88                          "PTI" }; 
89
[528]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
[547]106    // scan external peripherals to find PIC
[528]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
[709]149/////////////////////////////////////////////
[528]150void _ext_irq_alloc( unsigned int   isr_type,
151                     unsigned int   isr_channel,
152                     unsigned int*  wti_index )
153{
[811]154#if USE_PIC
[528]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
[709]159    unsigned int count = MAX_RETRY;
160
161    // check input arguments
[528]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)
[709]181   
[528]182    while ( 1 )
183    {
[709]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
[528]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        }
[709]212        count--;
[528]213    }   
[709]214
[528]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   
[547]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;
[528]225
[547]226#if GIET_DEBUG_IRQS
[709]227if ( _get_proctime() > GIET_DEBUG_IRQS )
[547]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
[811]233#endif // USE_PIC
[528]234}  // end ext_irq_alloc()
235
[709]236////////////////////////////////////////////////
[528]237void _ext_irq_release( unsigned int isr_type,
[709]238                       unsigned int channel )
[528]239{
[709]240    // check input arguments
[528]241    if ( isr_type >= GIET_ISR_TYPE_MAX )
242    {
[709]243        _printf("\n[GIET ERROR] in _ext_irq_release() : "
244                "illegal ISR type %d\n", isr_type );
[528]245        _exit();
246    }
[709]247    if ( channel >= GIET_ISR_CHANNEL_MAX )
[528]248    {
[709]249        _printf("\n[GIET ERROR] in _ext_irq_release() : "
250                "illegal ISR channel %d\n", channel );
[528]251        _exit();
252    }
253
[709]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) )
[697]262    {
[709]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;
[697]267    }
[709]268#if NB_TIM_CHANNELS
269    else if ( isr_type == ISR_TIMER )
[697]270    {
[709]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;
[697]275    }
[709]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   
[528]310    // desactivates dynamically allocated PIC entry
[709]311    unsigned int irq_id = _ext_irq_index[isr_type][channel];
[528]312    _pic_set_register( irq_id , IOPIC_MASK , 0 );
313
314    // releases dynamically allocated WTI mailbox
[709]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;
[528]318    else
319    {
[709]320        _printf("\n[GIET ERROR] in _ext_irq_release() : "
321                "WTI = %d / X = %d / Y = %d / P = %d\n", wti , x, y , p );
[528]322        _exit();
323    }
324}  // end ext_irq_release()
325
[440]326/////////////////
[258]327void _irq_demux() 
328{
[294]329    unsigned int gpid           = _get_procid();
[428]330    unsigned int cluster_xy     = gpid >> P_WIDTH;
[294]331    unsigned int x              = cluster_xy >> Y_WIDTH;
332    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
[648]333    unsigned int p              = gpid & ((1<<P_WIDTH)-1);
[258]334    unsigned int irq_id;
[294]335    unsigned int irq_type;
[258]336
337    // get the highest priority active IRQ index
[648]338    unsigned int icu_out_index = p * IRQ_PER_PROCESSOR;
[258]339
[294]340    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
[258]341
342    if (irq_id < 32) 
343    {
[294]344        static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
[346]345        unsigned int        entry = 0;
[294]346        unsigned int        isr_type;
347        unsigned int        channel;
[258]348
[294]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
[258]353        {
[294]354            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
355            _exit();
[258]356        }
[294]357
358        isr_type   = (entry    ) & 0x0000FFFF;
359        channel    = (entry>>16) & 0x00007FFF;
360
[547]361#if GIET_DEBUG_IRQS    // we don't take the TTY lock to avoid deadlocks
[709]362if ( _get_proctime() > GIET_DEBUG_IRQS )
[547]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",
[648]365               x , y , p , _get_proctime() ,
[547]366               _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] , channel );   
[294]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 );
[547]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 );
[294]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 );
[547]378        else if ( isr_type == ISR_CMA    ) _cma_isr    ( irq_type, irq_id, channel );
[297]379        else if ( isr_type == ISR_MMC    ) _mmc_isr    ( irq_type, irq_id, channel );
[322]380        else if ( isr_type == ISR_DMA    ) _dma_isr    ( irq_type, irq_id, channel );
[547]381        else if ( isr_type == ISR_SDC    ) _sdc_isr    ( irq_type, irq_id, channel );
[519]382        else if ( isr_type == ISR_MWR    ) _mwr_isr    ( irq_type, irq_id, channel );
[547]383        else if ( isr_type == ISR_HBA    ) _hba_isr    ( irq_type, irq_id, channel );
[294]384        else
[258]385        {
[310]386            _printf("\n[GIET ERROR] in _irq_demux() :"
387                    " illegal ISR type on processor[%d,%d,%d] at cycle %d\n"
[547]388                    " - irq_type = %s\n"
[310]389                    " - irq_id   = %d\n"
[547]390                    " - isr_type = %s\n",
[648]391                    x, y, p, _get_proctime(), 
[547]392                    _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] );   
393            _exit();
[258]394        }
395    }
[294]396    else   // no interrupt active
397    {
398        _isr_default();
399    } 
[258]400}
401
[440]402///////////////////
[294]403void _isr_default()
[258]404{
[294]405    unsigned int gpid       = _get_procid();
[428]406    unsigned int cluster_xy = gpid >> P_WIDTH;
[294]407    unsigned int x          = cluster_xy >> Y_WIDTH;
408    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[648]409    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[258]410
[322]411    _printf("\n[GIET WARNING] IRQ handler called but no active IRQ "
412            "on processor[%d,%d,%d] at cycle %d\n",
[648]413            x, y, p, _get_proctime() );
[258]414}
415
416
[440]417////////////////////////////////////////////////////////////
[294]418void _isr_wakup( unsigned int irq_type,   // HWI / WTI / PTI
419                 unsigned int irq_id,     // index returned by ICU
420                 unsigned int channel )   // unused
[258]421{
[428]422    unsigned int gpid       = _get_procid();
423    unsigned int cluster_xy = gpid >> P_WIDTH;
[294]424    unsigned int x          = cluster_xy >> Y_WIDTH;
425    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[528]426    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[428]427
[528]428    unsigned int value;     // WTI mailbox value
[709]429    unsigned int save_sr;   // save SR value in pre-empted thread stack
[258]430
[709]431    unsigned int ltid       = _get_thread_ltid();
[528]432
[294]433    if ( irq_type != IRQ_TYPE_WTI )
[258]434    {
[528]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() );
[294]438        _exit();
[258]439    }
440
[294]441    // get mailbox value and acknowledge WTI
442    _xcu_get_wti_value( cluster_xy, irq_id, &value );
443
[709]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"
[528]447        "  WTI index = %d / current ltid = %d / mailbox value = %x\n",
448        x , y , p , _get_proctime() , irq_id , ltid , value );
[258]449#endif
450
[528]451    // enter critical section and swich context (if required)
[709]452    if ( (ltid == IDLE_THREAD_INDEX) || (value != 0) )
[528]453    {
454        _it_disable( &save_sr );
455        _ctx_switch();
456        _it_restore( &save_sr );
457    }
458
[440]459} // end _isr_wakup
[258]460
[440]461///////////////////////////////////////////////////////////
[294]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
[258]465{
[428]466    unsigned int gpid       = _get_procid();
467    unsigned int cluster_xy = gpid >> P_WIDTH;
[440]468    unsigned int x          = cluster_xy >> Y_WIDTH;
469    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[528]470    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[258]471
[709]472    unsigned int save_sr;   // save SR value in pre-empted thread stack
[528]473
[440]474    if ( irq_type != IRQ_TYPE_PTI )
475    {
[528]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() );
[440]479        _exit();
480    }
[258]481
[440]482    // acknowledge PTI
483    _xcu_timer_reset_irq( cluster_xy, irq_id );
484
[709]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"
[528]489        "  WTI index = %d / current ltid = %d\n",
490        x , y , p , _get_proctime() , irq_id , ltid );
[258]491#endif
492
[528]493    // enter critical section and switch context
494    _it_disable( &save_sr );
[258]495    _ctx_switch();
[528]496    _it_restore( &save_sr );
497
[440]498}  // end _isr_tick
[258]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.