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

Last change on this file since 700 was 697, checked in by guerin, 9 years ago

kernel: release WTI mailbox associated with TTY

We don't block on giet_tty_alloc() anymore when launching the same app
again and again.

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