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

Last change on this file since 720 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
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{
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
[709]158    unsigned int count = MAX_RETRY;
159
160    // check input arguments
[528]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)
[709]180   
[528]181    while ( 1 )
182    {
[709]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
[528]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        }
[709]211        count--;
[528]212    }   
[709]213
[528]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   
[547]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;
[528]224
[547]225#if GIET_DEBUG_IRQS
[709]226if ( _get_proctime() > GIET_DEBUG_IRQS )
[547]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
[528]233}  // end ext_irq_alloc()
234
[709]235////////////////////////////////////////////////
[528]236void _ext_irq_release( unsigned int isr_type,
[709]237                       unsigned int channel )
[528]238{
[709]239    // check input arguments
[528]240    if ( isr_type >= GIET_ISR_TYPE_MAX )
241    {
[709]242        _printf("\n[GIET ERROR] in _ext_irq_release() : "
243                "illegal ISR type %d\n", isr_type );
[528]244        _exit();
245    }
[709]246    if ( channel >= GIET_ISR_CHANNEL_MAX )
[528]247    {
[709]248        _printf("\n[GIET ERROR] in _ext_irq_release() : "
249                "illegal ISR channel %d\n", channel );
[528]250        _exit();
251    }
252
[709]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) )
[697]261    {
[709]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;
[697]266    }
[709]267#if NB_TIM_CHANNELS
268    else if ( isr_type == ISR_TIMER )
[697]269    {
[709]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;
[697]274    }
[709]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   
[528]309    // desactivates dynamically allocated PIC entry
[709]310    unsigned int irq_id = _ext_irq_index[isr_type][channel];
[528]311    _pic_set_register( irq_id , IOPIC_MASK , 0 );
312
313    // releases dynamically allocated WTI mailbox
[709]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;
[528]317    else
318    {
[709]319        _printf("\n[GIET ERROR] in _ext_irq_release() : "
320                "WTI = %d / X = %d / Y = %d / P = %d\n", wti , x, y , p );
[528]321        _exit();
322    }
323}  // end ext_irq_release()
324
[440]325/////////////////
[258]326void _irq_demux() 
327{
[294]328    unsigned int gpid           = _get_procid();
[428]329    unsigned int cluster_xy     = gpid >> P_WIDTH;
[294]330    unsigned int x              = cluster_xy >> Y_WIDTH;
331    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
[648]332    unsigned int p              = gpid & ((1<<P_WIDTH)-1);
[258]333    unsigned int irq_id;
[294]334    unsigned int irq_type;
[258]335
336    // get the highest priority active IRQ index
[648]337    unsigned int icu_out_index = p * IRQ_PER_PROCESSOR;
[258]338
[294]339    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
[258]340
341    if (irq_id < 32) 
342    {
[294]343        static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
[346]344        unsigned int        entry = 0;
[294]345        unsigned int        isr_type;
346        unsigned int        channel;
[258]347
[294]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
[258]352        {
[294]353            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
354            _exit();
[258]355        }
[294]356
357        isr_type   = (entry    ) & 0x0000FFFF;
358        channel    = (entry>>16) & 0x00007FFF;
359
[547]360#if GIET_DEBUG_IRQS    // we don't take the TTY lock to avoid deadlocks
[709]361if ( _get_proctime() > GIET_DEBUG_IRQS )
[547]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",
[648]364               x , y , p , _get_proctime() ,
[547]365               _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] , channel );   
[294]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 );
[547]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 );
[294]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 );
[547]377        else if ( isr_type == ISR_CMA    ) _cma_isr    ( irq_type, irq_id, channel );
[297]378        else if ( isr_type == ISR_MMC    ) _mmc_isr    ( irq_type, irq_id, channel );
[322]379        else if ( isr_type == ISR_DMA    ) _dma_isr    ( irq_type, irq_id, channel );
[547]380        else if ( isr_type == ISR_SDC    ) _sdc_isr    ( irq_type, irq_id, channel );
[519]381        else if ( isr_type == ISR_MWR    ) _mwr_isr    ( irq_type, irq_id, channel );
[547]382        else if ( isr_type == ISR_HBA    ) _hba_isr    ( irq_type, irq_id, channel );
[294]383        else
[258]384        {
[310]385            _printf("\n[GIET ERROR] in _irq_demux() :"
386                    " illegal ISR type on processor[%d,%d,%d] at cycle %d\n"
[547]387                    " - irq_type = %s\n"
[310]388                    " - irq_id   = %d\n"
[547]389                    " - isr_type = %s\n",
[648]390                    x, y, p, _get_proctime(), 
[547]391                    _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] );   
392            _exit();
[258]393        }
394    }
[294]395    else   // no interrupt active
396    {
397        _isr_default();
398    } 
[258]399}
400
[440]401///////////////////
[294]402void _isr_default()
[258]403{
[294]404    unsigned int gpid       = _get_procid();
[428]405    unsigned int cluster_xy = gpid >> P_WIDTH;
[294]406    unsigned int x          = cluster_xy >> Y_WIDTH;
407    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[648]408    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[258]409
[322]410    _printf("\n[GIET WARNING] IRQ handler called but no active IRQ "
411            "on processor[%d,%d,%d] at cycle %d\n",
[648]412            x, y, p, _get_proctime() );
[258]413}
414
415
[440]416////////////////////////////////////////////////////////////
[294]417void _isr_wakup( unsigned int irq_type,   // HWI / WTI / PTI
418                 unsigned int irq_id,     // index returned by ICU
419                 unsigned int channel )   // unused
[258]420{
[428]421    unsigned int gpid       = _get_procid();
422    unsigned int cluster_xy = gpid >> P_WIDTH;
[294]423    unsigned int x          = cluster_xy >> Y_WIDTH;
424    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[528]425    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[428]426
[528]427    unsigned int value;     // WTI mailbox value
[709]428    unsigned int save_sr;   // save SR value in pre-empted thread stack
[258]429
[709]430    unsigned int ltid       = _get_thread_ltid();
[528]431
[294]432    if ( irq_type != IRQ_TYPE_WTI )
[258]433    {
[528]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() );
[294]437        _exit();
[258]438    }
439
[294]440    // get mailbox value and acknowledge WTI
441    _xcu_get_wti_value( cluster_xy, irq_id, &value );
442
[709]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"
[528]446        "  WTI index = %d / current ltid = %d / mailbox value = %x\n",
447        x , y , p , _get_proctime() , irq_id , ltid , value );
[258]448#endif
449
[528]450    // enter critical section and swich context (if required)
[709]451    if ( (ltid == IDLE_THREAD_INDEX) || (value != 0) )
[528]452    {
453        _it_disable( &save_sr );
454        _ctx_switch();
455        _it_restore( &save_sr );
456    }
457
[440]458} // end _isr_wakup
[258]459
[440]460///////////////////////////////////////////////////////////
[294]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
[258]464{
[428]465    unsigned int gpid       = _get_procid();
466    unsigned int cluster_xy = gpid >> P_WIDTH;
[440]467    unsigned int x          = cluster_xy >> Y_WIDTH;
468    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[528]469    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[258]470
[709]471    unsigned int save_sr;   // save SR value in pre-empted thread stack
[528]472
[440]473    if ( irq_type != IRQ_TYPE_PTI )
474    {
[528]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() );
[440]478        _exit();
479    }
[258]480
[440]481    // acknowledge PTI
482    _xcu_timer_reset_irq( cluster_xy, irq_id );
483
[709]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"
[528]488        "  WTI index = %d / current ltid = %d\n",
489        x , y , p , _get_proctime() , irq_id , ltid );
[258]490#endif
491
[528]492    // enter critical section and switch context
493    _it_disable( &save_sr );
[258]494    _ctx_switch();
[528]495    _it_restore( &save_sr );
496
[440]497}  // end _isr_tick
[258]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.