trap.c revision 1.83
1/*	$NetBSD: trap.c,v 1.83 2011/01/17 14:53:43 tsutsui 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) 1982, 1986, 1990, 1993
12 *	The Regents of the University of California.  All rights reserved.
13 *
14 * This code is derived from software contributed to Berkeley by
15 * the Systems Programming Group of the University of Utah Computer
16 * Science Department.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 * 3. Neither the name of the University nor the names of its contributors
27 *    may be used to endorse or promote products derived from this software
28 *    without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 * from: Utah $Hdr: trap.c 1.37 92/12/20$
43 *
44 *	@(#)trap.c	8.5 (Berkeley) 1/4/94
45 */
46/*
47 * Copyright (c) 1988 University of Utah.
48 *
49 * This code is derived from software contributed to Berkeley by
50 * the Systems Programming Group of the University of Utah Computer
51 * Science Department.
52 *
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
55 * are met:
56 * 1. Redistributions of source code must retain the above copyright
57 *    notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 *    notice, this list of conditions and the following disclaimer in the
60 *    documentation and/or other materials provided with the distribution.
61 * 3. All advertising materials mentioning features or use of this software
62 *    must display the following acknowledgement:
63 *	This product includes software developed by the University of
64 *	California, Berkeley and its contributors.
65 * 4. Neither the name of the University nor the names of its contributors
66 *    may be used to endorse or promote products derived from this software
67 *    without specific prior written permission.
68 *
69 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
79 * SUCH DAMAGE.
80 *
81 * from: Utah $Hdr: trap.c 1.37 92/12/20$
82 *
83 *	@(#)trap.c	8.5 (Berkeley) 1/4/94
84 */
85
86#include <sys/cdefs.h>
87__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.83 2011/01/17 14:53:43 tsutsui Exp $");
88
89#include "opt_ddb.h"
90#include "opt_execfmt.h"
91#include "opt_kgdb.h"
92#include "opt_compat_sunos.h"
93#include "opt_m68k_arch.h"
94
95#include <sys/param.h>
96#include <sys/systm.h>
97#include <sys/proc.h>
98#include <sys/acct.h>
99#include <sys/kernel.h>
100#include <sys/signalvar.h>
101#include <sys/resourcevar.h>
102#include <sys/sa.h>
103#include <sys/savar.h>
104#include <sys/syscall.h>
105#include <sys/syslog.h>
106#include <sys/userret.h>
107#include <sys/kauth.h>
108
109#ifdef DEBUG
110#include <dev/cons.h>
111#endif
112
113#include <machine/db_machdep.h>
114#include <machine/pcb.h>
115#include <machine/psl.h>
116#include <machine/trap.h>
117#include <machine/cpu.h>
118#include <machine/reg.h>
119
120#include <m68k/cacheops.h>
121
122#include <uvm/uvm_extern.h>
123
124#ifdef COMPAT_SUNOS
125#include <compat/sunos/sunos_syscall.h>
126extern struct emul emul_sunos;
127#endif
128
129#ifdef KGDB
130#include <sys/kgdb.h>
131#endif
132
133int	writeback(struct frame *, int);
134void	trap(struct frame *, int, u_int, u_int);
135
136#ifdef DEBUG
137void	dumpssw(u_short);
138void	dumpwb(int, u_short, u_int, u_int);
139#endif
140
141static inline void userret(struct lwp *, struct frame *, u_quad_t, u_int, int);
142
143int	astpending;
144
145const char *trap_type[] = {
146	"Bus error",
147	"Address error",
148	"Illegal instruction",
149	"Zero divide",
150	"CHK instruction",
151	"TRAPV instruction",
152	"Privilege violation",
153	"Trace trap",
154	"MMU fault",
155	"SSIR trap",
156	"Format error",
157	"68881 exception",
158	"Coprocessor violation",
159	"Async system trap"
160};
161int	trap_types = sizeof trap_type / sizeof trap_type[0];
162
163/*
164 * Size of various exception stack frames (minus the standard 8 bytes)
165 */
166short	exframesize[] = {
167	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
168	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
169	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
170	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
171	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
172	-1, -1,		/* type 5-6 - undefined */
173	FMT7SIZE,	/* type 7 - access error (68040) */
174	58,		/* type 8 - bus fault (68010) */
175	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
176	FMTASIZE,	/* type A - short bus fault (68020/030) */
177	FMTBSIZE,	/* type B - long bus fault (68020/030) */
178	-1, -1, -1, -1	/* type C-F - undefined */
179};
180
181#ifdef M68060
182#define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
183#define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
184#else
185#define	KDFAULT_060(c)	0
186#define	WRFAULT_060(c)	0
187#endif
188
189#ifdef M68040
190#define	KDFAULT_040(c)	(cputype == CPU_68040 && \
191			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
192#define	WRFAULT_040(c)	(cputype == CPU_68040 && \
193			 ((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW)
194#else
195#define	KDFAULT_040(c)	0
196#define	WRFAULT_040(c)	0
197#endif
198
199#if defined(M68030) || defined(M68020)
200#define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
201			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
202#define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
203			 (((c) & SSW_DF) != 0 && \
204			 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0))))
205#else
206#define	KDFAULT_OTH(c)	0
207#define	WRFAULT_OTH(c)	0
208#endif
209
210#define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
211#define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
212
213#ifdef DEBUG
214int mmudebug = 0;
215int mmupid = -1;
216#define MDB_FOLLOW	1
217#define MDB_WBFOLLOW	2
218#define MDB_WBFAILED	4
219#define MDB_ISPID(p)	((p) == mmupid)
220#endif
221
222/*
223 * trap and syscall both need the following work done before returning
224 * to user mode.
225 */
226static inline void
227userret(struct lwp *l, struct frame *fp, u_quad_t oticks, u_int faultaddr,
228    int fromtrap)
229{
230	struct proc *p = l->l_proc;
231#ifdef M68040
232	int sig;
233	int beenhere = 0;
234
235again:
236#endif
237	/* Invoke MI userret code */
238	mi_userret(l);
239
240	/*
241	 * If profiling, charge system time to the trapped pc.
242	 */
243	if (p->p_stflag & PST_PROFIL) {
244		extern int psratio;
245
246		addupc_task(l, fp->f_pc,
247			    (int)(p->p_sticks - oticks) * psratio);
248	}
249#ifdef M68040
250	/*
251	 * Deal with user mode writebacks (from trap, or from sigreturn).
252	 * If any writeback fails, go back and attempt signal delivery.
253	 * unless we have already been here and attempted the writeback
254	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
255	 * we just return to the user without successfully completing
256	 * the writebacks.  Maybe we should just drop the sucker?
257	 */
258	if (cputype == CPU_68040 && fp->f_format == FMT7) {
259		if (beenhere) {
260#ifdef DEBUG
261			if (mmudebug & MDB_WBFAILED)
262				printf(fromtrap ?
263		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
264		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
265				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
266#endif
267		} else if ((sig = writeback(fp, fromtrap))) {
268			ksiginfo_t ksi;
269			beenhere = 1;
270			oticks = p->p_sticks;
271			(void)memset(&ksi, 0, sizeof(ksi));
272			ksi.ksi_signo = sig;
273			ksi.ksi_addr = (void *)faultaddr;
274			ksi.ksi_code = BUS_OBJERR;
275			trapsignal(l, &ksi);
276			goto again;
277		}
278	}
279#endif
280}
281
282/*
283 * Used by the common m68k syscall() and child_return() functions.
284 * XXX: Temporary until all m68k ports share common trap()/userret() code.
285 */
286void machine_userret(struct lwp *, struct frame *, u_quad_t);
287
288void
289machine_userret(struct lwp *l, struct frame *f, u_quad_t t)
290{
291
292	userret(l, f, t, 0, 0);
293}
294
295/*
296 * Trap is called from locore to handle most types of processor traps,
297 * including events such as simulated software interrupts/AST's.
298 * System calls are broken out for efficiency.
299 */
300/*ARGSUSED*/
301void
302trap(struct frame *fp, int type, unsigned code, unsigned v)
303{
304	extern char fubail[], subail[];
305	struct lwp *l;
306	struct proc *p;
307	struct pcb *pcb;
308	void *onfault;
309	ksiginfo_t ksi;
310	int s;
311	int rv;
312	u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */;
313	static int panicking = 0;
314
315	curcpu()->ci_data.cpu_ntrap++;
316	l = curlwp;
317	p = l->l_proc;
318	pcb = lwp_getpcb(l);
319
320	KSI_INIT_TRAP(&ksi);
321	ksi.ksi_trap = type & ~T_USER;
322
323	if (USERMODE(fp->f_sr)) {
324		type |= T_USER;
325		sticks = p->p_sticks;
326		l->l_md.md_regs = fp->f_regs;
327		LWP_CACHE_CREDS(l, p);
328	}
329	switch (type) {
330
331	default:
332	dopanic:
333		/*
334		 * Let the kernel debugger see the trap frame that
335		 * caused us to panic.  This is a convenience so
336		 * one can see registers at the point of failure.
337		 */
338		s = splhigh();
339		panicking = 1;
340		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
341		printf("%s program counter = 0x%x\n",
342		    (type & T_USER) ? "user" : "kernel", fp->f_pc);
343#ifdef KGDB
344		/* If connected, step or cont returns 1 */
345		if (kgdb_trap(type, (db_regs_t *)fp))
346			goto kgdb_cont;
347#endif
348#ifdef DDB
349		(void)kdb_trap(type, (db_regs_t *)fp);
350#endif
351#ifdef KGDB
352	kgdb_cont:
353#endif
354		splx(s);
355		if (panicstr) {
356			printf("trap during panic!\n");
357#ifdef DEBUG
358			/* XXX should be a machine-dependent hook */
359			printf("(press a key)\n"); (void)cngetc();
360#endif
361		}
362		regdump((struct trapframe *)fp, 128);
363		type &= ~T_USER;
364		if ((u_int)type < trap_types)
365			panic(trap_type[type]);
366		panic("trap");
367
368	case T_BUSERR:		/* kernel bus error */
369		onfault = pcb->pcb_onfault;
370		if (onfault == NULL)
371			goto dopanic;
372		rv = EFAULT;
373		/* FALLTHROUGH */
374
375	copyfault:
376		/*
377		 * If we have arranged to catch this fault in any of the
378		 * copy to/from user space routines, set PC to return to
379		 * indicated location and set flag informing buserror code
380		 * that it may need to clean up stack frame.
381		 */
382		fp->f_stackadj = exframesize[fp->f_format];
383		fp->f_format = fp->f_vector = 0;
384		fp->f_pc = (int)onfault;
385		fp->f_regs[D0] = rv;
386		return;
387
388	case T_BUSERR|T_USER:	/* bus error */
389	case T_ADDRERR|T_USER:	/* address error */
390		ksi.ksi_addr = (void *)v;
391		ksi.ksi_signo = SIGBUS;
392		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
393			BUS_OBJERR : BUS_ADRERR;
394		break;
395
396	case T_COPERR:		/* kernel coprocessor violation */
397	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
398	case T_FMTERR:		/* ...just in case... */
399	/*
400	 * The user has most likely trashed the RTE or FP state info
401	 * in the stack frame of a signal handler.
402	 */
403		printf("pid %d: kernel %s exception\n", p->p_pid,
404		       type==T_COPERR ? "coprocessor" : "format");
405		type |= T_USER;
406
407		mutex_enter(p->p_lock);
408		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
409		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
410		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
411		sigdelset(&l->l_sigmask, SIGILL);
412		mutex_exit(p->p_lock);
413
414		ksi.ksi_signo = SIGILL;
415		ksi.ksi_addr = (void *)(int)fp->f_format;
416				/* XXX was ILL_RESAD_FAULT */
417		ksi.ksi_code = (type == T_COPERR) ?
418			ILL_COPROC : ILL_ILLOPC;
419		break;
420
421	case T_COPERR|T_USER:	/* user coprocessor violation */
422	/* What is a proper response here? */
423		ksi.ksi_signo = SIGFPE;
424		ksi.ksi_code = FPE_FLTINV;
425		break;
426
427	case T_FPERR|T_USER:	/* 68881 exceptions */
428	/*
429	 * We pass along the 68881 status register which locore stashed
430	 * in code for us.
431	 */
432		ksi.ksi_signo = SIGFPE;
433		ksi.ksi_code = fpsr2siginfocode(code);
434		break;
435
436#ifdef M68040
437	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
438	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
439		/* XXX need to FSAVE */
440		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
441		       p->p_pid, p->p_comm,
442		       fp->f_format == 2 ? "instruction" : "data type",
443		       fp->f_pc, fp->f_fmt2.f_iaddr);
444		/* XXX need to FRESTORE */
445		ksi.ksi_signo = SIGFPE;
446		ksi.ksi_code = FPE_FLTINV;
447		break;
448#endif
449
450	case T_ILLINST|T_USER:	/* illegal instruction fault */
451	case T_PRIVINST|T_USER:	/* privileged instruction fault */
452		ksi.ksi_addr = (void *)(int)fp->f_format;
453				/* XXX was ILL_PRIVIN_FAULT */
454		ksi.ksi_signo = SIGILL;
455		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
456			ILL_PRVOPC : ILL_ILLOPC;
457		break;
458
459	case T_ZERODIV|T_USER:	/* Divide by zero */
460		ksi.ksi_addr = (void *)(int)fp->f_format;
461				/* XXX was FPE_INTDIV_TRAP */
462		ksi.ksi_signo = SIGFPE;
463		ksi.ksi_code = FPE_FLTDIV;
464		break;
465
466	case T_CHKINST|T_USER:	/* CHK instruction trap */
467		ksi.ksi_addr = (void *)(int)fp->f_format;
468				/* XXX was FPE_SUBRNG_TRAP */
469		ksi.ksi_signo = SIGFPE;
470		break;
471
472	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
473		ksi.ksi_addr = (void *)(int)fp->f_format;
474				/* XXX was FPE_INTOVF_TRAP */
475		ksi.ksi_signo = SIGFPE;
476		break;
477
478	/*
479	 * XXX: Trace traps are a nightmare.
480	 *
481	 *	HP-UX uses trap #1 for breakpoints,
482	 *	NetBSD/m68k uses trap #2,
483	 *	SUN 3.x uses trap #15,
484	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
485	 *	handled elsewhere).
486	 *
487	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
488	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
489	 * supported yet.
490	 *
491	 * XXX: We should never get kernel-mode T_TRAP15
492	 * XXX: because locore.s now gives them special treatment.
493	 */
494	case T_TRAP15:		/* kernel breakpoint */
495#ifdef DEBUG
496		printf("unexpected kernel trace trap, type = %d\n", type);
497		printf("program counter = 0x%x\n", fp->f_pc);
498#endif
499		fp->f_sr &= ~PSL_T;
500		return;
501
502	case T_TRACE|T_USER:	/* user trace trap */
503#ifdef COMPAT_SUNOS
504		/*
505		 * SunOS uses Trap #2 for a "CPU cache flush".
506		 * Just flush the on-chip caches and return.
507		 */
508		if (p->p_emul == &emul_sunos) {
509			ICIA();
510			DCIU();
511			return;
512		}
513#endif
514		/* FALLTHROUGH */
515	case T_TRACE:		/* tracing a trap instruction */
516	case T_TRAP15|T_USER:	/* SUN user trace trap */
517		fp->f_sr &= ~PSL_T;
518		ksi.ksi_signo = SIGTRAP;
519		break;
520
521	case T_ASTFLT:		/* system async trap, cannot happen */
522		goto dopanic;
523
524	case T_ASTFLT|T_USER:	/* user async trap */
525		astpending = 0;
526		/*
527		 * We check for software interrupts first.  This is because
528		 * they are at a higher level than ASTs, and on a VAX would
529		 * interrupt the AST.  We assume that if we are processing
530		 * an AST that we must be at IPL0 so we don't bother to
531		 * check.  Note that we ensure that we are at least at SIR
532		 * IPL while processing the SIR.
533		 */
534		spl1();
535		/* fall into... */
536
537	case T_SSIR:		/* software interrupt */
538	case T_SSIR|T_USER:
539		/*
540		 * If this was not an AST trap, we are all done.
541		 */
542		if (type != (T_ASTFLT|T_USER)) {
543			curcpu()->ci_data.cpu_ntrap--;
544			return;
545		}
546		spl0();
547		if (l->l_pflag & LP_OWEUPC) {
548			l->l_pflag &= ~LP_OWEUPC;
549			ADDUPROF(l);
550		}
551		if (curcpu()->ci_want_resched)
552			preempt();
553		goto out;
554
555	case T_MMUFLT:		/* kernel mode page fault */
556		/*
557		 * If we were doing profiling ticks or other user mode
558		 * stuff from interrupt code, Just Say No.
559		 */
560		onfault = pcb->pcb_onfault;
561		if (onfault == fubail || onfault == subail) {
562			rv = EFAULT;
563			goto copyfault;
564		}
565		/* fall into ... */
566
567	case T_MMUFLT|T_USER:	/* page fault */
568	    {
569		vaddr_t va;
570		struct vmspace *vm = p->p_vmspace;
571		struct vm_map *map;
572		vm_prot_t ftype;
573		extern struct vm_map *kernel_map;
574
575		onfault = pcb->pcb_onfault;
576
577#ifdef DEBUG
578		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
579		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
580		       p->p_pid, code, v, fp->f_pc, fp->f_sr);
581#endif
582		/*
583		 * It is only a kernel address space fault iff:
584		 * 	1. (type & T_USER) == 0  and
585		 * 	2. pcb_onfault not set or
586		 *	3. pcb_onfault set but supervisor space data fault
587		 * The last can occur during an exec() copyin where the
588		 * argument space is lazy-allocated.
589		 */
590		if ((type & T_USER) == 0 && (onfault == NULL || KDFAULT(code)))
591			map = kernel_map;
592		else {
593			map = vm ? &vm->vm_map : kernel_map;
594			if ((l->l_flag & LW_SA)
595			    && (~l->l_pflag & LP_SA_NOBLOCK)) {
596				l->l_savp->savp_faultaddr = (vaddr_t)v;
597				l->l_pflag |= LP_SA_PAGEFAULT;
598			}
599		}
600
601		if (WRFAULT(code))
602			ftype = VM_PROT_WRITE;
603		else
604			ftype = VM_PROT_READ;
605
606		va = trunc_page((vaddr_t)v);
607
608		if (map == kernel_map && va == 0) {
609			printf("trap: bad kernel %s access at 0x%x\n",
610			    (ftype & VM_PROT_WRITE) ? "read/write" :
611			    "read", v);
612			goto dopanic;
613		}
614
615#ifdef DIAGNOSTIC
616		if (interrupt_depth && !panicking) {
617			printf("trap: calling uvm_fault() from interrupt!\n");
618			goto dopanic;
619		}
620#endif
621
622		pcb->pcb_onfault = NULL;
623		rv = uvm_fault(map, va, ftype);
624		pcb->pcb_onfault = onfault;
625#ifdef DEBUG
626		if (rv && MDB_ISPID(p->p_pid))
627			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
628			    map, va, ftype, rv);
629#endif
630		/*
631		 * If this was a stack access we keep track of the maximum
632		 * accessed stack size.  Also, if vm_fault gets a protection
633		 * failure it is due to accessing the stack region outside
634		 * the current limit and we need to reflect that as an access
635		 * error.
636		 */
637		if (rv == 0) {
638			if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
639				uvm_grow(p, va);
640
641			if (type == T_MMUFLT) {
642				if (ucas_ras_check(&fp->F_t)) {
643					return;
644				}
645#ifdef M68040
646				if (cputype == CPU_68040)
647					(void) writeback(fp, 1);
648#endif
649				return;
650			}
651			l->l_pflag &= ~LP_SA_PAGEFAULT;
652			goto out;
653		}
654		if (rv == EACCES) {
655			ksi.ksi_code = SEGV_ACCERR;
656			rv = EFAULT;
657		} else
658			ksi.ksi_code = SEGV_MAPERR;
659		if (type == T_MMUFLT) {
660			if (onfault)
661				goto copyfault;
662			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
663			    map, va, ftype, rv);
664			printf("  type %x, code [mmu,,ssw]: %x\n",
665			       type, code);
666			goto dopanic;
667		}
668		l->l_pflag &= ~LP_SA_PAGEFAULT;
669		ksi.ksi_addr = (void *)v;
670		if (rv == ENOMEM) {
671			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
672			       p->p_pid, p->p_comm,
673			       l->l_cred ?
674			       kauth_cred_geteuid(l->l_cred) : -1);
675			ksi.ksi_signo = SIGKILL;
676		} else {
677			ksi.ksi_signo = SIGSEGV;
678		}
679		break;
680	    }
681	}
682	trapsignal(l, &ksi);
683	if ((type & T_USER) == 0)
684		return;
685out:
686	userret(l, fp, sticks, v, 1);
687}
688
689#ifdef M68040
690#ifdef DEBUG
691struct writebackstats {
692	int calls;
693	int cpushes;
694	int move16s;
695	int wb1s, wb2s, wb3s;
696	int wbsize[4];
697} wbstats;
698
699const char *f7sz[] = { "longword", "byte", "word", "line" };
700const char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
701const char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
702		 "M-code", "k-data", "k-code", "RES" };
703const char wberrstr[] =
704    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
705#endif
706
707int
708writeback(struct frame *fp, int docachepush)
709{
710	struct fmt7 *f = &fp->f_fmt7;
711	struct lwp *l = curlwp;
712	struct proc *p = l->l_proc;
713	struct pcb *pcb = lwp_getpcb(l);
714	int err = 0;
715	u_int fa;
716	void *oonfault = pcb->pcb_onfault;
717	paddr_t pa;
718
719#ifdef DEBUG
720	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
721		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
722		dumpssw(f->f_ssw);
723	}
724	wbstats.calls++;
725#endif
726	/*
727	 * Deal with special cases first.
728	 */
729	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
730		/*
731		 * Dcache push fault.
732		 * Line-align the address and write out the push data to
733		 * the indicated physical address.
734		 */
735#ifdef DEBUG
736		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
737			printf(" pushing %s to PA %x, data %x",
738			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
739			       f->f_fa, f->f_pd0);
740			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
741				printf("/%x/%x/%x",
742				       f->f_pd1, f->f_pd2, f->f_pd3);
743			printf("\n");
744		}
745		if (f->f_wb1s & SSW4_WBSV)
746			panic("writeback: cache push with WB1S valid");
747		wbstats.cpushes++;
748#endif
749		/*
750		 * XXX there are security problems if we attempt to do a
751		 * cache push after a signal handler has been called.
752		 */
753		if (docachepush) {
754			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
755			    trunc_page(f->f_fa), VM_PROT_WRITE,
756			    VM_PROT_WRITE|PMAP_WIRED);
757			pmap_update(pmap_kernel());
758			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
759			memcpy((void *)fa, (void *)&f->f_pd0, 16);
760			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
761			DCFL(pa);
762			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
763				    (vaddr_t)&vmmap[PAGE_SIZE]);
764			pmap_update(pmap_kernel());
765		} else
766			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
767			       p->p_pid, p->p_comm, kauth_cred_geteuid(l->l_cred));
768	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
769		/*
770		 * MOVE16 fault.
771		 * Line-align the address and write out the push data to
772		 * the indicated virtual address.
773		 */
774#ifdef DEBUG
775		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
776			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
777			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
778			       f->f_pd2, f->f_pd3);
779		if (f->f_wb1s & SSW4_WBSV)
780			panic("writeback: MOVE16 with WB1S valid");
781		wbstats.move16s++;
782#endif
783		if (KDFAULT(f->f_wb1s))
784			memcpy((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0, 16);
785		else
786			err = suline((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0);
787		if (err) {
788			fa = f->f_fa & ~0xF;
789#ifdef DEBUG
790			if (mmudebug & MDB_WBFAILED)
791				printf(wberrstr, p->p_pid, p->p_comm,
792				       "MOVE16", fp->f_pc, f->f_fa,
793				       f->f_fa & ~0xF, f->f_pd0);
794#endif
795		}
796	} else if (f->f_wb1s & SSW4_WBSV) {
797		/*
798		 * Writeback #1.
799		 * Position the "memory-aligned" data and write it out.
800		 */
801		u_int wb1d = f->f_wb1d;
802		int off;
803
804#ifdef DEBUG
805		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
806			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
807		wbstats.wb1s++;
808		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
809#endif
810		off = (f->f_wb1a & 3) * 8;
811		switch (f->f_wb1s & SSW4_SZMASK) {
812		case SSW4_SZLW:
813			if (off)
814				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
815			if (KDFAULT(f->f_wb1s))
816				*(long *)f->f_wb1a = wb1d;
817			else
818				err = suword((void *)f->f_wb1a, wb1d);
819			break;
820		case SSW4_SZB:
821			off = 24 - off;
822			if (off)
823				wb1d >>= off;
824			if (KDFAULT(f->f_wb1s))
825				*(char *)f->f_wb1a = wb1d;
826			else
827				err = subyte((void *)f->f_wb1a, wb1d);
828			break;
829		case SSW4_SZW:
830			off = (off + 16) % 32;
831			if (off)
832				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
833			if (KDFAULT(f->f_wb1s))
834				*(short *)f->f_wb1a = wb1d;
835			else
836				err = susword((void *)f->f_wb1a, wb1d);
837			break;
838		}
839		if (err) {
840			fa = f->f_wb1a;
841#ifdef DEBUG
842			if (mmudebug & MDB_WBFAILED)
843				printf(wberrstr, p->p_pid, p->p_comm,
844				       "#1", fp->f_pc, f->f_fa,
845				       f->f_wb1a, f->f_wb1d);
846#endif
847		}
848	}
849	/*
850	 * Deal with the "normal" writebacks.
851	 *
852	 * XXX writeback2 is known to reflect a LINE size writeback after
853	 * a MOVE16 was already dealt with above.  Ignore it.
854	 */
855	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
856	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
857#ifdef DEBUG
858		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
859			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
860		wbstats.wb2s++;
861		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
862#endif
863		switch (f->f_wb2s & SSW4_SZMASK) {
864		case SSW4_SZLW:
865			if (KDFAULT(f->f_wb2s))
866				*(long *)f->f_wb2a = f->f_wb2d;
867			else
868				err = suword((void *)f->f_wb2a, f->f_wb2d);
869			break;
870		case SSW4_SZB:
871			if (KDFAULT(f->f_wb2s))
872				*(char *)f->f_wb2a = f->f_wb2d;
873			else
874				err = subyte((void *)f->f_wb2a, f->f_wb2d);
875			break;
876		case SSW4_SZW:
877			if (KDFAULT(f->f_wb2s))
878				*(short *)f->f_wb2a = f->f_wb2d;
879			else
880				err = susword((void *)f->f_wb2a, f->f_wb2d);
881			break;
882		}
883		if (err) {
884			fa = f->f_wb2a;
885#ifdef DEBUG
886			if (mmudebug & MDB_WBFAILED) {
887				printf(wberrstr, p->p_pid, p->p_comm,
888				       "#2", fp->f_pc, f->f_fa,
889				       f->f_wb2a, f->f_wb2d);
890				dumpssw(f->f_ssw);
891				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
892			}
893#endif
894		}
895	}
896	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
897#ifdef DEBUG
898		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
899			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
900		wbstats.wb3s++;
901		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
902#endif
903		switch (f->f_wb3s & SSW4_SZMASK) {
904		case SSW4_SZLW:
905			if (KDFAULT(f->f_wb3s))
906				*(long *)f->f_wb3a = f->f_wb3d;
907			else
908				err = suword((void *)f->f_wb3a, f->f_wb3d);
909			break;
910		case SSW4_SZB:
911			if (KDFAULT(f->f_wb3s))
912				*(char *)f->f_wb3a = f->f_wb3d;
913			else
914				err = subyte((void *)f->f_wb3a, f->f_wb3d);
915			break;
916		case SSW4_SZW:
917			if (KDFAULT(f->f_wb3s))
918				*(short *)f->f_wb3a = f->f_wb3d;
919			else
920				err = susword((void *)f->f_wb3a, f->f_wb3d);
921			break;
922#ifdef DEBUG
923		case SSW4_SZLN:
924			panic("writeback: wb3s indicates LINE write");
925#endif
926		}
927		if (err) {
928			fa = f->f_wb3a;
929#ifdef DEBUG
930			if (mmudebug & MDB_WBFAILED)
931				printf(wberrstr, p->p_pid, p->p_comm,
932				       "#3", fp->f_pc, f->f_fa,
933				       f->f_wb3a, f->f_wb3d);
934#endif
935		}
936	}
937	pcb->pcb_onfault = oonfault;
938	if (err)
939		err = SIGSEGV;
940	return (err);
941}
942
943#ifdef DEBUG
944void
945dumpssw(u_short ssw)
946{
947	printf(" SSW: %x: ", ssw);
948	if (ssw & SSW4_CP)
949		printf("CP,");
950	if (ssw & SSW4_CU)
951		printf("CU,");
952	if (ssw & SSW4_CT)
953		printf("CT,");
954	if (ssw & SSW4_CM)
955		printf("CM,");
956	if (ssw & SSW4_MA)
957		printf("MA,");
958	if (ssw & SSW4_ATC)
959		printf("ATC,");
960	if (ssw & SSW4_LK)
961		printf("LK,");
962	if (ssw & SSW4_RW)
963		printf("RW,");
964	printf(" SZ=%s, TT=%s, TM=%s\n",
965	       f7sz[(ssw & SSW4_SZMASK) >> 5],
966	       f7tt[(ssw & SSW4_TTMASK) >> 3],
967	       f7tm[ssw & SSW4_TMMASK]);
968}
969
970void
971dumpwb(int num, u_short s, u_int a, u_int d)
972{
973	struct proc *p = curproc;
974	paddr_t pa;
975
976	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
977	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
978	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
979	printf("               PA ");
980	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == false)
981		printf("<invalid address>");
982	else
983		printf("%lx, current value %lx", pa, fuword((void *)a));
984	printf("\n");
985}
986#endif
987#endif
988