1*ae16be0bSad /* $NetBSD: trap.c,v 1.46 2019/11/21 19:24:01 ad 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*ae16be0bSad __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.46 2019/11/21 19:24:01 ad 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>
97ec984a04Sfredette #include <sys/syscall.h>
98ec984a04Sfredette #include <sys/syslog.h>
99ef56cc40Scl #include <sys/userret.h>
10028e8a168Syamt #include <sys/kauth.h>
101ec984a04Sfredette #ifdef KGDB
102ec984a04Sfredette #include <sys/kgdb.h>
103ec984a04Sfredette #endif
104ec984a04Sfredette
105ec984a04Sfredette #include <uvm/uvm_extern.h>
106ec984a04Sfredette
107ec984a04Sfredette #include <machine/cpu.h>
108ec984a04Sfredette #include <machine/endian.h>
109e17efabeStsutsui #include <machine/pcb.h>
110ec984a04Sfredette #include <machine/psl.h>
111ec984a04Sfredette #include <machine/trap.h>
112ec984a04Sfredette #include <machine/reg.h>
113ec984a04Sfredette #include <machine/promlib.h>
114ec984a04Sfredette
115ec984a04Sfredette #include <sun2/sun2/fc.h>
116ec984a04Sfredette #include <sun2/sun2/machdep.h>
117ec984a04Sfredette
1180dc8ee94Smatt #ifdef DDB
1190dc8ee94Smatt #include <machine/db_machdep.h>
1200dc8ee94Smatt #include <ddb/db_extern.h>
1210dc8ee94Smatt #endif
1220dc8ee94Smatt
123ec984a04Sfredette #ifdef COMPAT_SUNOS
124ec984a04Sfredette #include <compat/sunos/sunos_syscall.h>
125ec984a04Sfredette extern struct emul emul_sunos;
126ec984a04Sfredette #endif
127ec984a04Sfredette
128ec984a04Sfredette #ifdef COMPAT_AOUT_M68K
129ec984a04Sfredette extern struct emul emul_netbsd_aoutm68k;
130ec984a04Sfredette #endif
131ec984a04Sfredette
132ec984a04Sfredette /* These are called from locore.s */
133d2eac2f6Smhitch void trap(struct trapframe *, int type, u_int code, u_int v);
13410b1a7beSchs void trap_kdebug(int type, struct trapframe tf);
13510b1a7beSchs int _nodb_trap(int type, struct trapframe *);
13610b1a7beSchs void straytrap(struct trapframe);
137ec984a04Sfredette
13810b1a7beSchs static void userret(struct lwp *, struct trapframe *, u_quad_t);
139ec984a04Sfredette
140ec984a04Sfredette int astpending;
141ec984a04Sfredette
1426df30aa4Stsutsui const char *trap_type[] = {
143ec984a04Sfredette "Bus error",
144ec984a04Sfredette "Address error",
145ec984a04Sfredette "Illegal instruction",
146ec984a04Sfredette "Zero divide",
147ec984a04Sfredette "CHK instruction",
148ec984a04Sfredette "TRAPV instruction",
149ec984a04Sfredette "Privilege violation",
150ec984a04Sfredette "Trace trap",
151ec984a04Sfredette "MMU fault",
152ec984a04Sfredette "SSIR trap",
153ec984a04Sfredette "Format error",
154ec984a04Sfredette "68881 exception",
155ec984a04Sfredette "Coprocessor violation",
156ec984a04Sfredette "Async system trap",
157ec984a04Sfredette "Unused? (14)",
158ec984a04Sfredette "Breakpoint",
159ec984a04Sfredette "FPU instruction",
160ec984a04Sfredette "FPU data format",
161ec984a04Sfredette };
162ec984a04Sfredette u_int trap_types = sizeof(trap_type) / sizeof(trap_type[0]);
163ec984a04Sfredette
164ec984a04Sfredette /*
165ec984a04Sfredette * Size of various exception stack frames (minus the standard 8 bytes)
166ec984a04Sfredette */
167ec984a04Sfredette short exframesize[] = {
168ec984a04Sfredette FMT0SIZE, /* type 0 - normal (68020/030/040/060) */
169ec984a04Sfredette FMT1SIZE, /* type 1 - throwaway (68020/030/040) */
170ec984a04Sfredette FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */
171ec984a04Sfredette FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */
172ec984a04Sfredette FMT4SIZE, /* type 4 - access error/fp disabled (68060) */
173ec984a04Sfredette -1, -1, /* type 5-6 - undefined */
174ec984a04Sfredette FMT7SIZE, /* type 7 - access error (68040) */
175ec984a04Sfredette FMT8SIZE, /* type 8 - bus fault (68010) */
176ec984a04Sfredette FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */
177ec984a04Sfredette FMTASIZE, /* type A - short bus fault (68020/030) */
178ec984a04Sfredette FMTBSIZE, /* type B - long bus fault (68020/030) */
179ec984a04Sfredette -1, -1, -1, -1 /* type C-F - undefined */
180ec984a04Sfredette };
181ec984a04Sfredette
182ec984a04Sfredette #define KDFAULT(c) (((c) & (SSW1_IF|SSW1_FCMASK)) == (FC_SUPERD))
183ec984a04Sfredette #define WRFAULT(c) (((c) & (SSW1_IF|SSW1_DF|SSW1_RW)) == (0))
184ec984a04Sfredette
185ec984a04Sfredette /* #define DEBUG XXX */
186ec984a04Sfredette
187ec984a04Sfredette #ifdef DEBUG
1888b21bb00Sfredette unsigned short buserr_reg;
189ec984a04Sfredette int mmudebug = 0;
190ec984a04Sfredette int mmupid = -1;
191ec984a04Sfredette #define MDB_ISPID(p) ((p) == mmupid)
192ec984a04Sfredette #define MDB_FOLLOW 1
193ec984a04Sfredette #define MDB_WBFOLLOW 2
194ec984a04Sfredette #define MDB_WBFAILED 4
195ec984a04Sfredette #define MDB_CPFAULT 8
196ec984a04Sfredette #endif
197ec984a04Sfredette
198ec984a04Sfredette /*
199ec984a04Sfredette * trap and syscall both need the following work done before
200ec984a04Sfredette * returning to user mode.
201ec984a04Sfredette */
202ec984a04Sfredette static void
userret(struct lwp * l,struct trapframe * tf,u_quad_t oticks)20310b1a7beSchs userret(struct lwp *l, struct trapframe *tf, u_quad_t oticks)
204ec984a04Sfredette {
205d2275d51Sthorpej struct proc *p = l->l_proc;
206ec984a04Sfredette
207ef56cc40Scl /* Invoke MI userret code */
208ef56cc40Scl mi_userret(l);
209ec984a04Sfredette
210ec984a04Sfredette /*
211ec984a04Sfredette * If profiling, charge system time to the trapped pc.
212ec984a04Sfredette */
213b07ec3fcSad if (p->p_stflag & PST_PROFIL) {
214ec984a04Sfredette extern int psratio;
215b07ec3fcSad addupc_task(l, tf->tf_pc,
216ec984a04Sfredette (int)(p->p_sticks - oticks) * psratio);
217ec984a04Sfredette }
218ec984a04Sfredette }
219ec984a04Sfredette
220ec984a04Sfredette /*
221ec984a04Sfredette * Used by the common m68k syscall() and child_return() functions.
222ec984a04Sfredette * XXX: Temporary until all m68k ports share common trap()/userret() code.
223ec984a04Sfredette */
224d2275d51Sthorpej void machine_userret(struct lwp *, struct frame *, u_quad_t);
225ec984a04Sfredette
226ec984a04Sfredette void
machine_userret(struct lwp * l,struct frame * f,u_quad_t t)22710b1a7beSchs machine_userret(struct lwp *l, struct frame *f, u_quad_t t)
228ec984a04Sfredette {
229ec984a04Sfredette
230d2275d51Sthorpej userret(l, &f->F_t, t);
231ec984a04Sfredette }
232ec984a04Sfredette
233ec984a04Sfredette /*
234ec984a04Sfredette * Trap is called from locore to handle most types of processor traps,
235ec984a04Sfredette * including events such as simulated software interrupts/AST's.
236ec984a04Sfredette * System calls are broken out for efficiency.
237ec984a04Sfredette */
238ec984a04Sfredette /*ARGSUSED*/
239ec984a04Sfredette void
trap(struct trapframe * tf,int type,u_int code,u_int v)240d2eac2f6Smhitch trap(struct trapframe *tf, int type, u_int code, u_int v)
241ec984a04Sfredette {
242d2275d51Sthorpej struct lwp *l;
243bbb634caSfredette struct proc *p;
244a626cff9Srmind struct pcb *pcb;
24541692372Scl ksiginfo_t ksi;
24641692372Scl int tmp;
24704aa4da3Schs int rv;
248ec984a04Sfredette u_quad_t sticks;
24904aa4da3Schs void *onfault;
250ec984a04Sfredette
251ccde4787Smatt curcpu()->ci_data.cpu_ntrap++;
252d2275d51Sthorpej l = curlwp;
25304aa4da3Schs p = l->l_proc;
25404aa4da3Schs pcb = lwp_getpcb(l);
25504aa4da3Schs onfault = pcb->pcb_onfault;
25641692372Scl
25768723a99Sthorpej KSI_INIT_TRAP(&ksi);
25841692372Scl ksi.ksi_trap = type & ~T_USER;
259ec984a04Sfredette
260a626cff9Srmind KASSERT(pcb != NULL);
261ec984a04Sfredette
262d2eac2f6Smhitch if (USERMODE(tf->tf_sr)) {
263ec984a04Sfredette type |= T_USER;
264ec984a04Sfredette sticks = p->p_sticks;
265d2eac2f6Smhitch l->l_md.md_regs = tf->tf_regs;
2662b79369cSad LWP_CACHE_CREDS(l, p);
267ec984a04Sfredette } else {
268ec984a04Sfredette sticks = 0;
269ec984a04Sfredette /* XXX: Detect trap recursion? */
270ec984a04Sfredette }
271ec984a04Sfredette
272ec984a04Sfredette switch (type) {
273ec984a04Sfredette default:
274ec984a04Sfredette dopanic:
275ec984a04Sfredette printf("trap type=0x%x, code=0x%x, v=0x%x\n", type, code, v);
276ec984a04Sfredette /*
277ec984a04Sfredette * Let the kernel debugger see the trap frame that
278ec984a04Sfredette * caused us to panic. This is a convenience so
279ec984a04Sfredette * one can see registers at the point of failure.
280ec984a04Sfredette */
281ec984a04Sfredette tmp = splhigh();
282ec984a04Sfredette #ifdef KGDB
283ec984a04Sfredette /* If connected, step or cont returns 1 */
284d2eac2f6Smhitch if (kgdb_trap(type, tf))
285ec984a04Sfredette goto kgdb_cont;
286ec984a04Sfredette #endif
287ec984a04Sfredette #ifdef DDB
288d2eac2f6Smhitch (void) kdb_trap(type, (db_regs_t *) tf);
289ec984a04Sfredette #endif
290ec984a04Sfredette #ifdef KGDB
291ec984a04Sfredette kgdb_cont:
292ec984a04Sfredette #endif
293ec984a04Sfredette splx(tmp);
294ec984a04Sfredette if (panicstr) {
295ec984a04Sfredette /*
296ec984a04Sfredette * Note: panic is smart enough to do:
297ec984a04Sfredette * boot(RB_AUTOBOOT | RB_NOSYNC, NULL)
298ec984a04Sfredette * if we call it again.
299ec984a04Sfredette */
300ec984a04Sfredette panic("trap during panic!");
301ec984a04Sfredette }
302d2eac2f6Smhitch regdump(tf, 128);
303ec984a04Sfredette type &= ~T_USER;
304ec984a04Sfredette if ((u_int)type < trap_types)
305ec984a04Sfredette panic(trap_type[type]);
306ec984a04Sfredette panic("trap type 0x%x", type);
307ec984a04Sfredette
308ec984a04Sfredette case T_BUSERR: /* kernel bus error */
30904aa4da3Schs if (onfault == NULL)
310ec984a04Sfredette goto dopanic;
31104aa4da3Schs rv = EFAULT;
312ec984a04Sfredette /*FALLTHROUGH*/
313ec984a04Sfredette
314ec984a04Sfredette copyfault:
315ec984a04Sfredette /*
316ec984a04Sfredette * If we have arranged to catch this fault in any of the
317ec984a04Sfredette * copy to/from user space routines, set PC to return to
318ec984a04Sfredette * indicated location and set flag informing buserror code
319ec984a04Sfredette * that it may need to clean up stack frame.
320ec984a04Sfredette */
321d2eac2f6Smhitch tf->tf_stackadj = exframesize[tf->tf_format];
322d2eac2f6Smhitch tf->tf_format = tf->tf_vector = 0;
32304aa4da3Schs tf->tf_pc = (int)onfault;
32404aa4da3Schs tf->tf_regs[D0] = rv;
325ec984a04Sfredette goto done;
326ec984a04Sfredette
327ec984a04Sfredette case T_BUSERR|T_USER: /* bus error */
328ec984a04Sfredette case T_ADDRERR|T_USER: /* address error */
32941692372Scl ksi.ksi_addr = (void *)v;
33041692372Scl ksi.ksi_signo = SIGBUS;
33141692372Scl ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
33241692372Scl BUS_OBJERR : BUS_ADRERR;
333ec984a04Sfredette break;
334ec984a04Sfredette
335ec984a04Sfredette case T_COPERR: /* kernel coprocessor violation */
336ec984a04Sfredette case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */
337ec984a04Sfredette case T_FMTERR: /* ...just in case... */
338ec984a04Sfredette /*
339ec984a04Sfredette * The user has most likely trashed the RTE or FP state info
340ec984a04Sfredette * in the stack frame of a signal handler.
341ec984a04Sfredette */
342ec984a04Sfredette printf("pid %d: kernel %s exception\n", p->p_pid,
343ec984a04Sfredette type==T_COPERR ? "coprocessor" : "format");
344ec984a04Sfredette type |= T_USER;
345b07ec3fcSad
346284c2b9aSad mutex_enter(p->p_lock);
347ec984a04Sfredette SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
348ec984a04Sfredette sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
349ec984a04Sfredette sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
350b07ec3fcSad sigdelset(&l->l_sigmask, SIGILL);
351284c2b9aSad mutex_exit(p->p_lock);
352b07ec3fcSad
35341692372Scl ksi.ksi_signo = SIGILL;
354d2eac2f6Smhitch ksi.ksi_addr = (void *)(int)tf->tf_format;
35541692372Scl ksi.ksi_code = (type == T_COPERR) ?
35641692372Scl ILL_COPROC : ILL_ILLOPC;
357ec984a04Sfredette break;
358ec984a04Sfredette
359ec984a04Sfredette case T_COPERR|T_USER: /* user coprocessor violation */
360ec984a04Sfredette /* What is a proper response here? */
36141692372Scl ksi.ksi_signo = SIGFPE;
36241692372Scl ksi.ksi_code = FPE_FLTINV;
363ec984a04Sfredette break;
364ec984a04Sfredette
365ec984a04Sfredette case T_FPERR|T_USER: /* 68881 exceptions */
366ec984a04Sfredette /*
367ec984a04Sfredette * We pass along the 68881 status register which locore stashed
368f055e182Smartin * in code for us.
369ec984a04Sfredette */
37041692372Scl ksi.ksi_signo = SIGFPE;
371f055e182Smartin ksi.ksi_code = fpsr2siginfocode(code);
372ec984a04Sfredette break;
373ec984a04Sfredette
374ec984a04Sfredette case T_FPEMULI: /* FPU faults in supervisor mode */
375ec984a04Sfredette case T_FPEMULD:
376ec984a04Sfredette if (nofault) /* Doing FPU probe? */
377ec984a04Sfredette longjmp(nofault);
378ec984a04Sfredette goto dopanic;
379ec984a04Sfredette
3805d1e8b27Swiz case T_FPEMULI|T_USER: /* unimplemented FP instruction */
381ec984a04Sfredette case T_FPEMULD|T_USER: /* unimplemented FP data type */
382ec984a04Sfredette #ifdef FPU_EMULATE
383a626cff9Srmind if (fpu_emulate(tf, &pcb->pcb_fpregs, &ksi) == 0)
384d2eac2f6Smhitch ; /* XXX - Deal with tracing? (tf->tf_sr & PSL_T) */
385ec984a04Sfredette #else
386ec984a04Sfredette uprintf("pid %d killed: no floating point support\n", p->p_pid);
38741692372Scl ksi.ksi_signo = SIGILL;
38841692372Scl ksi.ksi_code = ILL_ILLOPC;
389ec984a04Sfredette #endif
390ec984a04Sfredette break;
391ec984a04Sfredette
392ec984a04Sfredette case T_ILLINST|T_USER: /* illegal instruction fault */
393ec984a04Sfredette case T_PRIVINST|T_USER: /* privileged instruction fault */
394d2eac2f6Smhitch ksi.ksi_addr = (void *)(int)tf->tf_format;
39541692372Scl ksi.ksi_signo = SIGILL;
39641692372Scl ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
39741692372Scl ILL_PRVOPC : ILL_ILLOPC;
398ec984a04Sfredette break;
399ec984a04Sfredette
400ec984a04Sfredette case T_ZERODIV|T_USER: /* Divide by zero */
40141692372Scl ksi.ksi_code = FPE_FLTDIV;
402ec984a04Sfredette case T_CHKINST|T_USER: /* CHK instruction trap */
403ec984a04Sfredette case T_TRAPVINST|T_USER: /* TRAPV instruction trap */
404d2eac2f6Smhitch ksi.ksi_addr = (void *)(int)tf->tf_format;
40541692372Scl ksi.ksi_signo = SIGFPE;
406ec984a04Sfredette break;
407ec984a04Sfredette
408ec984a04Sfredette /*
409ec984a04Sfredette * XXX: Trace traps are a nightmare.
410ec984a04Sfredette *
411ec984a04Sfredette * HP-UX uses trap #1 for breakpoints,
412ec984a04Sfredette * NetBSD/m68k uses trap #2,
413ec984a04Sfredette * SUN 3.x uses trap #15,
414ec984a04Sfredette * DDB and KGDB uses trap #15 (for kernel breakpoints;
415ec984a04Sfredette * handled elsewhere).
416ec984a04Sfredette *
417ec984a04Sfredette * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
418ec984a04Sfredette * SUN 3.x traps get passed through as T_TRAP15 and are not really
419ec984a04Sfredette * supported yet.
420ec984a04Sfredette *
421ec984a04Sfredette * XXX: We should never get kernel-mode T_TRAP15
422ec984a04Sfredette * XXX: because locore.s now gives them special treatment.
423ec984a04Sfredette */
424ec984a04Sfredette case T_TRAP15: /* kernel breakpoint */
425d2eac2f6Smhitch tf->tf_sr &= ~PSL_T;
426ec984a04Sfredette goto done;
427ec984a04Sfredette
428ec984a04Sfredette case T_TRACE|T_USER: /* user trace trap */
429ec984a04Sfredette #ifdef COMPAT_SUNOS
430ec984a04Sfredette /*
431ec984a04Sfredette * SunOS uses Trap #2 for a "CPU cache flush"
432ec984a04Sfredette * Just flush the on-chip caches and return.
433ec984a04Sfredette * XXX - Too bad NetBSD uses trap 2...
434ec984a04Sfredette */
435ec984a04Sfredette if (p->p_emul == &emul_sunos) {
436ec984a04Sfredette /* get out fast */
437ec984a04Sfredette goto done;
438ec984a04Sfredette }
439ec984a04Sfredette #endif
440ec984a04Sfredette /* FALLTHROUGH */
441ec984a04Sfredette case T_TRACE: /* tracing a trap instruction */
442ec984a04Sfredette case T_TRAP15|T_USER: /* SUN user trace trap */
443d2eac2f6Smhitch tf->tf_sr &= ~PSL_T;
44441692372Scl ksi.ksi_signo = SIGTRAP;
445ec984a04Sfredette break;
446ec984a04Sfredette
447ec984a04Sfredette case T_ASTFLT: /* system async trap, cannot happen */
448ec984a04Sfredette goto dopanic;
449ec984a04Sfredette
450ec984a04Sfredette case T_ASTFLT|T_USER: /* user async trap */
451ec984a04Sfredette astpending = 0;
452ec984a04Sfredette /* T_SSIR is not used on a Sun2. */
453b07ec3fcSad if (l->l_pflag & LP_OWEUPC) {
454b07ec3fcSad l->l_pflag &= ~LP_OWEUPC;
455b07ec3fcSad ADDUPROF(l);
456ec984a04Sfredette }
457ec984a04Sfredette goto douret;
458ec984a04Sfredette
459ec984a04Sfredette case T_MMUFLT: /* kernel mode page fault */
460ec984a04Sfredette /* Hacks to avoid calling VM code from debugger. */
461ec984a04Sfredette #ifdef DDB
462ec984a04Sfredette if (db_recover != 0)
463ec984a04Sfredette goto dopanic;
464ec984a04Sfredette #endif
465ec984a04Sfredette #ifdef KGDB
466ec984a04Sfredette if (kgdb_recover != 0)
467ec984a04Sfredette goto dopanic;
468ec984a04Sfredette #endif
469ec984a04Sfredette /*FALLTHROUGH*/
470ec984a04Sfredette
471ec984a04Sfredette case T_MMUFLT|T_USER: { /* page fault */
472bbb634caSfredette vaddr_t va;
473bbb634caSfredette struct vmspace *vm = p->p_vmspace;
474bbb634caSfredette struct vm_map *map;
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",
481d2eac2f6Smhitch 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 */
49504aa4da3Schs if (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 */
51504aa4da3Schs pcb->pcb_onfault = NULL;
516ec984a04Sfredette rv = _pmap_fault(map, va, ftype);
51704aa4da3Schs pcb->pcb_onfault = onfault;
518ec984a04Sfredette
519ec984a04Sfredette #ifdef DEBUG
520ec984a04Sfredette if (rv && MDB_ISPID(p->p_pid)) {
52147fbb9d8Sdrochner printf("vm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
522ec984a04Sfredette map, va, ftype, rv);
523ec984a04Sfredette if (mmudebug & MDB_WBFAILED)
524ec984a04Sfredette Debugger();
525ec984a04Sfredette }
526ec984a04Sfredette #endif /* DEBUG */
527ec984a04Sfredette
528ec984a04Sfredette /*
529ec984a04Sfredette * If this was a stack access we keep track of the maximum
530ec984a04Sfredette * accessed stack size. Also, if vm_fault gets a protection
531ec984a04Sfredette * failure it is due to accessing the stack region outside
532ec984a04Sfredette * the current limit and we need to reflect that as an access
533ec984a04Sfredette * error.
534ec984a04Sfredette */
535ec984a04Sfredette if (rv == 0) {
53653524e44Schristos if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
53764969161Sjdolecek uvm_grow(p, va);
538fc7511b0Swrstuden
539ec984a04Sfredette goto finish;
5403c10927eScl }
54141692372Scl if (rv == EACCES) {
54241692372Scl ksi.ksi_code = SEGV_ACCERR;
54341692372Scl rv = EFAULT;
54441692372Scl } else
54541692372Scl ksi.ksi_code = SEGV_MAPERR;
546ec984a04Sfredette if ((type & T_USER) == 0) {
547ec984a04Sfredette /* supervisor mode fault */
54804aa4da3Schs if (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 }
55747fbb9d8Sdrochner printf("vm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
558ec984a04Sfredette map, va, ftype, rv);
559ec984a04Sfredette goto dopanic;
560ec984a04Sfredette }
56141692372Scl ksi.ksi_addr = (void *)v;
5626ff7c06cSmartin switch (rv) {
5636ff7c06cSmartin case ENOMEM:
564ec984a04Sfredette printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
565ec984a04Sfredette p->p_pid, p->p_comm,
566f474dcebSad l->l_cred ?
567f474dcebSad kauth_cred_geteuid(l->l_cred) : -1);
56841692372Scl ksi.ksi_signo = SIGKILL;
5696ff7c06cSmartin break;
5706ff7c06cSmartin case EINVAL:
5716ff7c06cSmartin ksi.ksi_signo = SIGBUS;
5726ff7c06cSmartin ksi.ksi_code = BUS_ADRERR;
5736ff7c06cSmartin break;
5746ff7c06cSmartin case EACCES:
57541692372Scl ksi.ksi_signo = SIGSEGV;
5766ff7c06cSmartin ksi.ksi_code = SEGV_ACCERR;
5776ff7c06cSmartin break;
5786ff7c06cSmartin default:
5796ff7c06cSmartin ksi.ksi_signo = SIGSEGV;
5806ff7c06cSmartin ksi.ksi_code = SEGV_MAPERR;
5816ff7c06cSmartin break;
582ec984a04Sfredette }
583ec984a04Sfredette break;
584ec984a04Sfredette } /* T_MMUFLT */
585ec984a04Sfredette } /* switch */
586ec984a04Sfredette
587ec984a04Sfredette finish:
588ec984a04Sfredette /* If trap was from supervisor mode, just return. */
589ec984a04Sfredette if ((type & T_USER) == 0)
590ec984a04Sfredette goto done;
591ec984a04Sfredette /* Post a signal if necessary. */
59241692372Scl if (ksi.ksi_signo)
59341692372Scl trapsignal(l, &ksi);
594ec984a04Sfredette douret:
595d2eac2f6Smhitch userret(l, tf, sticks);
596ec984a04Sfredette
597ec984a04Sfredette done:;
598ec984a04Sfredette /* XXX: Detect trap recursion? */
599ec984a04Sfredette }
600ec984a04Sfredette
601ec984a04Sfredette /*
602ec984a04Sfredette * This is used if we hit a kernel breakpoint or trace trap
603ec984a04Sfredette * when there is no debugger installed (or not attached).
604ec984a04Sfredette * Drop into the PROM temporarily...
605ec984a04Sfredette */
606ec984a04Sfredette int
_nodb_trap(int type,struct trapframe * tf)60710b1a7beSchs _nodb_trap(int type, struct trapframe *tf)
608ec984a04Sfredette {
609ec984a04Sfredette
610ec984a04Sfredette printf("\r\nKernel ");
611ec984a04Sfredette if ((0 <= type) && (type < trap_types))
612ec984a04Sfredette printf("%s", trap_type[type]);
613ec984a04Sfredette else
614ec984a04Sfredette printf("trap 0x%x", type);
615ec984a04Sfredette printf(", frame=%p\r\n", tf);
616ec984a04Sfredette printf("No debugger; doing PROM abort.\r\n");
617ec984a04Sfredette printf("To continue, type: c <RETURN>\r\n");
618ec984a04Sfredette prom_abort();
619ec984a04Sfredette /* OK then, just resume... */
620ec984a04Sfredette tf->tf_sr &= ~PSL_T;
621ec984a04Sfredette return(1);
622ec984a04Sfredette }
623ec984a04Sfredette
624ec984a04Sfredette /*
625ec984a04Sfredette * This is called by locore for supervisor-mode trace and
626ec984a04Sfredette * breakpoint traps. This is separate from trap() above
627ec984a04Sfredette * so that breakpoints in trap() will work.
628ec984a04Sfredette *
629ec984a04Sfredette * If we have both DDB and KGDB, let KGDB see it first,
630ec984a04Sfredette * because KGDB will just return 0 if not connected.
631ec984a04Sfredette */
632ec984a04Sfredette void
trap_kdebug(int type,struct trapframe tf)63310b1a7beSchs trap_kdebug(int type, struct trapframe tf)
634ec984a04Sfredette {
635ec984a04Sfredette
636ec984a04Sfredette #ifdef KGDB
637ec984a04Sfredette /* Let KGDB handle it (if connected) */
638ec984a04Sfredette if (kgdb_trap(type, &tf))
639ec984a04Sfredette return;
640ec984a04Sfredette #endif
641ec984a04Sfredette #ifdef DDB
642ec984a04Sfredette /* Let DDB handle it. */
643ec984a04Sfredette if (kdb_trap(type, &tf))
644ec984a04Sfredette return;
645ec984a04Sfredette #endif
646ec984a04Sfredette
647ec984a04Sfredette /* Drop into the PROM temporarily... */
648ec984a04Sfredette (void)_nodb_trap(type, &tf);
649ec984a04Sfredette }
650ec984a04Sfredette
651ec984a04Sfredette /*
652ec984a04Sfredette * Called by locore.s for an unexpected interrupt.
653ec984a04Sfredette * XXX - Almost identical to trap_kdebug...
654ec984a04Sfredette */
655ec984a04Sfredette void
straytrap(struct trapframe tf)65610b1a7beSchs straytrap(struct trapframe tf)
657ec984a04Sfredette {
658ec984a04Sfredette int type = -1;
659ec984a04Sfredette
660ec984a04Sfredette printf("unexpected trap; vector=0x%x at pc=0x%x\n",
661ec984a04Sfredette tf.tf_vector, tf.tf_pc);
662ec984a04Sfredette
663ec984a04Sfredette #ifdef KGDB
664ec984a04Sfredette /* Let KGDB handle it (if connected) */
665ec984a04Sfredette if (kgdb_trap(type, &tf))
666ec984a04Sfredette return;
667ec984a04Sfredette #endif
668ec984a04Sfredette #ifdef DDB
669ec984a04Sfredette /* Let DDB handle it. */
670ec984a04Sfredette if (kdb_trap(type, &tf))
671ec984a04Sfredette return;
672ec984a04Sfredette #endif
673ec984a04Sfredette
674ec984a04Sfredette /* Drop into the PROM temporarily... */
675ec984a04Sfredette (void)_nodb_trap(type, &tf);
676ec984a04Sfredette }
677