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