source: mainline/kernel/arch/ia64/src/interrupt.c@ 70259a55

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 70259a55 was 70259a55, checked in by Jakub Jermar <jakub@…>, 7 years ago

ia64: Use appropriate imm21 operand with BREAK

This commit changes the imm21 used with the BREAK instruction to conform
to the IA-64 Software Conventions and Runtime Architecture Guide. This
is necessary to be able to distinguish syscalls from compiler-generated
calls to architected software interrupts (e.g. integer divide by zero).

In order to be able to test the used immediate in break_instruction(),
we extend istate_t to hold the CR.IIM register.

  • 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 ia64interrupt
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 <print.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 <print.h>
50#include <proc/scheduler.h>
51#include <ipc/sysipc.h>
52#include <ipc/irq.h>
53#include <ipc/ipc.h>
54#include <synch/spinlock.h>
55#include <mm/tlb.h>
56#include <arch/mm/tlb.h>
57#include <symtab.h>
58#include <putchar.h>
59
60#define VECTORS_64_BUNDLE 20
61#define VECTORS_16_BUNDLE 48
62#define VECTORS_16_BUNDLE_START 0x50
63
64#define VECTOR_MAX 0x7f
65
66static const char *vector_names_64_bundle[VECTORS_64_BUNDLE] = {
67 "VHPT Translation vector",
68 "Instruction TLB vector",
69 "Data TLB vector",
70 "Alternate Instruction TLB vector",
71 "Alternate Data TLB vector",
72 "Data Nested TLB vector",
73 "Instruction Key Miss vector",
74 "Data Key Miss vector",
75 "Dirty-Bit vector",
76 "Instruction Access-Bit vector",
77 "Data Access-Bit vector",
78 "Break Instruction vector",
79 "External Interrupt vector",
80 "Virtual External Interrupt vector",
81 "Reserved",
82 "Reserved",
83 "Reserved",
84 "Reserved",
85 "Reserved",
86 "Reserved"
87};
88
89static const char *vector_names_16_bundle[VECTORS_16_BUNDLE] = {
90 "Page Not Present vector",
91 "Key Permission vector",
92 "Instruction Access rights vector",
93 "Data Access Rights vector",
94 "General Exception vector",
95 "Disabled FP-Register vector",
96 "NaT Consumption vector",
97 "Speculation vector",
98 "Reserved",
99 "Debug vector",
100 "Unaligned Reference vector",
101 "Unsupported Data Reference vector",
102 "Floating-point Fault vector",
103 "Floating-point Trap vector",
104 "Lower-Privilege Transfer Trap vector",
105 "Taken Branch Trap vector",
106 "Single Step Trap vector",
107 "Reserved",
108 "Reserved",
109 "Reserved",
110 "Reserved",
111 "Reserved",
112 "Reserved",
113 "Reserved",
114 "Reserved",
115 "IA-32 Exception vector",
116 "IA-32 Intercept vector",
117 "IA-32 Interrupt vector",
118 "Reserved",
119 "Reserved",
120 "Reserved"
121};
122
123static const char *vector_to_string(unsigned int n)
124{
125 assert(n <= VECTOR_MAX);
126
127 if (n >= VECTORS_16_BUNDLE_START)
128 return vector_names_16_bundle[n - VECTORS_16_BUNDLE_START];
129 else
130 return vector_names_64_bundle[n / 4];
131}
132
133void istate_decode(istate_t *istate)
134{
135 printf("ar.bsp=%p\tar.bspstore=%p\n",
136 (void *) istate->ar_bsp, (void *) istate->ar_bspstore);
137 printf("ar.rnat=%#0" PRIx64 "\tar.rsc=%#0" PRIx64 "\n",
138 istate->ar_rnat, istate->ar_rsc);
139 printf("ar.ifs=%#0" PRIx64 "\tar.pfs=%#0" PRIx64 "\n",
140 istate->ar_ifs, istate->ar_pfs);
141 printf("cr.isr=%#0" PRIx64 "\tcr.ipsr=%#0" PRIx64 "\n",
142 istate->cr_isr.value, istate->cr_ipsr.value);
143
144 printf("cr.iip=%#0" PRIxPTR ", #%u\t(%s)\n",
145 istate->cr_iip, istate->cr_isr.ei,
146 symtab_fmt_name_lookup(istate->cr_iip));
147 printf("cr.iipa=%#0" PRIxPTR "\t(%s)\n", istate->cr_iipa,
148 symtab_fmt_name_lookup(istate->cr_iipa));
149 printf("cr.ifa=%#0" PRIxPTR "\t(%s)\n", istate->cr_ifa,
150 symtab_fmt_name_lookup(istate->cr_ifa));
151}
152
153void general_exception(unsigned int n, istate_t *istate)
154{
155 const char *desc;
156
157 switch (istate->cr_isr.ge_code) {
158 case GE_ILLEGALOP:
159 desc = "Illegal Operation fault";
160 break;
161 case GE_PRIVOP:
162 desc = "Privileged Operation fault";
163 break;
164 case GE_PRIVREG:
165 desc = "Privileged Register fault";
166 break;
167 case GE_RESREGFLD:
168 desc = "Reserved Register/Field fault";
169 break;
170 case GE_DISBLDISTRAN:
171 desc = "Disabled Instruction Set Transition fault";
172 break;
173 case GE_ILLEGALDEP:
174 desc = "Illegal Dependency fault";
175 break;
176 default:
177 desc = "unknown";
178 break;
179 }
180
181 fault_if_from_uspace(istate, "General Exception (%s).", desc);
182 panic_badtrap(istate, n, "General Exception (%s).", desc);
183}
184
185void disabled_fp_register(unsigned int n, istate_t *istate)
186{
187#ifdef CONFIG_FPU_LAZY
188 scheduler_fpu_lazy_request();
189#else
190 fault_if_from_uspace(istate, "Interruption: %#hx (%s).",
191 (uint16_t) n, vector_to_string(n));
192 panic_badtrap(istate, n, "Interruption: %#hx (%s).",
193 (uint16_t) n, vector_to_string(n));
194#endif
195}
196
197
198#define BREAK_IMM_SYSCALL 0x40000U
199
200/** Handle syscall. */
201sysarg_t break_instruction(unsigned int n, istate_t *istate)
202{
203 sysarg_t ret;
204
205 if (istate->cr_iim != BREAK_IMM_SYSCALL) {
206 fault_if_from_uspace(istate, "Unknown software interrupt: %x",
207 (uint32_t) istate->cr_iim);
208 panic_badtrap(istate, n, "Interruption: %#hx (%s).",
209 (uint16_t) n, vector_to_string(n));
210 }
211
212 /*
213 * Move to next instruction after BREAK.
214 */
215 if (istate->cr_ipsr.ri == 2) {
216 istate->cr_ipsr.ri = 0;
217 istate->cr_iip += 16;
218 } else {
219 istate->cr_ipsr.ri++;
220 }
221
222 interrupts_enable();
223 ret = syscall_handler(istate->in0, istate->in1, istate->in2,
224 istate->in3, istate->in4, istate->in5, istate->in6);
225 interrupts_disable();
226
227 return ret;
228}
229
230void universal_handler(unsigned int n, istate_t *istate)
231{
232 fault_if_from_uspace(istate, "Interruption: %#hx (%s).",
233 n, vector_to_string(n));
234 panic_badtrap(istate, n, "Interruption: %#hx (%s).",
235 n, vector_to_string(n));
236}
237
238static void end_of_local_irq(void)
239{
240 asm volatile (
241 "mov cr.eoi = r0 ;;"
242 );
243}
244
245void external_interrupt(unsigned int n, istate_t *istate)
246{
247 cr_ivr_t ivr;
248
249 ivr.value = ivr_read();
250 srlz_d();
251
252 irq_t *irq;
253
254 switch (ivr.vector) {
255 case INTERRUPT_SPURIOUS:
256#ifdef CONFIG_DEBUG
257 printf("cpu%d: spurious interrupt\n", CPU->id);
258#endif
259 break;
260
261#ifdef CONFIG_SMP
262 case VECTOR_TLB_SHOOTDOWN_IPI:
263 tlb_shootdown_ipi_recv();
264 end_of_local_irq();
265 break;
266#endif
267
268 case INTERRUPT_TIMER:
269 irq = irq_dispatch_and_lock(ivr.vector);
270 if (irq) {
271 irq->handler(irq);
272 irq_spinlock_unlock(&irq->lock, false);
273 } else {
274 panic("Unhandled Internal Timer Interrupt (%d).",
275 ivr.vector);
276 }
277 break;
278 default:
279 irq = irq_dispatch_and_lock(ivr.vector);
280 if (irq) {
281 /*
282 * The IRQ handler was found.
283 */
284 if (irq->preack) {
285 /* Send EOI before processing the interrupt */
286 end_of_local_irq();
287 }
288 irq->handler(irq);
289 if (!irq->preack)
290 end_of_local_irq();
291 irq_spinlock_unlock(&irq->lock, false);
292 } else {
293 /*
294 * Unhandled interrupt.
295 */
296 end_of_local_irq();
297#ifdef CONFIG_DEBUG
298 printf("\nUnhandled External Interrupt Vector %d\n",
299 ivr.vector);
300#endif
301 }
302 break;
303 }
304}
305
306void trap_virtual_enable_irqs(uint16_t irqmask)
307{
308}
309
310void exception_init(void)
311{
312 unsigned int i;
313
314 for (i = 0; i < IVT_ITEMS; i++)
315 exc_register(i, "universal_handler", false, universal_handler);
316
317 exc_register(EXC_ALT_ITLB_FAULT,
318 vector_to_string(EXC_ALT_ITLB_FAULT), true,
319 alternate_instruction_tlb_fault);
320 exc_register(EXC_ALT_DTLB_FAULT,
321 vector_to_string(EXC_ALT_DTLB_FAULT), true,
322 alternate_data_tlb_fault);
323 exc_register(EXC_NESTED_TLB_FAULT,
324 vector_to_string(EXC_NESTED_TLB_FAULT), false,
325 data_nested_tlb_fault);
326 exc_register(EXC_DATA_D_BIT_FAULT,
327 vector_to_string(EXC_DATA_D_BIT_FAULT), true,
328 data_dirty_bit_fault);
329 exc_register(EXC_INST_A_BIT_FAULT,
330 vector_to_string(EXC_INST_A_BIT_FAULT), true,
331 instruction_access_bit_fault);
332 exc_register(EXC_DATA_A_BIT_FAULT,
333 vector_to_string(EXC_DATA_A_BIT_FAULT), true,
334 data_access_bit_fault);
335 exc_register(EXC_EXT_INTERRUPT,
336 vector_to_string(EXC_EXT_INTERRUPT), true,
337 external_interrupt);
338
339 exc_register(EXC_PAGE_NOT_PRESENT,
340 vector_to_string(EXC_PAGE_NOT_PRESENT), true,
341 page_not_present);
342 exc_register(EXC_DATA_AR_FAULT,
343 vector_to_string(EXC_DATA_AR_FAULT), true,
344 data_access_rights_fault);
345 exc_register(EXC_GENERAL_EXCEPTION,
346 vector_to_string(EXC_GENERAL_EXCEPTION), false,
347 general_exception);
348 exc_register(EXC_DISABLED_FP_REG,
349 vector_to_string(EXC_DISABLED_FP_REG), true,
350 disabled_fp_register);
351}
352
353/** @}
354 */
Note: See TracBrowser for help on using the repository browser.