xref: /netbsd-src/sys/arch/mvme68k/mvme68k/trap.c (revision c13a5359d541fd49b4c406f5b12209b1640235a5)
1 /*	$NetBSD: trap.c,v 1.117 2024/01/20 00:15:32 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.117 2024/01/20 00:15:32 thorpej 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
userret(struct lwp * l,struct frame * fp,u_quad_t oticks,u_int faultaddr,int fromtrap)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
machine_userret(struct lwp * l,struct frame * f,u_quad_t t)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
trap(struct frame * fp,int type,unsigned int code,unsigned int v)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 		break;
509 
510 	case T_ASTFLT:		/* system async trap, cannot happen */
511 		goto dopanic;
512 
513 	case T_ASTFLT|T_USER:	/* user async trap */
514 		astpending = 0;
515 		if (l->l_pflag & LP_OWEUPC) {
516 			l->l_pflag &= ~LP_OWEUPC;
517 			ADDUPROF(l);
518 		}
519 		goto out;
520 
521 	case T_MMUFLT:		/* kernel mode page fault */
522 	case T_MMUFLT|T_USER:	/* page fault */
523 	    {
524 		vaddr_t va;
525 		struct vmspace *vm = p->p_vmspace;
526 		struct vm_map *map;
527 		vm_prot_t ftype;
528 		extern struct vm_map *kernel_map;
529 
530 		onfault = pcb->pcb_onfault;
531 #ifdef DEBUG
532 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
533 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
534 		       p->p_pid, code, v, fp->f_pc, fp->f_sr);
535 #endif
536 		/*
537 		 * It is only a kernel address space fault iff:
538 		 * 	1. (type & T_USER) == 0  and
539 		 * 	2. pcb_onfault not set or
540 		 *	3. pcb_onfault set but supervisor space data fault
541 		 * The last can occur during an exec() copyin where the
542 		 * argument space is lazy-allocated.
543 		 */
544 		if ((type & T_USER) == 0 && (onfault == NULL || KDFAULT(code)))
545 			map = kernel_map;
546 		else {
547 			map = vm ? &vm->vm_map : kernel_map;
548 		}
549 
550 		if (WRFAULT(code))
551 			ftype = VM_PROT_WRITE;
552 		else
553 			ftype = VM_PROT_READ;
554 
555 		va = trunc_page((vaddr_t)v);
556 
557 		if (map == kernel_map && va == 0) {
558 			printf("trap: bad kernel %s access at 0x%x\n",
559 			    (ftype & VM_PROT_WRITE) ? "read/write" :
560 			    "read", v);
561 			goto dopanic;
562 		}
563 
564 #ifdef DIAGNOSTIC
565 		if (intr_depth && !panicking) {
566 			printf("trap: calling uvm_fault() from interrupt!\n");
567 			goto dopanic;
568 		}
569 #endif
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 defined(M68030) || defined(M68060)
593 				if (cputype == CPU_68040)
594 #endif
595 					(void)m68040_writeback(fp, 1);
596 #endif
597 				return;
598 			}
599 			goto out;
600 		}
601 		if (rv == EACCES) {
602 			ksi.ksi_code = SEGV_ACCERR;
603 			rv = EFAULT;
604 		} else
605 			ksi.ksi_code = SEGV_MAPERR;
606 		if (type == T_MMUFLT) {
607 			if (onfault)
608 				goto copyfault;
609 			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
610 			    map, va, ftype, rv);
611 			printf("  type %x, code [mmu,,ssw]: %x\n",
612 			       type, code);
613 			goto dopanic;
614 		}
615 		ksi.ksi_addr = (void *)v;
616 		switch (rv) {
617 		case ENOMEM:
618 			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
619 			       p->p_pid, p->p_comm,
620 			       l->l_cred ?
621 			       kauth_cred_geteuid(l->l_cred) : -1);
622 			ksi.ksi_signo = SIGKILL;
623 			break;
624 		case EINVAL:
625 			ksi.ksi_signo = SIGBUS;
626 			ksi.ksi_code = BUS_ADRERR;
627 			break;
628 		case EACCES:
629 			ksi.ksi_signo = SIGSEGV;
630 			ksi.ksi_code = SEGV_ACCERR;
631 			break;
632 		default:
633 			ksi.ksi_signo = SIGSEGV;
634 			ksi.ksi_code = SEGV_MAPERR;
635 			break;
636 		}
637 		break;
638 	    }
639 	}
640 	trapsignal(l, &ksi);
641 	if ((type & T_USER) == 0)
642 		return;
643 out:
644 	userret(l, fp, sticks, v, 1);
645 }
646