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