trap.c revision 1.65
1/* $NetBSD: trap.c,v 1.65 2007/03/08 16:37:44 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.65 2007/03/08 16:37:44 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 if (l == NULL) 321 l = &lwp0; 322 p = l->l_proc; 323 324#ifdef DIAGNOSTIC 325 if (l->l_addr == NULL) 326 panic("trap: no pcb"); 327#endif 328 329 if (USERMODE(frame.f_sr)) { 330 type |= T_USER; 331 sticks = p->p_sticks; 332 l->l_md.md_regs = frame.f_regs; 333 LWP_CACHE_CREDS(l, p); 334 } 335 switch (type) { 336 337 default: 338 dopanic: 339 /* 340 * Let the kernel debugger see the trap frame that 341 * caused us to panic. This is a convenience so 342 * one can see registers at the point of failure. 343 */ 344 s = splhigh(); 345 panicking = 1; 346 printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v); 347 printf("%s program counter = 0x%x\n", 348 (type & T_USER) ? "user" : "kernel", frame.f_pc); 349#ifdef KGDB 350 /* If connected, step or cont returns 1 */ 351 if (kgdb_trap(type, (db_regs_t *)&frame)) 352 goto kgdb_cont; 353#endif 354#ifdef DDB 355 (void)kdb_trap(type, (db_regs_t *)&frame); 356#endif 357#ifdef KGDB 358 kgdb_cont: 359#endif 360 splx(s); 361 if (panicstr) { 362 printf("trap during panic!\n"); 363#ifdef DEBUG 364 /* XXX should be a machine-dependent hook */ 365 printf("(press a key)\n"); (void)cngetc(); 366#endif 367 } 368 regdump((struct trapframe *)&frame, 128); 369 type &= ~T_USER; 370 if ((u_int)type < trap_types) 371 panic(trap_type[type]); 372 panic("trap"); 373 374 case T_BUSERR: /* kernel bus error */ 375 if (l->l_addr->u_pcb.pcb_onfault == 0) 376 goto dopanic; 377 /* FALLTHROUGH */ 378 379 copyfault: 380 /* 381 * If we have arranged to catch this fault in any of the 382 * copy to/from user space routines, set PC to return to 383 * indicated location and set flag informing buserror code 384 * that it may need to clean up stack frame. 385 */ 386 frame.f_stackadj = exframesize[frame.f_format]; 387 frame.f_format = frame.f_vector = 0; 388 frame.f_pc = (int) l->l_addr->u_pcb.pcb_onfault; 389 return; 390 391 case T_BUSERR|T_USER: /* bus error */ 392 case T_ADDRERR|T_USER: /* address error */ 393 ksi.ksi_addr = (void *)v; 394 ksi.ksi_signo = SIGBUS; 395 ksi.ksi_code = (type == (T_BUSERR|T_USER)) ? 396 BUS_OBJERR : BUS_ADRERR; 397 break; 398 399 case T_COPERR: /* kernel coprocessor violation */ 400 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 401 case T_FMTERR: /* ...just in case... */ 402 /* 403 * The user has most likely trashed the RTE or FP state info 404 * in the stack frame of a signal handler. 405 */ 406 printf("pid %d: kernel %s exception\n", p->p_pid, 407 type==T_COPERR ? "coprocessor" : "format"); 408 type |= T_USER; 409 410 mutex_enter(&p->p_smutex); 411 SIGACTION(p, SIGILL).sa_handler = SIG_DFL; 412 sigdelset(&p->p_sigctx.ps_sigignore, SIGILL); 413 sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL); 414 sigdelset(&l->l_sigmask, SIGILL); 415 mutex_exit(&p->p_smutex); 416 417 ksi.ksi_signo = SIGILL; 418 ksi.ksi_addr = (void *)(int)frame.f_format; 419 /* XXX was ILL_RESAD_FAULT */ 420 ksi.ksi_code = (type == T_COPERR) ? 421 ILL_COPROC : ILL_ILLOPC; 422 break; 423 424 case T_COPERR|T_USER: /* user coprocessor violation */ 425 /* What is a proper response here? */ 426 ksi.ksi_signo = SIGFPE; 427 ksi.ksi_code = FPE_FLTINV; 428 break; 429 430 case T_FPERR|T_USER: /* 68881 exceptions */ 431 /* 432 * We pass along the 68881 status register which locore stashed 433 * in code for us. Note that there is a possibility that the 434 * bit pattern of this register will conflict with one of the 435 * FPE_* codes defined in signal.h. Fortunately for us, the 436 * only such codes we use are all in the range 1-7 and the low 437 * 3 bits of the status register are defined as 0 so there is 438 * no clash. 439 */ 440 ksi.ksi_signo = SIGFPE; 441 ksi.ksi_addr = (void *)code; 442 break; 443 444#ifdef M68040 445 case T_FPEMULI|T_USER: /* unimplemented FP instruction */ 446 case T_FPEMULD|T_USER: /* unimplemented FP data type */ 447 /* XXX need to FSAVE */ 448 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 449 p->p_pid, p->p_comm, 450 frame.f_format == 2 ? "instruction" : "data type", 451 frame.f_pc, frame.f_fmt2.f_iaddr); 452 /* XXX need to FRESTORE */ 453 ksi.ksi_signo = SIGFPE; 454 ksi.ksi_code = FPE_FLTINV; 455 break; 456#endif 457 458 case T_ILLINST|T_USER: /* illegal instruction fault */ 459#ifdef COMPAT_HPUX 460 if (p->p_emul == &emul_hpux) { 461 ksi.ksi_addr = (void *)HPUX_ILL_ILLINST_TRAP; 462 ksi.ksi_signo = SIGILL; 463 break; 464 } 465 /* fall through */ 466#endif 467 case T_PRIVINST|T_USER: /* privileged instruction fault */ 468#ifdef COMPAT_HPUX 469 if (p->p_emul == &emul_hpux) 470 ksi.ksi_addr = (void *)HPUX_ILL_PRIV_TRAP; 471 else 472#endif 473 ksi.ksi_addr = (void *)(int)frame.f_format; 474 /* XXX was ILL_PRIVIN_FAULT */ 475 ksi.ksi_signo = SIGILL; 476 ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ? 477 ILL_PRVOPC : ILL_ILLOPC; 478 break; 479 480 case T_ZERODIV|T_USER: /* Divide by zero */ 481#ifdef COMPAT_HPUX 482 if (p->p_emul == &emul_hpux) 483 ksi.ksi_addr = (void *)HPUX_FPE_INTDIV_TRAP; 484 else 485#endif 486 ksi.ksi_addr = (void *)(int)frame.f_format; 487 /* XXX was FPE_INTDIV_TRAP */ 488 ksi.ksi_signo = SIGFPE; 489 ksi.ksi_code = FPE_FLTDIV; 490 break; 491 492 case T_CHKINST|T_USER: /* CHK instruction trap */ 493#ifdef COMPAT_HPUX 494 if (p->p_emul == &emul_hpux) { 495 /* handled differently under hp-ux */ 496 ksi.ksi_signo = SIGILL; 497 ksi.ksi_addr = (void *)HPUX_ILL_CHK_TRAP; 498 break; 499 } 500#endif 501 ksi.ksi_addr = (void *)(int)frame.f_format; 502 /* XXX was FPE_SUBRNG_TRAP */ 503 ksi.ksi_signo = SIGFPE; 504 break; 505 506 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 507#ifdef COMPAT_HPUX 508 if (p->p_emul == &emul_hpux) { 509 /* handled differently under hp-ux */ 510 ksi.ksi_signo = SIGILL; 511 ksi.ksi_addr = (void *)HPUX_ILL_TRAPV_TRAP; 512 break; 513 } 514#endif 515 ksi.ksi_addr = (void *)(int)frame.f_format; 516 /* XXX was FPE_INTOVF_TRAP */ 517 ksi.ksi_signo = SIGFPE; 518 break; 519 520 /* 521 * XXX: Trace traps are a nightmare. 522 * 523 * HP-UX uses trap #1 for breakpoints, 524 * NetBSD/m68k uses trap #2, 525 * SUN 3.x uses trap #15, 526 * DDB and KGDB uses trap #15 (for kernel breakpoints; 527 * handled elsewhere). 528 * 529 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 530 * SUN 3.x traps get passed through as T_TRAP15 and are not really 531 * supported yet. 532 * 533 * XXX: We should never get kernel-mode T_TRAP15 534 * XXX: because locore.s now gives them special treatment. 535 */ 536 case T_TRAP15: /* kernel breakpoint */ 537#ifdef DEBUG 538 printf("unexpected kernel trace trap, type = %d\n", type); 539 printf("program counter = 0x%x\n", frame.f_pc); 540#endif 541 frame.f_sr &= ~PSL_T; 542 return; 543 544 case T_TRACE|T_USER: /* user trace trap */ 545#ifdef COMPAT_SUNOS 546 /* 547 * SunOS uses Trap #2 for a "CPU cache flush". 548 * Just flush the on-chip caches and return. 549 */ 550 if (p->p_emul == &emul_sunos) { 551 ICIA(); 552 DCIU(); 553 return; 554 } 555#endif 556 /* FALLTHROUGH */ 557 case T_TRACE: /* tracing a trap instruction */ 558 case T_TRAP15|T_USER: /* SUN user trace trap */ 559 frame.f_sr &= ~PSL_T; 560 ksi.ksi_signo = SIGTRAP; 561 break; 562 563 case T_ASTFLT: /* system async trap, cannot happen */ 564 goto dopanic; 565 566 case T_ASTFLT|T_USER: /* user async trap */ 567 astpending = 0; 568 /* 569 * We check for software interrupts first. This is because 570 * they are at a higher level than ASTs, and on a VAX would 571 * interrupt the AST. We assume that if we are processing 572 * an AST that we must be at IPL0 so we don't bother to 573 * check. Note that we ensure that we are at least at SIR 574 * IPL while processing the SIR. 575 */ 576 spl1(); 577 /* fall into... */ 578 579 case T_SSIR: /* software interrupt */ 580 case T_SSIR|T_USER: 581 582 softintr_dispatch(); 583 584 /* 585 * If this was not an AST trap, we are all done. 586 */ 587 if (type != (T_ASTFLT|T_USER)) { 588 uvmexp.traps--; 589 return; 590 } 591 spl0(); 592 if (l->l_pflag & LP_OWEUPC) { 593 l->l_pflag &= ~LP_OWEUPC; 594 ADDUPROF(l); 595 } 596 if (want_resched) 597 preempt(); 598 goto out; 599 600 case T_MMUFLT: /* kernel mode page fault */ 601 /* 602 * If we were doing profiling ticks or other user mode 603 * stuff from interrupt code, Just Say No. 604 */ 605 if (l->l_addr->u_pcb.pcb_onfault == fubail || 606 l->l_addr->u_pcb.pcb_onfault == subail) 607 goto copyfault; 608 /* fall into ... */ 609 610 case T_MMUFLT|T_USER: /* page fault */ 611 { 612 vaddr_t va; 613 struct vmspace *vm = p->p_vmspace; 614 struct vm_map *map; 615 int rv; 616 vm_prot_t ftype; 617 extern struct vm_map *kernel_map; 618 619#ifdef DEBUG 620 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 621 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 622 p->p_pid, code, v, frame.f_pc, frame.f_sr); 623#endif 624 /* 625 * It is only a kernel address space fault iff: 626 * 1. (type & T_USER) == 0 and 627 * 2. pcb_onfault not set or 628 * 3. pcb_onfault set but supervisor space data fault 629 * The last can occur during an exec() copyin where the 630 * argument space is lazy-allocated. 631 */ 632 if ((type & T_USER) == 0 && 633 ((l->l_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code))) 634 map = kernel_map; 635 else 636 map = vm ? &vm->vm_map : kernel_map; 637 638 if (WRFAULT(code)) 639 ftype = VM_PROT_WRITE; 640 else 641 ftype = VM_PROT_READ; 642 643 va = trunc_page((vaddr_t)v); 644 645 if (map == kernel_map && va == 0) { 646 printf("trap: bad kernel %s access at 0x%x\n", 647 (ftype & VM_PROT_WRITE) ? "read/write" : 648 "read", v); 649 goto dopanic; 650 } 651 652#ifdef DIAGNOSTIC 653 if (interrupt_depth && !panicking) { 654 printf("trap: calling uvm_fault() from interrupt!\n"); 655 goto dopanic; 656 } 657#endif 658 659#ifdef COMPAT_HPUX 660 if (ISHPMMADDR(va)) { 661 int pmap_mapmulti(pmap_t, vaddr_t); 662 vaddr_t bva; 663 664 rv = pmap_mapmulti(map->pmap, va); 665 if (rv != 0) { 666 bva = HPMMBASEADDR(va); 667 rv = uvm_fault(map, bva, ftype); 668 if (rv == 0) 669 (void) pmap_mapmulti(map->pmap, va); 670 } 671 } else 672#endif 673 rv = uvm_fault(map, va, ftype); 674#ifdef DEBUG 675 if (rv && MDB_ISPID(p->p_pid)) 676 printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n", 677 map, va, ftype, rv); 678#endif 679 /* 680 * If this was a stack access we keep track of the maximum 681 * accessed stack size. Also, if vm_fault gets a protection 682 * failure it is due to accessing the stack region outside 683 * the current limit and we need to reflect that as an access 684 * error. 685 */ 686 if (rv == 0) { 687 if (map != kernel_map && (void *)va >= vm->vm_maxsaddr) 688 uvm_grow(p, va); 689 690 if (type == T_MMUFLT) { 691#ifdef M68040 692 if (cputype == CPU_68040) 693 (void) writeback(&frame, 1); 694#endif 695 return; 696 } 697 goto out; 698 } 699 if (rv == EACCES) { 700 ksi.ksi_code = SEGV_ACCERR; 701 rv = EFAULT; 702 } else 703 ksi.ksi_code = SEGV_MAPERR; 704 if (type == T_MMUFLT) { 705 if (l->l_addr->u_pcb.pcb_onfault) 706 goto copyfault; 707 printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n", 708 map, va, ftype, rv); 709 printf(" type %x, code [mmu,,ssw]: %x\n", 710 type, code); 711 goto dopanic; 712 } 713 ksi.ksi_addr = (void *)v; 714 if (rv == ENOMEM) { 715 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 716 p->p_pid, p->p_comm, 717 l->l_cred ? 718 kauth_cred_geteuid(l->l_cred) : -1); 719 ksi.ksi_signo = SIGKILL; 720 } else { 721 ksi.ksi_signo = SIGSEGV; 722 } 723 break; 724 } 725 } 726 trapsignal(l, &ksi); 727 if ((type & T_USER) == 0) 728 return; 729out: 730 userret(l, &frame, sticks, v, 1); 731} 732 733#ifdef M68040 734#ifdef DEBUG 735struct writebackstats { 736 int calls; 737 int cpushes; 738 int move16s; 739 int wb1s, wb2s, wb3s; 740 int wbsize[4]; 741} wbstats; 742 743const char *f7sz[] = { "longword", "byte", "word", "line" }; 744const char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 745const char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 746 "M-code", "k-data", "k-code", "RES" }; 747const char wberrstr[] = 748 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 749#endif 750 751int 752writeback(struct frame *fp, int docachepush) 753{ 754 struct fmt7 *f = &fp->f_fmt7; 755 struct lwp *l = curlwp; 756 struct proc *p = l->l_proc; 757 int err = 0; 758 u_int fa; 759 void *oonfault = l->l_addr->u_pcb.pcb_onfault; 760 paddr_t pa; 761 762#ifdef DEBUG 763 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 764 printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); 765 dumpssw(f->f_ssw); 766 } 767 wbstats.calls++; 768#endif 769 /* 770 * Deal with special cases first. 771 */ 772 if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { 773 /* 774 * Dcache push fault. 775 * Line-align the address and write out the push data to 776 * the indicated physical address. 777 */ 778#ifdef DEBUG 779 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 780 printf(" pushing %s to PA %x, data %x", 781 f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], 782 f->f_fa, f->f_pd0); 783 if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) 784 printf("/%x/%x/%x", 785 f->f_pd1, f->f_pd2, f->f_pd3); 786 printf("\n"); 787 } 788 if (f->f_wb1s & SSW4_WBSV) 789 panic("writeback: cache push with WB1S valid"); 790 wbstats.cpushes++; 791#endif 792 /* 793 * XXX there are security problems if we attempt to do a 794 * cache push after a signal handler has been called. 795 */ 796 if (docachepush) { 797 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, 798 trunc_page(f->f_fa), VM_PROT_WRITE, 799 VM_PROT_WRITE|PMAP_WIRED); 800 pmap_update(pmap_kernel()); 801 fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 802 bcopy((void *)&f->f_pd0, (void *)fa, 16); 803 (void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa); 804 DCFL(pa); 805 pmap_remove(pmap_kernel(), (vaddr_t)vmmap, 806 (vaddr_t)&vmmap[PAGE_SIZE]); 807 pmap_update(pmap_kernel()); 808 } else 809 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 810 p->p_pid, p->p_comm, kauth_cred_geteuid(l->l_cred)); 811 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 812 /* 813 * MOVE16 fault. 814 * Line-align the address and write out the push data to 815 * the indicated virtual address. 816 */ 817#ifdef DEBUG 818 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 819 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 820 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 821 f->f_pd2, f->f_pd3); 822 if (f->f_wb1s & SSW4_WBSV) 823 panic("writeback: MOVE16 with WB1S valid"); 824 wbstats.move16s++; 825#endif 826 if (KDFAULT(f->f_wb1s)) 827 bcopy((void *)&f->f_pd0, (void *)(f->f_fa & ~0xF), 16); 828 else 829 err = suline((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0); 830 if (err) { 831 fa = f->f_fa & ~0xF; 832#ifdef DEBUG 833 if (mmudebug & MDB_WBFAILED) 834 printf(wberrstr, p->p_pid, p->p_comm, 835 "MOVE16", fp->f_pc, f->f_fa, 836 f->f_fa & ~0xF, f->f_pd0); 837#endif 838 } 839 } else if (f->f_wb1s & SSW4_WBSV) { 840 /* 841 * Writeback #1. 842 * Position the "memory-aligned" data and write it out. 843 */ 844 u_int wb1d = f->f_wb1d; 845 int off; 846 847#ifdef DEBUG 848 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 849 dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 850 wbstats.wb1s++; 851 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 852#endif 853 off = (f->f_wb1a & 3) * 8; 854 switch (f->f_wb1s & SSW4_SZMASK) { 855 case SSW4_SZLW: 856 if (off) 857 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 858 if (KDFAULT(f->f_wb1s)) 859 *(long *)f->f_wb1a = wb1d; 860 else 861 err = suword((void *)f->f_wb1a, wb1d); 862 break; 863 case SSW4_SZB: 864 off = 24 - off; 865 if (off) 866 wb1d >>= off; 867 if (KDFAULT(f->f_wb1s)) 868 *(char *)f->f_wb1a = wb1d; 869 else 870 err = subyte((void *)f->f_wb1a, wb1d); 871 break; 872 case SSW4_SZW: 873 off = (off + 16) % 32; 874 if (off) 875 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 876 if (KDFAULT(f->f_wb1s)) 877 *(short *)f->f_wb1a = wb1d; 878 else 879 err = susword((void *)f->f_wb1a, wb1d); 880 break; 881 } 882 if (err) { 883 fa = f->f_wb1a; 884#ifdef DEBUG 885 if (mmudebug & MDB_WBFAILED) 886 printf(wberrstr, p->p_pid, p->p_comm, 887 "#1", fp->f_pc, f->f_fa, 888 f->f_wb1a, f->f_wb1d); 889#endif 890 } 891 } 892 /* 893 * Deal with the "normal" writebacks. 894 * 895 * XXX writeback2 is known to reflect a LINE size writeback after 896 * a MOVE16 was already dealt with above. Ignore it. 897 */ 898 if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 899 (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 900#ifdef DEBUG 901 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 902 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 903 wbstats.wb2s++; 904 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 905#endif 906 switch (f->f_wb2s & SSW4_SZMASK) { 907 case SSW4_SZLW: 908 if (KDFAULT(f->f_wb2s)) 909 *(long *)f->f_wb2a = f->f_wb2d; 910 else 911 err = suword((void *)f->f_wb2a, f->f_wb2d); 912 break; 913 case SSW4_SZB: 914 if (KDFAULT(f->f_wb2s)) 915 *(char *)f->f_wb2a = f->f_wb2d; 916 else 917 err = subyte((void *)f->f_wb2a, f->f_wb2d); 918 break; 919 case SSW4_SZW: 920 if (KDFAULT(f->f_wb2s)) 921 *(short *)f->f_wb2a = f->f_wb2d; 922 else 923 err = susword((void *)f->f_wb2a, f->f_wb2d); 924 break; 925 } 926 if (err) { 927 fa = f->f_wb2a; 928#ifdef DEBUG 929 if (mmudebug & MDB_WBFAILED) { 930 printf(wberrstr, p->p_pid, p->p_comm, 931 "#2", fp->f_pc, f->f_fa, 932 f->f_wb2a, f->f_wb2d); 933 dumpssw(f->f_ssw); 934 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 935 } 936#endif 937 } 938 } 939 if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 940#ifdef DEBUG 941 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 942 dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 943 wbstats.wb3s++; 944 wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 945#endif 946 switch (f->f_wb3s & SSW4_SZMASK) { 947 case SSW4_SZLW: 948 if (KDFAULT(f->f_wb3s)) 949 *(long *)f->f_wb3a = f->f_wb3d; 950 else 951 err = suword((void *)f->f_wb3a, f->f_wb3d); 952 break; 953 case SSW4_SZB: 954 if (KDFAULT(f->f_wb3s)) 955 *(char *)f->f_wb3a = f->f_wb3d; 956 else 957 err = subyte((void *)f->f_wb3a, f->f_wb3d); 958 break; 959 case SSW4_SZW: 960 if (KDFAULT(f->f_wb3s)) 961 *(short *)f->f_wb3a = f->f_wb3d; 962 else 963 err = susword((void *)f->f_wb3a, f->f_wb3d); 964 break; 965#ifdef DEBUG 966 case SSW4_SZLN: 967 panic("writeback: wb3s indicates LINE write"); 968#endif 969 } 970 if (err) { 971 fa = f->f_wb3a; 972#ifdef DEBUG 973 if (mmudebug & MDB_WBFAILED) 974 printf(wberrstr, p->p_pid, p->p_comm, 975 "#3", fp->f_pc, f->f_fa, 976 f->f_wb3a, f->f_wb3d); 977#endif 978 } 979 } 980 l->l_addr->u_pcb.pcb_onfault = oonfault; 981 if (err) 982 err = SIGSEGV; 983 return (err); 984} 985 986#ifdef DEBUG 987void 988dumpssw(u_short ssw) 989{ 990 printf(" SSW: %x: ", ssw); 991 if (ssw & SSW4_CP) 992 printf("CP,"); 993 if (ssw & SSW4_CU) 994 printf("CU,"); 995 if (ssw & SSW4_CT) 996 printf("CT,"); 997 if (ssw & SSW4_CM) 998 printf("CM,"); 999 if (ssw & SSW4_MA) 1000 printf("MA,"); 1001 if (ssw & SSW4_ATC) 1002 printf("ATC,"); 1003 if (ssw & SSW4_LK) 1004 printf("LK,"); 1005 if (ssw & SSW4_RW) 1006 printf("RW,"); 1007 printf(" SZ=%s, TT=%s, TM=%s\n", 1008 f7sz[(ssw & SSW4_SZMASK) >> 5], 1009 f7tt[(ssw & SSW4_TTMASK) >> 3], 1010 f7tm[ssw & SSW4_TMMASK]); 1011} 1012 1013void 1014dumpwb(int num, u_short s, u_int a, u_int d) 1015{ 1016 struct proc *p = curproc; 1017 paddr_t pa; 1018 1019 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 1020 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 1021 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 1022 printf(" PA "); 1023 if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == false) 1024 printf("<invalid address>"); 1025 else 1026 printf("%lx, current value %lx", pa, fuword((void *)a)); 1027 printf("\n"); 1028} 1029#endif 1030#endif 1031