xref: /netbsd/sys/arch/sun2/sun2/trap.c (revision 64969161)
1*64969161Sjdolecek /*	$NetBSD: trap.c,v 1.18 2004/08/28 17:53:02 jdolecek 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*64969161Sjdolecek __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.18 2004/08/28 17:53:02 jdolecek 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>
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 */
137ec984a04Sfredette void trap __P((int type, u_int code, u_int v, struct trapframe));
138ec984a04Sfredette void trap_kdebug __P((int type, struct trapframe tf));
139ec984a04Sfredette int _nodb_trap __P((int type, struct trapframe *));
140ec984a04Sfredette void straytrap __P((struct trapframe));
141ec984a04Sfredette 
142d2275d51Sthorpej static void userret __P((struct lwp *, struct trapframe *, u_quad_t));
143ec984a04Sfredette 
144ec984a04Sfredette int astpending;
145ec984a04Sfredette int want_resched;
146ec984a04Sfredette 
147ec984a04Sfredette 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
208d2275d51Sthorpej userret(l, tf, oticks)
209d2275d51Sthorpej 	struct lwp *l;
210bbb634caSfredette 	struct trapframe *tf;
211ec984a04Sfredette 	u_quad_t oticks;
212ec984a04Sfredette {
213d2275d51Sthorpej 	struct proc *p = l->l_proc;
214ec984a04Sfredette 
215ef56cc40Scl 	/* Invoke MI userret code */
216ef56cc40Scl 	mi_userret(l);
217ec984a04Sfredette 
218ec984a04Sfredette 	/*
219ec984a04Sfredette 	 * If profiling, charge system time to the trapped pc.
220ec984a04Sfredette 	 */
221ec984a04Sfredette 	if (p->p_flag & P_PROFIL) {
222ec984a04Sfredette 		extern int psratio;
223ec984a04Sfredette 		addupc_task(p, tf->tf_pc,
224ec984a04Sfredette 		            (int)(p->p_sticks - oticks) * psratio);
225ec984a04Sfredette 	}
226ec984a04Sfredette 
227d2275d51Sthorpej 	curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri;
228ec984a04Sfredette }
229ec984a04Sfredette 
230ec984a04Sfredette /*
231ec984a04Sfredette  * Used by the common m68k syscall() and child_return() functions.
232ec984a04Sfredette  * XXX: Temporary until all m68k ports share common trap()/userret() code.
233ec984a04Sfredette  */
234d2275d51Sthorpej void machine_userret(struct lwp *, struct frame *, u_quad_t);
235ec984a04Sfredette 
236ec984a04Sfredette void
237d2275d51Sthorpej machine_userret(l, f, t)
238d2275d51Sthorpej 	struct lwp *l;
239ec984a04Sfredette 	struct frame *f;
240ec984a04Sfredette 	u_quad_t t;
241ec984a04Sfredette {
242ec984a04Sfredette 
243d2275d51Sthorpej 	userret(l, &f->F_t, t);
244ec984a04Sfredette }
245ec984a04Sfredette 
246ec984a04Sfredette /*
247ec984a04Sfredette  * Trap is called from locore to handle most types of processor traps,
248ec984a04Sfredette  * including events such as simulated software interrupts/AST's.
249ec984a04Sfredette  * System calls are broken out for efficiency.
250ec984a04Sfredette  */
251ec984a04Sfredette /*ARGSUSED*/
252ec984a04Sfredette void
253ec984a04Sfredette trap(type, code, v, tf)
254ec984a04Sfredette 	int type;
255ec984a04Sfredette 	u_int code, v;
256ec984a04Sfredette 	struct trapframe tf;
257ec984a04Sfredette {
258d2275d51Sthorpej 	struct lwp *l;
259bbb634caSfredette 	struct proc *p;
26041692372Scl 	ksiginfo_t ksi;
26141692372Scl 	int tmp;
262ec984a04Sfredette 	u_quad_t sticks;
263ec984a04Sfredette 
264ec984a04Sfredette 	uvmexp.traps++;
265d2275d51Sthorpej 	l = curlwp;
26641692372Scl 
26768723a99Sthorpej 	KSI_INIT_TRAP(&ksi);
26841692372Scl 	ksi.ksi_trap = type & ~T_USER;
269ec984a04Sfredette 
270d2275d51Sthorpej 	if (l == NULL)
271d2275d51Sthorpej 		l = &lwp0;
272d2275d51Sthorpej 	p = l->l_proc;
273d2275d51Sthorpej 
274ec984a04Sfredette #ifdef	DIAGNOSTIC
275ec984a04Sfredette 	if (p->p_addr == NULL)
276ec984a04Sfredette 		panic("trap: no pcb");
277ec984a04Sfredette #endif
278ec984a04Sfredette 
279ec984a04Sfredette 	if (USERMODE(tf.tf_sr)) {
280ec984a04Sfredette 		type |= T_USER;
281ec984a04Sfredette 		sticks = p->p_sticks;
282d2275d51Sthorpej 		l->l_md.md_regs = tf.tf_regs;
283ec984a04Sfredette 	} else {
284ec984a04Sfredette 		sticks = 0;
285ec984a04Sfredette 		/* XXX: Detect trap recursion? */
286ec984a04Sfredette 	}
287ec984a04Sfredette 
288ec984a04Sfredette 	switch (type) {
289ec984a04Sfredette 	default:
290ec984a04Sfredette 	dopanic:
291ec984a04Sfredette 		printf("trap type=0x%x, code=0x%x, v=0x%x\n", type, code, v);
292ec984a04Sfredette 		/*
293ec984a04Sfredette 		 * Let the kernel debugger see the trap frame that
294ec984a04Sfredette 		 * caused us to panic.  This is a convenience so
295ec984a04Sfredette 		 * one can see registers at the point of failure.
296ec984a04Sfredette 		 */
297ec984a04Sfredette 		tmp = splhigh();
298ec984a04Sfredette #ifdef KGDB
299ec984a04Sfredette 		/* If connected, step or cont returns 1 */
300ec984a04Sfredette 		if (kgdb_trap(type, &tf))
301ec984a04Sfredette 			goto kgdb_cont;
302ec984a04Sfredette #endif
303ec984a04Sfredette #ifdef	DDB
304ec984a04Sfredette 		(void) kdb_trap(type, (db_regs_t *) &tf);
305ec984a04Sfredette #endif
306ec984a04Sfredette #ifdef KGDB
307ec984a04Sfredette 	kgdb_cont:
308ec984a04Sfredette #endif
309ec984a04Sfredette 		splx(tmp);
310ec984a04Sfredette 		if (panicstr) {
311ec984a04Sfredette 			/*
312ec984a04Sfredette 			 * Note: panic is smart enough to do:
313ec984a04Sfredette 			 *   boot(RB_AUTOBOOT | RB_NOSYNC, NULL)
314ec984a04Sfredette 			 * if we call it again.
315ec984a04Sfredette 			 */
316ec984a04Sfredette 			panic("trap during panic!");
317ec984a04Sfredette 		}
318ec984a04Sfredette 		regdump(&tf, 128);
319ec984a04Sfredette 		type &= ~T_USER;
320ec984a04Sfredette 		if ((u_int)type < trap_types)
321ec984a04Sfredette 			panic(trap_type[type]);
322ec984a04Sfredette 		panic("trap type 0x%x", type);
323ec984a04Sfredette 
324ec984a04Sfredette 	case T_BUSERR:		/* kernel bus error */
325d2275d51Sthorpej 		if (l->l_addr->u_pcb.pcb_onfault == NULL)
326ec984a04Sfredette 			goto dopanic;
327ec984a04Sfredette 		/*FALLTHROUGH*/
328ec984a04Sfredette 
329ec984a04Sfredette 	copyfault:
330ec984a04Sfredette 		/*
331ec984a04Sfredette 		 * If we have arranged to catch this fault in any of the
332ec984a04Sfredette 		 * copy to/from user space routines, set PC to return to
333ec984a04Sfredette 		 * indicated location and set flag informing buserror code
334ec984a04Sfredette 		 * that it may need to clean up stack frame.
335ec984a04Sfredette 		 */
336ec984a04Sfredette 		tf.tf_stackadj = exframesize[tf.tf_format];
337ec984a04Sfredette 		tf.tf_format = tf.tf_vector = 0;
338d2275d51Sthorpej 		tf.tf_pc = (int) l->l_addr->u_pcb.pcb_onfault;
339ec984a04Sfredette 		goto done;
340ec984a04Sfredette 
341ec984a04Sfredette 	case T_BUSERR|T_USER:	/* bus error */
342ec984a04Sfredette 	case T_ADDRERR|T_USER:	/* address error */
34341692372Scl 		ksi.ksi_addr = (void *)v;
34441692372Scl 		ksi.ksi_signo = SIGBUS;
34541692372Scl 		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
34641692372Scl 			BUS_OBJERR : BUS_ADRERR;
347ec984a04Sfredette 		break;
348ec984a04Sfredette 
349ec984a04Sfredette 	case T_COPERR:		/* kernel coprocessor violation */
350ec984a04Sfredette 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
351ec984a04Sfredette 	case T_FMTERR:		/* ...just in case... */
352ec984a04Sfredette 		/*
353ec984a04Sfredette 		 * The user has most likely trashed the RTE or FP state info
354ec984a04Sfredette 		 * in the stack frame of a signal handler.
355ec984a04Sfredette 		 */
356ec984a04Sfredette 		printf("pid %d: kernel %s exception\n", p->p_pid,
357ec984a04Sfredette 		       type==T_COPERR ? "coprocessor" : "format");
358ec984a04Sfredette 		type |= T_USER;
359ec984a04Sfredette 		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
360ec984a04Sfredette 		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
361ec984a04Sfredette 		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
362ec984a04Sfredette 		sigdelset(&p->p_sigctx.ps_sigmask, SIGILL);
36341692372Scl 		ksi.ksi_signo = SIGILL;
36441692372Scl 		ksi.ksi_addr = (void *)(int)tf.tf_format;
36541692372Scl 		ksi.ksi_code = (type == T_COPERR) ?
36641692372Scl 			ILL_COPROC : ILL_ILLOPC;
367ec984a04Sfredette 		break;
368ec984a04Sfredette 
369ec984a04Sfredette 	case T_COPERR|T_USER:	/* user coprocessor violation */
370ec984a04Sfredette 	/* What is a proper response here? */
37141692372Scl 		ksi.ksi_signo = SIGFPE;
37241692372Scl 		ksi.ksi_code = FPE_FLTINV;
373ec984a04Sfredette 		break;
374ec984a04Sfredette 
375ec984a04Sfredette 	case T_FPERR|T_USER:	/* 68881 exceptions */
376ec984a04Sfredette 		/*
377ec984a04Sfredette 		 * We pass along the 68881 status register which locore stashed
378ec984a04Sfredette 		 * in code for us.  Note that there is a possibility that the
379ec984a04Sfredette 		 * bit pattern of this register will conflict with one of the
380ec984a04Sfredette 		 * FPE_* codes defined in signal.h.  Fortunately for us, the
381ec984a04Sfredette 		 * only such codes we use are all in the range 1-7 and the low
382ec984a04Sfredette 		 * 3 bits of the status register are defined as 0 so there is
383ec984a04Sfredette 		 * no clash.
384ec984a04Sfredette 		 */
38541692372Scl 		ksi.ksi_signo = SIGFPE;
38641692372Scl 		ksi.ksi_addr = (void *)code;
387ec984a04Sfredette 		break;
388ec984a04Sfredette 
389ec984a04Sfredette 	case T_FPEMULI:		/* FPU faults in supervisor mode */
390ec984a04Sfredette 	case T_FPEMULD:
391ec984a04Sfredette 		if (nofault)	/* Doing FPU probe? */
392ec984a04Sfredette 			longjmp(nofault);
393ec984a04Sfredette 		goto dopanic;
394ec984a04Sfredette 
395ec984a04Sfredette 	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
396ec984a04Sfredette 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
397ec984a04Sfredette #ifdef	FPU_EMULATE
39841692372Scl 		if (fpu_emulate(&tf, &l->l_addr->u_pcb.pcb_fpregs, &ksi) == 0)
39941692372Scl 			; /* XXX - Deal with tracing? (tf.tf_sr & PSL_T) */
400ec984a04Sfredette #else
401ec984a04Sfredette 		uprintf("pid %d killed: no floating point support\n", p->p_pid);
40241692372Scl 		ksi.ksi_signo = SIGILL;
40341692372Scl 		ksi.ksi_code = ILL_ILLOPC;
404ec984a04Sfredette #endif
405ec984a04Sfredette 		break;
406ec984a04Sfredette 
407ec984a04Sfredette 	case T_ILLINST|T_USER:	/* illegal instruction fault */
408ec984a04Sfredette 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
40941692372Scl 		ksi.ksi_addr = (void *)(int)tf.tf_format;
41041692372Scl 		ksi.ksi_signo = SIGILL;
41141692372Scl 		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
41241692372Scl 			ILL_PRVOPC : ILL_ILLOPC;
413ec984a04Sfredette 		break;
414ec984a04Sfredette 
415ec984a04Sfredette 	case T_ZERODIV|T_USER:	/* Divide by zero */
41641692372Scl 		ksi.ksi_code = FPE_FLTDIV;
417ec984a04Sfredette 	case T_CHKINST|T_USER:	/* CHK instruction trap */
418ec984a04Sfredette 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
41941692372Scl 		ksi.ksi_addr = (void *)(int)tf.tf_format;
42041692372Scl 		ksi.ksi_signo = SIGFPE;
421ec984a04Sfredette 		break;
422ec984a04Sfredette 
423ec984a04Sfredette 	/*
424ec984a04Sfredette 	 * XXX: Trace traps are a nightmare.
425ec984a04Sfredette 	 *
426ec984a04Sfredette 	 *	HP-UX uses trap #1 for breakpoints,
427ec984a04Sfredette 	 *	NetBSD/m68k uses trap #2,
428ec984a04Sfredette 	 *	SUN 3.x uses trap #15,
429ec984a04Sfredette 	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
430ec984a04Sfredette 	 *	handled elsewhere).
431ec984a04Sfredette 	 *
432ec984a04Sfredette 	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
433ec984a04Sfredette 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
434ec984a04Sfredette 	 * supported yet.
435ec984a04Sfredette 	 *
436ec984a04Sfredette 	 * XXX: We should never get kernel-mode T_TRAP15
437ec984a04Sfredette 	 * XXX: because locore.s now gives them special treatment.
438ec984a04Sfredette 	 */
439ec984a04Sfredette 	case T_TRAP15:		/* kernel breakpoint */
440ec984a04Sfredette 		tf.tf_sr &= ~PSL_T;
441ec984a04Sfredette 		goto done;
442ec984a04Sfredette 
443ec984a04Sfredette 	case T_TRACE|T_USER:	/* user trace trap */
444ec984a04Sfredette #ifdef COMPAT_SUNOS
445ec984a04Sfredette 		/*
446ec984a04Sfredette 		 * SunOS uses Trap #2 for a "CPU cache flush"
447ec984a04Sfredette 		 * Just flush the on-chip caches and return.
448ec984a04Sfredette 		 * XXX - Too bad NetBSD uses trap 2...
449ec984a04Sfredette 		 */
450ec984a04Sfredette 		if (p->p_emul == &emul_sunos) {
451ec984a04Sfredette 			/* get out fast */
452ec984a04Sfredette 			goto done;
453ec984a04Sfredette 		}
454ec984a04Sfredette #endif
455ec984a04Sfredette 		/* FALLTHROUGH */
456ec984a04Sfredette 	case T_TRACE:		/* tracing a trap instruction */
457ec984a04Sfredette 	case T_TRAP15|T_USER:	/* SUN user trace trap */
458ec984a04Sfredette 		tf.tf_sr &= ~PSL_T;
45941692372Scl 		ksi.ksi_signo = SIGTRAP;
460ec984a04Sfredette 		break;
461ec984a04Sfredette 
462ec984a04Sfredette 	case T_ASTFLT:		/* system async trap, cannot happen */
463ec984a04Sfredette 		goto dopanic;
464ec984a04Sfredette 
465ec984a04Sfredette 	case T_ASTFLT|T_USER:	/* user async trap */
466ec984a04Sfredette 		astpending = 0;
467ec984a04Sfredette 		/* T_SSIR is not used on a Sun2. */
468ec984a04Sfredette 		if (p->p_flag & P_OWEUPC) {
469ec984a04Sfredette 			p->p_flag &= ~P_OWEUPC;
470ec984a04Sfredette 			ADDUPROF(p);
471ec984a04Sfredette 		}
472d2275d51Sthorpej 		if (want_resched)
473d2275d51Sthorpej 			preempt(0);
474ec984a04Sfredette 		goto douret;
475ec984a04Sfredette 
476ec984a04Sfredette 	case T_MMUFLT:		/* kernel mode page fault */
477ec984a04Sfredette 		/* Hacks to avoid calling VM code from debugger. */
478ec984a04Sfredette #ifdef	DDB
479ec984a04Sfredette 		if (db_recover != 0)
480ec984a04Sfredette 			goto dopanic;
481ec984a04Sfredette #endif
482ec984a04Sfredette #ifdef	KGDB
483ec984a04Sfredette 		if (kgdb_recover != 0)
484ec984a04Sfredette 			goto dopanic;
485ec984a04Sfredette #endif
486ec984a04Sfredette 		/*
487ec984a04Sfredette 		 * If we were doing profiling ticks or other user mode
488ec984a04Sfredette 		 * stuff from interrupt code, Just Say No.
489ec984a04Sfredette 		 */
490d2275d51Sthorpej 		if (l->l_addr->u_pcb.pcb_onfault == (caddr_t)fubail ||
491d2275d51Sthorpej 		    l->l_addr->u_pcb.pcb_onfault == (caddr_t)subail)
492ec984a04Sfredette 		{
493ec984a04Sfredette #ifdef	DEBUG
494ec984a04Sfredette 			if (mmudebug & MDB_CPFAULT) {
495ec984a04Sfredette 				printf("trap: copyfault fu/su bail\n");
496ec984a04Sfredette 				Debugger();
497ec984a04Sfredette 			}
498ec984a04Sfredette #endif
499ec984a04Sfredette 			goto copyfault;
500ec984a04Sfredette 		}
501ec984a04Sfredette 		/*FALLTHROUGH*/
502ec984a04Sfredette 
503ec984a04Sfredette 	case T_MMUFLT|T_USER: { 	/* page fault */
504bbb634caSfredette 		vaddr_t va;
505bbb634caSfredette 		struct vmspace *vm = p->p_vmspace;
506bbb634caSfredette 		struct vm_map *map;
507ec984a04Sfredette 		int rv;
508ec984a04Sfredette 		vm_prot_t ftype;
509821ec03eSchs 		extern struct vm_map *kernel_map;
510ec984a04Sfredette 
511ec984a04Sfredette #ifdef DEBUG
512ec984a04Sfredette 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
513ec984a04Sfredette 		printf("trap: T_MMUFLT pid=%d, code=0x%x, v=0x%x, pc=0x%x, sr=0x%x\n",
514ec984a04Sfredette 		       p->p_pid, code, v, tf.tf_pc, tf.tf_sr);
515ec984a04Sfredette #endif
516ec984a04Sfredette 
517ec984a04Sfredette 		/*
518ec984a04Sfredette 		 * It is only a kernel address space fault iff:
519ec984a04Sfredette 		 * 	1. (type & T_USER) == 0  and: (2 or 3)
520ec984a04Sfredette 		 * 	2. pcb_onfault not set or
521ec984a04Sfredette 		 *	3. pcb_onfault set but supervisor space data fault
522ec984a04Sfredette 		 * The last can occur during an exec() copyin where the
523ec984a04Sfredette 		 * argument space is lazy-allocated.
524ec984a04Sfredette 		 */
525ec984a04Sfredette 		map = &vm->vm_map;
526ec984a04Sfredette 		if ((type & T_USER) == 0) {
527ec984a04Sfredette 			/* supervisor mode fault */
528d2275d51Sthorpej 			if ((l->l_addr->u_pcb.pcb_onfault == NULL) || KDFAULT(code))
529ec984a04Sfredette 				map = kernel_map;
5303c10927eScl 		} else if (l->l_flag & L_SA) {
531ea5ec021Scl 			l->l_savp->savp_faultaddr = (vaddr_t)v;
5323c10927eScl 			l->l_flag |= L_SA_PAGEFAULT;
533ec984a04Sfredette 		}
534ec984a04Sfredette 
535ec984a04Sfredette 		if (WRFAULT(code))
536b744097aSchs 			ftype = VM_PROT_WRITE;
537ec984a04Sfredette 		else
538ec984a04Sfredette 			ftype = VM_PROT_READ;
539bbb634caSfredette 		va = m68k_trunc_page((vaddr_t)v);
540ec984a04Sfredette 
541ec984a04Sfredette 		/*
542ec984a04Sfredette 		 * Need to resolve the fault.
543ec984a04Sfredette 		 *
544ec984a04Sfredette 		 * We give the pmap code a chance to resolve faults by
545ec984a04Sfredette 		 * reloading translations that it was forced to unload.
546ec984a04Sfredette 		 * This function does that, and calls vm_fault if it
547ec984a04Sfredette 		 * could not resolve the fault by reloading the MMU.
548ec984a04Sfredette 		 * This function may also, for example, disallow any
549ec984a04Sfredette 		 * faults in the kernel text segment, etc.
550ec984a04Sfredette 		 */
551ec984a04Sfredette 		rv = _pmap_fault(map, va, ftype);
552ec984a04Sfredette 
553ec984a04Sfredette #ifdef	DEBUG
554ec984a04Sfredette 		if (rv && MDB_ISPID(p->p_pid)) {
555ec984a04Sfredette 			printf("vm_fault(%p, 0x%lx, 0x%x, 0) -> 0x%x\n",
556ec984a04Sfredette 			       map, va, ftype, rv);
557ec984a04Sfredette 			if (mmudebug & MDB_WBFAILED)
558ec984a04Sfredette 				Debugger();
559ec984a04Sfredette 		}
560ec984a04Sfredette #endif	/* DEBUG */
561ec984a04Sfredette 
562ec984a04Sfredette 		/*
563ec984a04Sfredette 		 * If this was a stack access we keep track of the maximum
564ec984a04Sfredette 		 * accessed stack size.  Also, if vm_fault gets a protection
565ec984a04Sfredette 		 * failure it is due to accessing the stack region outside
566ec984a04Sfredette 		 * the current limit and we need to reflect that as an access
567ec984a04Sfredette 		 * error.
568ec984a04Sfredette 		 */
569ec984a04Sfredette 		if (rv == 0) {
570*64969161Sjdolecek 			if (map != kernel_map && (caddr_t)va >= vm->vm_maxsaddr)
571*64969161Sjdolecek 				uvm_grow(p, va);
572ec984a04Sfredette 
5733c10927eScl 			if ((type & T_USER) != 0)
5743c10927eScl 				l->l_flag &= ~L_SA_PAGEFAULT;
575ec984a04Sfredette 			goto finish;
5763c10927eScl 		}
57741692372Scl 		if (rv == EACCES) {
57841692372Scl 			ksi.ksi_code = SEGV_ACCERR;
57941692372Scl 			rv = EFAULT;
58041692372Scl 		} else
58141692372Scl 			ksi.ksi_code = SEGV_MAPERR;
582ec984a04Sfredette 		if ((type & T_USER) == 0) {
583ec984a04Sfredette 			/* supervisor mode fault */
584d2275d51Sthorpej 			if (l->l_addr->u_pcb.pcb_onfault) {
585ec984a04Sfredette #ifdef	DEBUG
586ec984a04Sfredette 				if (mmudebug & MDB_CPFAULT) {
587ec984a04Sfredette 					printf("trap: copyfault pcb_onfault\n");
588ec984a04Sfredette 					Debugger();
589ec984a04Sfredette 				}
590ec984a04Sfredette #endif
591ec984a04Sfredette 				goto copyfault;
592ec984a04Sfredette 			}
593ec984a04Sfredette 			printf("vm_fault(%p, 0x%lx, 0x%x, 0) -> 0x%x\n",
594ec984a04Sfredette 			       map, va, ftype, rv);
595ec984a04Sfredette 			goto dopanic;
596ec984a04Sfredette 		}
5973c10927eScl 		l->l_flag &= ~L_SA_PAGEFAULT;
59841692372Scl 		ksi.ksi_addr = (void *)v;
599ec984a04Sfredette 		if (rv == ENOMEM) {
600ec984a04Sfredette 			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
601ec984a04Sfredette 			       p->p_pid, p->p_comm,
602ec984a04Sfredette 			       p->p_cred && p->p_ucred ?
603ec984a04Sfredette 			       p->p_ucred->cr_uid : -1);
60441692372Scl 			ksi.ksi_signo = SIGKILL;
605ec984a04Sfredette 		} else {
60641692372Scl 			ksi.ksi_signo = SIGSEGV;
607ec984a04Sfredette 		}
608ec984a04Sfredette 		break;
609ec984a04Sfredette 		} /* T_MMUFLT */
610ec984a04Sfredette 	} /* switch */
611ec984a04Sfredette 
612ec984a04Sfredette finish:
613ec984a04Sfredette 	/* If trap was from supervisor mode, just return. */
614ec984a04Sfredette 	if ((type & T_USER) == 0)
615ec984a04Sfredette 		goto done;
616ec984a04Sfredette 	/* Post a signal if necessary. */
61741692372Scl 	if (ksi.ksi_signo)
61841692372Scl 		trapsignal(l, &ksi);
619ec984a04Sfredette douret:
620d2275d51Sthorpej 	userret(l, &tf, sticks);
621ec984a04Sfredette 
622ec984a04Sfredette done:;
623ec984a04Sfredette 	/* XXX: Detect trap recursion? */
624ec984a04Sfredette }
625ec984a04Sfredette 
626ec984a04Sfredette /*
627ec984a04Sfredette  * This is used if we hit a kernel breakpoint or trace trap
628ec984a04Sfredette  * when there is no debugger installed (or not attached).
629ec984a04Sfredette  * Drop into the PROM temporarily...
630ec984a04Sfredette  */
631ec984a04Sfredette int
632ec984a04Sfredette _nodb_trap(type, tf)
633ec984a04Sfredette 	int type;
634ec984a04Sfredette 	struct trapframe *tf;
635ec984a04Sfredette {
636ec984a04Sfredette 
637ec984a04Sfredette 	printf("\r\nKernel ");
638ec984a04Sfredette 	if ((0 <= type) && (type < trap_types))
639ec984a04Sfredette 		printf("%s", trap_type[type]);
640ec984a04Sfredette 	else
641ec984a04Sfredette 		printf("trap 0x%x", type);
642ec984a04Sfredette 	printf(", frame=%p\r\n", tf);
643ec984a04Sfredette 	printf("No debugger; doing PROM abort.\r\n");
644ec984a04Sfredette 	printf("To continue, type: c <RETURN>\r\n");
645ec984a04Sfredette 	prom_abort();
646ec984a04Sfredette 	/* OK then, just resume... */
647ec984a04Sfredette 	tf->tf_sr &= ~PSL_T;
648ec984a04Sfredette 	return(1);
649ec984a04Sfredette }
650ec984a04Sfredette 
651ec984a04Sfredette /*
652ec984a04Sfredette  * This is called by locore for supervisor-mode trace and
653ec984a04Sfredette  * breakpoint traps.  This is separate from trap() above
654ec984a04Sfredette  * so that breakpoints in trap() will work.
655ec984a04Sfredette  *
656ec984a04Sfredette  * If we have both DDB and KGDB, let KGDB see it first,
657ec984a04Sfredette  * because KGDB will just return 0 if not connected.
658ec984a04Sfredette  */
659ec984a04Sfredette void
660ec984a04Sfredette trap_kdebug(type, tf)
661ec984a04Sfredette 	int type;
662ec984a04Sfredette 	struct trapframe tf;
663ec984a04Sfredette {
664ec984a04Sfredette 
665ec984a04Sfredette #ifdef	KGDB
666ec984a04Sfredette 	/* Let KGDB handle it (if connected) */
667ec984a04Sfredette 	if (kgdb_trap(type, &tf))
668ec984a04Sfredette 		return;
669ec984a04Sfredette #endif
670ec984a04Sfredette #ifdef	DDB
671ec984a04Sfredette 	/* Let DDB handle it. */
672ec984a04Sfredette 	if (kdb_trap(type, &tf))
673ec984a04Sfredette 		return;
674ec984a04Sfredette #endif
675ec984a04Sfredette 
676ec984a04Sfredette 	/* Drop into the PROM temporarily... */
677ec984a04Sfredette 	(void)_nodb_trap(type, &tf);
678ec984a04Sfredette }
679ec984a04Sfredette 
680ec984a04Sfredette /*
681ec984a04Sfredette  * Called by locore.s for an unexpected interrupt.
682ec984a04Sfredette  * XXX - Almost identical to trap_kdebug...
683ec984a04Sfredette  */
684ec984a04Sfredette void
685ec984a04Sfredette straytrap(tf)
686ec984a04Sfredette 	struct trapframe tf;
687ec984a04Sfredette {
688ec984a04Sfredette 	int type = -1;
689ec984a04Sfredette 
690ec984a04Sfredette 	printf("unexpected trap; vector=0x%x at pc=0x%x\n",
691ec984a04Sfredette 		tf.tf_vector, tf.tf_pc);
692ec984a04Sfredette 
693ec984a04Sfredette #ifdef	KGDB
694ec984a04Sfredette 	/* Let KGDB handle it (if connected) */
695ec984a04Sfredette 	if (kgdb_trap(type, &tf))
696ec984a04Sfredette 		return;
697ec984a04Sfredette #endif
698ec984a04Sfredette #ifdef	DDB
699ec984a04Sfredette 	/* Let DDB handle it. */
700ec984a04Sfredette 	if (kdb_trap(type, &tf))
701ec984a04Sfredette 		return;
702ec984a04Sfredette #endif
703ec984a04Sfredette 
704ec984a04Sfredette 	/* Drop into the PROM temporarily... */
705ec984a04Sfredette 	(void)_nodb_trap(type, &tf);
706ec984a04Sfredette }
707