source: soft/giet_vm/giet_kernel/irq_handler.c

Last change on this file was 811, checked in by bouyer, 11 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.