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