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