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