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