1 /* $NetBSD: trap.c,v 1.107 2014/03/24 19:52:27 christos 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.107 2014/03/24 19:52:27 christos 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 if (rv == ENOMEM) { 632 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 633 p->p_pid, p->p_comm, 634 l->l_cred ? 635 kauth_cred_geteuid(l->l_cred) : -1); 636 ksi.ksi_signo = SIGKILL; 637 } else { 638 ksi.ksi_signo = SIGSEGV; 639 } 640 break; 641 } 642 } 643 trapsignal(l, &ksi); 644 if ((type & T_USER) == 0) 645 return; 646 out: 647 userret(l, fp, sticks, v, 1); 648 } 649 650 #ifdef M68040 651 #ifdef DEBUG 652 struct writebackstats { 653 int calls; 654 int cpushes; 655 int move16s; 656 int wb1s, wb2s, wb3s; 657 int wbsize[4]; 658 } wbstats; 659 660 const char *f7sz[] = { "longword", "byte", "word", "line" }; 661 const char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 662 const char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 663 "M-code", "k-data", "k-code", "RES" }; 664 char wberrstr[] = 665 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 666 #endif 667 668 /* 669 * Because calling memcpy() for 16 bytes is *way* too much overhead ... 670 */ 671 static inline void fastcopy16(u_int *, u_int *); 672 static inline void 673 fastcopy16(u_int *src, u_int *dst) 674 { 675 676 *src++ = *dst++; 677 *src++ = *dst++; 678 *src++ = *dst++; 679 *src = *dst; 680 } 681 682 int 683 writeback(struct frame *fp, int docachepush) 684 { 685 struct fmt7 *f = &fp->f_fmt7; 686 struct lwp *l = curlwp; 687 struct proc *p = l->l_proc; 688 struct pcb *pcb = lwp_getpcb(l); 689 int err = 0; 690 u_int fa; 691 void *oonfault = pcb->pcb_onfault; 692 extern int suline(void *, void *); /* locore.s */ 693 694 #ifdef DEBUG 695 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 696 printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); 697 dumpssw(f->f_ssw); 698 } 699 wbstats.calls++; 700 #endif 701 /* 702 * Deal with special cases first. 703 */ 704 if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { 705 /* 706 * Dcache push fault. 707 * Line-align the address and write out the push data to 708 * the indicated physical address. 709 */ 710 #ifdef DEBUG 711 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 712 printf(" pushing %s to PA %x, data %x", 713 f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], 714 f->f_fa, f->f_pd0); 715 if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) 716 printf("/%x/%x/%x", 717 f->f_pd1, f->f_pd2, f->f_pd3); 718 printf("\n"); 719 } 720 if (f->f_wb1s & SSW4_WBSV) 721 panic("writeback: cache push with WB1S valid"); 722 wbstats.cpushes++; 723 #endif 724 /* 725 * XXX there are security problems if we attempt to do a 726 * cache push after a signal handler has been called. 727 */ 728 if (docachepush) { 729 paddr_t pa; 730 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, 731 trunc_page(f->f_fa), VM_PROT_WRITE, 732 VM_PROT_WRITE|PMAP_WIRED); 733 pmap_update(pmap_kernel()); 734 fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 735 fastcopy16(&f->f_pd0, (u_int *)fa); 736 (void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa); 737 DCFL_40(pa); 738 pmap_remove(pmap_kernel(), (vaddr_t)vmmap, 739 (vaddr_t)&vmmap[PAGE_SIZE]); 740 pmap_update(pmap_kernel()); 741 } else 742 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 743 p->p_pid, p->p_comm, kauth_cred_geteuid(l->l_cred)); 744 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 745 /* 746 * MOVE16 fault. 747 * Line-align the address and write out the push data to 748 * the indicated virtual address. 749 */ 750 #ifdef DEBUG 751 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 752 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 753 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 754 f->f_pd2, f->f_pd3); 755 if (f->f_wb1s & SSW4_WBSV) 756 panic("%s: MOVE16 with WB1S valid", __func__); 757 wbstats.move16s++; 758 #endif 759 if (KDFAULT_040(f->f_wb1s)) 760 fastcopy16(&f->f_pd0, (u_int *)(f->f_fa & ~0xF)); 761 else 762 err = suline((void *)(f->f_fa & ~0xF), 763 (void *)&f->f_pd0); 764 if (err) { 765 fa = f->f_fa & ~0xF; 766 #ifdef DEBUG 767 if (mmudebug & MDB_WBFAILED) 768 printf(wberrstr, p->p_pid, p->p_comm, 769 "MOVE16", fp->f_pc, f->f_fa, 770 f->f_fa & ~0xF, f->f_pd0); 771 #endif 772 } 773 } else if (f->f_wb1s & SSW4_WBSV) { 774 /* 775 * Writeback #1. 776 * Position the "memory-aligned" data and write it out. 777 */ 778 u_int wb1d = f->f_wb1d; 779 int off; 780 781 #ifdef DEBUG 782 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 783 dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 784 wbstats.wb1s++; 785 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 786 #endif 787 off = (f->f_wb1a & 3) * 8; 788 switch (f->f_wb1s & SSW4_SZMASK) { 789 case SSW4_SZLW: 790 if (off) 791 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 792 if (KDFAULT_040(f->f_wb1s)) 793 *(long *)f->f_wb1a = wb1d; 794 else 795 err = suword((void *)f->f_wb1a, wb1d); 796 break; 797 case SSW4_SZB: 798 off = 24 - off; 799 if (off) 800 wb1d >>= off; 801 if (KDFAULT_040(f->f_wb1s)) 802 *(char *)f->f_wb1a = wb1d; 803 else 804 err = subyte((void *)f->f_wb1a, wb1d); 805 break; 806 case SSW4_SZW: 807 off = (off + 16) % 32; 808 if (off) 809 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 810 if (KDFAULT_040(f->f_wb1s)) 811 *(short *)f->f_wb1a = wb1d; 812 else 813 err = susword((void *)f->f_wb1a, wb1d); 814 break; 815 } 816 if (err) { 817 fa = f->f_wb1a; 818 #ifdef DEBUG 819 if (mmudebug & MDB_WBFAILED) 820 printf(wberrstr, p->p_pid, p->p_comm, 821 "#1", fp->f_pc, f->f_fa, 822 f->f_wb1a, f->f_wb1d); 823 #endif 824 } 825 } 826 /* 827 * Deal with the "normal" writebacks. 828 * 829 * XXX writeback2 is known to reflect a LINE size writeback after 830 * a MOVE16 was already dealt with above. Ignore it. 831 */ 832 if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 833 (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 834 #ifdef DEBUG 835 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 836 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 837 wbstats.wb2s++; 838 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 839 #endif 840 switch (f->f_wb2s & SSW4_SZMASK) { 841 case SSW4_SZLW: 842 if (KDFAULT_040(f->f_wb2s)) 843 *(long *)f->f_wb2a = f->f_wb2d; 844 else 845 err = suword((void *)f->f_wb2a, f->f_wb2d); 846 break; 847 case SSW4_SZB: 848 if (KDFAULT_040(f->f_wb2s)) 849 *(char *)f->f_wb2a = f->f_wb2d; 850 else 851 err = subyte((void *)f->f_wb2a, f->f_wb2d); 852 break; 853 case SSW4_SZW: 854 if (KDFAULT_040(f->f_wb2s)) 855 *(short *)f->f_wb2a = f->f_wb2d; 856 else 857 err = susword((void *)f->f_wb2a, f->f_wb2d); 858 break; 859 } 860 if (err) { 861 fa = f->f_wb2a; 862 #ifdef DEBUG 863 if (mmudebug & MDB_WBFAILED) { 864 printf(wberrstr, p->p_pid, p->p_comm, 865 "#2", fp->f_pc, f->f_fa, 866 f->f_wb2a, f->f_wb2d); 867 dumpssw(f->f_ssw); 868 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 869 } 870 #endif 871 } 872 } 873 if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 874 #ifdef DEBUG 875 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 876 dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 877 wbstats.wb3s++; 878 wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 879 #endif 880 switch (f->f_wb3s & SSW4_SZMASK) { 881 case SSW4_SZLW: 882 if (KDFAULT_040(f->f_wb3s)) 883 *(long *)f->f_wb3a = f->f_wb3d; 884 else 885 err = suword((void *)f->f_wb3a, f->f_wb3d); 886 break; 887 case SSW4_SZB: 888 if (KDFAULT_040(f->f_wb3s)) 889 *(char *)f->f_wb3a = f->f_wb3d; 890 else 891 err = subyte((void *)f->f_wb3a, f->f_wb3d); 892 break; 893 case SSW4_SZW: 894 if (KDFAULT_040(f->f_wb3s)) 895 *(short *)f->f_wb3a = f->f_wb3d; 896 else 897 err = susword((void *)f->f_wb3a, f->f_wb3d); 898 break; 899 #ifdef DEBUG 900 case SSW4_SZLN: 901 panic("writeback: wb3s indicates LINE write"); 902 #endif 903 } 904 if (err) { 905 fa = f->f_wb3a; 906 #ifdef DEBUG 907 if (mmudebug & MDB_WBFAILED) 908 printf(wberrstr, p->p_pid, p->p_comm, 909 "#3", fp->f_pc, f->f_fa, 910 f->f_wb3a, f->f_wb3d); 911 #endif 912 } 913 } 914 pcb->pcb_onfault = oonfault; 915 if (err) 916 err = SIGSEGV; 917 return err; 918 } 919 920 #ifdef DEBUG 921 void 922 dumpssw(u_short ssw) 923 { 924 printf(" SSW: %x: ", ssw); 925 if (ssw & SSW4_CP) 926 printf("CP,"); 927 if (ssw & SSW4_CU) 928 printf("CU,"); 929 if (ssw & SSW4_CT) 930 printf("CT,"); 931 if (ssw & SSW4_CM) 932 printf("CM,"); 933 if (ssw & SSW4_MA) 934 printf("MA,"); 935 if (ssw & SSW4_ATC) 936 printf("ATC,"); 937 if (ssw & SSW4_LK) 938 printf("LK,"); 939 if (ssw & SSW4_RW) 940 printf("RW,"); 941 printf(" SZ=%s, TT=%s, TM=%s\n", 942 f7sz[(ssw & SSW4_SZMASK) >> 5], 943 f7tt[(ssw & SSW4_TTMASK) >> 3], 944 f7tm[ssw & SSW4_TMMASK]); 945 } 946 947 void 948 dumpwb(int num, u_short s, u_int a, u_int d) 949 { 950 struct lwp *l = curlwp; 951 struct proc *p = l->l_proc; 952 paddr_t pa; 953 954 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 955 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 956 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 957 printf(" PA "); 958 if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == false) 959 printf("<invalid address>"); 960 else 961 printf("%lx, current value %lx", pa, fuword((void *)a)); 962 printf("\n"); 963 } 964 #endif 965 #endif 966