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