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