1*ed517291Slukem /* $NetBSD: trap.c,v 1.10 2003/07/15 03:36:13 lukem Exp $ */ 2ec984a04Sfredette 3ec984a04Sfredette /* 4ec984a04Sfredette * Copyright (c) 1994 Gordon W. Ross 5ec984a04Sfredette * Copyright (c) 1993 Adam Glass 6ec984a04Sfredette * Copyright (c) 1988 University of Utah. 7ec984a04Sfredette * Copyright (c) 1982, 1986, 1990, 1993 8ec984a04Sfredette * The Regents of the University of California. All rights reserved. 9ec984a04Sfredette * 10ec984a04Sfredette * This code is derived from software contributed to Berkeley by 11ec984a04Sfredette * the Systems Programming Group of the University of Utah Computer 12ec984a04Sfredette * Science Department. 13ec984a04Sfredette * 14ec984a04Sfredette * Redistribution and use in source and binary forms, with or without 15ec984a04Sfredette * modification, are permitted provided that the following conditions 16ec984a04Sfredette * are met: 17ec984a04Sfredette * 1. Redistributions of source code must retain the above copyright 18ec984a04Sfredette * notice, this list of conditions and the following disclaimer. 19ec984a04Sfredette * 2. Redistributions in binary form must reproduce the above copyright 20ec984a04Sfredette * notice, this list of conditions and the following disclaimer in the 21ec984a04Sfredette * documentation and/or other materials provided with the distribution. 22ec984a04Sfredette * 3. All advertising materials mentioning features or use of this software 23ec984a04Sfredette * must display the following acknowledgement: 24ec984a04Sfredette * This product includes software developed by the University of 25ec984a04Sfredette * California, Berkeley and its contributors. 26ec984a04Sfredette * 4. Neither the name of the University nor the names of its contributors 27ec984a04Sfredette * may be used to endorse or promote products derived from this software 28ec984a04Sfredette * without specific prior written permission. 29ec984a04Sfredette * 30ec984a04Sfredette * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31ec984a04Sfredette * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32ec984a04Sfredette * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33ec984a04Sfredette * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34ec984a04Sfredette * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35ec984a04Sfredette * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36ec984a04Sfredette * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37ec984a04Sfredette * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38ec984a04Sfredette * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39ec984a04Sfredette * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40ec984a04Sfredette * SUCH DAMAGE. 41ec984a04Sfredette * 42ec984a04Sfredette * from: Utah Hdr: trap.c 1.37 92/12/20 43ec984a04Sfredette * from: @(#)trap.c 8.5 (Berkeley) 1/4/94 44ec984a04Sfredette */ 45ec984a04Sfredette 46*ed517291Slukem #include <sys/cdefs.h> 47*ed517291Slukem __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.10 2003/07/15 03:36:13 lukem Exp $"); 48*ed517291Slukem 49ec984a04Sfredette #include "opt_ddb.h" 50ec984a04Sfredette #include "opt_execfmt.h" 51d505b189Smartin #include "opt_fpu_emulate.h" 52d84d2c6cSlukem #include "opt_kgdb.h" 53ec984a04Sfredette #include "opt_compat_aout_m68k.h" 54ec984a04Sfredette #include "opt_compat_sunos.h" 55ec984a04Sfredette 56ec984a04Sfredette #include <sys/param.h> 57ec984a04Sfredette #include <sys/systm.h> 58ec984a04Sfredette #include <sys/proc.h> 59ec984a04Sfredette #include <sys/acct.h> 60ec984a04Sfredette #include <sys/kernel.h> 61ec984a04Sfredette #include <sys/signalvar.h> 62ec984a04Sfredette #include <sys/resourcevar.h> 63d2275d51Sthorpej #include <sys/sa.h> 64d2275d51Sthorpej #include <sys/savar.h> 65ec984a04Sfredette #include <sys/syscall.h> 66ec984a04Sfredette #include <sys/syslog.h> 67ec984a04Sfredette #include <sys/user.h> 68ec984a04Sfredette #ifdef KGDB 69ec984a04Sfredette #include <sys/kgdb.h> 70ec984a04Sfredette #endif 71ec984a04Sfredette 72ec984a04Sfredette #include <uvm/uvm_extern.h> 73ec984a04Sfredette 74ec984a04Sfredette #include <machine/cpu.h> 75ec984a04Sfredette #include <machine/endian.h> 76ec984a04Sfredette #include <machine/psl.h> 77ec984a04Sfredette #include <machine/trap.h> 78ec984a04Sfredette #include <machine/reg.h> 79ec984a04Sfredette #include <machine/promlib.h> 80ec984a04Sfredette 81ec984a04Sfredette #include <sun2/sun2/fc.h> 82ec984a04Sfredette #include <sun2/sun2/machdep.h> 83ec984a04Sfredette 840dc8ee94Smatt #ifdef DDB 850dc8ee94Smatt #include <machine/db_machdep.h> 860dc8ee94Smatt #include <ddb/db_extern.h> 870dc8ee94Smatt #endif 880dc8ee94Smatt 89ec984a04Sfredette #ifdef COMPAT_SUNOS 90ec984a04Sfredette #include <compat/sunos/sunos_syscall.h> 91ec984a04Sfredette extern struct emul emul_sunos; 92ec984a04Sfredette #endif 93ec984a04Sfredette 94ec984a04Sfredette #ifdef COMPAT_AOUT_M68K 95ec984a04Sfredette extern struct emul emul_netbsd_aoutm68k; 96ec984a04Sfredette #endif 97ec984a04Sfredette 98ec984a04Sfredette /* Special labels in m68k/copy.s */ 99ec984a04Sfredette extern char fubail[], subail[]; 100ec984a04Sfredette 101ec984a04Sfredette /* These are called from locore.s */ 102ec984a04Sfredette void trap __P((int type, u_int code, u_int v, struct trapframe)); 103ec984a04Sfredette void trap_kdebug __P((int type, struct trapframe tf)); 104ec984a04Sfredette int _nodb_trap __P((int type, struct trapframe *)); 105ec984a04Sfredette void straytrap __P((struct trapframe)); 106ec984a04Sfredette 107d2275d51Sthorpej static void userret __P((struct lwp *, struct trapframe *, u_quad_t)); 108ec984a04Sfredette 109ec984a04Sfredette int astpending; 110ec984a04Sfredette int want_resched; 111ec984a04Sfredette 112ec984a04Sfredette char *trap_type[] = { 113ec984a04Sfredette "Bus error", 114ec984a04Sfredette "Address error", 115ec984a04Sfredette "Illegal instruction", 116ec984a04Sfredette "Zero divide", 117ec984a04Sfredette "CHK instruction", 118ec984a04Sfredette "TRAPV instruction", 119ec984a04Sfredette "Privilege violation", 120ec984a04Sfredette "Trace trap", 121ec984a04Sfredette "MMU fault", 122ec984a04Sfredette "SSIR trap", 123ec984a04Sfredette "Format error", 124ec984a04Sfredette "68881 exception", 125ec984a04Sfredette "Coprocessor violation", 126ec984a04Sfredette "Async system trap", 127ec984a04Sfredette "Unused? (14)", 128ec984a04Sfredette "Breakpoint", 129ec984a04Sfredette "FPU instruction", 130ec984a04Sfredette "FPU data format", 131ec984a04Sfredette }; 132ec984a04Sfredette u_int trap_types = sizeof(trap_type) / sizeof(trap_type[0]); 133ec984a04Sfredette 134ec984a04Sfredette /* 135ec984a04Sfredette * Size of various exception stack frames (minus the standard 8 bytes) 136ec984a04Sfredette */ 137ec984a04Sfredette short exframesize[] = { 138ec984a04Sfredette FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ 139ec984a04Sfredette FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 140ec984a04Sfredette FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ 141ec984a04Sfredette FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ 142ec984a04Sfredette FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ 143ec984a04Sfredette -1, -1, /* type 5-6 - undefined */ 144ec984a04Sfredette FMT7SIZE, /* type 7 - access error (68040) */ 145ec984a04Sfredette FMT8SIZE, /* type 8 - bus fault (68010) */ 146ec984a04Sfredette FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 147ec984a04Sfredette FMTASIZE, /* type A - short bus fault (68020/030) */ 148ec984a04Sfredette FMTBSIZE, /* type B - long bus fault (68020/030) */ 149ec984a04Sfredette -1, -1, -1, -1 /* type C-F - undefined */ 150ec984a04Sfredette }; 151ec984a04Sfredette 152ec984a04Sfredette #define KDFAULT(c) (((c) & (SSW1_IF|SSW1_FCMASK)) == (FC_SUPERD)) 153ec984a04Sfredette #define WRFAULT(c) (((c) & (SSW1_IF|SSW1_DF|SSW1_RW)) == (0)) 154ec984a04Sfredette 155ec984a04Sfredette /* #define DEBUG XXX */ 156ec984a04Sfredette 157ec984a04Sfredette #ifdef DEBUG 1588b21bb00Sfredette unsigned short buserr_reg; 159ec984a04Sfredette int mmudebug = 0; 160ec984a04Sfredette int mmupid = -1; 161ec984a04Sfredette #define MDB_ISPID(p) ((p) == mmupid) 162ec984a04Sfredette #define MDB_FOLLOW 1 163ec984a04Sfredette #define MDB_WBFOLLOW 2 164ec984a04Sfredette #define MDB_WBFAILED 4 165ec984a04Sfredette #define MDB_CPFAULT 8 166ec984a04Sfredette #endif 167ec984a04Sfredette 168ec984a04Sfredette /* 169ec984a04Sfredette * trap and syscall both need the following work done before 170ec984a04Sfredette * returning to user mode. 171ec984a04Sfredette */ 172ec984a04Sfredette static void 173d2275d51Sthorpej userret(l, tf, oticks) 174d2275d51Sthorpej struct lwp *l; 175bbb634caSfredette struct trapframe *tf; 176ec984a04Sfredette u_quad_t oticks; 177ec984a04Sfredette { 178d2275d51Sthorpej struct proc *p = l->l_proc; 179ec984a04Sfredette int sig; 180ec984a04Sfredette 181ec984a04Sfredette /* take pending signals */ 182d2275d51Sthorpej while ((sig = CURSIG(l)) != 0) 183ec984a04Sfredette postsig(sig); 184ec984a04Sfredette 185d2275d51Sthorpej /* Invoke per-process kernel-exit handling, if any */ 186d2275d51Sthorpej if (p->p_userret) 187d2275d51Sthorpej (p->p_userret)(l, p->p_userret_arg); 188ec984a04Sfredette 189d2275d51Sthorpej /* Invoke any pending upcalls. */ 190d2275d51Sthorpej while (l->l_flag & L_SA_UPCALL) 191d2275d51Sthorpej sa_upcall_userret(l); 192ec984a04Sfredette 193ec984a04Sfredette /* 194ec984a04Sfredette * If profiling, charge system time to the trapped pc. 195ec984a04Sfredette */ 196ec984a04Sfredette if (p->p_flag & P_PROFIL) { 197ec984a04Sfredette extern int psratio; 198ec984a04Sfredette addupc_task(p, tf->tf_pc, 199ec984a04Sfredette (int)(p->p_sticks - oticks) * psratio); 200ec984a04Sfredette } 201ec984a04Sfredette 202d2275d51Sthorpej curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri; 203ec984a04Sfredette } 204ec984a04Sfredette 205ec984a04Sfredette /* 206ec984a04Sfredette * Used by the common m68k syscall() and child_return() functions. 207ec984a04Sfredette * XXX: Temporary until all m68k ports share common trap()/userret() code. 208ec984a04Sfredette */ 209d2275d51Sthorpej void machine_userret(struct lwp *, struct frame *, u_quad_t); 210ec984a04Sfredette 211ec984a04Sfredette void 212d2275d51Sthorpej machine_userret(l, f, t) 213d2275d51Sthorpej struct lwp *l; 214ec984a04Sfredette struct frame *f; 215ec984a04Sfredette u_quad_t t; 216ec984a04Sfredette { 217ec984a04Sfredette 218d2275d51Sthorpej userret(l, &f->F_t, t); 219ec984a04Sfredette } 220ec984a04Sfredette 221ec984a04Sfredette /* 222ec984a04Sfredette * Trap is called from locore to handle most types of processor traps, 223ec984a04Sfredette * including events such as simulated software interrupts/AST's. 224ec984a04Sfredette * System calls are broken out for efficiency. 225ec984a04Sfredette */ 226ec984a04Sfredette /*ARGSUSED*/ 227ec984a04Sfredette void 228ec984a04Sfredette trap(type, code, v, tf) 229ec984a04Sfredette int type; 230ec984a04Sfredette u_int code, v; 231ec984a04Sfredette struct trapframe tf; 232ec984a04Sfredette { 233d2275d51Sthorpej struct lwp *l; 234bbb634caSfredette struct proc *p; 235bbb634caSfredette int sig, tmp; 236ec984a04Sfredette u_int ucode; 237ec984a04Sfredette u_quad_t sticks; 238ec984a04Sfredette 239ec984a04Sfredette uvmexp.traps++; 240d2275d51Sthorpej l = curlwp; 241ec984a04Sfredette ucode = 0; 242ec984a04Sfredette sig = 0; 243ec984a04Sfredette 244ec984a04Sfredette /* I have verified that this DOES happen! -gwr */ 245d2275d51Sthorpej if (l == NULL) 246d2275d51Sthorpej l = &lwp0; 247d2275d51Sthorpej p = l->l_proc; 248d2275d51Sthorpej 249ec984a04Sfredette #ifdef DIAGNOSTIC 250ec984a04Sfredette if (p->p_addr == NULL) 251ec984a04Sfredette panic("trap: no pcb"); 252ec984a04Sfredette #endif 253ec984a04Sfredette 254ec984a04Sfredette if (USERMODE(tf.tf_sr)) { 255ec984a04Sfredette type |= T_USER; 256ec984a04Sfredette sticks = p->p_sticks; 257d2275d51Sthorpej l->l_md.md_regs = tf.tf_regs; 258ec984a04Sfredette } else { 259ec984a04Sfredette sticks = 0; 260ec984a04Sfredette /* XXX: Detect trap recursion? */ 261ec984a04Sfredette } 262ec984a04Sfredette 263ec984a04Sfredette switch (type) { 264ec984a04Sfredette default: 265ec984a04Sfredette dopanic: 266ec984a04Sfredette printf("trap type=0x%x, code=0x%x, v=0x%x\n", type, code, v); 267ec984a04Sfredette /* 268ec984a04Sfredette * Let the kernel debugger see the trap frame that 269ec984a04Sfredette * caused us to panic. This is a convenience so 270ec984a04Sfredette * one can see registers at the point of failure. 271ec984a04Sfredette */ 272ec984a04Sfredette tmp = splhigh(); 273ec984a04Sfredette #ifdef KGDB 274ec984a04Sfredette /* If connected, step or cont returns 1 */ 275ec984a04Sfredette if (kgdb_trap(type, &tf)) 276ec984a04Sfredette goto kgdb_cont; 277ec984a04Sfredette #endif 278ec984a04Sfredette #ifdef DDB 279ec984a04Sfredette (void) kdb_trap(type, (db_regs_t *) &tf); 280ec984a04Sfredette #endif 281ec984a04Sfredette #ifdef KGDB 282ec984a04Sfredette kgdb_cont: 283ec984a04Sfredette #endif 284ec984a04Sfredette splx(tmp); 285ec984a04Sfredette if (panicstr) { 286ec984a04Sfredette /* 287ec984a04Sfredette * Note: panic is smart enough to do: 288ec984a04Sfredette * boot(RB_AUTOBOOT | RB_NOSYNC, NULL) 289ec984a04Sfredette * if we call it again. 290ec984a04Sfredette */ 291ec984a04Sfredette panic("trap during panic!"); 292ec984a04Sfredette } 293ec984a04Sfredette regdump(&tf, 128); 294ec984a04Sfredette type &= ~T_USER; 295ec984a04Sfredette if ((u_int)type < trap_types) 296ec984a04Sfredette panic(trap_type[type]); 297ec984a04Sfredette panic("trap type 0x%x", type); 298ec984a04Sfredette 299ec984a04Sfredette case T_BUSERR: /* kernel bus error */ 300d2275d51Sthorpej if (l->l_addr->u_pcb.pcb_onfault == NULL) 301ec984a04Sfredette goto dopanic; 302ec984a04Sfredette /*FALLTHROUGH*/ 303ec984a04Sfredette 304ec984a04Sfredette copyfault: 305ec984a04Sfredette /* 306ec984a04Sfredette * If we have arranged to catch this fault in any of the 307ec984a04Sfredette * copy to/from user space routines, set PC to return to 308ec984a04Sfredette * indicated location and set flag informing buserror code 309ec984a04Sfredette * that it may need to clean up stack frame. 310ec984a04Sfredette */ 311ec984a04Sfredette tf.tf_stackadj = exframesize[tf.tf_format]; 312ec984a04Sfredette tf.tf_format = tf.tf_vector = 0; 313d2275d51Sthorpej tf.tf_pc = (int) l->l_addr->u_pcb.pcb_onfault; 314ec984a04Sfredette goto done; 315ec984a04Sfredette 316ec984a04Sfredette case T_BUSERR|T_USER: /* bus error */ 317ec984a04Sfredette case T_ADDRERR|T_USER: /* address error */ 318ec984a04Sfredette ucode = v; 319ec984a04Sfredette sig = SIGBUS; 320ec984a04Sfredette break; 321ec984a04Sfredette 322ec984a04Sfredette case T_COPERR: /* kernel coprocessor violation */ 323ec984a04Sfredette case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 324ec984a04Sfredette case T_FMTERR: /* ...just in case... */ 325ec984a04Sfredette /* 326ec984a04Sfredette * The user has most likely trashed the RTE or FP state info 327ec984a04Sfredette * in the stack frame of a signal handler. 328ec984a04Sfredette */ 329ec984a04Sfredette printf("pid %d: kernel %s exception\n", p->p_pid, 330ec984a04Sfredette type==T_COPERR ? "coprocessor" : "format"); 331ec984a04Sfredette type |= T_USER; 332ec984a04Sfredette SIGACTION(p, SIGILL).sa_handler = SIG_DFL; 333ec984a04Sfredette sigdelset(&p->p_sigctx.ps_sigignore, SIGILL); 334ec984a04Sfredette sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL); 335ec984a04Sfredette sigdelset(&p->p_sigctx.ps_sigmask, SIGILL); 336ec984a04Sfredette sig = SIGILL; 337ec984a04Sfredette ucode = tf.tf_format; 338ec984a04Sfredette break; 339ec984a04Sfredette 340ec984a04Sfredette case T_COPERR|T_USER: /* user coprocessor violation */ 341ec984a04Sfredette /* What is a proper response here? */ 342ec984a04Sfredette ucode = 0; 343ec984a04Sfredette sig = SIGFPE; 344ec984a04Sfredette break; 345ec984a04Sfredette 346ec984a04Sfredette case T_FPERR|T_USER: /* 68881 exceptions */ 347ec984a04Sfredette /* 348ec984a04Sfredette * We pass along the 68881 status register which locore stashed 349ec984a04Sfredette * in code for us. Note that there is a possibility that the 350ec984a04Sfredette * bit pattern of this register will conflict with one of the 351ec984a04Sfredette * FPE_* codes defined in signal.h. Fortunately for us, the 352ec984a04Sfredette * only such codes we use are all in the range 1-7 and the low 353ec984a04Sfredette * 3 bits of the status register are defined as 0 so there is 354ec984a04Sfredette * no clash. 355ec984a04Sfredette */ 356ec984a04Sfredette ucode = code; 357ec984a04Sfredette sig = SIGFPE; 358ec984a04Sfredette break; 359ec984a04Sfredette 360ec984a04Sfredette case T_FPEMULI: /* FPU faults in supervisor mode */ 361ec984a04Sfredette case T_FPEMULD: 362ec984a04Sfredette if (nofault) /* Doing FPU probe? */ 363ec984a04Sfredette longjmp(nofault); 364ec984a04Sfredette goto dopanic; 365ec984a04Sfredette 366ec984a04Sfredette case T_FPEMULI|T_USER: /* unimplemented FP instuction */ 367ec984a04Sfredette case T_FPEMULD|T_USER: /* unimplemented FP data type */ 368ec984a04Sfredette #ifdef FPU_EMULATE 369d2275d51Sthorpej sig = fpu_emulate(&tf, &l->l_addr->u_pcb.pcb_fpregs); 370ec984a04Sfredette /* XXX - Deal with tracing? (tf.tf_sr & PSL_T) */ 371ec984a04Sfredette #else 372ec984a04Sfredette uprintf("pid %d killed: no floating point support\n", p->p_pid); 373ec984a04Sfredette sig = SIGILL; 374ec984a04Sfredette #endif 375ec984a04Sfredette break; 376ec984a04Sfredette 377ec984a04Sfredette case T_ILLINST|T_USER: /* illegal instruction fault */ 378ec984a04Sfredette case T_PRIVINST|T_USER: /* privileged instruction fault */ 379ec984a04Sfredette ucode = tf.tf_format; 380ec984a04Sfredette sig = SIGILL; 381ec984a04Sfredette break; 382ec984a04Sfredette 383ec984a04Sfredette case T_ZERODIV|T_USER: /* Divide by zero */ 384ec984a04Sfredette case T_CHKINST|T_USER: /* CHK instruction trap */ 385ec984a04Sfredette case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 386ec984a04Sfredette ucode = tf.tf_format; 387ec984a04Sfredette sig = SIGFPE; 388ec984a04Sfredette break; 389ec984a04Sfredette 390ec984a04Sfredette /* 391ec984a04Sfredette * XXX: Trace traps are a nightmare. 392ec984a04Sfredette * 393ec984a04Sfredette * HP-UX uses trap #1 for breakpoints, 394ec984a04Sfredette * NetBSD/m68k uses trap #2, 395ec984a04Sfredette * SUN 3.x uses trap #15, 396ec984a04Sfredette * DDB and KGDB uses trap #15 (for kernel breakpoints; 397ec984a04Sfredette * handled elsewhere). 398ec984a04Sfredette * 399ec984a04Sfredette * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 400ec984a04Sfredette * SUN 3.x traps get passed through as T_TRAP15 and are not really 401ec984a04Sfredette * supported yet. 402ec984a04Sfredette * 403ec984a04Sfredette * XXX: We should never get kernel-mode T_TRAP15 404ec984a04Sfredette * XXX: because locore.s now gives them special treatment. 405ec984a04Sfredette */ 406ec984a04Sfredette case T_TRAP15: /* kernel breakpoint */ 407ec984a04Sfredette tf.tf_sr &= ~PSL_T; 408ec984a04Sfredette goto done; 409ec984a04Sfredette 410ec984a04Sfredette case T_TRACE|T_USER: /* user trace trap */ 411ec984a04Sfredette #ifdef COMPAT_SUNOS 412ec984a04Sfredette /* 413ec984a04Sfredette * SunOS uses Trap #2 for a "CPU cache flush" 414ec984a04Sfredette * Just flush the on-chip caches and return. 415ec984a04Sfredette * XXX - Too bad NetBSD uses trap 2... 416ec984a04Sfredette */ 417ec984a04Sfredette if (p->p_emul == &emul_sunos) { 418ec984a04Sfredette /* get out fast */ 419ec984a04Sfredette goto done; 420ec984a04Sfredette } 421ec984a04Sfredette #endif 422ec984a04Sfredette /* FALLTHROUGH */ 423ec984a04Sfredette case T_TRACE: /* tracing a trap instruction */ 424ec984a04Sfredette case T_TRAP15|T_USER: /* SUN user trace trap */ 425ec984a04Sfredette tf.tf_sr &= ~PSL_T; 426ec984a04Sfredette sig = SIGTRAP; 427ec984a04Sfredette break; 428ec984a04Sfredette 429ec984a04Sfredette case T_ASTFLT: /* system async trap, cannot happen */ 430ec984a04Sfredette goto dopanic; 431ec984a04Sfredette 432ec984a04Sfredette case T_ASTFLT|T_USER: /* user async trap */ 433ec984a04Sfredette astpending = 0; 434ec984a04Sfredette /* T_SSIR is not used on a Sun2. */ 435ec984a04Sfredette if (p->p_flag & P_OWEUPC) { 436ec984a04Sfredette p->p_flag &= ~P_OWEUPC; 437ec984a04Sfredette ADDUPROF(p); 438ec984a04Sfredette } 439d2275d51Sthorpej if (want_resched) 440d2275d51Sthorpej preempt(0); 441ec984a04Sfredette goto douret; 442ec984a04Sfredette 443ec984a04Sfredette case T_MMUFLT: /* kernel mode page fault */ 444ec984a04Sfredette /* Hacks to avoid calling VM code from debugger. */ 445ec984a04Sfredette #ifdef DDB 446ec984a04Sfredette if (db_recover != 0) 447ec984a04Sfredette goto dopanic; 448ec984a04Sfredette #endif 449ec984a04Sfredette #ifdef KGDB 450ec984a04Sfredette if (kgdb_recover != 0) 451ec984a04Sfredette goto dopanic; 452ec984a04Sfredette #endif 453ec984a04Sfredette /* 454ec984a04Sfredette * If we were doing profiling ticks or other user mode 455ec984a04Sfredette * stuff from interrupt code, Just Say No. 456ec984a04Sfredette */ 457d2275d51Sthorpej if (l->l_addr->u_pcb.pcb_onfault == (caddr_t)fubail || 458d2275d51Sthorpej l->l_addr->u_pcb.pcb_onfault == (caddr_t)subail) 459ec984a04Sfredette { 460ec984a04Sfredette #ifdef DEBUG 461ec984a04Sfredette if (mmudebug & MDB_CPFAULT) { 462ec984a04Sfredette printf("trap: copyfault fu/su bail\n"); 463ec984a04Sfredette Debugger(); 464ec984a04Sfredette } 465ec984a04Sfredette #endif 466ec984a04Sfredette goto copyfault; 467ec984a04Sfredette } 468ec984a04Sfredette /*FALLTHROUGH*/ 469ec984a04Sfredette 470ec984a04Sfredette case T_MMUFLT|T_USER: { /* page fault */ 471bbb634caSfredette vaddr_t va; 472bbb634caSfredette struct vmspace *vm = p->p_vmspace; 473bbb634caSfredette struct vm_map *map; 474ec984a04Sfredette int rv; 475ec984a04Sfredette vm_prot_t ftype; 476821ec03eSchs extern struct vm_map *kernel_map; 477ec984a04Sfredette 478ec984a04Sfredette #ifdef DEBUG 479ec984a04Sfredette if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 480ec984a04Sfredette printf("trap: T_MMUFLT pid=%d, code=0x%x, v=0x%x, pc=0x%x, sr=0x%x\n", 481ec984a04Sfredette p->p_pid, code, v, tf.tf_pc, tf.tf_sr); 482ec984a04Sfredette #endif 483ec984a04Sfredette 484ec984a04Sfredette /* 485ec984a04Sfredette * It is only a kernel address space fault iff: 486ec984a04Sfredette * 1. (type & T_USER) == 0 and: (2 or 3) 487ec984a04Sfredette * 2. pcb_onfault not set or 488ec984a04Sfredette * 3. pcb_onfault set but supervisor space data fault 489ec984a04Sfredette * The last can occur during an exec() copyin where the 490ec984a04Sfredette * argument space is lazy-allocated. 491ec984a04Sfredette */ 492ec984a04Sfredette map = &vm->vm_map; 493ec984a04Sfredette if ((type & T_USER) == 0) { 494ec984a04Sfredette /* supervisor mode fault */ 495d2275d51Sthorpej if ((l->l_addr->u_pcb.pcb_onfault == NULL) || KDFAULT(code)) 496ec984a04Sfredette map = kernel_map; 497ec984a04Sfredette } 498ec984a04Sfredette 499ec984a04Sfredette if (WRFAULT(code)) 500b744097aSchs ftype = VM_PROT_WRITE; 501ec984a04Sfredette else 502ec984a04Sfredette ftype = VM_PROT_READ; 503bbb634caSfredette va = m68k_trunc_page((vaddr_t)v); 504ec984a04Sfredette 505ec984a04Sfredette /* 506ec984a04Sfredette * Need to resolve the fault. 507ec984a04Sfredette * 508ec984a04Sfredette * We give the pmap code a chance to resolve faults by 509ec984a04Sfredette * reloading translations that it was forced to unload. 510ec984a04Sfredette * This function does that, and calls vm_fault if it 511ec984a04Sfredette * could not resolve the fault by reloading the MMU. 512ec984a04Sfredette * This function may also, for example, disallow any 513ec984a04Sfredette * faults in the kernel text segment, etc. 514ec984a04Sfredette */ 515ec984a04Sfredette rv = _pmap_fault(map, va, ftype); 516ec984a04Sfredette 517ec984a04Sfredette #ifdef DEBUG 518ec984a04Sfredette if (rv && MDB_ISPID(p->p_pid)) { 519ec984a04Sfredette printf("vm_fault(%p, 0x%lx, 0x%x, 0) -> 0x%x\n", 520ec984a04Sfredette map, va, ftype, rv); 521ec984a04Sfredette if (mmudebug & MDB_WBFAILED) 522ec984a04Sfredette Debugger(); 523ec984a04Sfredette } 524ec984a04Sfredette #endif /* DEBUG */ 525ec984a04Sfredette 526ec984a04Sfredette /* 527ec984a04Sfredette * If this was a stack access we keep track of the maximum 528ec984a04Sfredette * accessed stack size. Also, if vm_fault gets a protection 529ec984a04Sfredette * failure it is due to accessing the stack region outside 530ec984a04Sfredette * the current limit and we need to reflect that as an access 531ec984a04Sfredette * error. 532ec984a04Sfredette */ 533ec984a04Sfredette if ((map != kernel_map) && ((caddr_t)va >= vm->vm_maxsaddr)) { 534ec984a04Sfredette if (rv == 0) { 535ec984a04Sfredette unsigned nss; 536ec984a04Sfredette 537ec984a04Sfredette nss = btoc((u_int)(USRSTACK-va)); 538ec984a04Sfredette if (nss > vm->vm_ssize) 539ec984a04Sfredette vm->vm_ssize = nss; 540ec984a04Sfredette } else if (rv == EACCES) 541ec984a04Sfredette rv = EFAULT; 542ec984a04Sfredette } 543ec984a04Sfredette if (rv == 0) 544ec984a04Sfredette goto finish; 545ec984a04Sfredette 546ec984a04Sfredette if ((type & T_USER) == 0) { 547ec984a04Sfredette /* supervisor mode fault */ 548d2275d51Sthorpej if (l->l_addr->u_pcb.pcb_onfault) { 549ec984a04Sfredette #ifdef DEBUG 550ec984a04Sfredette if (mmudebug & MDB_CPFAULT) { 551ec984a04Sfredette printf("trap: copyfault pcb_onfault\n"); 552ec984a04Sfredette Debugger(); 553ec984a04Sfredette } 554ec984a04Sfredette #endif 555ec984a04Sfredette goto copyfault; 556ec984a04Sfredette } 557ec984a04Sfredette printf("vm_fault(%p, 0x%lx, 0x%x, 0) -> 0x%x\n", 558ec984a04Sfredette map, va, ftype, rv); 559ec984a04Sfredette goto dopanic; 560ec984a04Sfredette } 561ec984a04Sfredette ucode = v; 562ec984a04Sfredette if (rv == ENOMEM) { 563ec984a04Sfredette printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 564ec984a04Sfredette p->p_pid, p->p_comm, 565ec984a04Sfredette p->p_cred && p->p_ucred ? 566ec984a04Sfredette p->p_ucred->cr_uid : -1); 567ec984a04Sfredette sig = SIGKILL; 568ec984a04Sfredette } else { 569ec984a04Sfredette sig = SIGSEGV; 570ec984a04Sfredette } 571ec984a04Sfredette break; 572ec984a04Sfredette } /* T_MMUFLT */ 573ec984a04Sfredette } /* switch */ 574ec984a04Sfredette 575ec984a04Sfredette finish: 576ec984a04Sfredette /* If trap was from supervisor mode, just return. */ 577ec984a04Sfredette if ((type & T_USER) == 0) 578ec984a04Sfredette goto done; 579ec984a04Sfredette /* Post a signal if necessary. */ 580ec984a04Sfredette if (sig != 0) 581d2275d51Sthorpej trapsignal(l, sig, ucode); 582ec984a04Sfredette douret: 583d2275d51Sthorpej userret(l, &tf, sticks); 584ec984a04Sfredette 585ec984a04Sfredette done:; 586ec984a04Sfredette /* XXX: Detect trap recursion? */ 587ec984a04Sfredette } 588ec984a04Sfredette 589ec984a04Sfredette /* 590ec984a04Sfredette * This is used if we hit a kernel breakpoint or trace trap 591ec984a04Sfredette * when there is no debugger installed (or not attached). 592ec984a04Sfredette * Drop into the PROM temporarily... 593ec984a04Sfredette */ 594ec984a04Sfredette int 595ec984a04Sfredette _nodb_trap(type, tf) 596ec984a04Sfredette int type; 597ec984a04Sfredette struct trapframe *tf; 598ec984a04Sfredette { 599ec984a04Sfredette 600ec984a04Sfredette printf("\r\nKernel "); 601ec984a04Sfredette if ((0 <= type) && (type < trap_types)) 602ec984a04Sfredette printf("%s", trap_type[type]); 603ec984a04Sfredette else 604ec984a04Sfredette printf("trap 0x%x", type); 605ec984a04Sfredette printf(", frame=%p\r\n", tf); 606ec984a04Sfredette printf("No debugger; doing PROM abort.\r\n"); 607ec984a04Sfredette printf("To continue, type: c <RETURN>\r\n"); 608ec984a04Sfredette prom_abort(); 609ec984a04Sfredette /* OK then, just resume... */ 610ec984a04Sfredette tf->tf_sr &= ~PSL_T; 611ec984a04Sfredette return(1); 612ec984a04Sfredette } 613ec984a04Sfredette 614ec984a04Sfredette /* 615ec984a04Sfredette * This is called by locore for supervisor-mode trace and 616ec984a04Sfredette * breakpoint traps. This is separate from trap() above 617ec984a04Sfredette * so that breakpoints in trap() will work. 618ec984a04Sfredette * 619ec984a04Sfredette * If we have both DDB and KGDB, let KGDB see it first, 620ec984a04Sfredette * because KGDB will just return 0 if not connected. 621ec984a04Sfredette */ 622ec984a04Sfredette void 623ec984a04Sfredette trap_kdebug(type, tf) 624ec984a04Sfredette int type; 625ec984a04Sfredette struct trapframe tf; 626ec984a04Sfredette { 627ec984a04Sfredette 628ec984a04Sfredette #ifdef KGDB 629ec984a04Sfredette /* Let KGDB handle it (if connected) */ 630ec984a04Sfredette if (kgdb_trap(type, &tf)) 631ec984a04Sfredette return; 632ec984a04Sfredette #endif 633ec984a04Sfredette #ifdef DDB 634ec984a04Sfredette /* Let DDB handle it. */ 635ec984a04Sfredette if (kdb_trap(type, &tf)) 636ec984a04Sfredette return; 637ec984a04Sfredette #endif 638ec984a04Sfredette 639ec984a04Sfredette /* Drop into the PROM temporarily... */ 640ec984a04Sfredette (void)_nodb_trap(type, &tf); 641ec984a04Sfredette } 642ec984a04Sfredette 643ec984a04Sfredette /* 644ec984a04Sfredette * Called by locore.s for an unexpected interrupt. 645ec984a04Sfredette * XXX - Almost identical to trap_kdebug... 646ec984a04Sfredette */ 647ec984a04Sfredette void 648ec984a04Sfredette straytrap(tf) 649ec984a04Sfredette struct trapframe tf; 650ec984a04Sfredette { 651ec984a04Sfredette int type = -1; 652ec984a04Sfredette 653ec984a04Sfredette printf("unexpected trap; vector=0x%x at pc=0x%x\n", 654ec984a04Sfredette tf.tf_vector, tf.tf_pc); 655ec984a04Sfredette 656ec984a04Sfredette #ifdef KGDB 657ec984a04Sfredette /* Let KGDB handle it (if connected) */ 658ec984a04Sfredette if (kgdb_trap(type, &tf)) 659ec984a04Sfredette return; 660ec984a04Sfredette #endif 661ec984a04Sfredette #ifdef DDB 662ec984a04Sfredette /* Let DDB handle it. */ 663ec984a04Sfredette if (kdb_trap(type, &tf)) 664ec984a04Sfredette return; 665ec984a04Sfredette #endif 666ec984a04Sfredette 667ec984a04Sfredette /* Drop into the PROM temporarily... */ 668ec984a04Sfredette (void)_nodb_trap(type, &tf); 669ec984a04Sfredette } 670