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