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