trap.c revision 1.66
1/* $NetBSD: trap.c,v 1.66 2007/05/21 15:06:19 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.66 2007/05/21 15:06:19 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_compat_hpux.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/syscall.h> 103#include <sys/syslog.h> 104#include <sys/user.h> 105#include <sys/userret.h> 106#include <sys/kauth.h> 107 108#ifdef DEBUG 109#include <dev/cons.h> 110#endif 111 112#include <machine/db_machdep.h> 113#include <machine/psl.h> 114#include <machine/trap.h> 115#include <machine/cpu.h> 116#include <machine/reg.h> 117 118#include <m68k/cacheops.h> 119 120#include <uvm/uvm_extern.h> 121 122#ifdef COMPAT_HPUX 123#include <compat/hpux/hpux.h> 124#endif 125 126#ifdef COMPAT_SUNOS 127#include <compat/sunos/sunos_syscall.h> 128extern struct emul emul_sunos; 129#endif 130 131#ifdef KGDB 132#include <sys/kgdb.h> 133#endif 134 135int writeback(struct frame *, int); 136void trap(int, u_int, u_int, struct frame); 137 138#ifdef DEBUG 139void dumpssw(u_short); 140void dumpwb(int, u_short, u_int, u_int); 141#endif 142 143static inline void userret(struct lwp *, struct frame *, u_quad_t, u_int, int); 144 145int astpending; 146 147const char *trap_type[] = { 148 "Bus error", 149 "Address error", 150 "Illegal instruction", 151 "Zero divide", 152 "CHK instruction", 153 "TRAPV instruction", 154 "Privilege violation", 155 "Trace trap", 156 "MMU fault", 157 "SSIR trap", 158 "Format error", 159 "68881 exception", 160 "Coprocessor violation", 161 "Async system trap" 162}; 163int trap_types = sizeof trap_type / sizeof trap_type[0]; 164 165/* 166 * Size of various exception stack frames (minus the standard 8 bytes) 167 */ 168short exframesize[] = { 169 FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ 170 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 171 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ 172 FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ 173 FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ 174 -1, -1, /* type 5-6 - undefined */ 175 FMT7SIZE, /* type 7 - access error (68040) */ 176 58, /* type 8 - bus fault (68010) */ 177 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 178 FMTASIZE, /* type A - short bus fault (68020/030) */ 179 FMTBSIZE, /* type B - long bus fault (68020/030) */ 180 -1, -1, -1, -1 /* type C-F - undefined */ 181}; 182 183#ifdef M68060 184#define KDFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_TM_SV)) 185#define WRFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_RW_W)) 186#else 187#define KDFAULT_060(c) 0 188#define WRFAULT_060(c) 0 189#endif 190 191#ifdef M68040 192#define KDFAULT_040(c) (cputype == CPU_68040 && \ 193 ((c) & SSW4_TMMASK) == SSW4_TMKD) 194#define WRFAULT_040(c) (cputype == CPU_68040 && \ 195 ((c) & SSW4_RW) == 0) 196#else 197#define KDFAULT_040(c) 0 198#define WRFAULT_040(c) 0 199#endif 200 201#if defined(M68030) || defined(M68020) 202#define KDFAULT_OTH(c) (cputype <= CPU_68030 && \ 203 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 204#define WRFAULT_OTH(c) (cputype <= CPU_68030 && \ 205 ((c) & (SSW_DF|SSW_RW)) == SSW_DF) 206#else 207#define KDFAULT_OTH(c) 0 208#define WRFAULT_OTH(c) 0 209#endif 210 211#define KDFAULT(c) (KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c)) 212#define WRFAULT(c) (WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c)) 213 214#ifdef DEBUG 215int mmudebug = 0; 216int mmupid = -1; 217#define MDB_FOLLOW 1 218#define MDB_WBFOLLOW 2 219#define MDB_WBFAILED 4 220#define MDB_ISPID(p) ((p) == mmupid) 221#endif 222 223/* 224 * trap and syscall both need the following work done before returning 225 * to user mode. 226 */ 227static inline void 228userret(struct lwp *l, struct frame *fp, u_quad_t oticks, u_int faultaddr, 229 int fromtrap) 230{ 231 struct proc *p = l->l_proc; 232#ifdef M68040 233 int sig; 234 int beenhere = 0; 235 236again: 237#endif 238 /* Invoke MI userret code */ 239 mi_userret(l); 240 241 /* 242 * If profiling, charge system time to the trapped pc. 243 */ 244 if (p->p_stflag & PST_PROFIL) { 245 extern int psratio; 246 247 addupc_task(l, fp->f_pc, 248 (int)(p->p_sticks - oticks) * psratio); 249 } 250#ifdef M68040 251 /* 252 * Deal with user mode writebacks (from trap, or from sigreturn). 253 * If any writeback fails, go back and attempt signal delivery. 254 * unless we have already been here and attempted the writeback 255 * (e.g. bad address with user ignoring SIGSEGV). In that case 256 * we just return to the user without successfully completing 257 * the writebacks. Maybe we should just drop the sucker? 258 */ 259 if (cputype == CPU_68040 && fp->f_format == FMT7) { 260 if (beenhere) { 261#ifdef DEBUG 262 if (mmudebug & MDB_WBFAILED) 263 printf(fromtrap ? 264 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 265 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 266 p->p_pid, p->p_comm, fp->f_pc, faultaddr); 267#endif 268 } else if ((sig = writeback(fp, fromtrap))) { 269 ksiginfo_t ksi; 270 beenhere = 1; 271 oticks = p->p_sticks; 272 (void)memset(&ksi, 0, sizeof(ksi)); 273 ksi.ksi_signo = sig; 274 ksi.ksi_addr = (void *)faultaddr; 275 ksi.ksi_code = BUS_OBJERR; 276 trapsignal(l, &ksi); 277 goto again; 278 } 279 } 280#endif 281 curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri; 282} 283 284/* 285 * Used by the common m68k syscall() and child_return() functions. 286 * XXX: Temporary until all m68k ports share common trap()/userret() code. 287 */ 288void machine_userret(struct lwp *, struct frame *, u_quad_t); 289 290void 291machine_userret(struct lwp *l, struct frame *f, u_quad_t t) 292{ 293 294 userret(l, f, t, 0, 0); 295} 296 297/* 298 * Trap is called from locore to handle most types of processor traps, 299 * including events such as simulated software interrupts/AST's. 300 * System calls are broken out for efficiency. 301 */ 302/*ARGSUSED*/ 303void 304trap(int type, unsigned code, unsigned v, struct frame frame) 305{ 306 extern char fubail[], subail[]; 307 struct lwp *l; 308 struct proc *p; 309 ksiginfo_t ksi; 310 int s; 311 u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */; 312 static int panicking = 0; 313 314 uvmexp.traps++; 315 l = curlwp; 316 317 KSI_INIT_TRAP(&ksi); 318 ksi.ksi_trap = type & ~T_USER; 319 320 p = l->l_proc; 321 322#ifdef DIAGNOSTIC 323 if (l->l_addr == NULL) 324 panic("trap: no pcb"); 325#endif 326 327 if (USERMODE(frame.f_sr)) { 328 type |= T_USER; 329 sticks = p->p_sticks; 330 l->l_md.md_regs = frame.f_regs; 331 LWP_CACHE_CREDS(l, p); 332 } 333 switch (type) { 334 335 default: 336 dopanic: 337 /* 338 * Let the kernel debugger see the trap frame that 339 * caused us to panic. This is a convenience so 340 * one can see registers at the point of failure. 341 */ 342 s = splhigh(); 343 panicking = 1; 344 printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v); 345 printf("%s program counter = 0x%x\n", 346 (type & T_USER) ? "user" : "kernel", frame.f_pc); 347#ifdef KGDB 348 /* If connected, step or cont returns 1 */ 349 if (kgdb_trap(type, (db_regs_t *)&frame)) 350 goto kgdb_cont; 351#endif 352#ifdef DDB 353 (void)kdb_trap(type, (db_regs_t *)&frame); 354#endif 355#ifdef KGDB 356 kgdb_cont: 357#endif 358 splx(s); 359 if (panicstr) { 360 printf("trap during panic!\n"); 361#ifdef DEBUG 362 /* XXX should be a machine-dependent hook */ 363 printf("(press a key)\n"); (void)cngetc(); 364#endif 365 } 366 regdump((struct trapframe *)&frame, 128); 367 type &= ~T_USER; 368 if ((u_int)type < trap_types) 369 panic(trap_type[type]); 370 panic("trap"); 371 372 case T_BUSERR: /* kernel bus error */ 373 if (l->l_addr->u_pcb.pcb_onfault == 0) 374 goto dopanic; 375 /* FALLTHROUGH */ 376 377 copyfault: 378 /* 379 * If we have arranged to catch this fault in any of the 380 * copy to/from user space routines, set PC to return to 381 * indicated location and set flag informing buserror code 382 * that it may need to clean up stack frame. 383 */ 384 frame.f_stackadj = exframesize[frame.f_format]; 385 frame.f_format = frame.f_vector = 0; 386 frame.f_pc = (int) l->l_addr->u_pcb.pcb_onfault; 387 return; 388 389 case T_BUSERR|T_USER: /* bus error */ 390 case T_ADDRERR|T_USER: /* address error */ 391 ksi.ksi_addr = (void *)v; 392 ksi.ksi_signo = SIGBUS; 393 ksi.ksi_code = (type == (T_BUSERR|T_USER)) ? 394 BUS_OBJERR : BUS_ADRERR; 395 break; 396 397 case T_COPERR: /* kernel coprocessor violation */ 398 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 399 case T_FMTERR: /* ...just in case... */ 400 /* 401 * The user has most likely trashed the RTE or FP state info 402 * in the stack frame of a signal handler. 403 */ 404 printf("pid %d: kernel %s exception\n", p->p_pid, 405 type==T_COPERR ? "coprocessor" : "format"); 406 type |= T_USER; 407 408 mutex_enter(&p->p_smutex); 409 SIGACTION(p, SIGILL).sa_handler = SIG_DFL; 410 sigdelset(&p->p_sigctx.ps_sigignore, SIGILL); 411 sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL); 412 sigdelset(&l->l_sigmask, SIGILL); 413 mutex_exit(&p->p_smutex); 414 415 ksi.ksi_signo = SIGILL; 416 ksi.ksi_addr = (void *)(int)frame.f_format; 417 /* XXX was ILL_RESAD_FAULT */ 418 ksi.ksi_code = (type == T_COPERR) ? 419 ILL_COPROC : ILL_ILLOPC; 420 break; 421 422 case T_COPERR|T_USER: /* user coprocessor violation */ 423 /* What is a proper response here? */ 424 ksi.ksi_signo = SIGFPE; 425 ksi.ksi_code = FPE_FLTINV; 426 break; 427 428 case T_FPERR|T_USER: /* 68881 exceptions */ 429 /* 430 * We pass along the 68881 status register which locore stashed 431 * in code for us. Note that there is a possibility that the 432 * bit pattern of this register will conflict with one of the 433 * FPE_* codes defined in signal.h. Fortunately for us, the 434 * only such codes we use are all in the range 1-7 and the low 435 * 3 bits of the status register are defined as 0 so there is 436 * no clash. 437 */ 438 ksi.ksi_signo = SIGFPE; 439 ksi.ksi_addr = (void *)code; 440 break; 441 442#ifdef M68040 443 case T_FPEMULI|T_USER: /* unimplemented FP instruction */ 444 case T_FPEMULD|T_USER: /* unimplemented FP data type */ 445 /* XXX need to FSAVE */ 446 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 447 p->p_pid, p->p_comm, 448 frame.f_format == 2 ? "instruction" : "data type", 449 frame.f_pc, frame.f_fmt2.f_iaddr); 450 /* XXX need to FRESTORE */ 451 ksi.ksi_signo = SIGFPE; 452 ksi.ksi_code = FPE_FLTINV; 453 break; 454#endif 455 456 case T_ILLINST|T_USER: /* illegal instruction fault */ 457#ifdef COMPAT_HPUX 458 if (p->p_emul == &emul_hpux) { 459 ksi.ksi_addr = (void *)HPUX_ILL_ILLINST_TRAP; 460 ksi.ksi_signo = SIGILL; 461 break; 462 } 463 /* fall through */ 464#endif 465 case T_PRIVINST|T_USER: /* privileged instruction fault */ 466#ifdef COMPAT_HPUX 467 if (p->p_emul == &emul_hpux) 468 ksi.ksi_addr = (void *)HPUX_ILL_PRIV_TRAP; 469 else 470#endif 471 ksi.ksi_addr = (void *)(int)frame.f_format; 472 /* XXX was ILL_PRIVIN_FAULT */ 473 ksi.ksi_signo = SIGILL; 474 ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ? 475 ILL_PRVOPC : ILL_ILLOPC; 476 break; 477 478 case T_ZERODIV|T_USER: /* Divide by zero */ 479#ifdef COMPAT_HPUX 480 if (p->p_emul == &emul_hpux) 481 ksi.ksi_addr = (void *)HPUX_FPE_INTDIV_TRAP; 482 else 483#endif 484 ksi.ksi_addr = (void *)(int)frame.f_format; 485 /* XXX was FPE_INTDIV_TRAP */ 486 ksi.ksi_signo = SIGFPE; 487 ksi.ksi_code = FPE_FLTDIV; 488 break; 489 490 case T_CHKINST|T_USER: /* CHK instruction trap */ 491#ifdef COMPAT_HPUX 492 if (p->p_emul == &emul_hpux) { 493 /* handled differently under hp-ux */ 494 ksi.ksi_signo = SIGILL; 495 ksi.ksi_addr = (void *)HPUX_ILL_CHK_TRAP; 496 break; 497 } 498#endif 499 ksi.ksi_addr = (void *)(int)frame.f_format; 500 /* XXX was FPE_SUBRNG_TRAP */ 501 ksi.ksi_signo = SIGFPE; 502 break; 503 504 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 505#ifdef COMPAT_HPUX 506 if (p->p_emul == &emul_hpux) { 507 /* handled differently under hp-ux */ 508 ksi.ksi_signo = SIGILL; 509 ksi.ksi_addr = (void *)HPUX_ILL_TRAPV_TRAP; 510 break; 511 } 512#endif 513 ksi.ksi_addr = (void *)(int)frame.f_format; 514 /* XXX was FPE_INTOVF_TRAP */ 515 ksi.ksi_signo = SIGFPE; 516 break; 517 518 /* 519 * XXX: Trace traps are a nightmare. 520 * 521 * HP-UX uses trap #1 for breakpoints, 522 * NetBSD/m68k uses trap #2, 523 * SUN 3.x uses trap #15, 524 * DDB and KGDB uses trap #15 (for kernel breakpoints; 525 * handled elsewhere). 526 * 527 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 528 * SUN 3.x traps get passed through as T_TRAP15 and are not really 529 * supported yet. 530 * 531 * XXX: We should never get kernel-mode T_TRAP15 532 * XXX: because locore.s now gives them special treatment. 533 */ 534 case T_TRAP15: /* kernel breakpoint */ 535#ifdef DEBUG 536 printf("unexpected kernel trace trap, type = %d\n", type); 537 printf("program counter = 0x%x\n", frame.f_pc); 538#endif 539 frame.f_sr &= ~PSL_T; 540 return; 541 542 case T_TRACE|T_USER: /* user trace trap */ 543#ifdef COMPAT_SUNOS 544 /* 545 * SunOS uses Trap #2 for a "CPU cache flush". 546 * Just flush the on-chip caches and return. 547 */ 548 if (p->p_emul == &emul_sunos) { 549 ICIA(); 550 DCIU(); 551 return; 552 } 553#endif 554 /* FALLTHROUGH */ 555 case T_TRACE: /* tracing a trap instruction */ 556 case T_TRAP15|T_USER: /* SUN user trace trap */ 557 frame.f_sr &= ~PSL_T; 558 ksi.ksi_signo = SIGTRAP; 559 break; 560 561 case T_ASTFLT: /* system async trap, cannot happen */ 562 goto dopanic; 563 564 case T_ASTFLT|T_USER: /* user async trap */ 565 astpending = 0; 566 /* 567 * We check for software interrupts first. This is because 568 * they are at a higher level than ASTs, and on a VAX would 569 * interrupt the AST. We assume that if we are processing 570 * an AST that we must be at IPL0 so we don't bother to 571 * check. Note that we ensure that we are at least at SIR 572 * IPL while processing the SIR. 573 */ 574 spl1(); 575 /* fall into... */ 576 577 case T_SSIR: /* software interrupt */ 578 case T_SSIR|T_USER: 579 580 softintr_dispatch(); 581 582 /* 583 * If this was not an AST trap, we are all done. 584 */ 585 if (type != (T_ASTFLT|T_USER)) { 586 uvmexp.traps--; 587 return; 588 } 589 spl0(); 590 if (l->l_pflag & LP_OWEUPC) { 591 l->l_pflag &= ~LP_OWEUPC; 592 ADDUPROF(l); 593 } 594 if (curcpu()->ci_want_resched) 595 preempt(); 596 goto out; 597 598 case T_MMUFLT: /* kernel mode page fault */ 599 /* 600 * If we were doing profiling ticks or other user mode 601 * stuff from interrupt code, Just Say No. 602 */ 603 if (l->l_addr->u_pcb.pcb_onfault == fubail || 604 l->l_addr->u_pcb.pcb_onfault == subail) 605 goto copyfault; 606 /* fall into ... */ 607 608 case T_MMUFLT|T_USER: /* page fault */ 609 { 610 vaddr_t va; 611 struct vmspace *vm = p->p_vmspace; 612 struct vm_map *map; 613 int rv; 614 vm_prot_t ftype; 615 extern struct vm_map *kernel_map; 616 617#ifdef DEBUG 618 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 619 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 620 p->p_pid, code, v, frame.f_pc, frame.f_sr); 621#endif 622 /* 623 * It is only a kernel address space fault iff: 624 * 1. (type & T_USER) == 0 and 625 * 2. pcb_onfault not set or 626 * 3. pcb_onfault set but supervisor space data fault 627 * The last can occur during an exec() copyin where the 628 * argument space is lazy-allocated. 629 */ 630 if ((type & T_USER) == 0 && 631 ((l->l_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code))) 632 map = kernel_map; 633 else 634 map = vm ? &vm->vm_map : kernel_map; 635 636 if (WRFAULT(code)) 637 ftype = VM_PROT_WRITE; 638 else 639 ftype = VM_PROT_READ; 640 641 va = trunc_page((vaddr_t)v); 642 643 if (map == kernel_map && va == 0) { 644 printf("trap: bad kernel %s access at 0x%x\n", 645 (ftype & VM_PROT_WRITE) ? "read/write" : 646 "read", v); 647 goto dopanic; 648 } 649 650#ifdef DIAGNOSTIC 651 if (interrupt_depth && !panicking) { 652 printf("trap: calling uvm_fault() from interrupt!\n"); 653 goto dopanic; 654 } 655#endif 656 657#ifdef COMPAT_HPUX 658 if (ISHPMMADDR(va)) { 659 int pmap_mapmulti(pmap_t, vaddr_t); 660 vaddr_t bva; 661 662 rv = pmap_mapmulti(map->pmap, va); 663 if (rv != 0) { 664 bva = HPMMBASEADDR(va); 665 rv = uvm_fault(map, bva, ftype); 666 if (rv == 0) 667 (void) pmap_mapmulti(map->pmap, va); 668 } 669 } else 670#endif 671 rv = uvm_fault(map, va, ftype); 672#ifdef DEBUG 673 if (rv && MDB_ISPID(p->p_pid)) 674 printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n", 675 map, va, ftype, rv); 676#endif 677 /* 678 * If this was a stack access we keep track of the maximum 679 * accessed stack size. Also, if vm_fault gets a protection 680 * failure it is due to accessing the stack region outside 681 * the current limit and we need to reflect that as an access 682 * error. 683 */ 684 if (rv == 0) { 685 if (map != kernel_map && (void *)va >= vm->vm_maxsaddr) 686 uvm_grow(p, va); 687 688 if (type == T_MMUFLT) { 689#ifdef M68040 690 if (cputype == CPU_68040) 691 (void) writeback(&frame, 1); 692#endif 693 return; 694 } 695 goto out; 696 } 697 if (rv == EACCES) { 698 ksi.ksi_code = SEGV_ACCERR; 699 rv = EFAULT; 700 } else 701 ksi.ksi_code = SEGV_MAPERR; 702 if (type == T_MMUFLT) { 703 if (l->l_addr->u_pcb.pcb_onfault) 704 goto copyfault; 705 printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n", 706 map, va, ftype, rv); 707 printf(" type %x, code [mmu,,ssw]: %x\n", 708 type, code); 709 goto dopanic; 710 } 711 ksi.ksi_addr = (void *)v; 712 if (rv == ENOMEM) { 713 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 714 p->p_pid, p->p_comm, 715 l->l_cred ? 716 kauth_cred_geteuid(l->l_cred) : -1); 717 ksi.ksi_signo = SIGKILL; 718 } else { 719 ksi.ksi_signo = SIGSEGV; 720 } 721 break; 722 } 723 } 724 trapsignal(l, &ksi); 725 if ((type & T_USER) == 0) 726 return; 727out: 728 userret(l, &frame, sticks, v, 1); 729} 730 731#ifdef M68040 732#ifdef DEBUG 733struct writebackstats { 734 int calls; 735 int cpushes; 736 int move16s; 737 int wb1s, wb2s, wb3s; 738 int wbsize[4]; 739} wbstats; 740 741const char *f7sz[] = { "longword", "byte", "word", "line" }; 742const char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 743const char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 744 "M-code", "k-data", "k-code", "RES" }; 745const char wberrstr[] = 746 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 747#endif 748 749int 750writeback(struct frame *fp, int docachepush) 751{ 752 struct fmt7 *f = &fp->f_fmt7; 753 struct lwp *l = curlwp; 754 struct proc *p = l->l_proc; 755 int err = 0; 756 u_int fa; 757 void *oonfault = l->l_addr->u_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 bcopy((void *)&f->f_pd0, (void *)fa, 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 bcopy((void *)&f->f_pd0, (void *)(f->f_fa & ~0xF), 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 l->l_addr->u_pcb.pcb_onfault = oonfault; 979 if (err) 980 err = SIGSEGV; 981 return (err); 982} 983 984#ifdef DEBUG 985void 986dumpssw(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 1011void 1012dumpwb(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 1028#endif 1029