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