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