xref: /netbsd/sys/arch/news68k/news68k/trap.c (revision 5e6815ad)
1*5e6815adStsutsui /*	$NetBSD: trap.c,v 1.74 2023/04/22 10:09:12 tsutsui Exp $	*/
2a1099430Stsutsui 
3a1099430Stsutsui /*
48ac3875aSrmind  * Copyright (c) 1988 University of Utah.
5a1099430Stsutsui  * Copyright (c) 1982, 1986, 1990, 1993
6a1099430Stsutsui  *	The Regents of the University of California.  All rights reserved.
7a1099430Stsutsui  *
8a1099430Stsutsui  * This code is derived from software contributed to Berkeley by
9a1099430Stsutsui  * the Systems Programming Group of the University of Utah Computer
10a1099430Stsutsui  * Science Department.
11a1099430Stsutsui  *
12a1099430Stsutsui  * Redistribution and use in source and binary forms, with or without
13a1099430Stsutsui  * modification, are permitted provided that the following conditions
14a1099430Stsutsui  * are met:
15a1099430Stsutsui  * 1. Redistributions of source code must retain the above copyright
16a1099430Stsutsui  *    notice, this list of conditions and the following disclaimer.
17a1099430Stsutsui  * 2. Redistributions in binary form must reproduce the above copyright
18a1099430Stsutsui  *    notice, this list of conditions and the following disclaimer in the
19a1099430Stsutsui  *    documentation and/or other materials provided with the distribution.
20aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
21aad01611Sagc  *    may be used to endorse or promote products derived from this software
22aad01611Sagc  *    without specific prior written permission.
23aad01611Sagc  *
24aad01611Sagc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25aad01611Sagc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26aad01611Sagc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27aad01611Sagc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28aad01611Sagc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29aad01611Sagc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30aad01611Sagc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31aad01611Sagc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32aad01611Sagc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33aad01611Sagc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34aad01611Sagc  * SUCH DAMAGE.
35aad01611Sagc  *
36aad01611Sagc  * from: Utah $Hdr: trap.c 1.37 92/12/20$
37aad01611Sagc  *
38aad01611Sagc  *	@(#)trap.c	8.5 (Berkeley) 1/4/94
39aad01611Sagc  */
40a1099430Stsutsui 
41ed517291Slukem #include <sys/cdefs.h>
42*5e6815adStsutsui __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.74 2023/04/22 10:09:12 tsutsui Exp $");
43ed517291Slukem 
44a1099430Stsutsui #include "opt_ddb.h"
45a1099430Stsutsui #include "opt_execfmt.h"
46d84d2c6cSlukem #include "opt_kgdb.h"
47a1099430Stsutsui #include "opt_compat_sunos.h"
48bd01b4a3Smrg #include "opt_m68k_arch.h"
49a1099430Stsutsui 
50a1099430Stsutsui #include <sys/param.h>
51a1099430Stsutsui #include <sys/systm.h>
52a1099430Stsutsui #include <sys/proc.h>
53a1099430Stsutsui #include <sys/acct.h>
54273acb66Stsutsui #include <sys/syscall.h>
55ef56cc40Scl #include <sys/userret.h>
56b3b86226Syamt #include <sys/kauth.h>
57a1099430Stsutsui 
58273acb66Stsutsui #include <m68k/frame.h>
5940e5b839Schs #include <m68k/cacheops.h>
60273acb66Stsutsui 
61273acb66Stsutsui #include <machine/cpu.h>
62273acb66Stsutsui #include <machine/db_machdep.h>
63c62ccd21Stsutsui #include <machine/pcb.h>
64a1099430Stsutsui #include <machine/reg.h>
65273acb66Stsutsui #include <machine/trap.h>
66a1099430Stsutsui 
67a1099430Stsutsui #include <uvm/uvm_extern.h>
68a1099430Stsutsui 
69a1099430Stsutsui #include <dev/cons.h>
70a1099430Stsutsui 
71a1099430Stsutsui #ifdef COMPAT_SUNOS
7247ac3d6bStsutsui #include <compat/sunos/sunos_exec.h>
73a1099430Stsutsui #include <compat/sunos/sunos_syscall.h>
74a1099430Stsutsui #endif
75a1099430Stsutsui 
76d2eac2f6Smhitch void	trap(struct frame *fp, int type, u_int code, u_int v);
77a1099430Stsutsui 
78a1099430Stsutsui #ifdef DEBUG
79738ea71fStsutsui void	dumpssw(u_short);
80738ea71fStsutsui void	dumpwb(int, u_short, u_int, u_int);
81a1099430Stsutsui #endif
82a1099430Stsutsui 
8371b22303Sthorpej static inline void userret(struct lwp *l, struct frame *fp,
84738ea71fStsutsui 	    u_quad_t oticks, u_int faultaddr, int fromtrap);
85a1099430Stsutsui 
86a1099430Stsutsui int	astpending;
87a1099430Stsutsui 
88f9462547Stsutsui const char *trap_type[] = {
89a1099430Stsutsui 	"Bus error",
90a1099430Stsutsui 	"Address error",
91a1099430Stsutsui 	"Illegal instruction",
92a1099430Stsutsui 	"Zero divide",
93a1099430Stsutsui 	"CHK instruction",
94a1099430Stsutsui 	"TRAPV instruction",
95a1099430Stsutsui 	"Privilege violation",
96a1099430Stsutsui 	"Trace trap",
97a1099430Stsutsui 	"MMU fault",
98a1099430Stsutsui 	"SSIR trap",
99a1099430Stsutsui 	"Format error",
100a1099430Stsutsui 	"68881 exception",
101a1099430Stsutsui 	"Coprocessor violation",
102a1099430Stsutsui 	"Async system trap"
103a1099430Stsutsui };
104273acb66Stsutsui const int trap_types = sizeof trap_type / sizeof trap_type[0];
105a1099430Stsutsui 
106a1099430Stsutsui /*
107a1099430Stsutsui  * Size of various exception stack frames (minus the standard 8 bytes)
108a1099430Stsutsui  */
109a1099430Stsutsui short	exframesize[] = {
110a1099430Stsutsui 	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
111a1099430Stsutsui 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
112a1099430Stsutsui 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
113a1099430Stsutsui 	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
114a1099430Stsutsui 	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
115a1099430Stsutsui 	-1, -1,		/* type 5-6 - undefined */
116a1099430Stsutsui 	FMT7SIZE,	/* type 7 - access error (68040) */
117a1099430Stsutsui 	58,		/* type 8 - bus fault (68010) */
118a1099430Stsutsui 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
119a1099430Stsutsui 	FMTASIZE,	/* type A - short bus fault (68020/030) */
120a1099430Stsutsui 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
121a1099430Stsutsui 	-1, -1, -1, -1	/* type C-F - undefined */
122a1099430Stsutsui };
123a1099430Stsutsui 
124a1099430Stsutsui #ifdef M68060
125a1099430Stsutsui #define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
126a1099430Stsutsui #define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
127a1099430Stsutsui #else
128a1099430Stsutsui #define	KDFAULT_060(c)	0
129a1099430Stsutsui #define	WRFAULT_060(c)	0
130a1099430Stsutsui #endif
131a1099430Stsutsui 
132a1099430Stsutsui #ifdef M68040
133a1099430Stsutsui #define	KDFAULT_040(c)	(cputype == CPU_68040 && \
134a1099430Stsutsui 			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
135a1099430Stsutsui #define	WRFAULT_040(c)	(cputype == CPU_68040 && \
1369b0f085dSmhitch 			 ((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW)
137a1099430Stsutsui #else
138a1099430Stsutsui #define	KDFAULT_040(c)	0
139a1099430Stsutsui #define	WRFAULT_040(c)	0
140a1099430Stsutsui #endif
141a1099430Stsutsui 
142a1099430Stsutsui #if defined(M68030) || defined(M68020)
143a1099430Stsutsui #define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
144a1099430Stsutsui 			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
145a1099430Stsutsui #define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
1469b0f085dSmhitch 			 (((c) & SSW_DF) != 0 && \
1479b0f085dSmhitch 			 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0))))
148a1099430Stsutsui #else
149a1099430Stsutsui #define	KDFAULT_OTH(c)	0
150a1099430Stsutsui #define	WRFAULT_OTH(c)	0
151a1099430Stsutsui #endif
152a1099430Stsutsui 
153a1099430Stsutsui #define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
154a1099430Stsutsui #define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
155a1099430Stsutsui 
156a1099430Stsutsui #ifdef DEBUG
157a1099430Stsutsui int mmudebug = 0;
158a1099430Stsutsui int mmupid = -1;
159a1099430Stsutsui #define MDB_FOLLOW	1
160a1099430Stsutsui #define MDB_WBFOLLOW	2
161a1099430Stsutsui #define MDB_WBFAILED	4
162a1099430Stsutsui #define MDB_ISPID(p)	((p) == mmupid)
163a1099430Stsutsui #endif
164a1099430Stsutsui 
165a1099430Stsutsui /*
166a1099430Stsutsui  * trap and syscall both need the following work done before returning
167a1099430Stsutsui  * to user mode.
168a1099430Stsutsui  */
169a1099430Stsutsui static inline void
userret(struct lwp * l,struct frame * fp,u_quad_t oticks,u_int faultaddr,int fromtrap)170273acb66Stsutsui userret(struct lwp *l, struct frame *fp, u_quad_t oticks,
171273acb66Stsutsui     u_int faultaddr, int fromtrap)
172a1099430Stsutsui {
17371b22303Sthorpej 	struct proc *p = l->l_proc;
174a1099430Stsutsui #ifdef M68040
175afee7aa4Scl 	int sig;
176a1099430Stsutsui 	int beenhere = 0;
177a1099430Stsutsui 
178a1099430Stsutsui  again:
179a1099430Stsutsui #endif
180ef56cc40Scl 	/* Invoke MI userret code */
181ef56cc40Scl 	mi_userret(l);
182a1099430Stsutsui 
183a1099430Stsutsui 	/*
184a1099430Stsutsui 	 * If profiling, charge system time to the trapped pc.
185a1099430Stsutsui 	 */
1869a492751Stsutsui 	if (p->p_stflag & PST_PROFIL) {
187a1099430Stsutsui 		extern int psratio;
188a1099430Stsutsui 
1899a492751Stsutsui 		addupc_task(l, fp->f_pc,
190a1099430Stsutsui 			    (int)(p->p_sticks - oticks) * psratio);
191a1099430Stsutsui 	}
192a1099430Stsutsui #ifdef M68040
193a1099430Stsutsui 	/*
194a1099430Stsutsui 	 * Deal with user mode writebacks (from trap, or from sigreturn).
195a1099430Stsutsui 	 * If any writeback fails, go back and attempt signal delivery.
196a1099430Stsutsui 	 * unless we have already been here and attempted the writeback
197a1099430Stsutsui 	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
1989115df8cSwiz 	 * we just return to the user without successfully completing
199a1099430Stsutsui 	 * the writebacks.  Maybe we should just drop the sucker?
200a1099430Stsutsui 	 */
201a1099430Stsutsui 	if (cputype == CPU_68040 && fp->f_format == FMT7) {
202a1099430Stsutsui 		if (beenhere) {
203a1099430Stsutsui #ifdef DEBUG
204a1099430Stsutsui 			if (mmudebug & MDB_WBFAILED)
205a1099430Stsutsui 				printf(fromtrap ?
206a1099430Stsutsui 		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
207a1099430Stsutsui 		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
208a1099430Stsutsui 				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
209a1099430Stsutsui #endif
2105751cea6Sthorpej 		} else if ((sig = m68040_writeback(fp, fromtrap))) {
21141692372Scl 			ksiginfo_t ksi;
212a1099430Stsutsui 			beenhere = 1;
213a1099430Stsutsui 			oticks = p->p_sticks;
21441692372Scl 			(void)memset(&ksi, 0, sizeof(ksi));
21541692372Scl 			ksi.ksi_signo = sig;
21641692372Scl 			ksi.ksi_addr = (void *)faultaddr;
21741692372Scl 			ksi.ksi_code = BUS_OBJERR;
21841692372Scl 			trapsignal(l, &ksi);
219a1099430Stsutsui 			goto again;
220a1099430Stsutsui 		}
221a1099430Stsutsui 	}
222a1099430Stsutsui #endif
223a1099430Stsutsui }
224a1099430Stsutsui 
225a1099430Stsutsui /*
2264350a7f2Sscw  * Used by the common m68k syscall() and child_return() functions.
2274350a7f2Sscw  * XXX: Temporary until all m68k ports share common trap()/userret() code.
2284350a7f2Sscw  */
22971b22303Sthorpej void machine_userret(struct lwp *, struct frame *, u_quad_t);
2304350a7f2Sscw 
2314350a7f2Sscw void
machine_userret(struct lwp * l,struct frame * f,u_quad_t t)23252b46dcfStsutsui machine_userret(struct lwp *l, struct frame *f, u_quad_t t)
2334350a7f2Sscw {
2344350a7f2Sscw 
23571b22303Sthorpej 	userret(l, f, t, 0, 0);
2364350a7f2Sscw }
2374350a7f2Sscw 
2384350a7f2Sscw /*
239a1099430Stsutsui  * Trap is called from locore to handle most types of processor traps,
240a1099430Stsutsui  * including events such as simulated software interrupts/AST's.
241a1099430Stsutsui  * System calls are broken out for efficiency.
242a1099430Stsutsui  */
243a1099430Stsutsui void
trap(struct frame * fp,int type,u_int code,u_int v)244d2eac2f6Smhitch trap(struct frame *fp, int type, u_int code, u_int v)
245a1099430Stsutsui {
24671b22303Sthorpej 	struct lwp *l;
247a1099430Stsutsui 	struct proc *p;
2483dc24f5aSrmind 	struct pcb *pcb;
24904aa4da3Schs 	void *onfault;
25041692372Scl 	ksiginfo_t ksi;
25141692372Scl 	int s;
25204aa4da3Schs 	int rv;
253273acb66Stsutsui 	u_quad_t sticks = 0 /* XXX initializer works around compiler bug */;
254a1099430Stsutsui 
255ccde4787Smatt 	curcpu()->ci_data.cpu_ntrap++;
25671b22303Sthorpej 	l = curlwp;
25704aa4da3Schs 	p = l->l_proc;
25804aa4da3Schs 	pcb = lwp_getpcb(l);
25941692372Scl 
26068723a99Sthorpej 	KSI_INIT_TRAP(&ksi);
26141692372Scl 	ksi.ksi_trap = type & ~T_USER;
262a1099430Stsutsui 
263d2eac2f6Smhitch 	if (USERMODE(fp->f_sr)) {
264a1099430Stsutsui 		type |= T_USER;
265a1099430Stsutsui 		sticks = p->p_sticks;
266d2eac2f6Smhitch 		l->l_md.md_regs = fp->f_regs;
2672b79369cSad 		LWP_CACHE_CREDS(l, p);
268a1099430Stsutsui 	}
269a1099430Stsutsui 	switch (type) {
270a1099430Stsutsui 
271a1099430Stsutsui 	default:
272a1099430Stsutsui 	dopanic:
273a1099430Stsutsui 		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
274a1099430Stsutsui 		printf("%s program counter = 0x%x\n",
275d2eac2f6Smhitch 		    (type & T_USER) ? "user" : "kernel", fp->f_pc);
276a1099430Stsutsui 		/*
277a1099430Stsutsui 		 * Let the kernel debugger see the trap frame that
278a1099430Stsutsui 		 * caused us to panic.  This is a convenience so
279a1099430Stsutsui 		 * one can see registers at the point of failure.
280a1099430Stsutsui 		 */
281a1099430Stsutsui 		s = splhigh();
282a1099430Stsutsui #ifdef KGDB
283a1099430Stsutsui 		/* If connected, step or cont returns 1 */
284d2eac2f6Smhitch 		if (kgdb_trap(type, fp))
285a1099430Stsutsui 			goto kgdb_cont;
286a1099430Stsutsui #endif
287a1099430Stsutsui #ifdef DDB
288d2eac2f6Smhitch 		(void)kdb_trap(type, (db_regs_t *)fp);
289a1099430Stsutsui #endif
290a1099430Stsutsui #ifdef KGDB
291a1099430Stsutsui 	kgdb_cont:
292a1099430Stsutsui #endif
293a1099430Stsutsui 		splx(s);
294a1099430Stsutsui 		if (panicstr) {
295a1099430Stsutsui 			printf("trap during panic!\n");
296a1099430Stsutsui #ifdef DEBUG
297a1099430Stsutsui 			/* XXX should be a machine-dependent hook */
29823ffe7e3Stsutsui 			printf("(press a key)\n");
29923ffe7e3Stsutsui 			cnpollc(1);
30023ffe7e3Stsutsui 			(void)cngetc();
30123ffe7e3Stsutsui 			cnpollc(0);
302a1099430Stsutsui #endif
303a1099430Stsutsui 		}
304d2eac2f6Smhitch 		regdump((struct trapframe *)fp, 128);
305a1099430Stsutsui 		type &= ~T_USER;
306273acb66Stsutsui 		if ((u_int)type < trap_types)
307a1099430Stsutsui 			panic(trap_type[type]);
308a1099430Stsutsui 		panic("trap");
309a1099430Stsutsui 
310a1099430Stsutsui 	case T_BUSERR:		/* kernel bus error */
31104aa4da3Schs 		onfault = pcb->pcb_onfault;
31204aa4da3Schs 		if (onfault == NULL)
313a1099430Stsutsui 			goto dopanic;
31404aa4da3Schs 		rv = EFAULT;
315a1099430Stsutsui 		/* FALLTHROUGH */
316a1099430Stsutsui 
317a1099430Stsutsui 	copyfault:
318a1099430Stsutsui 		/*
319a1099430Stsutsui 		 * If we have arranged to catch this fault in any of the
320a1099430Stsutsui 		 * copy to/from user space routines, set PC to return to
321a1099430Stsutsui 		 * indicated location and set flag informing buserror code
322a1099430Stsutsui 		 * that it may need to clean up stack frame.
323a1099430Stsutsui 		 */
324d2eac2f6Smhitch 		fp->f_stackadj = exframesize[fp->f_format];
325d2eac2f6Smhitch 		fp->f_format = fp->f_vector = 0;
32604aa4da3Schs 		fp->f_pc = (int)onfault;
32704aa4da3Schs 		fp->f_regs[D0] = rv;
328a1099430Stsutsui 		return;
329a1099430Stsutsui 
330a1099430Stsutsui 	case T_BUSERR|T_USER:	/* bus error */
331a1099430Stsutsui 	case T_ADDRERR|T_USER:	/* address error */
33241692372Scl 		ksi.ksi_addr = (void *)v;
33341692372Scl 		ksi.ksi_signo = SIGBUS;
33441692372Scl 		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
33541692372Scl 			BUS_OBJERR : BUS_ADRERR;
336a1099430Stsutsui 		break;
337a1099430Stsutsui 
338a1099430Stsutsui 	case T_COPERR:		/* kernel coprocessor violation */
339a1099430Stsutsui 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
340a1099430Stsutsui 	case T_FMTERR:		/* ...just in case... */
341a1099430Stsutsui 	/*
342a1099430Stsutsui 	 * The user has most likely trashed the RTE or FP state info
343a1099430Stsutsui 	 * in the stack frame of a signal handler.
344a1099430Stsutsui 	 */
345a1099430Stsutsui 		printf("pid %d: kernel %s exception\n", p->p_pid,
346a1099430Stsutsui 		       type==T_COPERR ? "coprocessor" : "format");
347a1099430Stsutsui 		type |= T_USER;
3489a492751Stsutsui 
349284c2b9aSad 		mutex_enter(p->p_lock);
350de31133fSjdolecek 		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
351de31133fSjdolecek 		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
352de31133fSjdolecek 		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
3539a492751Stsutsui 		sigdelset(&l->l_sigmask, SIGILL);
354284c2b9aSad 		mutex_exit(p->p_lock);
3559a492751Stsutsui 
35641692372Scl 		ksi.ksi_signo = SIGILL;
357d2eac2f6Smhitch 		ksi.ksi_addr = (void *)(int)fp->f_format;
35841692372Scl 				/* XXX was ILL_RESAD_FAULT */
35941692372Scl 		ksi.ksi_code = (type == T_COPERR) ?
36041692372Scl 			ILL_COPROC : ILL_ILLOPC;
361a1099430Stsutsui 		break;
362a1099430Stsutsui 
363a1099430Stsutsui 	case T_COPERR|T_USER:	/* user coprocessor violation */
364a1099430Stsutsui 	/* What is a proper response here? */
36541692372Scl 		ksi.ksi_signo = SIGFPE;
36641692372Scl 		ksi.ksi_code = FPE_FLTINV;
367a1099430Stsutsui 		break;
368a1099430Stsutsui 
369a1099430Stsutsui 	case T_FPERR|T_USER:	/* 68881 exceptions */
370a1099430Stsutsui 	/*
371a1099430Stsutsui 	 * We pass along the 68881 status register which locore stashed
372f055e182Smartin 	 * in code for us.
373a1099430Stsutsui 	 */
37441692372Scl 		ksi.ksi_signo = SIGFPE;
375f055e182Smartin 		ksi.ksi_code = fpsr2siginfocode(code);
376a1099430Stsutsui 		break;
377a1099430Stsutsui 
378a1099430Stsutsui #ifdef M68040
3795d1e8b27Swiz 	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
380a1099430Stsutsui 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
381a1099430Stsutsui 		/* XXX need to FSAVE */
382a1099430Stsutsui 		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
383a1099430Stsutsui 		       p->p_pid, p->p_comm,
384d2eac2f6Smhitch 		       fp->f_format == 2 ? "instruction" : "data type",
385d2eac2f6Smhitch 		       fp->f_pc, fp->f_fmt2.f_iaddr);
386a1099430Stsutsui 		/* XXX need to FRESTORE */
38741692372Scl 		ksi.ksi_signo = SIGFPE;
38841692372Scl 		ksi.ksi_code = FPE_FLTINV;
389a1099430Stsutsui 		break;
390a1099430Stsutsui #endif
391a1099430Stsutsui 
392a1099430Stsutsui 	case T_ILLINST|T_USER:	/* illegal instruction fault */
393a1099430Stsutsui 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
394d2eac2f6Smhitch 		ksi.ksi_addr = (void *)(int)fp->f_format;
39541692372Scl 				/* XXX was ILL_PRIVIN_FAULT */
39641692372Scl 		ksi.ksi_signo = SIGILL;
39741692372Scl 		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
39841692372Scl 			ILL_PRVOPC : ILL_ILLOPC;
399a1099430Stsutsui 		break;
400a1099430Stsutsui 
401a1099430Stsutsui 	case T_ZERODIV|T_USER:	/* Divide by zero */
402d2eac2f6Smhitch 		ksi.ksi_addr = (void *)(int)fp->f_format;
40341692372Scl 				/* XXX was FPE_INTDIV_TRAP */
40441692372Scl 		ksi.ksi_signo = SIGFPE;
40541692372Scl 		ksi.ksi_code = FPE_FLTDIV;
406a1099430Stsutsui 		break;
407a1099430Stsutsui 
408a1099430Stsutsui 	case T_CHKINST|T_USER:	/* CHK instruction trap */
409d2eac2f6Smhitch 		ksi.ksi_addr = (void *)(int)fp->f_format;
41041692372Scl 				/* XXX was FPE_SUBRNG_TRAP */
41141692372Scl 		ksi.ksi_signo = SIGFPE;
412a1099430Stsutsui 		break;
413a1099430Stsutsui 
414a1099430Stsutsui 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
415d2eac2f6Smhitch 		ksi.ksi_addr = (void *)(int)fp->f_format;
41641692372Scl 				/* XXX was FPE_INTOVF_TRAP */
41741692372Scl 		ksi.ksi_signo = SIGFPE;
418a1099430Stsutsui 		break;
419a1099430Stsutsui 
420a1099430Stsutsui 	/*
421a1099430Stsutsui 	 * XXX: Trace traps are a nightmare.
422a1099430Stsutsui 	 *
423a1099430Stsutsui 	 *	HP-UX uses trap #1 for breakpoints,
424a1099430Stsutsui 	 *	NetBSD/m68k uses trap #2,
425a1099430Stsutsui 	 *	SUN 3.x uses trap #15,
426a1099430Stsutsui 	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
427a1099430Stsutsui 	 *	handled elsewhere).
428a1099430Stsutsui 	 *
429a1099430Stsutsui 	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
430a1099430Stsutsui 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
431a1099430Stsutsui 	 * supported yet.
432a1099430Stsutsui 	 *
433a1099430Stsutsui 	 * XXX: We should never get kernel-mode T_TRAP15
434a1099430Stsutsui 	 * XXX: because locore.s now gives them special treatment.
435a1099430Stsutsui 	 */
436a1099430Stsutsui 	case T_TRAP15:		/* kernel breakpoint */
437a1099430Stsutsui #ifdef DEBUG
438a1099430Stsutsui 		printf("unexpected kernel trace trap, type = %d\n", type);
439d2eac2f6Smhitch 		printf("program counter = 0x%x\n", fp->f_pc);
440a1099430Stsutsui #endif
441d2eac2f6Smhitch 		fp->f_sr &= ~PSL_T;
442a1099430Stsutsui 		return;
443a1099430Stsutsui 
444a1099430Stsutsui 	case T_TRACE|T_USER:	/* user trace trap */
445a1099430Stsutsui #ifdef COMPAT_SUNOS
446a1099430Stsutsui 		/*
447a1099430Stsutsui 		 * SunOS uses Trap #2 for a "CPU cache flush".
448a1099430Stsutsui 		 * Just flush the on-chip caches and return.
449a1099430Stsutsui 		 */
450a1099430Stsutsui 		if (p->p_emul == &emul_sunos) {
451a1099430Stsutsui 			ICIA();
452a1099430Stsutsui 			DCIU();
453a1099430Stsutsui 			return;
454a1099430Stsutsui 		}
455a1099430Stsutsui #endif
456a1099430Stsutsui 		/* FALLTHROUGH */
457273acb66Stsutsui 	case T_TRACE:		/* tracing a trap instruction */
458273acb66Stsutsui 	case T_TRAP15|T_USER:	/* SUN user trace trap */
459d2eac2f6Smhitch 		fp->f_sr &= ~PSL_T;
46041692372Scl 		ksi.ksi_signo = SIGTRAP;
461a1099430Stsutsui 		break;
462a1099430Stsutsui 
463a1099430Stsutsui 	case T_ASTFLT:		/* system async trap, cannot happen */
464a1099430Stsutsui 		goto dopanic;
465a1099430Stsutsui 
466a1099430Stsutsui 	case T_ASTFLT|T_USER:	/* user async trap */
467a1099430Stsutsui 		astpending = 0;
468a1099430Stsutsui 		/* T_SSIR is not used on news68k */
4699a492751Stsutsui 		if (l->l_pflag & LP_OWEUPC) {
4709a492751Stsutsui 			l->l_pflag &= ~LP_OWEUPC;
4719a492751Stsutsui 			ADDUPROF(l);
472a1099430Stsutsui 		}
473a1099430Stsutsui 		goto out;
474a1099430Stsutsui 
475a1099430Stsutsui 	case T_MMUFLT:		/* kernel mode page fault */
476a1099430Stsutsui 	case T_MMUFLT|T_USER:	/* page fault */
477a1099430Stsutsui 	    {
478a1099430Stsutsui 		vaddr_t va;
479a1099430Stsutsui 		struct vmspace *vm = p->p_vmspace;
480821ec03eSchs 		struct vm_map *map;
481a1099430Stsutsui 		vm_prot_t ftype;
482821ec03eSchs 		extern struct vm_map *kernel_map;
483a1099430Stsutsui 
48404aa4da3Schs 		onfault = pcb->pcb_onfault;
48504aa4da3Schs 
486a1099430Stsutsui #ifdef DEBUG
487a1099430Stsutsui 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
488a1099430Stsutsui 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
489d2eac2f6Smhitch 		       p->p_pid, code, v, fp->f_pc, fp->f_sr);
490a1099430Stsutsui #endif
491a1099430Stsutsui 		/*
492a1099430Stsutsui 		 * It is only a kernel address space fault iff:
493a1099430Stsutsui 		 * 	1. (type & T_USER) == 0  and
494a1099430Stsutsui 		 * 	2. pcb_onfault not set or
495a1099430Stsutsui 		 *	3. pcb_onfault set but supervisor space data fault
496a1099430Stsutsui 		 * The last can occur during an exec() copyin where the
497a1099430Stsutsui 		 * argument space is lazy-allocated.
498a1099430Stsutsui 		 */
49904aa4da3Schs 		if ((type & T_USER) == 0 && (onfault == NULL || KDFAULT(code)))
500a1099430Stsutsui 			map = kernel_map;
501fc7511b0Swrstuden 		else {
502a1099430Stsutsui 			map = vm ? &vm->vm_map : kernel_map;
503fc7511b0Swrstuden 		}
504a1099430Stsutsui 
505a1099430Stsutsui 		if (WRFAULT(code))
506b744097aSchs 			ftype = VM_PROT_WRITE;
507a1099430Stsutsui 		else
508a1099430Stsutsui 			ftype = VM_PROT_READ;
509a1099430Stsutsui 
510a1099430Stsutsui 		va = trunc_page((vaddr_t)v);
511a1099430Stsutsui 
512a1099430Stsutsui 		if (map == kernel_map && va == 0) {
513a1099430Stsutsui 			printf("trap: bad kernel %s access at 0x%x\n",
514a1099430Stsutsui 			    (ftype & VM_PROT_WRITE) ? "read/write" :
515a1099430Stsutsui 			    "read", v);
516a1099430Stsutsui 			goto dopanic;
517a1099430Stsutsui 		}
518a1099430Stsutsui 
51904aa4da3Schs 		pcb->pcb_onfault = NULL;
52047fbb9d8Sdrochner 		rv = uvm_fault(map, va, ftype);
52104aa4da3Schs 		pcb->pcb_onfault = onfault;
522a1099430Stsutsui #ifdef DEBUG
523a1099430Stsutsui 		if (rv && MDB_ISPID(p->p_pid))
52447fbb9d8Sdrochner 			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
525a1099430Stsutsui 			    map, va, ftype, rv);
526a1099430Stsutsui #endif
527a1099430Stsutsui 		/*
528a1099430Stsutsui 		 * If this was a stack access we keep track of the maximum
529a1099430Stsutsui 		 * accessed stack size.  Also, if vm_fault gets a protection
530a1099430Stsutsui 		 * failure it is due to accessing the stack region outside
531a1099430Stsutsui 		 * the current limit and we need to reflect that as an access
532a1099430Stsutsui 		 * error.
533a1099430Stsutsui 		 */
534ac3bc537Schs 		if (rv == 0) {
53553524e44Schristos 			if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
53664969161Sjdolecek 				uvm_grow(p, va);
537a1099430Stsutsui 
538a1099430Stsutsui 			if (type == T_MMUFLT) {
539a1099430Stsutsui #ifdef M68040
540a1099430Stsutsui 				if (cputype == CPU_68040)
5415751cea6Sthorpej 					(void) m68040_writeback(fp, 1);
542a1099430Stsutsui #endif
543a1099430Stsutsui 				return;
544a1099430Stsutsui 			}
545a1099430Stsutsui 			goto out;
546a1099430Stsutsui 		}
54741692372Scl 		if (rv == EACCES) {
54841692372Scl 			ksi.ksi_code = SEGV_ACCERR;
54941692372Scl 			rv = EFAULT;
55041692372Scl 		} else
55141692372Scl 			ksi.ksi_code = SEGV_MAPERR;
552a1099430Stsutsui 		if (type == T_MMUFLT) {
55304aa4da3Schs 			if (onfault)
554a1099430Stsutsui 				goto copyfault;
55547fbb9d8Sdrochner 			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
556a1099430Stsutsui 			    map, va, ftype, rv);
557a1099430Stsutsui 			printf("  type %x, code [mmu,,ssw]: %x\n",
558a1099430Stsutsui 			       type, code);
559a1099430Stsutsui 			goto dopanic;
560a1099430Stsutsui 		}
56141692372Scl 		ksi.ksi_addr = (void *)v;
5626ff7c06cSmartin 		switch (rv) {
5636ff7c06cSmartin 		case ENOMEM:
564a1099430Stsutsui 			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
565a1099430Stsutsui 			       p->p_pid, p->p_comm,
566f474dcebSad 			       l->l_cred ?
567f474dcebSad 			       kauth_cred_geteuid(l->l_cred) : -1);
56841692372Scl 			ksi.ksi_signo = SIGKILL;
5696ff7c06cSmartin 			break;
5706ff7c06cSmartin 		case EINVAL:
5716ff7c06cSmartin 			ksi.ksi_signo = SIGBUS;
5726ff7c06cSmartin 			ksi.ksi_code = BUS_ADRERR;
5736ff7c06cSmartin 			break;
5746ff7c06cSmartin 		case EACCES:
57541692372Scl 			ksi.ksi_signo = SIGSEGV;
5766ff7c06cSmartin 			ksi.ksi_code = SEGV_ACCERR;
5776ff7c06cSmartin 			break;
5786ff7c06cSmartin 		default:
5796ff7c06cSmartin 			ksi.ksi_signo = SIGSEGV;
5806ff7c06cSmartin 			ksi.ksi_code = SEGV_MAPERR;
5816ff7c06cSmartin 			break;
582a1099430Stsutsui 		}
583a1099430Stsutsui 		break;
584a1099430Stsutsui 	    }
585a1099430Stsutsui 	}
58641692372Scl 	trapsignal(l, &ksi);
587a1099430Stsutsui 	if ((type & T_USER) == 0)
588a1099430Stsutsui 		return;
589a1099430Stsutsui  out:
590d2eac2f6Smhitch 	userret(l, fp, sticks, v, 1);
591a1099430Stsutsui }
592