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