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