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