xref: /netbsd-src/sys/arch/x68k/x68k/trap.c (revision c13a5359d541fd49b4c406f5b12209b1640235a5)
1 /*	$NetBSD: trap.c,v 1.114 2024/01/20 00:15:33 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 1988 University of Utah.
5  * Copyright (c) 1982, 1986, 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * the Systems Programming Group of the University of Utah Computer
10  * Science Department.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * from: Utah $Hdr: trap.c 1.37 92/12/20$
37  *
38  *	@(#)trap.c	8.5 (Berkeley) 1/4/94
39  */
40 
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.114 2024/01/20 00:15:33 thorpej Exp $");
43 
44 #include "opt_ddb.h"
45 #include "opt_kgdb.h"
46 #include "opt_execfmt.h"
47 #include "opt_compat_sunos.h"
48 #include "opt_fpu_emulate.h"
49 #include "opt_m68k_arch.h"
50 
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/proc.h>
54 #include <sys/acct.h>
55 #include <sys/kernel.h>
56 #include <sys/signalvar.h>
57 #include <sys/resourcevar.h>
58 #include <sys/syscall.h>
59 #include <sys/syslog.h>
60 #include <sys/userret.h>
61 #include <sys/kauth.h>
62 
63 #include <machine/pcb.h>
64 #include <machine/psl.h>
65 #include <machine/trap.h>
66 #include <machine/cpu.h>
67 #include <machine/reg.h>
68 #include <machine/db_machdep.h>
69 #include <m68k/cacheops.h>
70 
71 #include <uvm/uvm_extern.h>
72 
73 #include <dev/cons.h>
74 
75 #ifdef FPU_EMULATE
76 #include <m68k/fpe/fpu_emulate.h>
77 #endif
78 
79 #ifdef COMPAT_SUNOS
80 #include <compat/sunos/sunos_exec.h>
81 #include <compat/sunos/sunos_syscall.h>
82 #endif
83 
84 void	trap(struct frame *, int, u_int, u_int);
85 
86 #if defined(M68040) || defined(M68060)
87 #ifdef DEBUG
88 void dumpssw(u_short);
89 void dumpwb(int, u_short, u_int, u_int);
90 #endif
91 #endif
92 
93 static inline void userret(struct lwp *, struct frame *, u_quad_t, u_int, int);
94 
95 const char *trap_type[] = {
96 	"Bus error",
97 	"Address error",
98 	"Illegal instruction",
99 	"Zero divide",
100 	"CHK instruction",
101 	"TRAPV instruction",
102 	"Privilege violation",
103 	"Trace trap",
104 	"MMU fault",
105 	"SSIR trap",
106 	"Format error",
107 	"68881 exception",
108 	"Coprocessor violation",
109 	"Async system trap"
110 };
111 int	trap_types = sizeof trap_type / sizeof trap_type[0];
112 
113 /*
114  * Size of various exception stack frames (minus the standard 8 bytes)
115  */
116 short	exframesize[] = {
117 	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
118 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
119 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
120 	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
121 	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
122 	-1, -1,		/* type 5-6 - undefined */
123 	FMT7SIZE,	/* type 7 - access error (68040) */
124 	58,		/* type 8 - bus fault (68010) */
125 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
126 	FMTASIZE,	/* type A - short bus fault (68020/030) */
127 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
128 	-1, -1, -1, -1	/* type C-F - undefined */
129 };
130 
131 #ifdef M68060
132 #define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
133 #define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
134 #else
135 #define	KDFAULT_060(c)	0
136 #define	WRFAULT_060(c)	0
137 #endif
138 
139 #ifdef M68040
140 #define	KDFAULT_040(c)	(cputype == CPU_68040 && \
141 			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
142 #define	WRFAULT_040(c)	(cputype == CPU_68040 && \
143 			 ((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW)
144 #else
145 #define	KDFAULT_040(c)	0
146 #define	WRFAULT_040(c)	0
147 #endif
148 
149 #if defined(M68030) || defined(M68020)
150 #define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
151 			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
152 #define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
153 			 (((c) & SSW_DF) != 0 && \
154 			 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0))))
155 #else
156 #define	KDFAULT_OTH(c)	0
157 #define	WRFAULT_OTH(c)	0
158 #endif
159 
160 #define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
161 #define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
162 
163 #ifdef DEBUG
164 int mmudebug = 0;
165 int mmupid = -1;
166 #define MDB_FOLLOW	1
167 #define MDB_WBFOLLOW	2
168 #define MDB_WBFAILED	4
169 #define MDB_ISPID(p)	((p) == mmupid)
170 #endif
171 
172 /*
173  * trap and syscall both need the following work done before returning
174  * to user mode.
175  */
176 static inline void
userret(struct lwp * l,struct frame * fp,u_quad_t oticks,u_int faultaddr,int fromtrap)177 userret(struct lwp *l, struct frame *fp, u_quad_t oticks, u_int faultaddr,
178     int fromtrap)
179 {
180 	struct proc *p = l->l_proc;
181 #ifdef M68040
182 	int sig;
183 	int beenhere = 0;
184 
185 again:
186 #endif
187 	/* Invoke MI userret code */
188 	mi_userret(l);
189 
190 	/*
191 	 * If profiling, charge system time to the trapped pc.
192 	 */
193 	if (p->p_stflag & PST_PROFIL) {
194 		extern int psratio;
195 
196 		addupc_task(l, fp->f_pc,
197 			    (int)(p->p_sticks - oticks) * psratio);
198 	}
199 #ifdef M68040
200 	/*
201 	 * Deal with user mode writebacks (from trap, or from sigreturn).
202 	 * If any writeback fails, go back and attempt signal delivery.
203 	 * unless we have already been here and attempted the writeback
204 	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
205 	 * we just return to the user without successfully completing
206 	 * the writebacks.  Maybe we should just drop the sucker?
207 	 */
208 	if (cputype == CPU_68040 && fp->f_format == FMT7) {
209 		if (beenhere) {
210 #ifdef DEBUG
211 			if (mmudebug & MDB_WBFAILED)
212 				printf(fromtrap ?
213 		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
214 		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
215 				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
216 #endif
217 		} else if ((sig = m68040_writeback(fp, fromtrap))) {
218 			ksiginfo_t ksi;
219 			beenhere = 1;
220 			oticks = p->p_sticks;
221 			(void)memset(&ksi, 0, sizeof(ksi));
222 			ksi.ksi_signo = sig;
223 			ksi.ksi_addr = (void *)faultaddr;
224 			ksi.ksi_code = BUS_OBJERR;
225 			trapsignal(l, &ksi);
226 			goto again;
227 		}
228 	}
229 #endif
230 }
231 
232 /*
233  * Used by the common m68k syscall() and child_return() functions.
234  * XXX: Temporary until all m68k ports share common trap()/userret() code.
235  */
236 void machine_userret(struct lwp *, struct frame *, u_quad_t);
237 
238 void
machine_userret(struct lwp * l,struct frame * f,u_quad_t t)239 machine_userret(struct lwp *l, struct frame *f, u_quad_t t)
240 {
241 
242 	userret(l, f, t, 0, 0);
243 }
244 
245 /*
246  * Trap is called from locore to handle most types of processor traps,
247  * including events such as simulated software interrupts/AST's.
248  * System calls are broken out for efficiency.
249  */
250 /*ARGSUSED*/
251 void
trap(struct frame * fp,int type,unsigned code,unsigned v)252 trap(struct frame *fp, int type, unsigned code, unsigned v)
253 {
254 	struct lwp *l;
255 	struct proc *p;
256 	struct pcb *pcb;
257 	void *onfault;
258 	ksiginfo_t ksi;
259 	int s;
260 	int rv;
261 	u_quad_t sticks = 0 /* XXX initializer works around compiler bug */;
262 
263 	curcpu()->ci_data.cpu_ntrap++;
264 	l = curlwp;
265 	p = l->l_proc;
266 	pcb = lwp_getpcb(l);
267 	KASSERT(pcb != NULL);
268 
269 	KSI_INIT_TRAP(&ksi);
270 	ksi.ksi_trap = type & ~T_USER;
271 
272 	if (USERMODE(fp->f_sr)) {
273 		type |= T_USER;
274 		sticks = p->p_sticks;
275 		l->l_md.md_regs = fp->f_regs;
276 	}
277 	switch (type) {
278 
279 	default:
280 	dopanic:
281 		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
282 		printf("%s program counter = 0x%x\n",
283 		    (type & T_USER) ? "user" : "kernel", fp->f_pc);
284 		/*
285 		 * Let the kernel debugger see the trap frame that
286 		 * caused us to panic.  This is a convenience so
287 		 * one can see registers at the point of failure.
288 		 */
289 		s = splhigh();
290 #ifdef KGDB
291 		/* If connected, step or cont returns 1 */
292 		if (kgdb_trap(type, fp))
293 			goto kgdb_cont;
294 #endif
295 #ifdef DDB
296 		(void)kdb_trap(type, (db_regs_t *)fp);
297 #endif
298 #ifdef KGDB
299 	kgdb_cont:
300 #endif
301 		splx(s);
302 		if (panicstr) {
303 			printf("trap during panic!\n");
304 #ifdef DEBUG
305 			/* XXX should be a machine-dependent hook */
306 			printf("(press a key)\n");
307 			cnpollc(1);
308 			(void)cngetc();
309 			cnpollc(0);
310 #endif
311 		}
312 		regdump((struct trapframe *)fp, 128);
313 		type &= ~T_USER;
314 		if ((u_int)type < trap_types)
315 			panic(trap_type[type]);
316 		panic("trap");
317 
318 	case T_BUSERR:		/* kernel bus error */
319 		onfault = pcb->pcb_onfault;
320 		if (onfault == NULL)
321 			goto dopanic;
322 		rv = EFAULT;
323 		/* FALLTHROUGH */
324 
325 	copyfault:
326 		/*
327 		 * If we have arranged to catch this fault in any of the
328 		 * copy to/from user space routines, set PC to return to
329 		 * indicated location and set flag informing buserror code
330 		 * that it may need to clean up stack frame.
331 		 */
332 		fp->f_stackadj = exframesize[fp->f_format];
333 		fp->f_format = fp->f_vector = 0;
334 		fp->f_pc = (int)onfault;
335 		fp->f_regs[D0] = rv;
336 		return;
337 
338 	case T_BUSERR|T_USER:	/* bus error */
339 	case T_ADDRERR|T_USER:	/* address error */
340 		ksi.ksi_addr = (void *)v;
341 		ksi.ksi_signo = SIGBUS;
342 		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
343 			BUS_OBJERR : BUS_ADRERR;
344 		break;
345 
346 	case T_COPERR:		/* kernel coprocessor violation */
347 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
348 	case T_FMTERR:		/* ...just in case... */
349 	/*
350 	 * The user has most likely trashed the RTE or FP state info
351 	 * in the stack frame of a signal handler.
352 	 */
353 		printf("pid %d: kernel %s exception\n", p->p_pid,
354 		       type==T_COPERR ? "coprocessor" : "format");
355 		type |= T_USER;
356 
357 		mutex_enter(p->p_lock);
358 		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
359 		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
360 		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
361 		sigdelset(&l->l_sigmask, SIGILL);
362 		mutex_exit(p->p_lock);
363 
364 		ksi.ksi_signo = SIGILL;
365 		ksi.ksi_addr = (void *)(int)fp->f_format;
366 				/* XXX was ILL_RESAD_FAULT */
367 		ksi.ksi_code = (type == T_COPERR) ?
368 			ILL_COPROC : ILL_ILLOPC;
369 		break;
370 
371 	case T_COPERR|T_USER:	/* user coprocessor violation */
372 	/* What is a proper response here? */
373 		ksi.ksi_signo = SIGFPE;
374 		ksi.ksi_code = FPE_FLTINV;
375 		break;
376 
377 	case T_FPERR|T_USER:	/* 68881 exceptions */
378 	/*
379 	 * We pass along the 68881 status which locore stashed
380 	 * in code for us.
381 	 */
382 		ksi.ksi_signo = SIGFPE;
383 		ksi.ksi_code = fpsr2siginfocode(code);
384 		break;
385 
386 	/*
387 	 * FPU faults in supervisor mode.
388 	 */
389 	case T_ILLINST:	/* fnop generates this, apparently. */
390 	case T_FPEMULI:
391 	case T_FPEMULD: {
392 		extern label_t *nofault;
393 
394 		if (nofault)	/* If we're probing. */
395 			longjmp(nofault);
396 		if (type == T_ILLINST)
397 			printf("Kernel Illegal Instruction trap.\n");
398 		else
399 			printf("Kernel FPU trap.\n");
400 		goto dopanic;
401 	}
402 
403 	/*
404 	 * Unimplemented FPU instructions/datatypes.
405 	 */
406 	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
407 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
408 #ifdef FPU_EMULATE
409 		if (fpu_emulate(fp, &pcb->pcb_fpregs, &ksi) == 0)
410 			; /* XXX - Deal with tracing? (fp->f_sr & PSL_T) */
411 		break;
412 #elif defined(M68040) || defined(M68060)
413 		/* XXX need to FSAVE */
414 		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
415 		       p->p_pid, p->p_comm,
416 		       fp->f_format == 2 ? "instruction" : "data type",
417 		       fp->f_pc, fp->f_fmt2.f_iaddr);
418 		/* XXX need to FRESTORE */
419 		ksi.ksi_signo = SIGFPE;
420 		ksi.ksi_code = FPE_FLTINV;
421 		break;
422 #endif
423 
424 	case T_ILLINST|T_USER:	/* illegal instruction fault */
425 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
426 		ksi.ksi_addr = (void *)(int)fp->f_format;
427 				/* XXX was ILL_PRIVIN_FAULT */
428 		ksi.ksi_signo = SIGILL;
429 		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
430 			ILL_PRVOPC : ILL_ILLOPC;
431 		break;
432 
433 	case T_ZERODIV|T_USER:	/* Divide by zero */
434 		ksi.ksi_addr = (void *)(int)fp->f_format;
435 				/* XXX was FPE_INTDIV_TRAP */
436 		ksi.ksi_signo = SIGFPE;
437 		ksi.ksi_code = FPE_FLTDIV;
438 		break;
439 
440 	case T_CHKINST|T_USER:	/* CHK instruction trap */
441 		ksi.ksi_addr = (void *)(int)fp->f_format;
442 				/* XXX was FPE_SUBRNG_TRAP */
443 		ksi.ksi_signo = SIGFPE;
444 		break;
445 
446 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
447 		ksi.ksi_addr = (void *)(int)fp->f_format;
448 				/* XXX was FPE_INTOVF_TRAP */
449 		ksi.ksi_signo = SIGFPE;
450 		break;
451 
452 	/*
453 	 * XXX: Trace traps are a nightmare.
454 	 *
455 	 *	HP-UX uses trap #1 for breakpoints,
456 	 *	NetBSD/m68k uses trap #2,
457 	 *	SUN 3.x uses trap #15,
458 	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
459 	 *	handled elsewhere).
460 	 *
461 	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
462 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
463 	 * supported yet.
464 	 *
465 	 * XXX: We should never get kernel-mode T_TRAP15
466 	 * XXX: because locore.s now gives them special treatment.
467 	 */
468 	case T_TRAP15:		/* kernel breakpoint */
469 #ifdef DEBUG
470 		printf("unexpected kernel trace trap, type = %d\n", type);
471 		printf("program counter = 0x%x\n", fp->f_pc);
472 #endif
473 		fp->f_sr &= ~PSL_T;
474 		return;
475 
476 	case T_TRACE|T_USER:	/* user trace trap */
477 #ifdef COMPAT_SUNOS
478 		/*
479 		 * SunOS uses Trap #2 for a "CPU cache flush".
480 		 * Just flush the on-chip caches and return.
481 		 */
482 		if (p->p_emul == &emul_sunos) {
483 			ICIA();
484 			DCIU();
485 			return;
486 		}
487 #endif
488 		/* FALLTHROUGH */
489 	case T_TRACE:		/* tracing a trap instruction */
490 	case T_TRAP15|T_USER:	/* SUN user trace trap */
491 		fp->f_sr &= ~PSL_T;
492 		ksi.ksi_signo = SIGTRAP;
493 		break;
494 
495 	case T_ASTFLT:		/* system async trap, cannot happen */
496 		goto dopanic;
497 
498 	case T_ASTFLT|T_USER:	/* user async trap */
499 		astpending = 0;
500 		/*
501 		 * We check for software interrupts first.  This is because
502 		 * they are at a higher level than ASTs, and on a VAX would
503 		 * interrupt the AST.  We assume that if we are processing
504 		 * an AST that we must be at IPL0 so we don't bother to
505 		 * check.  Note that we ensure that we are at least at SIR
506 		 * IPL while processing the SIR.
507 		 */
508 		spl1();
509 		/* fall into... */
510 
511 	case T_SSIR:		/* software interrupt */
512 	case T_SSIR|T_USER:
513 		/*
514 		 * If this was not an AST trap, we are all done.
515 		 */
516 		if (type != (T_ASTFLT|T_USER)) {
517 			curcpu()->ci_data.cpu_ntrap--;
518 			return;
519 		}
520 		spl0();
521 		if (l->l_pflag & LP_OWEUPC) {
522 			l->l_pflag &= ~LP_OWEUPC;
523 			ADDUPROF(l);
524 		}
525 		goto out;
526 
527 	case T_MMUFLT:		/* kernel mode page fault */
528 	case T_MMUFLT|T_USER:	/* page fault */
529 	    {
530 		vaddr_t va;
531 		struct vmspace *vm = p->p_vmspace;
532 		struct vm_map *map;
533 		vm_prot_t ftype;
534 		extern struct vm_map *kernel_map;
535 
536 		onfault = pcb->pcb_onfault;
537 
538 #ifdef DEBUG
539 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
540 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
541 		       p->p_pid, code, v, fp->f_pc, fp->f_sr);
542 #endif
543 		/*
544 		 * It is only a kernel address space fault iff:
545 		 *	1. (type & T_USER) == 0  and
546 		 *	2. pcb_onfault not set or
547 		 *	3. pcb_onfault set but supervisor space data fault
548 		 * The last can occur during an exec() copyin where the
549 		 * argument space is lazy-allocated.
550 		 */
551 		if ((type & T_USER) == 0 && (onfault == NULL || KDFAULT(code)))
552 			map = kernel_map;
553 		else {
554 			map = vm ? &vm->vm_map : kernel_map;
555 		}
556 
557 		if (WRFAULT(code))
558 			ftype = VM_PROT_WRITE;
559 		else
560 			ftype = VM_PROT_READ;
561 
562 		va = trunc_page((vaddr_t)v);
563 
564 		if (map == kernel_map && va == 0) {
565 			printf("trap: bad kernel %s access at 0x%x\n",
566 			    (ftype & VM_PROT_WRITE) ? "read/write" :
567 			    "read", v);
568 			goto dopanic;
569 		}
570 
571 		pcb->pcb_onfault = NULL;
572 		rv = uvm_fault(map, va, ftype);
573 		pcb->pcb_onfault = onfault;
574 #ifdef DEBUG
575 		if (rv && MDB_ISPID(p->p_pid))
576 			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
577 			    map, va, ftype, rv);
578 #endif
579 		/*
580 		 * If this was a stack access we keep track of the maximum
581 		 * accessed stack size.  Also, if vm_fault gets a protection
582 		 * failure it is due to accessing the stack region outside
583 		 * the current limit and we need to reflect that as an access
584 		 * error.
585 		 */
586 		if (rv == 0) {
587 			if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
588 				uvm_grow(p, va);
589 
590 			if (type == T_MMUFLT) {
591 #ifdef M68040
592 				if (cputype == CPU_68040)
593 					(void) m68040_writeback(fp, 1);
594 #endif
595 				return;
596 			}
597 			goto out;
598 		}
599 		if (rv == EACCES) {
600 			ksi.ksi_code = SEGV_ACCERR;
601 			rv = EFAULT;
602 		} else
603 			ksi.ksi_code = SEGV_MAPERR;
604 		if (type == T_MMUFLT) {
605 			if (onfault)
606 				goto copyfault;
607 			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
608 			    map, va, ftype, rv);
609 			printf("  type %x, code [mmu,,ssw]: %x\n",
610 			       type, code);
611 			goto dopanic;
612 		}
613 		ksi.ksi_addr = (void *)v;
614 		switch (rv) {
615 		case ENOMEM:
616 			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
617 			       p->p_pid, p->p_comm,
618 			       l->l_cred ?
619 			       kauth_cred_geteuid(l->l_cred) : -1);
620 			ksi.ksi_signo = SIGKILL;
621 			break;
622 		case EINVAL:
623 			ksi.ksi_signo = SIGBUS;
624 			ksi.ksi_code = BUS_ADRERR;
625 			break;
626 		case EACCES:
627 			ksi.ksi_signo = SIGSEGV;
628 			ksi.ksi_code = SEGV_ACCERR;
629 			break;
630 		default:
631 			ksi.ksi_signo = SIGSEGV;
632 			ksi.ksi_code = SEGV_MAPERR;
633 			break;
634 		}
635 		break;
636 	    }
637 	}
638 	if (ksi.ksi_signo)
639 		trapsignal(l, &ksi);
640 	if ((type & T_USER) == 0)
641 		return;
642 out:
643 	userret(l, fp, sticks, v, 1);
644 }
645