source: mainline/kernel/arch/ia64/src/interrupt.c

Last change on this file was 2a103b5, checked in by Jakub Jermar <jakub@…>, 6 years ago

Introduce PIC operations indirection mechanism

Some architectures switch from one interrupt controller implementation
to another during runtime. By providing a cleaner indirection mechanism,
it is possible e.g. for the ia32 IRQ 7 handler to distinguish i8259
spurious interrupts from actual IRQ 7 device interrupts, even when the
i8259 interrupt controller is no longer active.

  • Property mode set to 100644
File size: 9.0 KB
Line 
1/*
2 * Copyright (c) 2005 Jakub Jermar
3 * Copyright (c) 2005 Jakub Vana
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup kernel_ia64_interrupt
31 * @{
32 */
33/** @file
34 */
35
36#include <arch/interrupt.h>
37#include <assert.h>
38#include <interrupt.h>
39#include <ddi/irq.h>
40#include <panic.h>
41#include <stdio.h>
42#include <console/console.h>
43#include <typedefs.h>
44#include <arch/asm.h>
45#include <barrier.h>
46#include <arch/register.h>
47#include <arch.h>
48#include <syscall/syscall.h>
49#include <proc/scheduler.h>
50#include <ipc/sysipc.h>
51#include <ipc/irq.h>
52#include <ipc/ipc.h>
53#include <synch/spinlock.h>
54#include <mm/tlb.h>
55#include <arch/mm/tlb.h>
56#include <symtab.h>
57
58#define VECTORS_64_BUNDLE 20
59#define VECTORS_16_BUNDLE 48
60#define VECTORS_16_BUNDLE_START 0x50
61
62#define VECTOR_MAX 0x7f
63
64static const char *vector_names_64_bundle[VECTORS_64_BUNDLE] = {
65 "VHPT Translation vector",
66 "Instruction TLB vector",
67 "Data TLB vector",
68 "Alternate Instruction TLB vector",
69 "Alternate Data TLB vector",
70 "Data Nested TLB vector",
71 "Instruction Key Miss vector",
72 "Data Key Miss vector",
73 "Dirty-Bit vector",
74 "Instruction Access-Bit vector",
75 "Data Access-Bit vector",
76 "Break Instruction vector",
77 "External Interrupt vector",
78 "Virtual External Interrupt vector",
79 "Reserved",
80 "Reserved",
81 "Reserved",
82 "Reserved",
83 "Reserved",
84 "Reserved"
85};
86
87static const char *vector_names_16_bundle[VECTORS_16_BUNDLE] = {
88 "Page Not Present vector",
89 "Key Permission vector",
90 "Instruction Access rights vector",
91 "Data Access Rights vector",
92 "General Exception vector",
93 "Disabled FP-Register vector",
94 "NaT Consumption vector",
95 "Speculation vector",
96 "Reserved",
97 "Debug vector",
98 "Unaligned Reference vector",
99 "Unsupported Data Reference vector",
100 "Floating-point Fault vector",
101 "Floating-point Trap vector",
102 "Lower-Privilege Transfer Trap vector",
103 "Taken Branch Trap vector",
104 "Single Step Trap vector",
105 "Reserved",
106 "Reserved",
107 "Reserved",
108 "Reserved",
109 "Reserved",
110 "Reserved",
111 "Reserved",
112 "Reserved",
113 "IA-32 Exception vector",
114 "IA-32 Intercept vector",
115 "IA-32 Interrupt vector",
116 "Reserved",
117 "Reserved",
118 "Reserved"
119};
120
121static const char *vector_to_string(unsigned int n)
122{
123 assert(n <= VECTOR_MAX);
124
125 if (n >= VECTORS_16_BUNDLE_START)
126 return vector_names_16_bundle[n - VECTORS_16_BUNDLE_START];
127 else
128 return vector_names_64_bundle[n / 4];
129}
130
131void istate_decode(istate_t *istate)
132{
133 printf("ar.bsp=%p\tar.bspstore=%p\n",
134 (void *) istate->ar_bsp, (void *) istate->ar_bspstore);
135 printf("ar.rnat=%#0" PRIx64 "\tar.rsc=%#0" PRIx64 "\n",
136 istate->ar_rnat, istate->ar_rsc);
137 printf("ar.ifs=%#0" PRIx64 "\tar.pfs=%#0" PRIx64 "\n",
138 istate->ar_ifs, istate->ar_pfs);
139 printf("cr.isr=%#0" PRIx64 "\tcr.ipsr=%#0" PRIx64 "\n",
140 istate->cr_isr.value, istate->cr_ipsr.value);
141
142 printf("cr.iip=%#0" PRIxPTR ", #%u\t(%s)\n",
143 istate->cr_iip, istate->cr_isr.ei,
144 symtab_fmt_name_lookup(istate->cr_iip));
145 printf("cr.iipa=%#0" PRIxPTR "\t(%s)\n", istate->cr_iipa,
146 symtab_fmt_name_lookup(istate->cr_iipa));
147 printf("cr.ifa=%#0" PRIxPTR "\t(%s)\n", istate->cr_ifa,
148 symtab_fmt_name_lookup(istate->cr_ifa));
149}
150
151void general_exception(unsigned int n, istate_t *istate)
152{
153 const char *desc;
154
155 switch (istate->cr_isr.ge_code) {
156 case GE_ILLEGALOP:
157 desc = "Illegal Operation fault";
158 break;
159 case GE_PRIVOP:
160 desc = "Privileged Operation fault";
161 break;
162 case GE_PRIVREG:
163 desc = "Privileged Register fault";
164 break;
165 case GE_RESREGFLD:
166 desc = "Reserved Register/Field fault";
167 break;
168 case GE_DISBLDISTRAN:
169 desc = "Disabled Instruction Set Transition fault";
170 break;
171 case GE_ILLEGALDEP:
172 desc = "Illegal Dependency fault";
173 break;
174 default:
175 desc = "unknown";
176 break;
177 }
178
179 fault_if_from_uspace(istate, "General Exception (%s).", desc);
180 panic_badtrap(istate, n, "General Exception (%s).", desc);
181}
182
183void disabled_fp_register(unsigned int n, istate_t *istate)
184{
185#ifdef CONFIG_FPU_LAZY
186 scheduler_fpu_lazy_request();
187#else
188 fault_if_from_uspace(istate, "Interruption: %#hx (%s).",
189 (uint16_t) n, vector_to_string(n));
190 panic_badtrap(istate, n, "Interruption: %#hx (%s).",
191 (uint16_t) n, vector_to_string(n));
192#endif
193}
194
195#define BREAK_IMM_SYSCALL 0x40000U
196
197/** Handle syscall. */
198sysarg_t break_instruction(unsigned int n, istate_t *istate)
199{
200 sysarg_t ret;
201
202 if (istate->cr_iim != BREAK_IMM_SYSCALL) {
203 fault_if_from_uspace(istate, "Unknown software interrupt: %x",
204 (uint32_t) istate->cr_iim);
205 panic_badtrap(istate, n, "Interruption: %#hx (%s).",
206 (uint16_t) n, vector_to_string(n));
207 }
208
209 /*
210 * Move to next instruction after BREAK.
211 */
212 if (istate->cr_ipsr.ri == 2) {
213 istate->cr_ipsr.ri = 0;
214 istate->cr_iip += 16;
215 } else {
216 istate->cr_ipsr.ri++;
217 }
218
219 interrupts_enable();
220 ret = syscall_handler(istate->in0, istate->in1, istate->in2,
221 istate->in3, istate->in4, istate->in5, istate->in6);
222 interrupts_disable();
223
224 return ret;
225}
226
227void universal_handler(unsigned int n, istate_t *istate)
228{
229 fault_if_from_uspace(istate, "Interruption: %#hx (%s).",
230 n, vector_to_string(n));
231 panic_badtrap(istate, n, "Interruption: %#hx (%s).",
232 n, vector_to_string(n));
233}
234
235static void end_of_local_irq(void)
236{
237 asm volatile (
238 "mov cr.eoi = r0 ;;"
239 );
240}
241
242void external_interrupt(unsigned int n, istate_t *istate)
243{
244 cr_ivr_t ivr;
245
246 ivr.value = ivr_read();
247 srlz_d();
248
249 irq_t *irq;
250
251 switch (ivr.vector) {
252 case INTERRUPT_SPURIOUS:
253#ifdef CONFIG_DEBUG
254 printf("cpu%d: spurious interrupt\n", CPU->id);
255#endif
256 break;
257
258#ifdef CONFIG_SMP
259 case VECTOR_TLB_SHOOTDOWN_IPI:
260 tlb_shootdown_ipi_recv();
261 end_of_local_irq();
262 break;
263#endif
264
265 case INTERRUPT_TIMER:
266 irq = irq_dispatch_and_lock(ivr.vector);
267 if (irq) {
268 irq->handler(irq);
269 irq_spinlock_unlock(&irq->lock, false);
270 } else {
271 panic("Unhandled Internal Timer Interrupt (%d).",
272 ivr.vector);
273 }
274 break;
275 default:
276 irq = irq_dispatch_and_lock(ivr.vector);
277 if (irq) {
278 /*
279 * The IRQ handler was found.
280 */
281 if (irq->preack) {
282 /* Send EOI before processing the interrupt */
283 end_of_local_irq();
284 }
285 irq->handler(irq);
286 if (!irq->preack)
287 end_of_local_irq();
288 irq_spinlock_unlock(&irq->lock, false);
289 } else {
290 /*
291 * Unhandled interrupt.
292 */
293 end_of_local_irq();
294#ifdef CONFIG_DEBUG
295 printf("\nUnhandled External Interrupt Vector %d\n",
296 ivr.vector);
297#endif
298 }
299 break;
300 }
301}
302
303void exception_init(void)
304{
305 unsigned int i;
306
307 for (i = 0; i < IVT_ITEMS; i++)
308 exc_register(i, "universal_handler", false, universal_handler);
309
310 exc_register(EXC_ALT_ITLB_FAULT,
311 vector_to_string(EXC_ALT_ITLB_FAULT), true,
312 alternate_instruction_tlb_fault);
313 exc_register(EXC_ALT_DTLB_FAULT,
314 vector_to_string(EXC_ALT_DTLB_FAULT), true,
315 alternate_data_tlb_fault);
316 exc_register(EXC_NESTED_TLB_FAULT,
317 vector_to_string(EXC_NESTED_TLB_FAULT), false,
318 data_nested_tlb_fault);
319 exc_register(EXC_DATA_D_BIT_FAULT,
320 vector_to_string(EXC_DATA_D_BIT_FAULT), true,
321 data_dirty_bit_fault);
322 exc_register(EXC_INST_A_BIT_FAULT,
323 vector_to_string(EXC_INST_A_BIT_FAULT), true,
324 instruction_access_bit_fault);
325 exc_register(EXC_DATA_A_BIT_FAULT,
326 vector_to_string(EXC_DATA_A_BIT_FAULT), true,
327 data_access_bit_fault);
328 exc_register(EXC_EXT_INTERRUPT,
329 vector_to_string(EXC_EXT_INTERRUPT), true,
330 external_interrupt);
331
332 exc_register(EXC_PAGE_NOT_PRESENT,
333 vector_to_string(EXC_PAGE_NOT_PRESENT), true,
334 page_not_present);
335 exc_register(EXC_DATA_AR_FAULT,
336 vector_to_string(EXC_DATA_AR_FAULT), true,
337 data_access_rights_fault);
338 exc_register(EXC_GENERAL_EXCEPTION,
339 vector_to_string(EXC_GENERAL_EXCEPTION), false,
340 general_exception);
341 exc_register(EXC_DISABLED_FP_REG,
342 vector_to_string(EXC_DISABLED_FP_REG), true,
343 disabled_fp_register);
344}
345
346/** @}
347 */
Note: See TracBrowser for help on using the repository browser.