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