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