xref: /netbsd/sys/arch/sun2/sun2/trap.c (revision 28e8a168)
1*28e8a168Syamt /*	$NetBSD: trap.c,v 1.25 2006/05/15 12:36:39 yamt 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*28e8a168Syamt __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.25 2006/05/15 12:36:39 yamt 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>
97d2275d51Sthorpej #include <sys/sa.h>
98d2275d51Sthorpej #include <sys/savar.h>
99ec984a04Sfredette #include <sys/syscall.h>
100ec984a04Sfredette #include <sys/syslog.h>
101ec984a04Sfredette #include <sys/user.h>
102ef56cc40Scl #include <sys/userret.h>
103*28e8a168Syamt #include <sys/kauth.h>
104ec984a04Sfredette #ifdef	KGDB
105ec984a04Sfredette #include <sys/kgdb.h>
106ec984a04Sfredette #endif
107ec984a04Sfredette 
108ec984a04Sfredette #include <uvm/uvm_extern.h>
109ec984a04Sfredette 
110ec984a04Sfredette #include <machine/cpu.h>
111ec984a04Sfredette #include <machine/endian.h>
112ec984a04Sfredette #include <machine/psl.h>
113ec984a04Sfredette #include <machine/trap.h>
114ec984a04Sfredette #include <machine/reg.h>
115ec984a04Sfredette #include <machine/promlib.h>
116ec984a04Sfredette 
117ec984a04Sfredette #include <sun2/sun2/fc.h>
118ec984a04Sfredette #include <sun2/sun2/machdep.h>
119ec984a04Sfredette 
1200dc8ee94Smatt #ifdef DDB
1210dc8ee94Smatt #include <machine/db_machdep.h>
1220dc8ee94Smatt #include <ddb/db_extern.h>
1230dc8ee94Smatt #endif
1240dc8ee94Smatt 
125ec984a04Sfredette #ifdef COMPAT_SUNOS
126ec984a04Sfredette #include <compat/sunos/sunos_syscall.h>
127ec984a04Sfredette extern struct emul emul_sunos;
128ec984a04Sfredette #endif
129ec984a04Sfredette 
130ec984a04Sfredette #ifdef COMPAT_AOUT_M68K
131ec984a04Sfredette extern struct emul emul_netbsd_aoutm68k;
132ec984a04Sfredette #endif
133ec984a04Sfredette 
134ec984a04Sfredette /* Special labels in m68k/copy.s */
135ec984a04Sfredette extern char fubail[], subail[];
136ec984a04Sfredette 
137ec984a04Sfredette /* These are called from locore.s */
13810b1a7beSchs void trap(int type, u_int code, u_int v, struct trapframe);
13910b1a7beSchs void trap_kdebug(int type, struct trapframe tf);
14010b1a7beSchs int _nodb_trap(int type, struct trapframe *);
14110b1a7beSchs void straytrap(struct trapframe);
142ec984a04Sfredette 
14310b1a7beSchs static void userret(struct lwp *, struct trapframe *, u_quad_t);
144ec984a04Sfredette 
145ec984a04Sfredette int astpending;
146ec984a04Sfredette int want_resched;
147ec984a04Sfredette 
1486df30aa4Stsutsui const char *trap_type[] = {
149ec984a04Sfredette 	"Bus error",
150ec984a04Sfredette 	"Address error",
151ec984a04Sfredette 	"Illegal instruction",
152ec984a04Sfredette 	"Zero divide",
153ec984a04Sfredette 	"CHK instruction",
154ec984a04Sfredette 	"TRAPV instruction",
155ec984a04Sfredette 	"Privilege violation",
156ec984a04Sfredette 	"Trace trap",
157ec984a04Sfredette 	"MMU fault",
158ec984a04Sfredette 	"SSIR trap",
159ec984a04Sfredette 	"Format error",
160ec984a04Sfredette 	"68881 exception",
161ec984a04Sfredette 	"Coprocessor violation",
162ec984a04Sfredette 	"Async system trap",
163ec984a04Sfredette 	"Unused? (14)",
164ec984a04Sfredette 	"Breakpoint",
165ec984a04Sfredette 	"FPU instruction",
166ec984a04Sfredette 	"FPU data format",
167ec984a04Sfredette };
168ec984a04Sfredette u_int trap_types = sizeof(trap_type) / sizeof(trap_type[0]);
169ec984a04Sfredette 
170ec984a04Sfredette /*
171ec984a04Sfredette  * Size of various exception stack frames (minus the standard 8 bytes)
172ec984a04Sfredette  */
173ec984a04Sfredette short	exframesize[] = {
174ec984a04Sfredette 	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
175ec984a04Sfredette 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
176ec984a04Sfredette 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
177ec984a04Sfredette 	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
178ec984a04Sfredette 	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
179ec984a04Sfredette 	-1, -1, 	/* type 5-6 - undefined */
180ec984a04Sfredette 	FMT7SIZE,	/* type 7 - access error (68040) */
181ec984a04Sfredette 	FMT8SIZE,	/* type 8 - bus fault (68010) */
182ec984a04Sfredette 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
183ec984a04Sfredette 	FMTASIZE,	/* type A - short bus fault (68020/030) */
184ec984a04Sfredette 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
185ec984a04Sfredette 	-1, -1, -1, -1	/* type C-F - undefined */
186ec984a04Sfredette };
187ec984a04Sfredette 
188ec984a04Sfredette #define KDFAULT(c)	(((c) & (SSW1_IF|SSW1_FCMASK)) == (FC_SUPERD))
189ec984a04Sfredette #define WRFAULT(c)	(((c) & (SSW1_IF|SSW1_DF|SSW1_RW)) == (0))
190ec984a04Sfredette 
191ec984a04Sfredette /* #define	DEBUG XXX */
192ec984a04Sfredette 
193ec984a04Sfredette #ifdef DEBUG
1948b21bb00Sfredette unsigned short buserr_reg;
195ec984a04Sfredette int mmudebug = 0;
196ec984a04Sfredette int mmupid = -1;
197ec984a04Sfredette #define MDB_ISPID(p)	((p) == mmupid)
198ec984a04Sfredette #define MDB_FOLLOW	1
199ec984a04Sfredette #define MDB_WBFOLLOW	2
200ec984a04Sfredette #define MDB_WBFAILED	4
201ec984a04Sfredette #define MDB_CPFAULT 	8
202ec984a04Sfredette #endif
203ec984a04Sfredette 
204ec984a04Sfredette /*
205ec984a04Sfredette  * trap and syscall both need the following work done before
206ec984a04Sfredette  * returning to user mode.
207ec984a04Sfredette  */
208ec984a04Sfredette static void
20910b1a7beSchs userret(struct lwp *l, struct trapframe *tf, u_quad_t oticks)
210ec984a04Sfredette {
211d2275d51Sthorpej 	struct proc *p = l->l_proc;
212ec984a04Sfredette 
213ef56cc40Scl 	/* Invoke MI userret code */
214ef56cc40Scl 	mi_userret(l);
215ec984a04Sfredette 
216ec984a04Sfredette 	/*
217ec984a04Sfredette 	 * If profiling, charge system time to the trapped pc.
218ec984a04Sfredette 	 */
219ec984a04Sfredette 	if (p->p_flag & P_PROFIL) {
220ec984a04Sfredette 		extern int psratio;
221ec984a04Sfredette 		addupc_task(p, tf->tf_pc,
222ec984a04Sfredette 		            (int)(p->p_sticks - oticks) * psratio);
223ec984a04Sfredette 	}
224ec984a04Sfredette 
225d2275d51Sthorpej 	curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri;
226ec984a04Sfredette }
227ec984a04Sfredette 
228ec984a04Sfredette /*
229ec984a04Sfredette  * Used by the common m68k syscall() and child_return() functions.
230ec984a04Sfredette  * XXX: Temporary until all m68k ports share common trap()/userret() code.
231ec984a04Sfredette  */
232d2275d51Sthorpej void machine_userret(struct lwp *, struct frame *, u_quad_t);
233ec984a04Sfredette 
234ec984a04Sfredette void
23510b1a7beSchs machine_userret(struct lwp *l, struct frame *f, u_quad_t t)
236ec984a04Sfredette {
237ec984a04Sfredette 
238d2275d51Sthorpej 	userret(l, &f->F_t, t);
239ec984a04Sfredette }
240ec984a04Sfredette 
241ec984a04Sfredette /*
242ec984a04Sfredette  * Trap is called from locore to handle most types of processor traps,
243ec984a04Sfredette  * including events such as simulated software interrupts/AST's.
244ec984a04Sfredette  * System calls are broken out for efficiency.
245ec984a04Sfredette  */
246ec984a04Sfredette /*ARGSUSED*/
247ec984a04Sfredette void
24810b1a7beSchs trap(int type, u_int code, u_int v, struct trapframe tf)
249ec984a04Sfredette {
250d2275d51Sthorpej 	struct lwp *l;
251bbb634caSfredette 	struct proc *p;
25241692372Scl 	ksiginfo_t ksi;
25341692372Scl 	int tmp;
254ec984a04Sfredette 	u_quad_t sticks;
255ec984a04Sfredette 
256ec984a04Sfredette 	uvmexp.traps++;
257d2275d51Sthorpej 	l = curlwp;
25841692372Scl 
25968723a99Sthorpej 	KSI_INIT_TRAP(&ksi);
26041692372Scl 	ksi.ksi_trap = type & ~T_USER;
261ec984a04Sfredette 
262d2275d51Sthorpej 	if (l == NULL)
263d2275d51Sthorpej 		l = &lwp0;
264d2275d51Sthorpej 	p = l->l_proc;
265d2275d51Sthorpej 
266ec984a04Sfredette #ifdef	DIAGNOSTIC
267ec984a04Sfredette 	if (p->p_addr == NULL)
268ec984a04Sfredette 		panic("trap: no pcb");
269ec984a04Sfredette #endif
270ec984a04Sfredette 
271ec984a04Sfredette 	if (USERMODE(tf.tf_sr)) {
272ec984a04Sfredette 		type |= T_USER;
273ec984a04Sfredette 		sticks = p->p_sticks;
274d2275d51Sthorpej 		l->l_md.md_regs = tf.tf_regs;
275ec984a04Sfredette 	} else {
276ec984a04Sfredette 		sticks = 0;
277ec984a04Sfredette 		/* XXX: Detect trap recursion? */
278ec984a04Sfredette 	}
279ec984a04Sfredette 
280ec984a04Sfredette 	switch (type) {
281ec984a04Sfredette 	default:
282ec984a04Sfredette 	dopanic:
283ec984a04Sfredette 		printf("trap type=0x%x, code=0x%x, v=0x%x\n", type, code, v);
284ec984a04Sfredette 		/*
285ec984a04Sfredette 		 * Let the kernel debugger see the trap frame that
286ec984a04Sfredette 		 * caused us to panic.  This is a convenience so
287ec984a04Sfredette 		 * one can see registers at the point of failure.
288ec984a04Sfredette 		 */
289ec984a04Sfredette 		tmp = splhigh();
290ec984a04Sfredette #ifdef KGDB
291ec984a04Sfredette 		/* If connected, step or cont returns 1 */
292ec984a04Sfredette 		if (kgdb_trap(type, &tf))
293ec984a04Sfredette 			goto kgdb_cont;
294ec984a04Sfredette #endif
295ec984a04Sfredette #ifdef	DDB
296ec984a04Sfredette 		(void) kdb_trap(type, (db_regs_t *) &tf);
297ec984a04Sfredette #endif
298ec984a04Sfredette #ifdef KGDB
299ec984a04Sfredette 	kgdb_cont:
300ec984a04Sfredette #endif
301ec984a04Sfredette 		splx(tmp);
302ec984a04Sfredette 		if (panicstr) {
303ec984a04Sfredette 			/*
304ec984a04Sfredette 			 * Note: panic is smart enough to do:
305ec984a04Sfredette 			 *   boot(RB_AUTOBOOT | RB_NOSYNC, NULL)
306ec984a04Sfredette 			 * if we call it again.
307ec984a04Sfredette 			 */
308ec984a04Sfredette 			panic("trap during panic!");
309ec984a04Sfredette 		}
310ec984a04Sfredette 		regdump(&tf, 128);
311ec984a04Sfredette 		type &= ~T_USER;
312ec984a04Sfredette 		if ((u_int)type < trap_types)
313ec984a04Sfredette 			panic(trap_type[type]);
314ec984a04Sfredette 		panic("trap type 0x%x", type);
315ec984a04Sfredette 
316ec984a04Sfredette 	case T_BUSERR:		/* kernel bus error */
317d2275d51Sthorpej 		if (l->l_addr->u_pcb.pcb_onfault == NULL)
318ec984a04Sfredette 			goto dopanic;
319ec984a04Sfredette 		/*FALLTHROUGH*/
320ec984a04Sfredette 
321ec984a04Sfredette 	copyfault:
322ec984a04Sfredette 		/*
323ec984a04Sfredette 		 * If we have arranged to catch this fault in any of the
324ec984a04Sfredette 		 * copy to/from user space routines, set PC to return to
325ec984a04Sfredette 		 * indicated location and set flag informing buserror code
326ec984a04Sfredette 		 * that it may need to clean up stack frame.
327ec984a04Sfredette 		 */
328ec984a04Sfredette 		tf.tf_stackadj = exframesize[tf.tf_format];
329ec984a04Sfredette 		tf.tf_format = tf.tf_vector = 0;
330d2275d51Sthorpej 		tf.tf_pc = (int) l->l_addr->u_pcb.pcb_onfault;
331ec984a04Sfredette 		goto done;
332ec984a04Sfredette 
333ec984a04Sfredette 	case T_BUSERR|T_USER:	/* bus error */
334ec984a04Sfredette 	case T_ADDRERR|T_USER:	/* address error */
33541692372Scl 		ksi.ksi_addr = (void *)v;
33641692372Scl 		ksi.ksi_signo = SIGBUS;
33741692372Scl 		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
33841692372Scl 			BUS_OBJERR : BUS_ADRERR;
339ec984a04Sfredette 		break;
340ec984a04Sfredette 
341ec984a04Sfredette 	case T_COPERR:		/* kernel coprocessor violation */
342ec984a04Sfredette 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
343ec984a04Sfredette 	case T_FMTERR:		/* ...just in case... */
344ec984a04Sfredette 		/*
345ec984a04Sfredette 		 * The user has most likely trashed the RTE or FP state info
346ec984a04Sfredette 		 * in the stack frame of a signal handler.
347ec984a04Sfredette 		 */
348ec984a04Sfredette 		printf("pid %d: kernel %s exception\n", p->p_pid,
349ec984a04Sfredette 		       type==T_COPERR ? "coprocessor" : "format");
350ec984a04Sfredette 		type |= T_USER;
351ec984a04Sfredette 		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
352ec984a04Sfredette 		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
353ec984a04Sfredette 		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
354ec984a04Sfredette 		sigdelset(&p->p_sigctx.ps_sigmask, SIGILL);
35541692372Scl 		ksi.ksi_signo = SIGILL;
35641692372Scl 		ksi.ksi_addr = (void *)(int)tf.tf_format;
35741692372Scl 		ksi.ksi_code = (type == T_COPERR) ?
35841692372Scl 			ILL_COPROC : ILL_ILLOPC;
359ec984a04Sfredette 		break;
360ec984a04Sfredette 
361ec984a04Sfredette 	case T_COPERR|T_USER:	/* user coprocessor violation */
362ec984a04Sfredette 	/* What is a proper response here? */
36341692372Scl 		ksi.ksi_signo = SIGFPE;
36441692372Scl 		ksi.ksi_code = FPE_FLTINV;
365ec984a04Sfredette 		break;
366ec984a04Sfredette 
367ec984a04Sfredette 	case T_FPERR|T_USER:	/* 68881 exceptions */
368ec984a04Sfredette 		/*
369ec984a04Sfredette 		 * We pass along the 68881 status register which locore stashed
370ec984a04Sfredette 		 * in code for us.  Note that there is a possibility that the
371ec984a04Sfredette 		 * bit pattern of this register will conflict with one of the
372ec984a04Sfredette 		 * FPE_* codes defined in signal.h.  Fortunately for us, the
373ec984a04Sfredette 		 * only such codes we use are all in the range 1-7 and the low
374ec984a04Sfredette 		 * 3 bits of the status register are defined as 0 so there is
375ec984a04Sfredette 		 * no clash.
376ec984a04Sfredette 		 */
37741692372Scl 		ksi.ksi_signo = SIGFPE;
37841692372Scl 		ksi.ksi_addr = (void *)code;
379ec984a04Sfredette 		break;
380ec984a04Sfredette 
381ec984a04Sfredette 	case T_FPEMULI:		/* FPU faults in supervisor mode */
382ec984a04Sfredette 	case T_FPEMULD:
383ec984a04Sfredette 		if (nofault)	/* Doing FPU probe? */
384ec984a04Sfredette 			longjmp(nofault);
385ec984a04Sfredette 		goto dopanic;
386ec984a04Sfredette 
3875d1e8b27Swiz 	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
388ec984a04Sfredette 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
389ec984a04Sfredette #ifdef	FPU_EMULATE
39041692372Scl 		if (fpu_emulate(&tf, &l->l_addr->u_pcb.pcb_fpregs, &ksi) == 0)
39141692372Scl 			; /* XXX - Deal with tracing? (tf.tf_sr & PSL_T) */
392ec984a04Sfredette #else
393ec984a04Sfredette 		uprintf("pid %d killed: no floating point support\n", p->p_pid);
39441692372Scl 		ksi.ksi_signo = SIGILL;
39541692372Scl 		ksi.ksi_code = ILL_ILLOPC;
396ec984a04Sfredette #endif
397ec984a04Sfredette 		break;
398ec984a04Sfredette 
399ec984a04Sfredette 	case T_ILLINST|T_USER:	/* illegal instruction fault */
400ec984a04Sfredette 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
40141692372Scl 		ksi.ksi_addr = (void *)(int)tf.tf_format;
40241692372Scl 		ksi.ksi_signo = SIGILL;
40341692372Scl 		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
40441692372Scl 			ILL_PRVOPC : ILL_ILLOPC;
405ec984a04Sfredette 		break;
406ec984a04Sfredette 
407ec984a04Sfredette 	case T_ZERODIV|T_USER:	/* Divide by zero */
40841692372Scl 		ksi.ksi_code = FPE_FLTDIV;
409ec984a04Sfredette 	case T_CHKINST|T_USER:	/* CHK instruction trap */
410ec984a04Sfredette 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
41141692372Scl 		ksi.ksi_addr = (void *)(int)tf.tf_format;
41241692372Scl 		ksi.ksi_signo = SIGFPE;
413ec984a04Sfredette 		break;
414ec984a04Sfredette 
415ec984a04Sfredette 	/*
416ec984a04Sfredette 	 * XXX: Trace traps are a nightmare.
417ec984a04Sfredette 	 *
418ec984a04Sfredette 	 *	HP-UX uses trap #1 for breakpoints,
419ec984a04Sfredette 	 *	NetBSD/m68k uses trap #2,
420ec984a04Sfredette 	 *	SUN 3.x uses trap #15,
421ec984a04Sfredette 	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
422ec984a04Sfredette 	 *	handled elsewhere).
423ec984a04Sfredette 	 *
424ec984a04Sfredette 	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
425ec984a04Sfredette 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
426ec984a04Sfredette 	 * supported yet.
427ec984a04Sfredette 	 *
428ec984a04Sfredette 	 * XXX: We should never get kernel-mode T_TRAP15
429ec984a04Sfredette 	 * XXX: because locore.s now gives them special treatment.
430ec984a04Sfredette 	 */
431ec984a04Sfredette 	case T_TRAP15:		/* kernel breakpoint */
432ec984a04Sfredette 		tf.tf_sr &= ~PSL_T;
433ec984a04Sfredette 		goto done;
434ec984a04Sfredette 
435ec984a04Sfredette 	case T_TRACE|T_USER:	/* user trace trap */
436ec984a04Sfredette #ifdef COMPAT_SUNOS
437ec984a04Sfredette 		/*
438ec984a04Sfredette 		 * SunOS uses Trap #2 for a "CPU cache flush"
439ec984a04Sfredette 		 * Just flush the on-chip caches and return.
440ec984a04Sfredette 		 * XXX - Too bad NetBSD uses trap 2...
441ec984a04Sfredette 		 */
442ec984a04Sfredette 		if (p->p_emul == &emul_sunos) {
443ec984a04Sfredette 			/* get out fast */
444ec984a04Sfredette 			goto done;
445ec984a04Sfredette 		}
446ec984a04Sfredette #endif
447ec984a04Sfredette 		/* FALLTHROUGH */
448ec984a04Sfredette 	case T_TRACE:		/* tracing a trap instruction */
449ec984a04Sfredette 	case T_TRAP15|T_USER:	/* SUN user trace trap */
450ec984a04Sfredette 		tf.tf_sr &= ~PSL_T;
45141692372Scl 		ksi.ksi_signo = SIGTRAP;
452ec984a04Sfredette 		break;
453ec984a04Sfredette 
454ec984a04Sfredette 	case T_ASTFLT:		/* system async trap, cannot happen */
455ec984a04Sfredette 		goto dopanic;
456ec984a04Sfredette 
457ec984a04Sfredette 	case T_ASTFLT|T_USER:	/* user async trap */
458ec984a04Sfredette 		astpending = 0;
459ec984a04Sfredette 		/* T_SSIR is not used on a Sun2. */
460ec984a04Sfredette 		if (p->p_flag & P_OWEUPC) {
461ec984a04Sfredette 			p->p_flag &= ~P_OWEUPC;
462ec984a04Sfredette 			ADDUPROF(p);
463ec984a04Sfredette 		}
464d2275d51Sthorpej 		if (want_resched)
465d2275d51Sthorpej 			preempt(0);
466ec984a04Sfredette 		goto douret;
467ec984a04Sfredette 
468ec984a04Sfredette 	case T_MMUFLT:		/* kernel mode page fault */
469ec984a04Sfredette 		/* Hacks to avoid calling VM code from debugger. */
470ec984a04Sfredette #ifdef	DDB
471ec984a04Sfredette 		if (db_recover != 0)
472ec984a04Sfredette 			goto dopanic;
473ec984a04Sfredette #endif
474ec984a04Sfredette #ifdef	KGDB
475ec984a04Sfredette 		if (kgdb_recover != 0)
476ec984a04Sfredette 			goto dopanic;
477ec984a04Sfredette #endif
478ec984a04Sfredette 		/*
479ec984a04Sfredette 		 * If we were doing profiling ticks or other user mode
480ec984a04Sfredette 		 * stuff from interrupt code, Just Say No.
481ec984a04Sfredette 		 */
482d2275d51Sthorpej 		if (l->l_addr->u_pcb.pcb_onfault == (caddr_t)fubail ||
483d2275d51Sthorpej 		    l->l_addr->u_pcb.pcb_onfault == (caddr_t)subail)
484ec984a04Sfredette 		{
485ec984a04Sfredette #ifdef	DEBUG
486ec984a04Sfredette 			if (mmudebug & MDB_CPFAULT) {
487ec984a04Sfredette 				printf("trap: copyfault fu/su bail\n");
488ec984a04Sfredette 				Debugger();
489ec984a04Sfredette 			}
490ec984a04Sfredette #endif
491ec984a04Sfredette 			goto copyfault;
492ec984a04Sfredette 		}
493ec984a04Sfredette 		/*FALLTHROUGH*/
494ec984a04Sfredette 
495ec984a04Sfredette 	case T_MMUFLT|T_USER: { 	/* page fault */
496bbb634caSfredette 		vaddr_t va;
497bbb634caSfredette 		struct vmspace *vm = p->p_vmspace;
498bbb634caSfredette 		struct vm_map *map;
499ec984a04Sfredette 		int rv;
500ec984a04Sfredette 		vm_prot_t ftype;
501821ec03eSchs 		extern struct vm_map *kernel_map;
502ec984a04Sfredette 
503ec984a04Sfredette #ifdef DEBUG
504ec984a04Sfredette 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
505ec984a04Sfredette 		printf("trap: T_MMUFLT pid=%d, code=0x%x, v=0x%x, pc=0x%x, sr=0x%x\n",
506ec984a04Sfredette 		       p->p_pid, code, v, tf.tf_pc, tf.tf_sr);
507ec984a04Sfredette #endif
508ec984a04Sfredette 
509ec984a04Sfredette 		/*
510ec984a04Sfredette 		 * It is only a kernel address space fault iff:
511ec984a04Sfredette 		 * 	1. (type & T_USER) == 0  and: (2 or 3)
512ec984a04Sfredette 		 * 	2. pcb_onfault not set or
513ec984a04Sfredette 		 *	3. pcb_onfault set but supervisor space data fault
514ec984a04Sfredette 		 * The last can occur during an exec() copyin where the
515ec984a04Sfredette 		 * argument space is lazy-allocated.
516ec984a04Sfredette 		 */
517ec984a04Sfredette 		map = &vm->vm_map;
518ec984a04Sfredette 		if ((type & T_USER) == 0) {
519ec984a04Sfredette 			/* supervisor mode fault */
520d2275d51Sthorpej 			if ((l->l_addr->u_pcb.pcb_onfault == NULL) || KDFAULT(code))
521ec984a04Sfredette 				map = kernel_map;
5223c10927eScl 		} else if (l->l_flag & L_SA) {
523ea5ec021Scl 			l->l_savp->savp_faultaddr = (vaddr_t)v;
5243c10927eScl 			l->l_flag |= L_SA_PAGEFAULT;
525ec984a04Sfredette 		}
526ec984a04Sfredette 
527ec984a04Sfredette 		if (WRFAULT(code))
528b744097aSchs 			ftype = VM_PROT_WRITE;
529ec984a04Sfredette 		else
530ec984a04Sfredette 			ftype = VM_PROT_READ;
531bbb634caSfredette 		va = m68k_trunc_page((vaddr_t)v);
532ec984a04Sfredette 
533ec984a04Sfredette 		/*
534ec984a04Sfredette 		 * Need to resolve the fault.
535ec984a04Sfredette 		 *
536ec984a04Sfredette 		 * We give the pmap code a chance to resolve faults by
537ec984a04Sfredette 		 * reloading translations that it was forced to unload.
538ec984a04Sfredette 		 * This function does that, and calls vm_fault if it
539ec984a04Sfredette 		 * could not resolve the fault by reloading the MMU.
540ec984a04Sfredette 		 * This function may also, for example, disallow any
541ec984a04Sfredette 		 * faults in the kernel text segment, etc.
542ec984a04Sfredette 		 */
543ec984a04Sfredette 		rv = _pmap_fault(map, va, ftype);
544ec984a04Sfredette 
545ec984a04Sfredette #ifdef	DEBUG
546ec984a04Sfredette 		if (rv && MDB_ISPID(p->p_pid)) {
54747fbb9d8Sdrochner 			printf("vm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
548ec984a04Sfredette 			       map, va, ftype, rv);
549ec984a04Sfredette 			if (mmudebug & MDB_WBFAILED)
550ec984a04Sfredette 				Debugger();
551ec984a04Sfredette 		}
552ec984a04Sfredette #endif	/* DEBUG */
553ec984a04Sfredette 
554ec984a04Sfredette 		/*
555ec984a04Sfredette 		 * If this was a stack access we keep track of the maximum
556ec984a04Sfredette 		 * accessed stack size.  Also, if vm_fault gets a protection
557ec984a04Sfredette 		 * failure it is due to accessing the stack region outside
558ec984a04Sfredette 		 * the current limit and we need to reflect that as an access
559ec984a04Sfredette 		 * error.
560ec984a04Sfredette 		 */
561ec984a04Sfredette 		if (rv == 0) {
56264969161Sjdolecek 			if (map != kernel_map && (caddr_t)va >= vm->vm_maxsaddr)
56364969161Sjdolecek 				uvm_grow(p, va);
564ec984a04Sfredette 
5653c10927eScl 			if ((type & T_USER) != 0)
5663c10927eScl 				l->l_flag &= ~L_SA_PAGEFAULT;
567ec984a04Sfredette 			goto finish;
5683c10927eScl 		}
56941692372Scl 		if (rv == EACCES) {
57041692372Scl 			ksi.ksi_code = SEGV_ACCERR;
57141692372Scl 			rv = EFAULT;
57241692372Scl 		} else
57341692372Scl 			ksi.ksi_code = SEGV_MAPERR;
574ec984a04Sfredette 		if ((type & T_USER) == 0) {
575ec984a04Sfredette 			/* supervisor mode fault */
576d2275d51Sthorpej 			if (l->l_addr->u_pcb.pcb_onfault) {
577ec984a04Sfredette #ifdef	DEBUG
578ec984a04Sfredette 				if (mmudebug & MDB_CPFAULT) {
579ec984a04Sfredette 					printf("trap: copyfault pcb_onfault\n");
580ec984a04Sfredette 					Debugger();
581ec984a04Sfredette 				}
582ec984a04Sfredette #endif
583ec984a04Sfredette 				goto copyfault;
584ec984a04Sfredette 			}
58547fbb9d8Sdrochner 			printf("vm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
586ec984a04Sfredette 			       map, va, ftype, rv);
587ec984a04Sfredette 			goto dopanic;
588ec984a04Sfredette 		}
5893c10927eScl 		l->l_flag &= ~L_SA_PAGEFAULT;
59041692372Scl 		ksi.ksi_addr = (void *)v;
591ec984a04Sfredette 		if (rv == ENOMEM) {
592ec984a04Sfredette 			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
593ec984a04Sfredette 			       p->p_pid, p->p_comm,
5948ccb6c93Selad 			       p->p_cred ?
5958ccb6c93Selad 			       kauth_cred_geteuid(p->p_cred) : -1);
59641692372Scl 			ksi.ksi_signo = SIGKILL;
597ec984a04Sfredette 		} else {
59841692372Scl 			ksi.ksi_signo = SIGSEGV;
599ec984a04Sfredette 		}
600ec984a04Sfredette 		break;
601ec984a04Sfredette 		} /* T_MMUFLT */
602ec984a04Sfredette 	} /* switch */
603ec984a04Sfredette 
604ec984a04Sfredette finish:
605ec984a04Sfredette 	/* If trap was from supervisor mode, just return. */
606ec984a04Sfredette 	if ((type & T_USER) == 0)
607ec984a04Sfredette 		goto done;
608ec984a04Sfredette 	/* Post a signal if necessary. */
60941692372Scl 	if (ksi.ksi_signo)
61041692372Scl 		trapsignal(l, &ksi);
611ec984a04Sfredette douret:
612d2275d51Sthorpej 	userret(l, &tf, sticks);
613ec984a04Sfredette 
614ec984a04Sfredette done:;
615ec984a04Sfredette 	/* XXX: Detect trap recursion? */
616ec984a04Sfredette }
617ec984a04Sfredette 
618ec984a04Sfredette /*
619ec984a04Sfredette  * This is used if we hit a kernel breakpoint or trace trap
620ec984a04Sfredette  * when there is no debugger installed (or not attached).
621ec984a04Sfredette  * Drop into the PROM temporarily...
622ec984a04Sfredette  */
623ec984a04Sfredette int
62410b1a7beSchs _nodb_trap(int type, struct trapframe *tf)
625ec984a04Sfredette {
626ec984a04Sfredette 
627ec984a04Sfredette 	printf("\r\nKernel ");
628ec984a04Sfredette 	if ((0 <= type) && (type < trap_types))
629ec984a04Sfredette 		printf("%s", trap_type[type]);
630ec984a04Sfredette 	else
631ec984a04Sfredette 		printf("trap 0x%x", type);
632ec984a04Sfredette 	printf(", frame=%p\r\n", tf);
633ec984a04Sfredette 	printf("No debugger; doing PROM abort.\r\n");
634ec984a04Sfredette 	printf("To continue, type: c <RETURN>\r\n");
635ec984a04Sfredette 	prom_abort();
636ec984a04Sfredette 	/* OK then, just resume... */
637ec984a04Sfredette 	tf->tf_sr &= ~PSL_T;
638ec984a04Sfredette 	return(1);
639ec984a04Sfredette }
640ec984a04Sfredette 
641ec984a04Sfredette /*
642ec984a04Sfredette  * This is called by locore for supervisor-mode trace and
643ec984a04Sfredette  * breakpoint traps.  This is separate from trap() above
644ec984a04Sfredette  * so that breakpoints in trap() will work.
645ec984a04Sfredette  *
646ec984a04Sfredette  * If we have both DDB and KGDB, let KGDB see it first,
647ec984a04Sfredette  * because KGDB will just return 0 if not connected.
648ec984a04Sfredette  */
649ec984a04Sfredette void
65010b1a7beSchs trap_kdebug(int type, struct trapframe tf)
651ec984a04Sfredette {
652ec984a04Sfredette 
653ec984a04Sfredette #ifdef	KGDB
654ec984a04Sfredette 	/* Let KGDB handle it (if connected) */
655ec984a04Sfredette 	if (kgdb_trap(type, &tf))
656ec984a04Sfredette 		return;
657ec984a04Sfredette #endif
658ec984a04Sfredette #ifdef	DDB
659ec984a04Sfredette 	/* Let DDB handle it. */
660ec984a04Sfredette 	if (kdb_trap(type, &tf))
661ec984a04Sfredette 		return;
662ec984a04Sfredette #endif
663ec984a04Sfredette 
664ec984a04Sfredette 	/* Drop into the PROM temporarily... */
665ec984a04Sfredette 	(void)_nodb_trap(type, &tf);
666ec984a04Sfredette }
667ec984a04Sfredette 
668ec984a04Sfredette /*
669ec984a04Sfredette  * Called by locore.s for an unexpected interrupt.
670ec984a04Sfredette  * XXX - Almost identical to trap_kdebug...
671ec984a04Sfredette  */
672ec984a04Sfredette void
67310b1a7beSchs straytrap(struct trapframe tf)
674ec984a04Sfredette {
675ec984a04Sfredette 	int type = -1;
676ec984a04Sfredette 
677ec984a04Sfredette 	printf("unexpected trap; vector=0x%x at pc=0x%x\n",
678ec984a04Sfredette 		tf.tf_vector, tf.tf_pc);
679ec984a04Sfredette 
680ec984a04Sfredette #ifdef	KGDB
681ec984a04Sfredette 	/* Let KGDB handle it (if connected) */
682ec984a04Sfredette 	if (kgdb_trap(type, &tf))
683ec984a04Sfredette 		return;
684ec984a04Sfredette #endif
685ec984a04Sfredette #ifdef	DDB
686ec984a04Sfredette 	/* Let DDB handle it. */
687ec984a04Sfredette 	if (kdb_trap(type, &tf))
688ec984a04Sfredette 		return;
689ec984a04Sfredette #endif
690ec984a04Sfredette 
691ec984a04Sfredette 	/* Drop into the PROM temporarily... */
692ec984a04Sfredette 	(void)_nodb_trap(type, &tf);
693ec984a04Sfredette }
694