1 /* $NetBSD: trap.c,v 1.16 2023/10/05 19:41:04 ad Exp $ */
2
3 /*-
4 * Copyright (c) 2005 Marcel Moolenaar
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*-
30 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
31 * All rights reserved.
32 *
33 * This code is derived from software contributed to The NetBSD Foundation
34 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
35 * NASA Ames Research Center, by Charles M. Hannum, and by Ross Harvey.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56 * POSSIBILITY OF SUCH DAMAGE.
57 */
58
59
60 #include "opt_ddb.h"
61
62 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
63
64 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.16 2023/10/05 19:41:04 ad Exp $");
65
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/proc.h>
69
70 #include <sys/userret.h>
71
72 #include <uvm/uvm_extern.h>
73
74 #include <machine/frame.h>
75 #include <machine/md_var.h>
76 #include <machine/cpu.h>
77 #include <machine/cpufunc.h>
78 #include <machine/ia64_cpu.h>
79 #include <machine/fpu.h>
80 #ifdef DDB
81 #include <machine/db_machdep.h>
82 #include <ddb/db_extern.h>
83 #endif
84
85 #include <ia64/disasm/disasm.h>
86
87
88 static const char *ia64_vector_names[] = {
89 "VHPT Translation", /* 0 */
90 "Instruction TLB", /* 1 */
91 "Data TLB", /* 2 */
92 "Alternate Instruction TLB", /* 3 */
93 "Alternate Data TLB", /* 4 */
94 "Data Nested TLB", /* 5 */
95 "Instruction Key Miss", /* 6 */
96 "Data Key Miss", /* 7 */
97 "Dirty-Bit", /* 8 */
98 "Instruction Access-Bit", /* 9 */
99 "Data Access-Bit", /* 10 */
100 "Break Instruction", /* 11 */
101 "External Interrupt", /* 12 */
102 "Reserved 13", /* 13 */
103 "Reserved 14", /* 14 */
104 "Reserved 15", /* 15 */
105 "Reserved 16", /* 16 */
106 "Reserved 17", /* 17 */
107 "Reserved 18", /* 18 */
108 "Reserved 19", /* 19 */
109 "Page Not Present", /* 20 */
110 "Key Permission", /* 21 */
111 "Instruction Access Rights", /* 22 */
112 "Data Access Rights", /* 23 */
113 "General Exception", /* 24 */
114 "Disabled FP-Register", /* 25 */
115 "NaT Consumption", /* 26 */
116 "Speculation", /* 27 */
117 "Reserved 28", /* 28 */
118 "Debug", /* 29 */
119 "Unaligned Reference", /* 30 */
120 "Unsupported Data Reference", /* 31 */
121 "Floating-point Fault", /* 32 */
122 "Floating-point Trap", /* 33 */
123 "Lower-Privilege Transfer Trap", /* 34 */
124 "Taken Branch Trap", /* 35 */
125 "Single Step Trap", /* 36 */
126 "Reserved 37", /* 37 */
127 "Reserved 38", /* 38 */
128 "Reserved 39", /* 39 */
129 "Reserved 40", /* 40 */
130 "Reserved 41", /* 41 */
131 "Reserved 42", /* 42 */
132 "Reserved 43", /* 43 */
133 "Reserved 44", /* 44 */
134 "IA-32 Exception", /* 45 */
135 "IA-32 Intercept", /* 46 */
136 "IA-32 Interrupt", /* 47 */
137 "Reserved 48", /* 48 */
138 "Reserved 49", /* 49 */
139 "Reserved 50", /* 50 */
140 "Reserved 51", /* 51 */
141 "Reserved 52", /* 52 */
142 "Reserved 53", /* 53 */
143 "Reserved 54", /* 54 */
144 "Reserved 55", /* 55 */
145 "Reserved 56", /* 56 */
146 "Reserved 57", /* 57 */
147 "Reserved 58", /* 58 */
148 "Reserved 59", /* 59 */
149 "Reserved 60", /* 60 */
150 "Reserved 61", /* 61 */
151 "Reserved 62", /* 62 */
152 "Reserved 63", /* 63 */
153 "Reserved 64", /* 64 */
154 "Reserved 65", /* 65 */
155 "Reserved 66", /* 66 */
156 "Reserved 67", /* 67 */
157 };
158
159 struct bitname {
160 uint64_t mask;
161 const char* name;
162 };
163
164 static void
printbits(uint64_t mask,struct bitname * bn,int count)165 printbits(uint64_t mask, struct bitname *bn, int count)
166 {
167 int i, first = 1;
168 uint64_t bit;
169
170 for (i = 0; i < count; i++) {
171 /*
172 * Handle fields wider than one bit.
173 */
174 bit = bn[i].mask & ~(bn[i].mask - 1);
175 if (bn[i].mask > bit) {
176 if (first)
177 first = 0;
178 else
179 printf(",");
180 printf("%s=%ld", bn[i].name,
181 (mask & bn[i].mask) / bit);
182 } else if (mask & bit) {
183 if (first)
184 first = 0;
185 else
186 printf(",");
187 printf("%s", bn[i].name);
188 }
189 }
190 }
191
192 struct bitname psr_bits[] = {
193 {IA64_PSR_BE, "be"},
194 {IA64_PSR_UP, "up"},
195 {IA64_PSR_AC, "ac"},
196 {IA64_PSR_MFL, "mfl"},
197 {IA64_PSR_MFH, "mfh"},
198 {IA64_PSR_IC, "ic"},
199 {IA64_PSR_I, "i"},
200 {IA64_PSR_PK, "pk"},
201 {IA64_PSR_DT, "dt"},
202 {IA64_PSR_DFL, "dfl"},
203 {IA64_PSR_DFH, "dfh"},
204 {IA64_PSR_SP, "sp"},
205 {IA64_PSR_PP, "pp"},
206 {IA64_PSR_DI, "di"},
207 {IA64_PSR_SI, "si"},
208 {IA64_PSR_DB, "db"},
209 {IA64_PSR_LP, "lp"},
210 {IA64_PSR_TB, "tb"},
211 {IA64_PSR_RT, "rt"},
212 {IA64_PSR_CPL, "cpl"},
213 {IA64_PSR_IS, "is"},
214 {IA64_PSR_MC, "mc"},
215 {IA64_PSR_IT, "it"},
216 {IA64_PSR_ID, "id"},
217 {IA64_PSR_DA, "da"},
218 {IA64_PSR_DD, "dd"},
219 {IA64_PSR_SS, "ss"},
220 {IA64_PSR_RI, "ri"},
221 {IA64_PSR_ED, "ed"},
222 {IA64_PSR_BN, "bn"},
223 {IA64_PSR_IA, "ia"},
224 };
225
226 static void
printpsr(uint64_t psr)227 printpsr(uint64_t psr)
228 {
229 printbits(psr, psr_bits, sizeof(psr_bits)/sizeof(psr_bits[0]));
230 }
231
232 struct bitname isr_bits[] = {
233 {IA64_ISR_CODE, "code"},
234 {IA64_ISR_VECTOR, "vector"},
235 {IA64_ISR_X, "x"},
236 {IA64_ISR_W, "w"},
237 {IA64_ISR_R, "r"},
238 {IA64_ISR_NA, "na"},
239 {IA64_ISR_SP, "sp"},
240 {IA64_ISR_RS, "rs"},
241 {IA64_ISR_IR, "ir"},
242 {IA64_ISR_NI, "ni"},
243 {IA64_ISR_SO, "so"},
244 {IA64_ISR_EI, "ei"},
245 {IA64_ISR_ED, "ed"},
246 };
247
printisr(uint64_t isr)248 static void printisr(uint64_t isr)
249 {
250 printbits(isr, isr_bits, sizeof(isr_bits)/sizeof(isr_bits[0]));
251 }
252
253 static void
printtrap(int vector,struct trapframe * tf,int isfatal,int user)254 printtrap(int vector, struct trapframe *tf, int isfatal, int user)
255 {
256
257 printf("\n");
258 printf("%s %s trap (cpu %lu):\n", isfatal? "fatal" : "handled",
259 user ? "user" : "kernel", curcpu()->ci_cpuid);
260 printf("\n");
261 printf(" trap vector = 0x%x (%s)\n",
262 vector, ia64_vector_names[vector]);
263 printf(" cr.iip = 0x%lx\n", tf->tf_special.iip);
264 printf(" cr.ipsr = 0x%lx (", tf->tf_special.psr);
265 printpsr(tf->tf_special.psr);
266 printf(")\n");
267 printf(" cr.isr = 0x%lx (", tf->tf_special.isr);
268 printisr(tf->tf_special.isr);
269 printf(")\n");
270 printf(" cr.ifa = 0x%lx\n", tf->tf_special.ifa);
271 if (tf->tf_special.psr & IA64_PSR_IS) {
272 printf(" ar.cflg = 0x%lx\n", ia64_get_cflg());
273 printf(" ar.csd = 0x%lx\n", ia64_get_csd());
274 printf(" ar.ssd = 0x%lx\n", ia64_get_ssd());
275 }
276 printf(" curlwp = %p\n", curlwp);
277 if (curproc != NULL)
278 printf(" pid = %d, comm = %s\n",
279 curproc->p_pid, curproc->p_comm);
280 printf("\n");
281 }
282
283 /*
284 * We got a trap caused by a break instruction and the immediate was 0.
285 * This indicates that we may have a break.b with some non-zero immediate.
286 * The break.b doesn't cause the immediate to be put in cr.iim. Hence,
287 * we need to disassemble the bundle and return the immediate found there.
288 * This may be a 0 value anyway. Return 0 for any error condition. This
289 * will result in a SIGILL, which is pretty much the best thing to do.
290 */
291 static uint64_t
trap_decode_break(struct trapframe * tf)292 trap_decode_break(struct trapframe *tf)
293 {
294 struct asm_bundle bundle;
295 struct asm_inst *inst;
296 int slot;
297
298 if (!asm_decode(tf->tf_special.iip, &bundle))
299 return (0);
300
301 slot = ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_0) ? 0 :
302 ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_1) ? 1 : 2;
303 inst = bundle.b_inst + slot;
304
305 /*
306 * Sanity checking: It must be a break instruction and the operand
307 * that has the break value must be an immediate.
308 */
309 if (inst->i_op != ASM_OP_BREAK ||
310 inst->i_oper[1].o_type != ASM_OPER_IMM)
311 return (0);
312
313 return (inst->i_oper[1].o_value);
314 }
315
316
317 /*
318 * Start a new LWP
319 */
320 void
startlwp(void * arg)321 startlwp(void *arg)
322 {
323 panic("XXX %s implement", __func__);
324 }
325
326 #ifdef DDB
327 int call_debugger = 1;
328
329 /*
330 * Enter the debugger due to a trap.
331 */
332
333 int
ia64_trap(int type,int code,db_regs_t * regs)334 ia64_trap(int type, int code, db_regs_t *regs)
335 {
336
337 /* XXX: Switch stacks ? */
338
339 /* Debugger is not re-entrant. */
340
341 ddb_regp = regs;
342 db_trap(type, code);
343 return 1; /* XXX: Always handled ??? */
344
345 }
346
347 #endif
348
349 void
trap_panic(int vector,struct trapframe * tf)350 trap_panic(int vector, struct trapframe *tf)
351 {
352
353 printtrap(vector, tf, 1, TRAPF_USERMODE(tf));
354
355 #ifdef DDB
356 if (ia64_trap(vector, 0, tf)) return;
357 #endif
358 panic("trap");
359
360 return;
361 }
362
363 /*
364 *
365 */
366 int
do_ast(struct trapframe * tf)367 do_ast(struct trapframe *tf)
368 {
369 printf("%s: not yet\n", __func__);
370 return 0;
371 }
372
373 /*
374 * Trap is called from exception.s to handle most types of processor traps.
375 */
376 /*ARGSUSED*/
377 void
trap(int vector,struct trapframe * tf)378 trap(int vector, struct trapframe *tf)
379 {
380
381 struct proc *p;
382 struct lwp *l;
383 uint64_t ucode;
384 int sig, user;
385 ksiginfo_t ksi;
386
387 user = TRAPF_USERMODE(tf) ? 1 : 0;
388
389 l = curlwp;
390
391 ucode = 0;
392
393 #if 0
394 printtrap(vector, tf, 0, TRAPF_USERMODE(tf));
395 #endif
396 if (user) {
397 ia64_set_fpsr(IA64_FPSR_DEFAULT);
398 p = l->l_proc;
399 l->l_md.md_tf = tf;
400 } else {
401 p = NULL;
402 }
403 sig = 0;
404 switch (vector) {
405 case IA64_VEC_VHPT:
406 /*
407 * This one is tricky. We should hardwire the VHPT, but
408 * don't at this time. I think we're mostly lucky that
409 * the VHPT is mapped.
410 */
411 trap_panic(vector, tf);
412 break;
413
414 case IA64_VEC_ITLB:
415 case IA64_VEC_DTLB:
416 case IA64_VEC_EXT_INTR:
417 /* We never call trap() with these vectors. */
418 trap_panic(vector, tf);
419 break;
420
421 case IA64_VEC_ALT_ITLB:
422 case IA64_VEC_ALT_DTLB:
423 /*
424 * These should never happen, because regions 0-4 use the
425 * VHPT. If we get one of these it means we didn't program
426 * the region registers correctly.
427 */
428 trap_panic(vector, tf);
429 break;
430
431 case IA64_VEC_NESTED_DTLB:
432 /*
433 * We never call trap() with this vector. We may want to
434 * do that in the future in case the nested TLB handler
435 * could not find the translation it needs. In that case
436 * we could switch to a special (hardwired) stack and
437 * come here to produce a nice panic().
438 */
439 trap_panic(vector, tf);
440 break;
441
442 case IA64_VEC_IKEY_MISS:
443 case IA64_VEC_DKEY_MISS:
444 case IA64_VEC_KEY_PERMISSION:
445 /*
446 * We don't use protection keys, so we should never get
447 * these faults.
448 */
449 trap_panic(vector, tf);
450 break;
451
452 case IA64_VEC_DIRTY_BIT:
453 case IA64_VEC_INST_ACCESS:
454 case IA64_VEC_DATA_ACCESS:
455 /*
456 * We get here if we read or write to a page of which the
457 * PTE does not have the access bit or dirty bit set and
458 * we can not find the PTE in our datastructures. This
459 * either means we have a stale PTE in the TLB, or we lost
460 * the PTE in our datastructures.
461 */
462 trap_panic(vector, tf);
463 break;
464
465 case IA64_VEC_BREAK:
466 if (user) {
467 ucode = (int)tf->tf_special.ifa & 0x1FFFFF;
468 if (ucode == 0) {
469 /*
470 * A break.b doesn't cause the immediate to be
471 * stored in cr.iim (and saved in the TF in
472 * tf_special.ifa). We need to decode the
473 * instruction to find out what the immediate
474 * was. Note that if the break instruction
475 * didn't happen to be a break.b, but any
476 * other break with an immediate of 0, we
477 * will do unnecessary work to get the value
478 * we already had. Not an issue, because a
479 * break 0 is invalid.
480 */
481 ucode = trap_decode_break(tf);
482 }
483 if (ucode < 0x80000) {
484 /* Software interrupts. */
485 switch (ucode) {
486 case 0: /* Unknown error. */
487 sig = SIGILL;
488 break;
489 case 1: /* Integer divide by zero. */
490 sig = SIGFPE;
491 ucode = FPE_INTDIV;
492 break;
493 case 2: /* Integer overflow. */
494 sig = SIGFPE;
495 ucode = FPE_INTOVF;
496 break;
497 case 3: /* Range check/bounds check. */
498 sig = SIGFPE;
499 ucode = FPE_FLTSUB;
500 break;
501 case 6: /* Decimal overflow. */
502 case 7: /* Decimal divide by zero. */
503 case 8: /* Packed decimal error. */
504 case 9: /* Invalid ASCII digit. */
505 case 10: /* Invalid decimal digit. */
506 sig = SIGFPE;
507 ucode = FPE_FLTINV;
508 break;
509 case 4: /* Null pointer dereference. */
510 case 5: /* Misaligned data. */
511 case 11: /* Paragraph stack overflow. */
512 sig = SIGSEGV;
513 break;
514 default:
515 sig = SIGILL;
516 break;
517 }
518 } else if (ucode < 0x100000) {
519 /* Debugger breakpoint. */
520 tf->tf_special.psr &= ~IA64_PSR_SS;
521 sig = SIGTRAP;
522 #if 0
523 } else if (ucode == 0x100000) {
524 break_syscall(tf);
525 return; /* do_ast() already called. */
526 } else if (ucode == 0x180000) {
527 mcontext_t mc;
528
529 error = copyin((void*)tf->tf_scratch.gr8,
530 &mc, sizeof(mc));
531 if (!error) {
532 set_mcontext(td, &mc);
533 return; /* Don't call do_ast()!!! */
534 }
535 sig = SIGSEGV;
536 ucode = tf->tf_scratch.gr8;
537 #endif
538 } else
539 sig = SIGILL;
540 } else {
541 trap_panic(vector, tf);
542 goto out;
543 }
544 break;
545
546 case IA64_VEC_PAGE_NOT_PRESENT:
547 case IA64_VEC_INST_ACCESS_RIGHTS:
548 case IA64_VEC_DATA_ACCESS_RIGHTS: {
549 struct pcb * const pcb = lwp_getpcb(l);
550 vaddr_t va;
551 struct vm_map *map;
552 vm_prot_t ftype;
553 uint64_t onfault;
554 int error = 0;
555
556 va = trunc_page(tf->tf_special.ifa);
557
558 if (va >= VM_MAXUSER_ADDRESS) {
559 /*
560 * Don't allow user-mode faults for kernel virtual
561 * addresses, including the gateway page.
562 */
563 if (user)
564 goto no_fault_in;
565 map = kernel_map;
566 } else {
567 map = (p != NULL) ? &p->p_vmspace->vm_map : NULL;
568 if (map == NULL)
569 goto no_fault_in;
570 }
571
572 if (tf->tf_special.isr & IA64_ISR_X)
573 ftype = VM_PROT_EXECUTE;
574 else if (tf->tf_special.isr & IA64_ISR_W)
575 ftype = VM_PROT_WRITE;
576 else
577 ftype = VM_PROT_READ;
578
579 onfault = pcb->pcb_onfault;
580 pcb->pcb_onfault = 0;
581 error = uvm_fault(map, va, ftype);
582 pcb->pcb_onfault = onfault;
583
584 if (error == 0)
585 goto out;
586
587 no_fault_in:
588 if (!user) {
589 /* Check for copyin/copyout fault. */
590 if (pcb->pcb_onfault != 0) {
591 tf->tf_special.iip = pcb->pcb_onfault;
592 tf->tf_special.psr &= ~IA64_PSR_RI;
593 tf->tf_scratch.gr8 = error;
594 goto out;
595 }
596 trap_panic(vector, tf);
597 }
598 ucode = va;
599 sig = (error == EACCES) ? SIGBUS : SIGSEGV;
600 break;
601 }
602
603 /* XXX: Fill in the rest */
604
605 case IA64_VEC_SPECULATION:
606 /*
607 * The branching behaviour of the chk instruction is not
608 * implemented by the processor. All we need to do is
609 * compute the target address of the branch and make sure
610 * that control is transferred to that address.
611 * We should do this in the IVT table and not by entring
612 * the kernel...
613 */
614 tf->tf_special.iip += tf->tf_special.ifa << 4;
615 tf->tf_special.psr &= ~IA64_PSR_RI;
616 goto out;
617
618 /* XXX: Fill in the rest */
619
620 case IA64_VEC_DEBUG:
621 case IA64_VEC_SINGLE_STEP_TRAP:
622 tf->tf_special.psr &= ~IA64_PSR_SS;
623 if (!user) {
624 trap_panic(vector, tf);
625 goto out;
626 }
627 sig = SIGTRAP;
628 break;
629
630
631
632 default:
633 /* Reserved vectors get here. Should never happen of course. */
634 trap_panic(vector, tf);
635 break;
636 }
637
638 printf("sig = %d", sig);
639 KASSERT(sig != 0);
640
641 KSI_INIT(&ksi);
642 ksi.ksi_signo = sig;
643 ksi.ksi_code = ucode;
644 trapsignal(l, &ksi);
645
646 out:
647 if (user) {
648 mi_userret(l);
649 }
650 return;
651 }
652