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