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 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 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 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 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 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 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 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 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 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 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