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