1 /* $NetBSD: trap.c,v 1.105 2011/02/08 20:20:20 rmind 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. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah $Hdr: trap.c 1.37 92/12/20$ 37 * 38 * @(#)trap.c 8.5 (Berkeley) 1/4/94 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.105 2011/02/08 20:20:20 rmind Exp $"); 43 44 #include "opt_ddb.h" 45 #include "opt_execfmt.h" 46 #include "opt_kgdb.h" 47 #include "opt_compat_sunos.h" 48 #include "opt_m68k_arch.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/sa.h> 58 #include <sys/savar.h> 59 #include <sys/syslog.h> 60 #include <sys/userret.h> 61 #include <sys/kauth.h> 62 63 #ifdef DEBUG 64 #include <dev/cons.h> 65 #endif 66 67 #include <machine/db_machdep.h> 68 #include <machine/pcb.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/cacheops.h> 75 76 #include <uvm/uvm_extern.h> 77 78 #ifdef COMPAT_SUNOS 79 #include <compat/sunos/sunos_syscall.h> 80 #include <compat/sunos/sunos_exec.h> 81 #endif 82 83 int writeback(struct frame *fp, int docachepush); 84 void trap(struct frame *fp, int type, u_int code, u_int v); 85 86 #if defined(M68040) || defined(M68060) 87 #ifdef DEBUG 88 void dumpssw(u_short); 89 void dumpwb(int, u_short, u_int, u_int); 90 #endif 91 #endif 92 93 static inline void userret(struct lwp *l, struct frame *fp, 94 u_quad_t oticks, u_int faultaddr, int fromtrap); 95 96 int astpending; 97 98 const char *trap_type[] = { 99 "Bus error", 100 "Address error", 101 "Illegal instruction", 102 "Zero divide", 103 "CHK instruction", 104 "TRAPV instruction", 105 "Privilege violation", 106 "Trace trap", 107 "MMU fault", 108 "SSIR trap", 109 "Format error", 110 "68881 exception", 111 "Coprocessor violation", 112 "Async system trap" 113 }; 114 int trap_types = sizeof trap_type / sizeof trap_type[0]; 115 116 /* 117 * Size of various exception stack frames (minus the standard 8 bytes) 118 */ 119 short exframesize[] = { 120 FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ 121 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 122 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ 123 FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ 124 FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ 125 -1, -1, /* type 5-6 - undefined */ 126 FMT7SIZE, /* type 7 - access error (68040) */ 127 58, /* type 8 - bus fault (68010) */ 128 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 129 FMTASIZE, /* type A - short bus fault (68020/030) */ 130 FMTBSIZE, /* type B - long bus fault (68020/030) */ 131 -1, -1, -1, -1 /* type C-F - undefined */ 132 }; 133 134 #ifdef M68060 135 #if defined(M68020) || defined(M68030) || defined(M68040) 136 #define KDFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_TM_SV)) 137 #define WRFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_RW_W)) 138 #else 139 #define KDFAULT_060(c) ((c) & FSLW_TM_SV) 140 #define WRFAULT_060(c) ((c) & FSLW_RW_W) 141 #endif 142 #else 143 #define KDFAULT_060(c) 0 144 #define WRFAULT_060(c) 0 145 #endif 146 147 #ifdef M68040 148 #if defined(M68020) || defined(M68030) || defined(M68060) 149 #define KDFAULT_040(c) (cputype == CPU_68040 && \ 150 ((c) & SSW4_TMMASK) == SSW4_TMKD) 151 #define WRFAULT_040(c) (cputype == CPU_68040 && \ 152 ((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW) 153 #else 154 #define KDFAULT_040(c) (((c) & SSW4_TMMASK) == SSW4_TMKD) 155 #define WRFAULT_040(c) (((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW) 156 #endif 157 #else 158 #define KDFAULT_040(c) 0 159 #define WRFAULT_040(c) 0 160 #endif 161 162 #if defined(M68030) || defined(M68020) 163 #if defined(M68040) || defined(M68060) 164 #define KDFAULT_OTH(c) (cputype <= CPU_68030 && \ 165 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 166 #define WRFAULT_OTH(c) (cputype <= CPU_68030 && \ 167 (((c) & SSW_DF) != 0 && \ 168 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0)))) 169 #else 170 #define KDFAULT_OTH(c) (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 171 #define WRFAULT_OTH(c) (((c) & SSW_DF) != 0 && \ 172 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0))) 173 #endif 174 #else 175 #define KDFAULT_OTH(c) 0 176 #define WRFAULT_OTH(c) 0 177 #endif 178 179 #define KDFAULT(c) (KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c)) 180 #define WRFAULT(c) (WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c)) 181 182 #ifdef DEBUG 183 int mmudebug = 0; 184 int mmupid = -1; 185 #define MDB_FOLLOW 1 186 #define MDB_WBFOLLOW 2 187 #define MDB_WBFAILED 4 188 #define MDB_ISPID(p) ((p) == mmupid) 189 #endif 190 191 192 /* 193 * trap and syscall both need the following work done before returning 194 * to user mode. 195 */ 196 static inline void 197 userret(struct lwp *l, struct frame *fp, u_quad_t oticks, u_int faultaddr, 198 int fromtrap) 199 { 200 struct proc *p = l->l_proc; 201 #ifdef M68040 202 int sig; 203 int beenhere = 0; 204 205 again: 206 #endif 207 /* Invoke MI userret code */ 208 mi_userret(l); 209 210 /* 211 * If profiling, charge system time to the trapped pc. 212 */ 213 if (p->p_stflag & PST_PROFIL) { 214 extern int psratio; 215 216 addupc_task(l, fp->f_pc, 217 (int)(p->p_sticks - oticks) * psratio); 218 } 219 220 #ifdef M68040 221 /* 222 * Deal with user mode writebacks (from trap, or from sigreturn). 223 * If any writeback fails, go back and attempt signal delivery. 224 * unless we have already been here and attempted the writeback 225 * (e.g. bad address with user ignoring SIGSEGV). In that case 226 * we just return to the user without successfully completing 227 * the writebacks. Maybe we should just drop the sucker? 228 */ 229 if ( 230 #if defined(M68030) || defined(M68060) 231 cputype == CPU_68040 && 232 #endif 233 fp->f_format == FMT7) { 234 if (beenhere) { 235 #ifdef DEBUG 236 if (mmudebug & MDB_WBFAILED) 237 printf(fromtrap ? 238 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 239 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 240 p->p_pid, p->p_comm, fp->f_pc, faultaddr); 241 #endif 242 } else if ((sig = writeback(fp, fromtrap))) { 243 ksiginfo_t ksi; 244 beenhere = 1; 245 oticks = p->p_sticks; 246 (void)memset(&ksi, 0, sizeof(ksi)); 247 ksi.ksi_signo = sig; 248 ksi.ksi_addr = (void *)faultaddr; 249 ksi.ksi_code = BUS_OBJERR; 250 trapsignal(l, &ksi); 251 goto again; 252 } 253 } 254 #endif 255 } 256 257 /* 258 * Used by the common m68k syscall() and child_return() functions. 259 * XXX: Temporary until all m68k ports share common trap()/userret() code. 260 */ 261 void machine_userret(struct lwp *, struct frame *, u_quad_t); 262 263 void 264 machine_userret(struct lwp *l, struct frame *f, u_quad_t t) 265 { 266 267 userret(l, f, t, 0, 0); 268 } 269 270 /* 271 * Trap is called from locore to handle most types of processor traps, 272 * including events such as simulated software interrupts/AST's. 273 * System calls are broken out for efficiency. 274 */ 275 /*ARGSUSED*/ 276 void 277 trap(struct frame *fp, int type, unsigned int code, unsigned int v) 278 { 279 extern char fubail[], subail[]; 280 struct lwp *l; 281 struct proc *p; 282 struct pcb *pcb; 283 void *onfault; 284 ksiginfo_t ksi; 285 int s; 286 int rv; 287 u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */; 288 static int panicking = 0; 289 290 curcpu()->ci_data.cpu_ntrap++; 291 l = curlwp; 292 p = l->l_proc; 293 pcb = lwp_getpcb(l); 294 295 KSI_INIT_TRAP(&ksi); 296 ksi.ksi_trap = type & ~T_USER; 297 298 if (USERMODE(fp->f_sr)) { 299 type |= T_USER; 300 sticks = p->p_sticks; 301 l->l_md.md_regs = fp->f_regs; 302 LWP_CACHE_CREDS(l, p); 303 } 304 switch (type) { 305 306 default: 307 dopanic: 308 /* 309 * Let the kernel debugger see the trap frame that 310 * caused us to panic. This is a convenience so 311 * one can see registers at the point of failure. 312 */ 313 s = splhigh(); 314 panicking = 1; 315 printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v); 316 printf("%s program counter = 0x%x\n", 317 (type & T_USER) ? "user" : "kernel", fp->f_pc); 318 #ifdef KGDB 319 /* If connected, step or cont returns 1 */ 320 if (kgdb_trap(type, fp)) 321 goto kgdb_cont; 322 #endif 323 #ifdef DDB 324 (void)kdb_trap(type, (db_regs_t *)fp); 325 #endif 326 #ifdef KGDB 327 kgdb_cont: 328 #endif 329 splx(s); 330 if (panicstr) { 331 printf("trap during panic!\n"); 332 #ifdef DEBUG 333 /* XXX should be a machine-dependent hook */ 334 printf("(press a key)\n"); (void)cngetc(); 335 #endif 336 } 337 regdump((struct trapframe *)fp, 128); 338 type &= ~T_USER; 339 if ((u_int)type < trap_types) 340 panic(trap_type[type]); 341 panic("trap"); 342 343 case T_BUSERR: /* kernel bus error */ 344 if (pcb->pcb_onfault == NULL) 345 goto dopanic; 346 rv = EFAULT; 347 /* FALLTHROUGH */ 348 349 copyfault: 350 /* 351 * If we have arranged to catch this fault in any of the 352 * copy to/from user space routines, set PC to return to 353 * indicated location and set flag informing buserror code 354 * that it may need to clean up stack frame. 355 */ 356 fp->f_stackadj = exframesize[fp->f_format]; 357 fp->f_format = fp->f_vector = 0; 358 fp->f_pc = (int)pcb->pcb_onfault; 359 fp->f_regs[D0] = rv; 360 return; 361 362 case T_BUSERR|T_USER: /* bus error */ 363 case T_ADDRERR|T_USER: /* address error */ 364 ksi.ksi_addr = (void *)v; 365 ksi.ksi_signo = SIGBUS; 366 ksi.ksi_code = (type == (T_BUSERR|T_USER)) ? 367 BUS_OBJERR : BUS_ADRERR; 368 break; 369 370 case T_COPERR: /* kernel coprocessor violation */ 371 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 372 case T_FMTERR: /* ...just in case... */ 373 /* 374 * The user has most likely trashed the RTE or FP state info 375 * in the stack frame of a signal handler. 376 */ 377 printf("pid %d: kernel %s exception\n", p->p_pid, 378 type==T_COPERR ? "coprocessor" : "format"); 379 type |= T_USER; 380 381 mutex_enter(p->p_lock); 382 SIGACTION(p, SIGILL).sa_handler = SIG_DFL; 383 sigdelset(&p->p_sigctx.ps_sigignore, SIGILL); 384 sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL); 385 sigdelset(&l->l_sigmask, SIGILL); 386 mutex_exit(p->p_lock); 387 388 ksi.ksi_signo = SIGILL; 389 ksi.ksi_addr = (void *)(int)fp->f_format; 390 /* XXX was ILL_RESAD_FAULT */ 391 ksi.ksi_code = (type == T_COPERR) ? 392 ILL_COPROC : ILL_ILLOPC; 393 break; 394 395 case T_COPERR|T_USER: /* user coprocessor violation */ 396 /* What is a proper response here? */ 397 ksi.ksi_signo = SIGFPE; 398 ksi.ksi_code = FPE_FLTINV; 399 break; 400 401 case T_FPERR|T_USER: /* 68881 exceptions */ 402 /* 403 * We pass along the 68881 status register which locore stashed 404 * in code for us. 405 */ 406 ksi.ksi_signo = SIGFPE; 407 ksi.ksi_code = fpsr2siginfocode(code); 408 break; 409 410 /* 411 * FPU faults in supervisor mode. 412 */ 413 case T_ILLINST: /* fnop generates this, apparently. */ 414 case T_FPEMULI: 415 case T_FPEMULD: 416 { 417 extern label_t *nofault; 418 419 if (nofault) /* If we're probing. */ 420 longjmp(nofault); 421 if (type == T_ILLINST) 422 printf("Kernel Illegal Instruction trap.\n"); 423 else 424 printf("Kernel FPU trap.\n"); 425 goto dopanic; 426 } 427 428 case T_FPEMULI|T_USER: /* unimplemented FP instruction */ 429 case T_FPEMULD|T_USER: /* unimplemented FP data type */ 430 #if defined(M68040) || defined(M68060) 431 /* XXX need to FSAVE */ 432 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 433 p->p_pid, p->p_comm, 434 fp->f_format == 2 ? "instruction" : "data type", 435 fp->f_pc, fp->f_fmt2.f_iaddr); 436 /* XXX need to FRESTORE */ 437 ksi.ksi_signo = SIGFPE; 438 ksi.ksi_code = FPE_FLTINV; 439 break; 440 #endif 441 442 case T_ILLINST|T_USER: /* illegal instruction fault */ 443 case T_PRIVINST|T_USER: /* privileged instruction fault */ 444 ksi.ksi_addr = (void *)(int)fp->f_format; 445 /* XXX was ILL_PRIVIN_FAULT */ 446 ksi.ksi_signo = SIGILL; 447 ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ? 448 ILL_PRVOPC : ILL_ILLOPC; 449 break; 450 451 case T_ZERODIV|T_USER: /* Divide by zero */ 452 ksi.ksi_addr = (void *)(int)fp->f_format; 453 /* XXX was FPE_INTDIV_TRAP */ 454 ksi.ksi_signo = SIGFPE; 455 ksi.ksi_code = FPE_FLTDIV; 456 break; 457 458 case T_CHKINST|T_USER: /* CHK instruction trap */ 459 ksi.ksi_addr = (void *)(int)fp->f_format; 460 /* XXX was FPE_SUBRNG_TRAP */ 461 ksi.ksi_signo = SIGFPE; 462 break; 463 464 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 465 ksi.ksi_addr = (void *)(int)fp->f_format; 466 /* XXX was FPE_INTOVF_TRAP */ 467 ksi.ksi_signo = SIGFPE; 468 break; 469 470 /* 471 * XXX: Trace traps are a nightmare. 472 * 473 * HP-UX uses trap #1 for breakpoints, 474 * NetBSD/m68k uses trap #2, 475 * SUN 3.x uses trap #15, 476 * DDB and KGDB uses trap #15 (for kernel breakpoints; 477 * handled elsewhere). 478 * 479 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 480 * SUN 3.x traps get passed through as T_TRAP15 and are not really 481 * supported yet. 482 * 483 * XXX: We should never get kernel-mode T_TRAP15 484 * XXX: because locore.s now gives them special treatment. 485 */ 486 case T_TRAP15: /* kernel breakpoint */ 487 #ifdef DEBUG 488 printf("unexpected kernel trace trap, type = %d\n", type); 489 printf("program counter = 0x%x\n", fp->f_pc); 490 #endif 491 fp->f_sr &= ~PSL_T; 492 return; 493 494 case T_TRACE|T_USER: /* user trace trap */ 495 #ifdef COMPAT_SUNOS 496 /* 497 * SunOS uses Trap #2 for a "CPU cache flush". 498 * Just flush the on-chip caches and return. 499 */ 500 if (p->p_emul == &emul_sunos) { 501 ICIA(); 502 DCIU(); 503 return; 504 } 505 #endif 506 /* FALLTHROUGH */ 507 case T_TRACE: /* tracing a trap instruction */ 508 case T_TRAP15|T_USER: /* SUN user trace trap */ 509 fp->f_sr &= ~PSL_T; 510 ksi.ksi_signo = SIGTRAP; 511 break; 512 513 case T_ASTFLT: /* system async trap, cannot happen */ 514 goto dopanic; 515 516 case T_ASTFLT|T_USER: /* user async trap */ 517 astpending = 0; 518 if (l->l_pflag & LP_OWEUPC) { 519 l->l_pflag &= ~LP_OWEUPC; 520 ADDUPROF(l); 521 } 522 if (curcpu()->ci_want_resched) 523 preempt(); 524 goto out; 525 526 case T_MMUFLT: /* kernel mode page fault */ 527 /* 528 * If we were doing profiling ticks or other user mode 529 * stuff from interrupt code, Just Say No. 530 */ 531 rv = EFAULT; 532 if (pcb->pcb_onfault == fubail || pcb->pcb_onfault == subail) 533 goto copyfault; 534 /* fall into ... */ 535 536 case T_MMUFLT|T_USER: /* page fault */ 537 { 538 vaddr_t va; 539 struct vmspace *vm = p->p_vmspace; 540 struct vm_map *map; 541 vm_prot_t ftype; 542 extern struct vm_map *kernel_map; 543 544 onfault = pcb->pcb_onfault; 545 #ifdef DEBUG 546 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 547 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 548 p->p_pid, code, v, fp->f_pc, fp->f_sr); 549 #endif 550 /* 551 * It is only a kernel address space fault iff: 552 * 1. (type & T_USER) == 0 and 553 * 2. pcb_onfault not set or 554 * 3. pcb_onfault set but supervisor space data fault 555 * The last can occur during an exec() copyin where the 556 * argument space is lazy-allocated. 557 */ 558 if ((type & T_USER) == 0 && (onfault == NULL || KDFAULT(code))) 559 map = kernel_map; 560 else { 561 map = vm ? &vm->vm_map : kernel_map; 562 if ((l->l_flag & LW_SA) 563 && (~l->l_pflag & LP_SA_NOBLOCK)) { 564 l->l_savp->savp_faultaddr = (vaddr_t)v; 565 l->l_pflag |= LP_SA_PAGEFAULT; 566 } 567 } 568 569 if (WRFAULT(code)) 570 ftype = VM_PROT_WRITE; 571 else 572 ftype = VM_PROT_READ; 573 574 va = trunc_page((vaddr_t)v); 575 576 if (map == kernel_map && va == 0) { 577 printf("trap: bad kernel %s access at 0x%x\n", 578 (ftype & VM_PROT_WRITE) ? "read/write" : 579 "read", v); 580 goto dopanic; 581 } 582 583 #ifdef DIAGNOSTIC 584 if (interrupt_depth && !panicking) { 585 printf("trap: calling uvm_fault() from interrupt!\n"); 586 goto dopanic; 587 } 588 #endif 589 590 pcb->pcb_onfault = NULL; 591 rv = uvm_fault(map, va, ftype); 592 pcb->pcb_onfault = onfault; 593 #ifdef DEBUG 594 if (rv && MDB_ISPID(p->p_pid)) 595 printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n", 596 map, va, ftype, rv); 597 #endif 598 /* 599 * If this was a stack access we keep track of the maximum 600 * accessed stack size. Also, if vm_fault gets a protection 601 * failure it is due to accessing the stack region outside 602 * the current limit and we need to reflect that as an access 603 * error. 604 */ 605 if (rv == 0) { 606 if (map != kernel_map && (void *)va >= vm->vm_maxsaddr) 607 uvm_grow(p, va); 608 609 if (type == T_MMUFLT) { 610 if (ucas_ras_check(&fp->F_t)) { 611 return; 612 } 613 #ifdef M68040 614 #if defined(M68030) || defined(M68060) 615 if (cputype == CPU_68040) 616 #endif 617 (void)writeback(fp, 1); 618 #endif 619 return; 620 } 621 l->l_pflag &= ~LP_SA_PAGEFAULT; 622 goto out; 623 } 624 if (rv == EACCES) { 625 ksi.ksi_code = SEGV_ACCERR; 626 rv = EFAULT; 627 } else 628 ksi.ksi_code = SEGV_MAPERR; 629 if (type == T_MMUFLT) { 630 if (onfault) 631 goto copyfault; 632 printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n", 633 map, va, ftype, rv); 634 printf(" type %x, code [mmu,,ssw]: %x\n", 635 type, code); 636 goto dopanic; 637 } 638 l->l_pflag &= ~LP_SA_PAGEFAULT; 639 ksi.ksi_addr = (void *)v; 640 if (rv == ENOMEM) { 641 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 642 p->p_pid, p->p_comm, 643 l->l_cred ? 644 kauth_cred_geteuid(l->l_cred) : -1); 645 ksi.ksi_signo = SIGKILL; 646 } else { 647 ksi.ksi_signo = SIGSEGV; 648 } 649 break; 650 } 651 } 652 trapsignal(l, &ksi); 653 if ((type & T_USER) == 0) 654 return; 655 out: 656 userret(l, fp, sticks, v, 1); 657 } 658 659 #ifdef M68040 660 #ifdef DEBUG 661 struct writebackstats { 662 int calls; 663 int cpushes; 664 int move16s; 665 int wb1s, wb2s, wb3s; 666 int wbsize[4]; 667 } wbstats; 668 669 const char *f7sz[] = { "longword", "byte", "word", "line" }; 670 const char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 671 const char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 672 "M-code", "k-data", "k-code", "RES" }; 673 char wberrstr[] = 674 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 675 #endif 676 677 /* 678 * Because calling memcpy() for 16 bytes is *way* too much overhead ... 679 */ 680 static inline void fastcopy16(u_int *, u_int *); 681 static inline void 682 fastcopy16(u_int *src, u_int *dst) 683 { 684 685 *src++ = *dst++; 686 *src++ = *dst++; 687 *src++ = *dst++; 688 *src = *dst; 689 } 690 691 int 692 writeback(struct frame *fp, int docachepush) 693 { 694 struct fmt7 *f = &fp->f_fmt7; 695 struct lwp *l = curlwp; 696 struct proc *p = l->l_proc; 697 struct pcb *pcb = lwp_getpcb(l); 698 int err = 0; 699 u_int fa; 700 void *oonfault = pcb->pcb_onfault; 701 extern int suline(void *, void *); /* locore.s */ 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 paddr_t pa; 739 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, 740 trunc_page(f->f_fa), VM_PROT_WRITE, 741 VM_PROT_WRITE|PMAP_WIRED); 742 pmap_update(pmap_kernel()); 743 fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 744 fastcopy16(&f->f_pd0, (u_int *)fa); 745 (void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa); 746 DCFL_40(pa); 747 pmap_remove(pmap_kernel(), (vaddr_t)vmmap, 748 (vaddr_t)&vmmap[PAGE_SIZE]); 749 pmap_update(pmap_kernel()); 750 } else 751 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 752 p->p_pid, p->p_comm, kauth_cred_geteuid(l->l_cred)); 753 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 754 /* 755 * MOVE16 fault. 756 * Line-align the address and write out the push data to 757 * the indicated virtual address. 758 */ 759 #ifdef DEBUG 760 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 761 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 762 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 763 f->f_pd2, f->f_pd3); 764 if (f->f_wb1s & SSW4_WBSV) 765 panic("%s: MOVE16 with WB1S valid", __func__); 766 wbstats.move16s++; 767 #endif 768 if (KDFAULT_040(f->f_wb1s)) 769 fastcopy16(&f->f_pd0, (u_int *)(f->f_fa & ~0xF)); 770 else 771 err = suline((void *)(f->f_fa & ~0xF), 772 (void *)&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_040(f->f_wb1s)) 802 *(long *)f->f_wb1a = wb1d; 803 else 804 err = suword((void *)f->f_wb1a, wb1d); 805 break; 806 case SSW4_SZB: 807 off = 24 - off; 808 if (off) 809 wb1d >>= off; 810 if (KDFAULT_040(f->f_wb1s)) 811 *(char *)f->f_wb1a = wb1d; 812 else 813 err = subyte((void *)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_040(f->f_wb1s)) 820 *(short *)f->f_wb1a = wb1d; 821 else 822 err = susword((void *)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_040(f->f_wb2s)) 852 *(long *)f->f_wb2a = f->f_wb2d; 853 else 854 err = suword((void *)f->f_wb2a, f->f_wb2d); 855 break; 856 case SSW4_SZB: 857 if (KDFAULT_040(f->f_wb2s)) 858 *(char *)f->f_wb2a = f->f_wb2d; 859 else 860 err = subyte((void *)f->f_wb2a, f->f_wb2d); 861 break; 862 case SSW4_SZW: 863 if (KDFAULT_040(f->f_wb2s)) 864 *(short *)f->f_wb2a = f->f_wb2d; 865 else 866 err = susword((void *)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_040(f->f_wb3s)) 892 *(long *)f->f_wb3a = f->f_wb3d; 893 else 894 err = suword((void *)f->f_wb3a, f->f_wb3d); 895 break; 896 case SSW4_SZB: 897 if (KDFAULT_040(f->f_wb3s)) 898 *(char *)f->f_wb3a = f->f_wb3d; 899 else 900 err = subyte((void *)f->f_wb3a, f->f_wb3d); 901 break; 902 case SSW4_SZW: 903 if (KDFAULT_040(f->f_wb3s)) 904 *(short *)f->f_wb3a = f->f_wb3d; 905 else 906 err = susword((void *)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 pcb->pcb_onfault = oonfault; 924 if (err) 925 err = SIGSEGV; 926 return err; 927 } 928 929 #ifdef DEBUG 930 void 931 dumpssw(u_short ssw) 932 { 933 printf(" SSW: %x: ", ssw); 934 if (ssw & SSW4_CP) 935 printf("CP,"); 936 if (ssw & SSW4_CU) 937 printf("CU,"); 938 if (ssw & SSW4_CT) 939 printf("CT,"); 940 if (ssw & SSW4_CM) 941 printf("CM,"); 942 if (ssw & SSW4_MA) 943 printf("MA,"); 944 if (ssw & SSW4_ATC) 945 printf("ATC,"); 946 if (ssw & SSW4_LK) 947 printf("LK,"); 948 if (ssw & SSW4_RW) 949 printf("RW,"); 950 printf(" SZ=%s, TT=%s, TM=%s\n", 951 f7sz[(ssw & SSW4_SZMASK) >> 5], 952 f7tt[(ssw & SSW4_TTMASK) >> 3], 953 f7tm[ssw & SSW4_TMMASK]); 954 } 955 956 void 957 dumpwb(int num, u_short s, u_int a, u_int d) 958 { 959 struct lwp *l = curlwp; 960 struct proc *p = l->l_proc; 961 paddr_t pa; 962 963 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 964 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 965 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 966 printf(" PA "); 967 if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == false) 968 printf("<invalid address>"); 969 else 970 printf("%lx, current value %lx", pa, fuword((void *)a)); 971 printf("\n"); 972 } 973 #endif 974 #endif 975