1 /* $NetBSD: trap.c,v 1.7 2002/05/14 02:58:34 matt Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Gordon W. Ross 5 * Copyright (c) 1993 Adam Glass 6 * Copyright (c) 1988 University of Utah. 7 * Copyright (c) 1982, 1986, 1990, 1993 8 * The Regents of the University of California. All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * the Systems Programming Group of the University of Utah Computer 12 * Science Department. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 * from: Utah Hdr: trap.c 1.37 92/12/20 43 * from: @(#)trap.c 8.5 (Berkeley) 1/4/94 44 */ 45 46 #include "opt_ddb.h" 47 #include "opt_execfmt.h" 48 #include "opt_kgdb.h" 49 #include "opt_compat_aout_m68k.h" 50 #include "opt_compat_sunos.h" 51 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/proc.h> 55 #include <sys/acct.h> 56 #include <sys/kernel.h> 57 #include <sys/signalvar.h> 58 #include <sys/resourcevar.h> 59 #include <sys/syscall.h> 60 #include <sys/syslog.h> 61 #include <sys/user.h> 62 #ifdef KGDB 63 #include <sys/kgdb.h> 64 #endif 65 66 #include <uvm/uvm_extern.h> 67 68 #include <machine/cpu.h> 69 #include <machine/endian.h> 70 #include <machine/psl.h> 71 #include <machine/trap.h> 72 #include <machine/reg.h> 73 #include <machine/promlib.h> 74 75 #include <sun2/sun2/fc.h> 76 #include <sun2/sun2/machdep.h> 77 78 #ifdef DDB 79 #include <machine/db_machdep.h> 80 #include <ddb/db_extern.h> 81 #endif 82 83 #ifdef COMPAT_SUNOS 84 #include <compat/sunos/sunos_syscall.h> 85 extern struct emul emul_sunos; 86 #endif 87 88 #ifdef COMPAT_AOUT_M68K 89 extern struct emul emul_netbsd_aoutm68k; 90 #endif 91 92 /* Special labels in m68k/copy.s */ 93 extern char fubail[], subail[]; 94 95 /* These are called from locore.s */ 96 void trap __P((int type, u_int code, u_int v, struct trapframe)); 97 void trap_kdebug __P((int type, struct trapframe tf)); 98 int _nodb_trap __P((int type, struct trapframe *)); 99 void straytrap __P((struct trapframe)); 100 101 static void userret __P((struct proc *, struct trapframe *, u_quad_t)); 102 103 int astpending; 104 int want_resched; 105 106 char *trap_type[] = { 107 "Bus error", 108 "Address error", 109 "Illegal instruction", 110 "Zero divide", 111 "CHK instruction", 112 "TRAPV instruction", 113 "Privilege violation", 114 "Trace trap", 115 "MMU fault", 116 "SSIR trap", 117 "Format error", 118 "68881 exception", 119 "Coprocessor violation", 120 "Async system trap", 121 "Unused? (14)", 122 "Breakpoint", 123 "FPU instruction", 124 "FPU data format", 125 }; 126 u_int trap_types = sizeof(trap_type) / sizeof(trap_type[0]); 127 128 /* 129 * Size of various exception stack frames (minus the standard 8 bytes) 130 */ 131 short exframesize[] = { 132 FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ 133 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 134 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ 135 FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ 136 FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ 137 -1, -1, /* type 5-6 - undefined */ 138 FMT7SIZE, /* type 7 - access error (68040) */ 139 FMT8SIZE, /* type 8 - bus fault (68010) */ 140 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 141 FMTASIZE, /* type A - short bus fault (68020/030) */ 142 FMTBSIZE, /* type B - long bus fault (68020/030) */ 143 -1, -1, -1, -1 /* type C-F - undefined */ 144 }; 145 146 #define KDFAULT(c) (((c) & (SSW1_IF|SSW1_FCMASK)) == (FC_SUPERD)) 147 #define WRFAULT(c) (((c) & (SSW1_IF|SSW1_DF|SSW1_RW)) == (0)) 148 149 /* #define DEBUG XXX */ 150 151 #ifdef DEBUG 152 unsigned short buserr_reg; 153 int mmudebug = 0; 154 int mmupid = -1; 155 #define MDB_ISPID(p) ((p) == mmupid) 156 #define MDB_FOLLOW 1 157 #define MDB_WBFOLLOW 2 158 #define MDB_WBFAILED 4 159 #define MDB_CPFAULT 8 160 #endif 161 162 /* 163 * trap and syscall both need the following work done before 164 * returning to user mode. 165 */ 166 static void 167 userret(p, tf, oticks) 168 struct proc *p; 169 struct trapframe *tf; 170 u_quad_t oticks; 171 { 172 int sig; 173 174 /* take pending signals */ 175 while ((sig = CURSIG(p)) != 0) 176 postsig(sig); 177 178 p->p_priority = p->p_usrpri; 179 180 if (want_resched) { 181 /* 182 * We are being preempted. 183 */ 184 preempt(NULL); 185 while ((sig = CURSIG(p)) != 0) 186 postsig(sig); 187 } 188 189 /* 190 * If profiling, charge system time to the trapped pc. 191 */ 192 if (p->p_flag & P_PROFIL) { 193 extern int psratio; 194 addupc_task(p, tf->tf_pc, 195 (int)(p->p_sticks - oticks) * psratio); 196 } 197 198 curcpu()->ci_schedstate.spc_curpriority = p->p_priority; 199 } 200 201 /* 202 * Used by the common m68k syscall() and child_return() functions. 203 * XXX: Temporary until all m68k ports share common trap()/userret() code. 204 */ 205 void machine_userret(struct proc *, struct frame *, u_quad_t); 206 207 void 208 machine_userret(p, f, t) 209 struct proc *p; 210 struct frame *f; 211 u_quad_t t; 212 { 213 214 userret(p, &f->F_t, t); 215 } 216 217 /* 218 * Trap is called from locore to handle most types of processor traps, 219 * including events such as simulated software interrupts/AST's. 220 * System calls are broken out for efficiency. 221 */ 222 /*ARGSUSED*/ 223 void 224 trap(type, code, v, tf) 225 int type; 226 u_int code, v; 227 struct trapframe tf; 228 { 229 struct proc *p; 230 int sig, tmp; 231 u_int ucode; 232 u_quad_t sticks; 233 234 uvmexp.traps++; 235 p = curproc; 236 ucode = 0; 237 sig = 0; 238 239 /* I have verified that this DOES happen! -gwr */ 240 if (p == NULL) 241 p = &proc0; 242 #ifdef DIAGNOSTIC 243 if (p->p_addr == NULL) 244 panic("trap: no pcb"); 245 #endif 246 247 if (USERMODE(tf.tf_sr)) { 248 type |= T_USER; 249 sticks = p->p_sticks; 250 p->p_md.md_regs = tf.tf_regs; 251 } else { 252 sticks = 0; 253 /* XXX: Detect trap recursion? */ 254 } 255 256 switch (type) { 257 default: 258 dopanic: 259 printf("trap type=0x%x, code=0x%x, v=0x%x\n", type, code, v); 260 /* 261 * Let the kernel debugger see the trap frame that 262 * caused us to panic. This is a convenience so 263 * one can see registers at the point of failure. 264 */ 265 tmp = splhigh(); 266 #ifdef KGDB 267 /* If connected, step or cont returns 1 */ 268 if (kgdb_trap(type, &tf)) 269 goto kgdb_cont; 270 #endif 271 #ifdef DDB 272 (void) kdb_trap(type, (db_regs_t *) &tf); 273 #endif 274 #ifdef KGDB 275 kgdb_cont: 276 #endif 277 splx(tmp); 278 if (panicstr) { 279 /* 280 * Note: panic is smart enough to do: 281 * boot(RB_AUTOBOOT | RB_NOSYNC, NULL) 282 * if we call it again. 283 */ 284 panic("trap during panic!"); 285 } 286 regdump(&tf, 128); 287 type &= ~T_USER; 288 if ((u_int)type < trap_types) 289 panic(trap_type[type]); 290 panic("trap type 0x%x", type); 291 292 case T_BUSERR: /* kernel bus error */ 293 if (p->p_addr->u_pcb.pcb_onfault == NULL) 294 goto dopanic; 295 /*FALLTHROUGH*/ 296 297 copyfault: 298 /* 299 * If we have arranged to catch this fault in any of the 300 * copy to/from user space routines, set PC to return to 301 * indicated location and set flag informing buserror code 302 * that it may need to clean up stack frame. 303 */ 304 tf.tf_stackadj = exframesize[tf.tf_format]; 305 tf.tf_format = tf.tf_vector = 0; 306 tf.tf_pc = (int) p->p_addr->u_pcb.pcb_onfault; 307 goto done; 308 309 case T_BUSERR|T_USER: /* bus error */ 310 case T_ADDRERR|T_USER: /* address error */ 311 ucode = v; 312 sig = SIGBUS; 313 break; 314 315 case T_COPERR: /* kernel coprocessor violation */ 316 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 317 case T_FMTERR: /* ...just in case... */ 318 /* 319 * The user has most likely trashed the RTE or FP state info 320 * in the stack frame of a signal handler. 321 */ 322 printf("pid %d: kernel %s exception\n", p->p_pid, 323 type==T_COPERR ? "coprocessor" : "format"); 324 type |= T_USER; 325 SIGACTION(p, SIGILL).sa_handler = SIG_DFL; 326 sigdelset(&p->p_sigctx.ps_sigignore, SIGILL); 327 sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL); 328 sigdelset(&p->p_sigctx.ps_sigmask, SIGILL); 329 sig = SIGILL; 330 ucode = tf.tf_format; 331 break; 332 333 case T_COPERR|T_USER: /* user coprocessor violation */ 334 /* What is a proper response here? */ 335 ucode = 0; 336 sig = SIGFPE; 337 break; 338 339 case T_FPERR|T_USER: /* 68881 exceptions */ 340 /* 341 * We pass along the 68881 status register which locore stashed 342 * in code for us. Note that there is a possibility that the 343 * bit pattern of this register will conflict with one of the 344 * FPE_* codes defined in signal.h. Fortunately for us, the 345 * only such codes we use are all in the range 1-7 and the low 346 * 3 bits of the status register are defined as 0 so there is 347 * no clash. 348 */ 349 ucode = code; 350 sig = SIGFPE; 351 break; 352 353 case T_FPEMULI: /* FPU faults in supervisor mode */ 354 case T_FPEMULD: 355 if (nofault) /* Doing FPU probe? */ 356 longjmp(nofault); 357 goto dopanic; 358 359 case T_FPEMULI|T_USER: /* unimplemented FP instuction */ 360 case T_FPEMULD|T_USER: /* unimplemented FP data type */ 361 #ifdef FPU_EMULATE 362 sig = fpu_emulate(&tf, &p->p_addr->u_pcb.pcb_fpregs); 363 /* XXX - Deal with tracing? (tf.tf_sr & PSL_T) */ 364 #else 365 uprintf("pid %d killed: no floating point support\n", p->p_pid); 366 sig = SIGILL; 367 #endif 368 break; 369 370 case T_ILLINST|T_USER: /* illegal instruction fault */ 371 case T_PRIVINST|T_USER: /* privileged instruction fault */ 372 ucode = tf.tf_format; 373 sig = SIGILL; 374 break; 375 376 case T_ZERODIV|T_USER: /* Divide by zero */ 377 case T_CHKINST|T_USER: /* CHK instruction trap */ 378 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 379 ucode = tf.tf_format; 380 sig = SIGFPE; 381 break; 382 383 /* 384 * XXX: Trace traps are a nightmare. 385 * 386 * HP-UX uses trap #1 for breakpoints, 387 * NetBSD/m68k uses trap #2, 388 * SUN 3.x uses trap #15, 389 * DDB and KGDB uses trap #15 (for kernel breakpoints; 390 * handled elsewhere). 391 * 392 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 393 * SUN 3.x traps get passed through as T_TRAP15 and are not really 394 * supported yet. 395 * 396 * XXX: We should never get kernel-mode T_TRAP15 397 * XXX: because locore.s now gives them special treatment. 398 */ 399 case T_TRAP15: /* kernel breakpoint */ 400 tf.tf_sr &= ~PSL_T; 401 goto done; 402 403 case T_TRACE|T_USER: /* user trace trap */ 404 #ifdef COMPAT_SUNOS 405 /* 406 * SunOS uses Trap #2 for a "CPU cache flush" 407 * Just flush the on-chip caches and return. 408 * XXX - Too bad NetBSD uses trap 2... 409 */ 410 if (p->p_emul == &emul_sunos) { 411 /* get out fast */ 412 goto done; 413 } 414 #endif 415 /* FALLTHROUGH */ 416 case T_TRACE: /* tracing a trap instruction */ 417 case T_TRAP15|T_USER: /* SUN user trace trap */ 418 tf.tf_sr &= ~PSL_T; 419 sig = SIGTRAP; 420 break; 421 422 case T_ASTFLT: /* system async trap, cannot happen */ 423 goto dopanic; 424 425 case T_ASTFLT|T_USER: /* user async trap */ 426 astpending = 0; 427 /* T_SSIR is not used on a Sun2. */ 428 if (p->p_flag & P_OWEUPC) { 429 p->p_flag &= ~P_OWEUPC; 430 ADDUPROF(p); 431 } 432 goto douret; 433 434 case T_MMUFLT: /* kernel mode page fault */ 435 /* Hacks to avoid calling VM code from debugger. */ 436 #ifdef DDB 437 if (db_recover != 0) 438 goto dopanic; 439 #endif 440 #ifdef KGDB 441 if (kgdb_recover != 0) 442 goto dopanic; 443 #endif 444 /* 445 * If we were doing profiling ticks or other user mode 446 * stuff from interrupt code, Just Say No. 447 */ 448 if (p->p_addr->u_pcb.pcb_onfault == (caddr_t)fubail || 449 p->p_addr->u_pcb.pcb_onfault == (caddr_t)subail) 450 { 451 #ifdef DEBUG 452 if (mmudebug & MDB_CPFAULT) { 453 printf("trap: copyfault fu/su bail\n"); 454 Debugger(); 455 } 456 #endif 457 goto copyfault; 458 } 459 /*FALLTHROUGH*/ 460 461 case T_MMUFLT|T_USER: { /* page fault */ 462 vaddr_t va; 463 struct vmspace *vm = p->p_vmspace; 464 struct vm_map *map; 465 int rv; 466 vm_prot_t ftype; 467 extern struct vm_map *kernel_map; 468 469 #ifdef DEBUG 470 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 471 printf("trap: T_MMUFLT pid=%d, code=0x%x, v=0x%x, pc=0x%x, sr=0x%x\n", 472 p->p_pid, code, v, tf.tf_pc, tf.tf_sr); 473 #endif 474 475 /* 476 * It is only a kernel address space fault iff: 477 * 1. (type & T_USER) == 0 and: (2 or 3) 478 * 2. pcb_onfault not set or 479 * 3. pcb_onfault set but supervisor space data fault 480 * The last can occur during an exec() copyin where the 481 * argument space is lazy-allocated. 482 */ 483 map = &vm->vm_map; 484 if ((type & T_USER) == 0) { 485 /* supervisor mode fault */ 486 if ((p->p_addr->u_pcb.pcb_onfault == NULL) || KDFAULT(code)) 487 map = kernel_map; 488 } 489 490 if (WRFAULT(code)) 491 ftype = VM_PROT_WRITE; 492 else 493 ftype = VM_PROT_READ; 494 va = m68k_trunc_page((vaddr_t)v); 495 496 /* 497 * Need to resolve the fault. 498 * 499 * We give the pmap code a chance to resolve faults by 500 * reloading translations that it was forced to unload. 501 * This function does that, and calls vm_fault if it 502 * could not resolve the fault by reloading the MMU. 503 * This function may also, for example, disallow any 504 * faults in the kernel text segment, etc. 505 */ 506 rv = _pmap_fault(map, va, ftype); 507 508 #ifdef DEBUG 509 if (rv && MDB_ISPID(p->p_pid)) { 510 printf("vm_fault(%p, 0x%lx, 0x%x, 0) -> 0x%x\n", 511 map, va, ftype, rv); 512 if (mmudebug & MDB_WBFAILED) 513 Debugger(); 514 } 515 #endif /* DEBUG */ 516 517 /* 518 * If this was a stack access we keep track of the maximum 519 * accessed stack size. Also, if vm_fault gets a protection 520 * failure it is due to accessing the stack region outside 521 * the current limit and we need to reflect that as an access 522 * error. 523 */ 524 if ((map != kernel_map) && ((caddr_t)va >= vm->vm_maxsaddr)) { 525 if (rv == 0) { 526 unsigned nss; 527 528 nss = btoc((u_int)(USRSTACK-va)); 529 if (nss > vm->vm_ssize) 530 vm->vm_ssize = nss; 531 } else if (rv == EACCES) 532 rv = EFAULT; 533 } 534 if (rv == 0) 535 goto finish; 536 537 if ((type & T_USER) == 0) { 538 /* supervisor mode fault */ 539 if (p->p_addr->u_pcb.pcb_onfault) { 540 #ifdef DEBUG 541 if (mmudebug & MDB_CPFAULT) { 542 printf("trap: copyfault pcb_onfault\n"); 543 Debugger(); 544 } 545 #endif 546 goto copyfault; 547 } 548 printf("vm_fault(%p, 0x%lx, 0x%x, 0) -> 0x%x\n", 549 map, va, ftype, rv); 550 goto dopanic; 551 } 552 ucode = v; 553 if (rv == ENOMEM) { 554 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 555 p->p_pid, p->p_comm, 556 p->p_cred && p->p_ucred ? 557 p->p_ucred->cr_uid : -1); 558 sig = SIGKILL; 559 } else { 560 sig = SIGSEGV; 561 } 562 break; 563 } /* T_MMUFLT */ 564 } /* switch */ 565 566 finish: 567 /* If trap was from supervisor mode, just return. */ 568 if ((type & T_USER) == 0) 569 goto done; 570 /* Post a signal if necessary. */ 571 if (sig != 0) 572 trapsignal(p, sig, ucode); 573 douret: 574 userret(p, &tf, sticks); 575 576 done:; 577 /* XXX: Detect trap recursion? */ 578 } 579 580 /* 581 * This is used if we hit a kernel breakpoint or trace trap 582 * when there is no debugger installed (or not attached). 583 * Drop into the PROM temporarily... 584 */ 585 int 586 _nodb_trap(type, tf) 587 int type; 588 struct trapframe *tf; 589 { 590 591 printf("\r\nKernel "); 592 if ((0 <= type) && (type < trap_types)) 593 printf("%s", trap_type[type]); 594 else 595 printf("trap 0x%x", type); 596 printf(", frame=%p\r\n", tf); 597 printf("No debugger; doing PROM abort.\r\n"); 598 printf("To continue, type: c <RETURN>\r\n"); 599 prom_abort(); 600 /* OK then, just resume... */ 601 tf->tf_sr &= ~PSL_T; 602 return(1); 603 } 604 605 /* 606 * This is called by locore for supervisor-mode trace and 607 * breakpoint traps. This is separate from trap() above 608 * so that breakpoints in trap() will work. 609 * 610 * If we have both DDB and KGDB, let KGDB see it first, 611 * because KGDB will just return 0 if not connected. 612 */ 613 void 614 trap_kdebug(type, tf) 615 int type; 616 struct trapframe tf; 617 { 618 619 #ifdef KGDB 620 /* Let KGDB handle it (if connected) */ 621 if (kgdb_trap(type, &tf)) 622 return; 623 #endif 624 #ifdef DDB 625 /* Let DDB handle it. */ 626 if (kdb_trap(type, &tf)) 627 return; 628 #endif 629 630 /* Drop into the PROM temporarily... */ 631 (void)_nodb_trap(type, &tf); 632 } 633 634 /* 635 * Called by locore.s for an unexpected interrupt. 636 * XXX - Almost identical to trap_kdebug... 637 */ 638 void 639 straytrap(tf) 640 struct trapframe tf; 641 { 642 int type = -1; 643 644 printf("unexpected trap; vector=0x%x at pc=0x%x\n", 645 tf.tf_vector, tf.tf_pc); 646 647 #ifdef KGDB 648 /* Let KGDB handle it (if connected) */ 649 if (kgdb_trap(type, &tf)) 650 return; 651 #endif 652 #ifdef DDB 653 /* Let DDB handle it. */ 654 if (kdb_trap(type, &tf)) 655 return; 656 #endif 657 658 /* Drop into the PROM temporarily... */ 659 (void)_nodb_trap(type, &tf); 660 } 661