1 /* $NetBSD: trap.c,v 1.97 2002/10/20 02:37:26 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 <sys/cdefs.h> 46 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.97 2002/10/20 02:37:26 chs Exp $"); 47 48 #include "opt_ddb.h" 49 #include "opt_execfmt.h" 50 #include "opt_kgdb.h" 51 #include "opt_compat_sunos.h" 52 #include "opt_compat_hpux.h" 53 54 #include <machine/hp300spu.h> /* XXX param.h includes cpu.h */ 55 56 #include <sys/param.h> 57 #include <sys/systm.h> 58 #include <sys/proc.h> 59 #include <sys/acct.h> 60 #include <sys/kernel.h> 61 #include <sys/signalvar.h> 62 #include <sys/ras.h> 63 #include <sys/resourcevar.h> 64 #include <sys/syscall.h> 65 #include <sys/syslog.h> 66 #include <sys/user.h> 67 68 #include <m68k/frame.h> 69 #include <m68k/cacheops.h> 70 71 #include <machine/db_machdep.h> 72 #include <machine/psl.h> 73 #include <machine/trap.h> 74 #include <machine/cpu.h> 75 #include <machine/reg.h> 76 #include <machine/intr.h> 77 78 #include <uvm/uvm_extern.h> 79 80 #include <dev/cons.h> 81 82 #ifdef COMPAT_HPUX 83 #include <compat/hpux/hpux.h> 84 #endif 85 86 #ifdef COMPAT_SUNOS 87 #include <compat/sunos/sunos_syscall.h> 88 extern struct emul emul_sunos; 89 #endif 90 91 int writeback __P((struct frame *fp, int docachepush)); 92 void trap __P((int type, u_int code, u_int v, struct frame frame)); 93 94 #ifdef DEBUG 95 void dumpssw __P((u_short)); 96 void dumpwb __P((int, u_short, u_int, u_int)); 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 #ifdef M68040 401 case T_FPEMULI|T_USER: /* unimplemented FP instuction */ 402 case T_FPEMULD|T_USER: /* unimplemented FP data type */ 403 /* XXX need to FSAVE */ 404 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 405 p->p_pid, p->p_comm, 406 frame.f_format == 2 ? "instruction" : "data type", 407 frame.f_pc, frame.f_fmt2.f_iaddr); 408 /* XXX need to FRESTORE */ 409 i = SIGFPE; 410 break; 411 #endif 412 413 case T_ILLINST|T_USER: /* illegal instruction fault */ 414 #ifdef COMPAT_HPUX 415 if (p->p_emul == &emul_hpux) { 416 ucode = HPUX_ILL_ILLINST_TRAP; 417 i = SIGILL; 418 break; 419 } 420 /* fall through */ 421 #endif 422 case T_PRIVINST|T_USER: /* privileged instruction fault */ 423 #ifdef COMPAT_HPUX 424 if (p->p_emul == &emul_hpux) 425 ucode = HPUX_ILL_PRIV_TRAP; 426 else 427 #endif 428 ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 429 i = SIGILL; 430 break; 431 432 case T_ZERODIV|T_USER: /* Divide by zero */ 433 #ifdef COMPAT_HPUX 434 if (p->p_emul == &emul_hpux) 435 ucode = HPUX_FPE_INTDIV_TRAP; 436 else 437 #endif 438 ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 439 i = SIGFPE; 440 break; 441 442 case T_CHKINST|T_USER: /* CHK instruction trap */ 443 #ifdef COMPAT_HPUX 444 if (p->p_emul == &emul_hpux) { 445 /* handled differently under hp-ux */ 446 i = SIGILL; 447 ucode = HPUX_ILL_CHK_TRAP; 448 break; 449 } 450 #endif 451 ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 452 i = SIGFPE; 453 break; 454 455 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 456 #ifdef COMPAT_HPUX 457 if (p->p_emul == &emul_hpux) { 458 /* handled differently under hp-ux */ 459 i = SIGILL; 460 ucode = HPUX_ILL_TRAPV_TRAP; 461 break; 462 } 463 #endif 464 ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 465 i = SIGFPE; 466 break; 467 468 /* 469 * XXX: Trace traps are a nightmare. 470 * 471 * HP-UX uses trap #1 for breakpoints, 472 * NetBSD/m68k uses trap #2, 473 * SUN 3.x uses trap #15, 474 * DDB and KGDB uses trap #15 (for kernel breakpoints; 475 * handled elsewhere). 476 * 477 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 478 * SUN 3.x traps get passed through as T_TRAP15 and are not really 479 * supported yet. 480 * 481 * XXX: We should never get kernel-mode T_TRAP15 482 * XXX: because locore.s now gives them special treatment. 483 */ 484 case T_TRAP15: /* kernel breakpoint */ 485 #ifdef DEBUG 486 printf("unexpected kernel trace trap, type = %d\n", type); 487 printf("program counter = 0x%x\n", frame.f_pc); 488 #endif 489 frame.f_sr &= ~PSL_T; 490 return; 491 492 case T_TRACE|T_USER: /* user trace trap */ 493 #ifdef COMPAT_SUNOS 494 /* 495 * SunOS uses Trap #2 for a "CPU cache flush". 496 * Just flush the on-chip caches and return. 497 */ 498 if (p->p_emul == &emul_sunos) { 499 ICIA(); 500 DCIU(); 501 return; 502 } 503 #endif 504 /* FALLTHROUGH */ 505 case T_TRACE: /* tracing a trap instruction */ 506 case T_TRAP15|T_USER: /* SUN user trace trap */ 507 /* 508 * Don't go stepping into a RAS. 509 */ 510 if ((p->p_nras != 0) && 511 (ras_lookup(p, (caddr_t)frame.f_pc) != (caddr_t)-1)) 512 goto out; 513 frame.f_sr &= ~PSL_T; 514 i = SIGTRAP; 515 break; 516 517 case T_ASTFLT: /* system async trap, cannot happen */ 518 goto dopanic; 519 520 case T_ASTFLT|T_USER: /* user async trap */ 521 astpending = 0; 522 /* 523 * We check for software interrupts first. This is because 524 * they are at a higher level than ASTs, and on a VAX would 525 * interrupt the AST. We assume that if we are processing 526 * an AST that we must be at IPL0 so we don't bother to 527 * check. Note that we ensure that we are at least at SIR 528 * IPL while processing the SIR. 529 */ 530 spl1(); 531 /* fall into... */ 532 533 case T_SSIR: /* software interrupt */ 534 case T_SSIR|T_USER: 535 536 softintr_dispatch(); 537 538 /* 539 * If this was not an AST trap, we are all done. 540 */ 541 if (type != (T_ASTFLT|T_USER)) { 542 uvmexp.traps--; 543 return; 544 } 545 spl0(); 546 if (p->p_flag & P_OWEUPC) { 547 p->p_flag &= ~P_OWEUPC; 548 ADDUPROF(p); 549 } 550 goto out; 551 552 case T_MMUFLT: /* kernel mode page fault */ 553 /* 554 * If we were doing profiling ticks or other user mode 555 * stuff from interrupt code, Just Say No. 556 */ 557 if (p->p_addr->u_pcb.pcb_onfault == fubail || 558 p->p_addr->u_pcb.pcb_onfault == subail) 559 goto copyfault; 560 /* fall into ... */ 561 562 case T_MMUFLT|T_USER: /* page fault */ 563 { 564 vaddr_t va; 565 struct vmspace *vm = p->p_vmspace; 566 struct vm_map *map; 567 int rv; 568 vm_prot_t ftype; 569 extern struct vm_map *kernel_map; 570 571 #ifdef DEBUG 572 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 573 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 574 p->p_pid, code, v, frame.f_pc, frame.f_sr); 575 #endif 576 /* 577 * It is only a kernel address space fault iff: 578 * 1. (type & T_USER) == 0 and 579 * 2. pcb_onfault not set or 580 * 3. pcb_onfault set but supervisor space data fault 581 * The last can occur during an exec() copyin where the 582 * argument space is lazy-allocated. 583 */ 584 if ((type & T_USER) == 0 && 585 ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code))) 586 map = kernel_map; 587 else 588 map = vm ? &vm->vm_map : kernel_map; 589 590 if (WRFAULT(code)) 591 ftype = VM_PROT_READ | VM_PROT_WRITE; 592 else 593 ftype = VM_PROT_READ; 594 595 va = trunc_page((vaddr_t)v); 596 597 if (map == kernel_map && va == 0) { 598 printf("trap: bad kernel %s access at 0x%x\n", 599 (ftype & VM_PROT_WRITE) ? "read/write" : 600 "read", v); 601 goto dopanic; 602 } 603 604 #ifdef COMPAT_HPUX 605 if (ISHPMMADDR(va)) { 606 int pmap_mapmulti __P((pmap_t, vaddr_t)); 607 vaddr_t bva; 608 609 rv = pmap_mapmulti(map->pmap, va); 610 if (rv != 0) { 611 bva = HPMMBASEADDR(va); 612 rv = uvm_fault(map, bva, 0, ftype); 613 if (rv == 0) 614 (void) pmap_mapmulti(map->pmap, va); 615 } 616 } else 617 #endif 618 rv = uvm_fault(map, va, 0, ftype); 619 #ifdef DEBUG 620 if (rv && MDB_ISPID(p->p_pid)) 621 printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", 622 map, va, ftype, rv); 623 #endif 624 /* 625 * If this was a stack access we keep track of the maximum 626 * accessed stack size. Also, if vm_fault gets a protection 627 * failure it is due to accessing the stack region outside 628 * the current limit and we need to reflect that as an access 629 * error. 630 */ 631 if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr) 632 && map != kernel_map) { 633 if (rv == 0) { 634 unsigned nss; 635 636 nss = btoc(USRSTACK-(unsigned)va); 637 if (nss > vm->vm_ssize) 638 vm->vm_ssize = nss; 639 } else if (rv == EACCES) 640 rv = EFAULT; 641 } 642 if (rv == 0) { 643 if (type == T_MMUFLT) { 644 #ifdef M68040 645 if (cputype == CPU_68040) 646 (void) writeback(&frame, 1); 647 #endif 648 return; 649 } 650 goto out; 651 } 652 if (type == T_MMUFLT) { 653 if (p->p_addr->u_pcb.pcb_onfault) 654 goto copyfault; 655 printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", 656 map, va, ftype, rv); 657 printf(" type %x, code [mmu,,ssw]: %x\n", 658 type, code); 659 goto dopanic; 660 } 661 ucode = v; 662 if (rv == ENOMEM) { 663 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 664 p->p_pid, p->p_comm, 665 p->p_cred && p->p_ucred ? 666 p->p_ucred->cr_uid : -1); 667 i = SIGKILL; 668 } else { 669 i = SIGSEGV; 670 } 671 break; 672 } 673 } 674 trapsignal(p, i, ucode); 675 if ((type & T_USER) == 0) 676 return; 677 out: 678 userret(p, &frame, sticks, v, 1); 679 } 680 681 #ifdef M68040 682 #ifdef DEBUG 683 struct writebackstats { 684 int calls; 685 int cpushes; 686 int move16s; 687 int wb1s, wb2s, wb3s; 688 int wbsize[4]; 689 } wbstats; 690 691 char *f7sz[] = { "longword", "byte", "word", "line" }; 692 char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 693 char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 694 "M-code", "k-data", "k-code", "RES" }; 695 char wberrstr[] = 696 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 697 #endif 698 699 int 700 writeback(fp, docachepush) 701 struct frame *fp; 702 int docachepush; 703 { 704 struct fmt7 *f = &fp->f_fmt7; 705 struct proc *p = curproc; 706 int err = 0; 707 u_int fa; 708 caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault; 709 paddr_t pa; 710 711 #ifdef DEBUG 712 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 713 printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); 714 dumpssw(f->f_ssw); 715 } 716 wbstats.calls++; 717 #endif 718 /* 719 * Deal with special cases first. 720 */ 721 if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { 722 /* 723 * Dcache push fault. 724 * Line-align the address and write out the push data to 725 * the indicated physical address. 726 */ 727 #ifdef DEBUG 728 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 729 printf(" pushing %s to PA %x, data %x", 730 f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], 731 f->f_fa, f->f_pd0); 732 if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) 733 printf("/%x/%x/%x", 734 f->f_pd1, f->f_pd2, f->f_pd3); 735 printf("\n"); 736 } 737 if (f->f_wb1s & SSW4_WBSV) 738 panic("writeback: cache push with WB1S valid"); 739 wbstats.cpushes++; 740 #endif 741 /* 742 * XXX there are security problems if we attempt to do a 743 * cache push after a signal handler has been called. 744 */ 745 if (docachepush) { 746 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, 747 trunc_page(f->f_fa), VM_PROT_WRITE, 748 VM_PROT_WRITE|PMAP_WIRED); 749 pmap_update(pmap_kernel()); 750 fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 751 memcpy((caddr_t)fa, (caddr_t)&f->f_pd0, 16); 752 (void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa); 753 DCFL(pa); 754 pmap_remove(pmap_kernel(), (vaddr_t)vmmap, 755 (vaddr_t)&vmmap[NBPG]); 756 pmap_update(pmap_kernel()); 757 } else 758 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 759 p->p_pid, p->p_comm, p->p_ucred->cr_uid); 760 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 761 /* 762 * MOVE16 fault. 763 * Line-align the address and write out the push data to 764 * the indicated virtual address. 765 */ 766 #ifdef DEBUG 767 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 768 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 769 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 770 f->f_pd2, f->f_pd3); 771 if (f->f_wb1s & SSW4_WBSV) 772 panic("writeback: MOVE16 with WB1S valid"); 773 wbstats.move16s++; 774 #endif 775 if (KDFAULT(f->f_wb1s)) 776 memcpy((caddr_t)(f->f_fa & ~0xF), 777 (caddr_t)&f->f_pd0, 16); 778 else 779 err = suline((caddr_t)(f->f_fa & ~0xF), 780 (caddr_t)&f->f_pd0); 781 if (err) { 782 fa = f->f_fa & ~0xF; 783 #ifdef DEBUG 784 if (mmudebug & MDB_WBFAILED) 785 printf(wberrstr, p->p_pid, p->p_comm, 786 "MOVE16", fp->f_pc, f->f_fa, 787 f->f_fa & ~0xF, f->f_pd0); 788 #endif 789 } 790 } else if (f->f_wb1s & SSW4_WBSV) { 791 /* 792 * Writeback #1. 793 * Position the "memory-aligned" data and write it out. 794 */ 795 u_int wb1d = f->f_wb1d; 796 int off; 797 798 #ifdef DEBUG 799 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 800 dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 801 wbstats.wb1s++; 802 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 803 #endif 804 off = (f->f_wb1a & 3) * 8; 805 switch (f->f_wb1s & SSW4_SZMASK) { 806 case SSW4_SZLW: 807 if (off) 808 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 809 if (KDFAULT(f->f_wb1s)) 810 *(long *)f->f_wb1a = wb1d; 811 else 812 err = suword((caddr_t)f->f_wb1a, wb1d); 813 break; 814 case SSW4_SZB: 815 off = 24 - off; 816 if (off) 817 wb1d >>= off; 818 if (KDFAULT(f->f_wb1s)) 819 *(char *)f->f_wb1a = wb1d; 820 else 821 err = subyte((caddr_t)f->f_wb1a, wb1d); 822 break; 823 case SSW4_SZW: 824 off = (off + 16) % 32; 825 if (off) 826 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 827 if (KDFAULT(f->f_wb1s)) 828 *(short *)f->f_wb1a = wb1d; 829 else 830 err = susword((caddr_t)f->f_wb1a, wb1d); 831 break; 832 } 833 if (err) { 834 fa = f->f_wb1a; 835 #ifdef DEBUG 836 if (mmudebug & MDB_WBFAILED) 837 printf(wberrstr, p->p_pid, p->p_comm, 838 "#1", fp->f_pc, f->f_fa, 839 f->f_wb1a, f->f_wb1d); 840 #endif 841 } 842 } 843 /* 844 * Deal with the "normal" writebacks. 845 * 846 * XXX writeback2 is known to reflect a LINE size writeback after 847 * a MOVE16 was already dealt with above. Ignore it. 848 */ 849 if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 850 (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 851 #ifdef DEBUG 852 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 853 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 854 wbstats.wb2s++; 855 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 856 #endif 857 switch (f->f_wb2s & SSW4_SZMASK) { 858 case SSW4_SZLW: 859 if (KDFAULT(f->f_wb2s)) 860 *(long *)f->f_wb2a = f->f_wb2d; 861 else 862 err = suword((caddr_t)f->f_wb2a, f->f_wb2d); 863 break; 864 case SSW4_SZB: 865 if (KDFAULT(f->f_wb2s)) 866 *(char *)f->f_wb2a = f->f_wb2d; 867 else 868 err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); 869 break; 870 case SSW4_SZW: 871 if (KDFAULT(f->f_wb2s)) 872 *(short *)f->f_wb2a = f->f_wb2d; 873 else 874 err = susword((caddr_t)f->f_wb2a, f->f_wb2d); 875 break; 876 } 877 if (err) { 878 fa = f->f_wb2a; 879 #ifdef DEBUG 880 if (mmudebug & MDB_WBFAILED) { 881 printf(wberrstr, p->p_pid, p->p_comm, 882 "#2", fp->f_pc, f->f_fa, 883 f->f_wb2a, f->f_wb2d); 884 dumpssw(f->f_ssw); 885 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 886 } 887 #endif 888 } 889 } 890 if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 891 #ifdef DEBUG 892 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 893 dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 894 wbstats.wb3s++; 895 wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 896 #endif 897 switch (f->f_wb3s & SSW4_SZMASK) { 898 case SSW4_SZLW: 899 if (KDFAULT(f->f_wb3s)) 900 *(long *)f->f_wb3a = f->f_wb3d; 901 else 902 err = suword((caddr_t)f->f_wb3a, f->f_wb3d); 903 break; 904 case SSW4_SZB: 905 if (KDFAULT(f->f_wb3s)) 906 *(char *)f->f_wb3a = f->f_wb3d; 907 else 908 err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); 909 break; 910 case SSW4_SZW: 911 if (KDFAULT(f->f_wb3s)) 912 *(short *)f->f_wb3a = f->f_wb3d; 913 else 914 err = susword((caddr_t)f->f_wb3a, f->f_wb3d); 915 break; 916 #ifdef DEBUG 917 case SSW4_SZLN: 918 panic("writeback: wb3s indicates LINE write"); 919 #endif 920 } 921 if (err) { 922 fa = f->f_wb3a; 923 #ifdef DEBUG 924 if (mmudebug & MDB_WBFAILED) 925 printf(wberrstr, p->p_pid, p->p_comm, 926 "#3", fp->f_pc, f->f_fa, 927 f->f_wb3a, f->f_wb3d); 928 #endif 929 } 930 } 931 p->p_addr->u_pcb.pcb_onfault = oonfault; 932 if (err) 933 err = SIGSEGV; 934 return (err); 935 } 936 937 #ifdef DEBUG 938 void 939 dumpssw(ssw) 940 u_short ssw; 941 { 942 printf(" SSW: %x: ", ssw); 943 if (ssw & SSW4_CP) 944 printf("CP,"); 945 if (ssw & SSW4_CU) 946 printf("CU,"); 947 if (ssw & SSW4_CT) 948 printf("CT,"); 949 if (ssw & SSW4_CM) 950 printf("CM,"); 951 if (ssw & SSW4_MA) 952 printf("MA,"); 953 if (ssw & SSW4_ATC) 954 printf("ATC,"); 955 if (ssw & SSW4_LK) 956 printf("LK,"); 957 if (ssw & SSW4_RW) 958 printf("RW,"); 959 printf(" SZ=%s, TT=%s, TM=%s\n", 960 f7sz[(ssw & SSW4_SZMASK) >> 5], 961 f7tt[(ssw & SSW4_TTMASK) >> 3], 962 f7tm[ssw & SSW4_TMMASK]); 963 } 964 965 void 966 dumpwb(num, s, a, d) 967 int num; 968 u_short s; 969 u_int a, d; 970 { 971 struct proc *p = curproc; 972 paddr_t pa; 973 974 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 975 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 976 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 977 printf(" PA "); 978 if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE) 979 printf("<invalid address>"); 980 else 981 printf("%lx, current value %lx", pa, fuword((caddr_t)a)); 982 printf("\n"); 983 } 984 #endif 985 #endif 986