1 /* $NetBSD: trap.c,v 1.59 2002/10/28 00:55:19 chs Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1986, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah $Hdr: trap.c 1.37 92/12/20$ 41 * 42 * @(#)trap.c 8.5 (Berkeley) 1/4/94 43 */ 44 45 #include "opt_ddb.h" 46 #include "opt_kgdb.h" 47 #include "opt_execfmt.h" 48 #include "opt_compat_sunos.h" 49 #include "opt_compat_hpux.h" 50 #include "opt_m680x0.h" 51 #include "opt_fpu_emulate.h" 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/proc.h> 56 #include <sys/acct.h> 57 #include <sys/kernel.h> 58 #include <sys/signalvar.h> 59 #include <sys/resourcevar.h> 60 #include <sys/syscall.h> 61 #include <sys/syslog.h> 62 #include <sys/user.h> 63 64 #include <machine/psl.h> 65 #include <machine/trap.h> 66 #include <machine/cpu.h> 67 #include <machine/reg.h> 68 #include <machine/db_machdep.h> 69 #include <m68k/cacheops.h> 70 71 #include <uvm/uvm_extern.h> 72 73 #include <dev/cons.h> 74 75 #ifdef FPU_EMULATE 76 #include <m68k/fpe/fpu_emulate.h> 77 #endif 78 79 #ifdef COMPAT_HPUX 80 #include <compat/hpux/hpux.h> 81 extern struct emul emul_hpux; 82 #endif 83 84 #ifdef COMPAT_SUNOS 85 #include <compat/sunos/sunos_exec.h> 86 #include <compat/sunos/sunos_syscall.h> 87 #endif 88 89 int writeback __P((struct frame *fp, int docachepush)); 90 void trap __P((int type, u_int code, u_int v, struct frame frame)); 91 92 #if defined(M68040) || defined(M68060) 93 #ifdef DEBUG 94 static void dumpssw __P((u_short)); 95 static void dumpwb __P((int, u_short, u_int, u_int)); 96 #endif 97 #endif 98 99 static inline void userret __P((struct proc *p, struct frame *fp, 100 u_quad_t oticks, u_int faultaddr, int fromtrap)); 101 102 int astpending; 103 104 char *trap_type[] = { 105 "Bus error", 106 "Address error", 107 "Illegal instruction", 108 "Zero divide", 109 "CHK instruction", 110 "TRAPV instruction", 111 "Privilege violation", 112 "Trace trap", 113 "MMU fault", 114 "SSIR trap", 115 "Format error", 116 "68881 exception", 117 "Coprocessor violation", 118 "Async system trap" 119 }; 120 int trap_types = sizeof trap_type / sizeof trap_type[0]; 121 122 /* 123 * Size of various exception stack frames (minus the standard 8 bytes) 124 */ 125 short exframesize[] = { 126 FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ 127 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 128 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ 129 FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ 130 FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ 131 -1, -1, /* type 5-6 - undefined */ 132 FMT7SIZE, /* type 7 - access error (68040) */ 133 58, /* type 8 - bus fault (68010) */ 134 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 135 FMTASIZE, /* type A - short bus fault (68020/030) */ 136 FMTBSIZE, /* type B - long bus fault (68020/030) */ 137 -1, -1, -1, -1 /* type C-F - undefined */ 138 }; 139 140 #ifdef M68060 141 #define KDFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_TM_SV)) 142 #define WRFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_RW_W)) 143 #else 144 #define KDFAULT_060(c) 0 145 #define WRFAULT_060(c) 0 146 #endif 147 148 #ifdef M68040 149 #define KDFAULT_040(c) (cputype == CPU_68040 && \ 150 ((c) & SSW4_TMMASK) == SSW4_TMKD) 151 #define WRFAULT_040(c) (cputype == CPU_68040 && \ 152 ((c) & SSW4_RW) == 0) 153 #else 154 #define KDFAULT_040(c) 0 155 #define WRFAULT_040(c) 0 156 #endif 157 158 #if defined(M68030) || defined(M68020) 159 #define KDFAULT_OTH(c) (cputype <= CPU_68030 && \ 160 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 161 #define WRFAULT_OTH(c) (cputype <= CPU_68030 && \ 162 ((c) & (SSW_DF|SSW_RW)) == SSW_DF) 163 #else 164 #define KDFAULT_OTH(c) 0 165 #define WRFAULT_OTH(c) 0 166 #endif 167 168 #define KDFAULT(c) (KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c)) 169 #define WRFAULT(c) (WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c)) 170 171 #ifdef DEBUG 172 int mmudebug = 0; 173 int mmupid = -1; 174 #define MDB_FOLLOW 1 175 #define MDB_WBFOLLOW 2 176 #define MDB_WBFAILED 4 177 #define MDB_ISPID(p) ((p) == mmupid) 178 #endif 179 180 /* 181 * trap and syscall both need the following work done before returning 182 * to user mode. 183 */ 184 static inline void 185 userret(p, fp, oticks, faultaddr, fromtrap) 186 struct proc *p; 187 struct frame *fp; 188 u_quad_t oticks; 189 u_int faultaddr; 190 int fromtrap; 191 { 192 int sig; 193 #ifdef M68040 194 int beenhere = 0; 195 196 again: 197 #endif 198 /* take pending signals */ 199 while ((sig = CURSIG(p)) != 0) 200 postsig(sig); 201 p->p_priority = p->p_usrpri; 202 if (want_resched) { 203 /* 204 * We are being preempted. 205 */ 206 preempt(NULL); 207 while ((sig = CURSIG(p)) != 0) 208 postsig(sig); 209 } 210 211 /* 212 * If profiling, charge system time to the trapped pc. 213 */ 214 if (p->p_flag & P_PROFIL) { 215 extern int psratio; 216 217 addupc_task(p, fp->f_pc, 218 (int)(p->p_sticks - oticks) * psratio); 219 } 220 #ifdef M68040 221 /* 222 * Deal with user mode writebacks (from trap, or from sigreturn). 223 * If any writeback fails, go back and attempt signal delivery. 224 * unless we have already been here and attempted the writeback 225 * (e.g. bad address with user ignoring SIGSEGV). In that case 226 * we just return to the user without sucessfully completing 227 * the writebacks. Maybe we should just drop the sucker? 228 */ 229 if (cputype == CPU_68040 && fp->f_format == FMT7) { 230 if (beenhere) { 231 #ifdef DEBUG 232 if (mmudebug & MDB_WBFAILED) 233 printf(fromtrap ? 234 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 235 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 236 p->p_pid, p->p_comm, fp->f_pc, faultaddr); 237 #endif 238 } else if ((sig = writeback(fp, fromtrap))) { 239 beenhere = 1; 240 oticks = p->p_sticks; 241 trapsignal(p, sig, faultaddr); 242 goto again; 243 } 244 } 245 #endif 246 curcpu()->ci_schedstate.spc_curpriority = p->p_priority; 247 } 248 249 /* 250 * Used by the common m68k syscall() and child_return() functions. 251 * XXX: Temporary until all m68k ports share common trap()/userret() code. 252 */ 253 void machine_userret(struct proc *, struct frame *, u_quad_t); 254 255 void 256 machine_userret(p, f, t) 257 struct proc *p; 258 struct frame *f; 259 u_quad_t t; 260 { 261 262 userret(p, f, t, 0, 0); 263 } 264 265 /* 266 * Trap is called from locore to handle most types of processor traps, 267 * including events such as simulated software interrupts/AST's. 268 * System calls are broken out for efficiency. 269 */ 270 /*ARGSUSED*/ 271 void 272 trap(type, code, v, frame) 273 int type; 274 unsigned code; 275 unsigned v; 276 struct frame frame; 277 { 278 extern char fubail[], subail[]; 279 struct proc *p; 280 int i, s; 281 u_int ucode; 282 u_quad_t sticks = 0 /* XXX initializer works around compiler bug */; 283 284 uvmexp.traps++; 285 p = curproc; 286 ucode = 0; 287 288 /* I have verified that this DOES happen! -gwr */ 289 if (p == NULL) 290 p = &proc0; 291 #ifdef DIAGNOSTIC 292 if (p->p_addr == NULL) 293 panic("trap: no pcb"); 294 #endif 295 296 if (USERMODE(frame.f_sr)) { 297 type |= T_USER; 298 sticks = p->p_sticks; 299 p->p_md.md_regs = frame.f_regs; 300 } 301 switch (type) { 302 303 default: 304 dopanic: 305 printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v); 306 printf("%s program counter = 0x%x\n", 307 (type & T_USER) ? "user" : "kernel", frame.f_pc); 308 /* 309 * Let the kernel debugger see the trap frame that 310 * caused us to panic. This is a convenience so 311 * one can see registers at the point of failure. 312 */ 313 s = splhigh(); 314 #ifdef KGDB 315 /* If connected, step or cont returns 1 */ 316 if (kgdb_trap(type, &frame)) 317 goto kgdb_cont; 318 #endif 319 #ifdef DDB 320 (void)kdb_trap(type, (db_regs_t *)&frame); 321 #endif 322 #ifdef KGDB 323 kgdb_cont: 324 #endif 325 splx(s); 326 if (panicstr) { 327 printf("trap during panic!\n"); 328 #ifdef DEBUG 329 /* XXX should be a machine-dependent hook */ 330 printf("(press a key)\n"); (void)cngetc(); 331 #endif 332 } 333 regdump((struct trapframe *)&frame, 128); 334 type &= ~T_USER; 335 if ((u_int)type < trap_types) 336 panic(trap_type[type]); 337 panic("trap"); 338 339 case T_BUSERR: /* kernel bus error */ 340 if (p->p_addr->u_pcb.pcb_onfault == 0) 341 goto dopanic; 342 /* FALLTHROUGH */ 343 344 copyfault: 345 /* 346 * If we have arranged to catch this fault in any of the 347 * copy to/from user space routines, set PC to return to 348 * indicated location and set flag informing buserror code 349 * that it may need to clean up stack frame. 350 */ 351 frame.f_stackadj = exframesize[frame.f_format]; 352 frame.f_format = frame.f_vector = 0; 353 frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 354 return; 355 356 case T_BUSERR|T_USER: /* bus error */ 357 case T_ADDRERR|T_USER: /* address error */ 358 ucode = v; 359 i = SIGBUS; 360 break; 361 362 case T_COPERR: /* kernel coprocessor violation */ 363 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 364 case T_FMTERR: /* ...just in case... */ 365 /* 366 * The user has most likely trashed the RTE or FP state info 367 * in the stack frame of a signal handler. 368 */ 369 printf("pid %d: kernel %s exception\n", p->p_pid, 370 type==T_COPERR ? "coprocessor" : "format"); 371 type |= T_USER; 372 SIGACTION(p, SIGILL).sa_handler = SIG_DFL; 373 sigdelset(&p->p_sigctx.ps_sigignore, SIGILL); 374 sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL); 375 sigdelset(&p->p_sigctx.ps_sigmask, SIGILL); 376 i = SIGILL; 377 ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 378 break; 379 380 case T_COPERR|T_USER: /* user coprocessor violation */ 381 /* What is a proper response here? */ 382 ucode = 0; 383 i = SIGFPE; 384 break; 385 386 case T_FPERR|T_USER: /* 68881 exceptions */ 387 /* 388 * We pass along the 68881 status which locore stashed 389 * in code for us. Note that there is a possibility that the 390 * bit pattern of this will conflict with one of the 391 * FPE_* codes defined in signal.h. Fortunately for us, the 392 * only such codes we use are all in the range 1-7 and the low 393 * 3 bits of the status are defined as 0 so there is 394 * no clash. 395 */ 396 ucode = code; 397 i = SIGFPE; 398 break; 399 400 /* 401 * FPU faults in supervisor mode. 402 */ 403 case T_ILLINST: /* fnop generates this, apparently. */ 404 case T_FPEMULI: 405 case T_FPEMULD: { 406 extern label_t *nofault; 407 408 if (nofault) /* If we're probing. */ 409 longjmp(nofault); 410 if (type == T_ILLINST) 411 printf("Kernel Illegal Instruction trap.\n"); 412 else 413 printf("Kernel FPU trap.\n"); 414 goto dopanic; 415 } 416 417 /* 418 * Unimplemented FPU instructions/datatypes. 419 */ 420 case T_FPEMULI|T_USER: /* unimplemented FP instuction */ 421 case T_FPEMULD|T_USER: /* unimplemented FP data type */ 422 #ifdef FPU_EMULATE 423 i = fpu_emulate(&frame, &p->p_addr->u_pcb.pcb_fpregs); 424 /* XXX -- deal with tracing? (frame.f_sr & PSL_T) */ 425 break; 426 #elif defined(M68040) || defined(M68060) 427 /* XXX need to FSAVE */ 428 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 429 p->p_pid, p->p_comm, 430 frame.f_format == 2 ? "instruction" : "data type", 431 frame.f_pc, frame.f_fmt2.f_iaddr); 432 /* XXX need to FRESTORE */ 433 i = SIGFPE; 434 break; 435 #endif 436 437 case T_ILLINST|T_USER: /* illegal instruction fault */ 438 #ifdef COMPAT_HPUX 439 if (p->p_emul == &emul_hpux) { 440 ucode = HPUX_ILL_ILLINST_TRAP; 441 i = SIGILL; 442 break; 443 } 444 /* fall through */ 445 #endif 446 case T_PRIVINST|T_USER: /* privileged instruction fault */ 447 #ifdef COMPAT_HPUX 448 if (p->p_emul == &emul_hpux) 449 ucode = HPUX_ILL_PRIV_TRAP; 450 else 451 #endif 452 ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 453 i = SIGILL; 454 break; 455 456 case T_ZERODIV|T_USER: /* Divide by zero */ 457 #ifdef COMPAT_HPUX 458 if (p->p_emul == &emul_hpux) 459 ucode = HPUX_FPE_INTDIV_TRAP; 460 else 461 #endif 462 ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 463 i = SIGFPE; 464 break; 465 466 case T_CHKINST|T_USER: /* CHK instruction trap */ 467 #ifdef COMPAT_HPUX 468 if (p->p_emul == &emul_hpux) { 469 /* handled differently under hp-ux */ 470 i = SIGILL; 471 ucode = HPUX_ILL_CHK_TRAP; 472 break; 473 } 474 #endif 475 ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 476 i = SIGFPE; 477 break; 478 479 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 480 #ifdef COMPAT_HPUX 481 if (p->p_emul == &emul_hpux) { 482 /* handled differently under hp-ux */ 483 i = SIGILL; 484 ucode = HPUX_ILL_TRAPV_TRAP; 485 break; 486 } 487 #endif 488 ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 489 i = SIGFPE; 490 break; 491 492 /* 493 * XXX: Trace traps are a nightmare. 494 * 495 * HP-UX uses trap #1 for breakpoints, 496 * NetBSD/m68k uses trap #2, 497 * SUN 3.x uses trap #15, 498 * DDB and KGDB uses trap #15 (for kernel breakpoints; 499 * handled elsewhere). 500 * 501 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 502 * SUN 3.x traps get passed through as T_TRAP15 and are not really 503 * supported yet. 504 * 505 * XXX: We should never get kernel-mode T_TRAP15 506 * XXX: because locore.s now gives them special treatment. 507 */ 508 case T_TRAP15: /* kernel breakpoint */ 509 #ifdef DEBUG 510 printf("unexpected kernel trace trap, type = %d\n", type); 511 printf("program counter = 0x%x\n", frame.f_pc); 512 #endif 513 frame.f_sr &= ~PSL_T; 514 return; 515 516 case T_TRACE|T_USER: /* user trace trap */ 517 #ifdef COMPAT_SUNOS 518 /* 519 * SunOS uses Trap #2 for a "CPU cache flush". 520 * Just flush the on-chip caches and return. 521 */ 522 if (p->p_emul == &emul_sunos) { 523 ICIA(); 524 DCIU(); 525 return; 526 } 527 #endif 528 /* FALLTHROUGH */ 529 case T_TRACE: /* tracing a trap instruction */ 530 case T_TRAP15|T_USER: /* SUN user trace trap */ 531 frame.f_sr &= ~PSL_T; 532 i = SIGTRAP; 533 break; 534 535 case T_ASTFLT: /* system async trap, cannot happen */ 536 goto dopanic; 537 538 case T_ASTFLT|T_USER: /* user async trap */ 539 astpending = 0; 540 /* 541 * We check for software interrupts first. This is because 542 * they are at a higher level than ASTs, and on a VAX would 543 * interrupt the AST. We assume that if we are processing 544 * an AST that we must be at IPL0 so we don't bother to 545 * check. Note that we ensure that we are at least at SIR 546 * IPL while processing the SIR. 547 */ 548 spl1(); 549 /* fall into... */ 550 551 case T_SSIR: /* software interrupt */ 552 case T_SSIR|T_USER: 553 if (ssir & SIR_NET) { 554 void netintr __P((void)); 555 siroff(SIR_NET); 556 uvmexp.softs++; 557 netintr(); 558 } 559 if (ssir & SIR_CLOCK) { 560 siroff(SIR_CLOCK); 561 uvmexp.softs++; 562 softclock(NULL); 563 } 564 if (ssir & SIR_SERIAL) { 565 #include "zsc.h" 566 #if NZSC > 0 567 void zssoft __P((int)); 568 #endif 569 siroff(SIR_SERIAL); 570 uvmexp.softs++; 571 #if NZSC > 0 572 zssoft(0); 573 #endif 574 } 575 if (ssir & SIR_KBD) { 576 #include "kbd.h" 577 #if NKBD > 0 578 void kbdsoftint __P((void)); 579 #endif 580 siroff(SIR_KBD); 581 uvmexp.softs++; 582 #if NKBD > 0 583 kbdsoftint(); 584 #endif 585 } 586 /* 587 * If this was not an AST trap, we are all done. 588 */ 589 if (type != (T_ASTFLT|T_USER)) { 590 uvmexp.traps--; 591 return; 592 } 593 spl0(); 594 if (p->p_flag & P_OWEUPC) { 595 p->p_flag &= ~P_OWEUPC; 596 ADDUPROF(p); 597 } 598 goto out; 599 600 case T_MMUFLT: /* kernel mode page fault */ 601 /* 602 * If we were doing profiling ticks or other user mode 603 * stuff from interrupt code, Just Say No. 604 */ 605 if (p->p_addr->u_pcb.pcb_onfault == fubail || 606 p->p_addr->u_pcb.pcb_onfault == subail) 607 goto copyfault; 608 /* fall into ... */ 609 610 case T_MMUFLT|T_USER: /* page fault */ 611 { 612 vaddr_t va; 613 struct vmspace *vm = p->p_vmspace; 614 struct vm_map *map; 615 int rv; 616 vm_prot_t ftype; 617 extern struct vm_map *kernel_map; 618 619 #ifdef DEBUG 620 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 621 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 622 p->p_pid, code, v, frame.f_pc, frame.f_sr); 623 #endif 624 /* 625 * It is only a kernel address space fault iff: 626 * 1. (type & T_USER) == 0 and 627 * 2. pcb_onfault not set or 628 * 3. pcb_onfault set but supervisor space data fault 629 * The last can occur during an exec() copyin where the 630 * argument space is lazy-allocated. 631 */ 632 if ((type & T_USER) == 0 && 633 ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code))) 634 map = kernel_map; 635 else 636 map = vm ? &vm->vm_map : kernel_map; 637 638 if (WRFAULT(code)) 639 ftype = VM_PROT_WRITE; 640 else 641 ftype = VM_PROT_READ; 642 643 va = trunc_page((vaddr_t)v); 644 645 if (map == kernel_map && va == 0) { 646 printf("trap: bad kernel %s access at 0x%x\n", 647 (ftype & VM_PROT_WRITE) ? "read/write" : 648 "read", v); 649 goto dopanic; 650 } 651 652 #ifdef COMPAT_HPUX 653 if (ISHPMMADDR(va)) { 654 int pmap_mapmulti __P((pmap_t, vaddr_t)); 655 vaddr_t bva; 656 657 rv = pmap_mapmulti(map->pmap, va); 658 if (rv != 0) { 659 bva = HPMMBASEADDR(va); 660 rv = uvm_fault(map, bva, 0, ftype); 661 if (rv == 0) 662 (void) pmap_mapmulti(map->pmap, va); 663 } 664 } else 665 #endif 666 rv = uvm_fault(map, va, 0, ftype); 667 #ifdef DEBUG 668 if (rv && MDB_ISPID(p->p_pid)) 669 printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", 670 map, va, ftype, rv); 671 #endif 672 /* 673 * If this was a stack access we keep track of the maximum 674 * accessed stack size. Also, if vm_fault gets a protection 675 * failure it is due to accessing the stack region outside 676 * the current limit and we need to reflect that as an access 677 * error. 678 */ 679 if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr) 680 && map != kernel_map) { 681 if (rv == 0) { 682 unsigned nss; 683 684 nss = btoc(USRSTACK-(unsigned)va); 685 if (nss > vm->vm_ssize) 686 vm->vm_ssize = nss; 687 } else if (rv == EACCES) 688 rv = EFAULT; 689 } 690 if (rv == 0) { 691 if (type == T_MMUFLT) { 692 #ifdef M68040 693 if (cputype == CPU_68040) 694 (void) writeback(&frame, 1); 695 #endif 696 return; 697 } 698 goto out; 699 } 700 if (type == T_MMUFLT) { 701 if (p->p_addr->u_pcb.pcb_onfault) 702 goto copyfault; 703 printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", 704 map, va, ftype, rv); 705 printf(" type %x, code [mmu,,ssw]: %x\n", 706 type, code); 707 goto dopanic; 708 } 709 ucode = v; 710 if (rv == ENOMEM) { 711 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 712 p->p_pid, p->p_comm, 713 p->p_cred && p->p_ucred ? 714 p->p_ucred->cr_uid : -1); 715 i = SIGKILL; 716 } else { 717 i = SIGSEGV; 718 } 719 break; 720 } 721 } 722 if (i) 723 trapsignal(p, i, ucode); 724 if ((type & T_USER) == 0) 725 return; 726 out: 727 userret(p, &frame, sticks, v, 1); 728 } 729 730 #ifdef M68040 731 #ifdef DEBUG 732 struct writebackstats { 733 int calls; 734 int cpushes; 735 int move16s; 736 int wb1s, wb2s, wb3s; 737 int wbsize[4]; 738 } wbstats; 739 740 char *f7sz[] = { "longword", "byte", "word", "line" }; 741 char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 742 char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 743 "M-code", "k-data", "k-code", "RES" }; 744 char wberrstr[] = 745 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 746 #endif 747 748 int 749 writeback(fp, docachepush) 750 struct frame *fp; 751 int docachepush; 752 { 753 struct fmt7 *f = &fp->f_fmt7; 754 struct proc *p = curproc; 755 int err = 0; 756 u_int fa; 757 caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault; 758 paddr_t pa; 759 760 #ifdef DEBUG 761 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 762 printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); 763 dumpssw(f->f_ssw); 764 } 765 wbstats.calls++; 766 #endif 767 /* 768 * Deal with special cases first. 769 */ 770 if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { 771 /* 772 * Dcache push fault. 773 * Line-align the address and write out the push data to 774 * the indicated physical address. 775 */ 776 #ifdef DEBUG 777 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 778 printf(" pushing %s to PA %x, data %x", 779 f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], 780 f->f_fa, f->f_pd0); 781 if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) 782 printf("/%x/%x/%x", 783 f->f_pd1, f->f_pd2, f->f_pd3); 784 printf("\n"); 785 } 786 if (f->f_wb1s & SSW4_WBSV) 787 panic("writeback: cache push with WB1S valid"); 788 wbstats.cpushes++; 789 #endif 790 /* 791 * XXX there are security problems if we attempt to do a 792 * cache push after a signal handler has been called. 793 */ 794 if (docachepush) { 795 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, 796 trunc_page(f->f_fa), VM_PROT_WRITE, 797 VM_PROT_WRITE|PMAP_WIRED); 798 pmap_update(pmap_kernel()); 799 fa = (u_int)&vmmap[m68k_page_offset(f->f_fa) & ~0xF]; 800 memcpy((caddr_t)fa, (caddr_t)&f->f_pd0, 16); 801 (void) pmap_extract(pmap_kernel(), (paddr_t)fa, &pa); 802 DCFL(pa); 803 pmap_remove(pmap_kernel(), (vaddr_t)vmmap, 804 (vaddr_t)&vmmap[NBPG]); 805 pmap_update(pmap_kernel()); 806 } else 807 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 808 p->p_pid, p->p_comm, p->p_ucred->cr_uid); 809 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 810 /* 811 * MOVE16 fault. 812 * Line-align the address and write out the push data to 813 * the indicated virtual address. 814 */ 815 #ifdef DEBUG 816 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 817 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 818 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 819 f->f_pd2, f->f_pd3); 820 if (f->f_wb1s & SSW4_WBSV) 821 panic("writeback: MOVE16 with WB1S valid"); 822 wbstats.move16s++; 823 #endif 824 if (KDFAULT(f->f_wb1s)) 825 memcpy((caddr_t)(f->f_fa & ~0xF), 826 (caddr_t)&f->f_pd0, 16); 827 else 828 err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0); 829 if (err) { 830 fa = f->f_fa & ~0xF; 831 #ifdef DEBUG 832 if (mmudebug & MDB_WBFAILED) 833 printf(wberrstr, p->p_pid, p->p_comm, 834 "MOVE16", fp->f_pc, f->f_fa, 835 f->f_fa & ~0xF, f->f_pd0); 836 #endif 837 } 838 } else if (f->f_wb1s & SSW4_WBSV) { 839 /* 840 * Writeback #1. 841 * Position the "memory-aligned" data and write it out. 842 */ 843 u_int wb1d = f->f_wb1d; 844 int off; 845 846 #ifdef DEBUG 847 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 848 dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 849 wbstats.wb1s++; 850 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 851 #endif 852 off = (f->f_wb1a & 3) * 8; 853 switch (f->f_wb1s & SSW4_SZMASK) { 854 case SSW4_SZLW: 855 if (off) 856 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 857 if (KDFAULT(f->f_wb1s)) 858 *(long *)f->f_wb1a = wb1d; 859 else 860 err = suword((caddr_t)f->f_wb1a, wb1d); 861 break; 862 case SSW4_SZB: 863 off = 24 - off; 864 if (off) 865 wb1d >>= off; 866 if (KDFAULT(f->f_wb1s)) 867 *(char *)f->f_wb1a = wb1d; 868 else 869 err = subyte((caddr_t)f->f_wb1a, wb1d); 870 break; 871 case SSW4_SZW: 872 off = (off + 16) % 32; 873 if (off) 874 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 875 if (KDFAULT(f->f_wb1s)) 876 *(short *)f->f_wb1a = wb1d; 877 else 878 err = susword((caddr_t)f->f_wb1a, wb1d); 879 break; 880 } 881 if (err) { 882 fa = f->f_wb1a; 883 #ifdef DEBUG 884 if (mmudebug & MDB_WBFAILED) 885 printf(wberrstr, p->p_pid, p->p_comm, 886 "#1", fp->f_pc, f->f_fa, 887 f->f_wb1a, f->f_wb1d); 888 #endif 889 } 890 } 891 /* 892 * Deal with the "normal" writebacks. 893 * 894 * XXX writeback2 is known to reflect a LINE size writeback after 895 * a MOVE16 was already dealt with above. Ignore it. 896 */ 897 if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 898 (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 899 #ifdef DEBUG 900 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 901 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 902 wbstats.wb2s++; 903 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 904 #endif 905 switch (f->f_wb2s & SSW4_SZMASK) { 906 case SSW4_SZLW: 907 if (KDFAULT(f->f_wb2s)) 908 *(long *)f->f_wb2a = f->f_wb2d; 909 else 910 err = suword((caddr_t)f->f_wb2a, f->f_wb2d); 911 break; 912 case SSW4_SZB: 913 if (KDFAULT(f->f_wb2s)) 914 *(char *)f->f_wb2a = f->f_wb2d; 915 else 916 err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); 917 break; 918 case SSW4_SZW: 919 if (KDFAULT(f->f_wb2s)) 920 *(short *)f->f_wb2a = f->f_wb2d; 921 else 922 err = susword((caddr_t)f->f_wb2a, f->f_wb2d); 923 break; 924 } 925 if (err) { 926 fa = f->f_wb2a; 927 #ifdef DEBUG 928 if (mmudebug & MDB_WBFAILED) { 929 printf(wberrstr, p->p_pid, p->p_comm, 930 "#2", fp->f_pc, f->f_fa, 931 f->f_wb2a, f->f_wb2d); 932 dumpssw(f->f_ssw); 933 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 934 } 935 #endif 936 } 937 } 938 if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 939 #ifdef DEBUG 940 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 941 dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 942 wbstats.wb3s++; 943 wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 944 #endif 945 switch (f->f_wb3s & SSW4_SZMASK) { 946 case SSW4_SZLW: 947 if (KDFAULT(f->f_wb3s)) 948 *(long *)f->f_wb3a = f->f_wb3d; 949 else 950 err = suword((caddr_t)f->f_wb3a, f->f_wb3d); 951 break; 952 case SSW4_SZB: 953 if (KDFAULT(f->f_wb3s)) 954 *(char *)f->f_wb3a = f->f_wb3d; 955 else 956 err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); 957 break; 958 case SSW4_SZW: 959 if (KDFAULT(f->f_wb3s)) 960 *(short *)f->f_wb3a = f->f_wb3d; 961 else 962 err = susword((caddr_t)f->f_wb3a, f->f_wb3d); 963 break; 964 #ifdef DEBUG 965 case SSW4_SZLN: 966 panic("writeback: wb3s indicates LINE write"); 967 #endif 968 } 969 if (err) { 970 fa = f->f_wb3a; 971 #ifdef DEBUG 972 if (mmudebug & MDB_WBFAILED) 973 printf(wberrstr, p->p_pid, p->p_comm, 974 "#3", fp->f_pc, f->f_fa, 975 f->f_wb3a, f->f_wb3d); 976 #endif 977 } 978 } 979 p->p_addr->u_pcb.pcb_onfault = oonfault; 980 if (err) 981 err = SIGSEGV; 982 return (err); 983 } 984 985 #ifdef DEBUG 986 static void 987 dumpssw(ssw) 988 u_short ssw; 989 { 990 printf(" SSW: %x: ", ssw); 991 if (ssw & SSW4_CP) 992 printf("CP,"); 993 if (ssw & SSW4_CU) 994 printf("CU,"); 995 if (ssw & SSW4_CT) 996 printf("CT,"); 997 if (ssw & SSW4_CM) 998 printf("CM,"); 999 if (ssw & SSW4_MA) 1000 printf("MA,"); 1001 if (ssw & SSW4_ATC) 1002 printf("ATC,"); 1003 if (ssw & SSW4_LK) 1004 printf("LK,"); 1005 if (ssw & SSW4_RW) 1006 printf("RW,"); 1007 printf(" SZ=%s, TT=%s, TM=%s\n", 1008 f7sz[(ssw & SSW4_SZMASK) >> 5], 1009 f7tt[(ssw & SSW4_TTMASK) >> 3], 1010 f7tm[ssw & SSW4_TMMASK]); 1011 } 1012 1013 static void 1014 dumpwb(num, s, a, d) 1015 int num; 1016 u_short s; 1017 u_int a, d; 1018 { 1019 struct proc *p = curproc; 1020 paddr_t pa; 1021 1022 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 1023 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 1024 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 1025 printf(" PA "); 1026 if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE) 1027 printf("<invalid address>"); 1028 else 1029 printf("%lx, current value %lx", pa, fuword((caddr_t)a)); 1030 printf("\n"); 1031 } 1032 #endif 1033 #endif 1034