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