trap.c revision 1.68
11.68Smhitch/*	$NetBSD: trap.c,v 1.68 2007/09/01 21:31:56 mhitch Exp $	*/
21.7Sdbj
31.7Sdbj/*
41.10Sabs * This file was taken from mvme68k/mvme68k/trap.c
51.7Sdbj * should probably be re-synced when needed.
61.16Sdbj * Darrin B. Jewell <jewell@mit.edu> Tue Aug  3 10:53:12 UTC 1999
71.16Sdbj * original cvs id: NetBSD: trap.c,v 1.32 1999/08/03 10:52:06 dbj Exp
81.7Sdbj */
91.1Sdbj
101.1Sdbj/*
111.1Sdbj * Copyright (c) 1982, 1986, 1990, 1993
121.1Sdbj *	The Regents of the University of California.  All rights reserved.
131.1Sdbj *
141.1Sdbj * This code is derived from software contributed to Berkeley by
151.1Sdbj * the Systems Programming Group of the University of Utah Computer
161.1Sdbj * Science Department.
171.1Sdbj *
181.1Sdbj * Redistribution and use in source and binary forms, with or without
191.1Sdbj * modification, are permitted provided that the following conditions
201.1Sdbj * are met:
211.1Sdbj * 1. Redistributions of source code must retain the above copyright
221.1Sdbj *    notice, this list of conditions and the following disclaimer.
231.1Sdbj * 2. Redistributions in binary form must reproduce the above copyright
241.1Sdbj *    notice, this list of conditions and the following disclaimer in the
251.1Sdbj *    documentation and/or other materials provided with the distribution.
261.43Sagc * 3. Neither the name of the University nor the names of its contributors
271.43Sagc *    may be used to endorse or promote products derived from this software
281.43Sagc *    without specific prior written permission.
291.43Sagc *
301.43Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
311.43Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
321.43Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
331.43Sagc * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
341.43Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
351.43Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
361.43Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
371.43Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
381.43Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
391.43Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
401.43Sagc * SUCH DAMAGE.
411.43Sagc *
421.43Sagc * from: Utah $Hdr: trap.c 1.37 92/12/20$
431.43Sagc *
441.43Sagc *	@(#)trap.c	8.5 (Berkeley) 1/4/94
451.43Sagc */
461.43Sagc/*
471.43Sagc * Copyright (c) 1988 University of Utah.
481.43Sagc *
491.43Sagc * This code is derived from software contributed to Berkeley by
501.43Sagc * the Systems Programming Group of the University of Utah Computer
511.43Sagc * Science Department.
521.43Sagc *
531.43Sagc * Redistribution and use in source and binary forms, with or without
541.43Sagc * modification, are permitted provided that the following conditions
551.43Sagc * are met:
561.43Sagc * 1. Redistributions of source code must retain the above copyright
571.43Sagc *    notice, this list of conditions and the following disclaimer.
581.43Sagc * 2. Redistributions in binary form must reproduce the above copyright
591.43Sagc *    notice, this list of conditions and the following disclaimer in the
601.43Sagc *    documentation and/or other materials provided with the distribution.
611.1Sdbj * 3. All advertising materials mentioning features or use of this software
621.1Sdbj *    must display the following acknowledgement:
631.1Sdbj *	This product includes software developed by the University of
641.1Sdbj *	California, Berkeley and its contributors.
651.1Sdbj * 4. Neither the name of the University nor the names of its contributors
661.1Sdbj *    may be used to endorse or promote products derived from this software
671.1Sdbj *    without specific prior written permission.
681.1Sdbj *
691.1Sdbj * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
701.1Sdbj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
711.1Sdbj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
721.1Sdbj * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
731.1Sdbj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
741.1Sdbj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
751.1Sdbj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
761.1Sdbj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
771.1Sdbj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
781.1Sdbj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
791.1Sdbj * SUCH DAMAGE.
801.1Sdbj *
811.1Sdbj * from: Utah $Hdr: trap.c 1.37 92/12/20$
821.1Sdbj *
831.1Sdbj *	@(#)trap.c	8.5 (Berkeley) 1/4/94
841.1Sdbj */
851.42Slukem
861.42Slukem#include <sys/cdefs.h>
871.68Smhitch__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.68 2007/09/01 21:31:56 mhitch Exp $");
881.2Sthorpej
891.5Sjonathan#include "opt_ddb.h"
901.9Sitohy#include "opt_execfmt.h"
911.33Slukem#include "opt_kgdb.h"
921.3Sthorpej#include "opt_compat_sunos.h"
931.4Sthorpej#include "opt_compat_hpux.h"
941.1Sdbj
951.1Sdbj#include <sys/param.h>
961.1Sdbj#include <sys/systm.h>
971.1Sdbj#include <sys/proc.h>
981.1Sdbj#include <sys/acct.h>
991.1Sdbj#include <sys/kernel.h>
1001.1Sdbj#include <sys/signalvar.h>
1011.1Sdbj#include <sys/resourcevar.h>
1021.1Sdbj#include <sys/syscall.h>
1031.1Sdbj#include <sys/syslog.h>
1041.1Sdbj#include <sys/user.h>
1051.47Scl#include <sys/userret.h>
1061.59Syamt#include <sys/kauth.h>
1071.16Sdbj
1081.16Sdbj#ifdef DEBUG
1091.16Sdbj#include <dev/cons.h>
1101.14Sdbj#endif
1111.1Sdbj
1121.16Sdbj#include <machine/db_machdep.h>
1131.1Sdbj#include <machine/psl.h>
1141.1Sdbj#include <machine/trap.h>
1151.1Sdbj#include <machine/cpu.h>
1161.1Sdbj#include <machine/reg.h>
1171.1Sdbj
1181.16Sdbj#include <m68k/cacheops.h>
1191.16Sdbj
1201.7Sdbj#include <uvm/uvm_extern.h>
1211.1Sdbj
1221.1Sdbj#ifdef COMPAT_HPUX
1231.1Sdbj#include <compat/hpux/hpux.h>
1241.1Sdbj#endif
1251.1Sdbj
1261.1Sdbj#ifdef COMPAT_SUNOS
1271.1Sdbj#include <compat/sunos/sunos_syscall.h>
1281.1Sdbjextern struct emul emul_sunos;
1291.1Sdbj#endif
1301.1Sdbj
1311.37Sjdolecek#ifdef KGDB
1321.37Sjdolecek#include <sys/kgdb.h>
1331.37Sjdolecek#endif
1341.37Sjdolecek
1351.53Schsint	writeback(struct frame *, int);
1361.67Smhitchvoid	trap(struct frame *, int, u_int, u_int);
1371.16Sdbj
1381.16Sdbj#ifdef DEBUG
1391.53Schsvoid	dumpssw(u_short);
1401.53Schsvoid	dumpwb(int, u_short, u_int, u_int);
1411.16Sdbj#endif
1421.16Sdbj
1431.53Schsstatic inline void userret(struct lwp *, struct frame *, u_quad_t, u_int, int);
1441.1Sdbj
1451.7Sdbjint	astpending;
1461.1Sdbj
1471.54Sheconst char *trap_type[] = {
1481.1Sdbj	"Bus error",
1491.1Sdbj	"Address error",
1501.1Sdbj	"Illegal instruction",
1511.1Sdbj	"Zero divide",
1521.1Sdbj	"CHK instruction",
1531.1Sdbj	"TRAPV instruction",
1541.1Sdbj	"Privilege violation",
1551.1Sdbj	"Trace trap",
1561.1Sdbj	"MMU fault",
1571.1Sdbj	"SSIR trap",
1581.1Sdbj	"Format error",
1591.1Sdbj	"68881 exception",
1601.1Sdbj	"Coprocessor violation",
1611.1Sdbj	"Async system trap"
1621.1Sdbj};
1631.1Sdbjint	trap_types = sizeof trap_type / sizeof trap_type[0];
1641.1Sdbj
1651.1Sdbj/*
1661.1Sdbj * Size of various exception stack frames (minus the standard 8 bytes)
1671.1Sdbj */
1681.1Sdbjshort	exframesize[] = {
1691.16Sdbj	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
1701.1Sdbj	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
1711.16Sdbj	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
1721.16Sdbj	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
1731.16Sdbj	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
1741.16Sdbj	-1, -1,		/* type 5-6 - undefined */
1751.1Sdbj	FMT7SIZE,	/* type 7 - access error (68040) */
1761.1Sdbj	58,		/* type 8 - bus fault (68010) */
1771.1Sdbj	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
1781.1Sdbj	FMTASIZE,	/* type A - short bus fault (68020/030) */
1791.1Sdbj	FMTBSIZE,	/* type B - long bus fault (68020/030) */
1801.1Sdbj	-1, -1, -1, -1	/* type C-F - undefined */
1811.1Sdbj};
1821.1Sdbj
1831.16Sdbj#ifdef M68060
1841.16Sdbj#define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
1851.16Sdbj#define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
1861.16Sdbj#else
1871.16Sdbj#define	KDFAULT_060(c)	0
1881.16Sdbj#define	WRFAULT_060(c)	0
1891.16Sdbj#endif
1901.16Sdbj
1911.1Sdbj#ifdef M68040
1921.16Sdbj#define	KDFAULT_040(c)	(cputype == CPU_68040 && \
1931.16Sdbj			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
1941.16Sdbj#define	WRFAULT_040(c)	(cputype == CPU_68040 && \
1951.68Smhitch			 ((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW)
1961.16Sdbj#else
1971.16Sdbj#define	KDFAULT_040(c)	0
1981.16Sdbj#define	WRFAULT_040(c)	0
1991.16Sdbj#endif
2001.16Sdbj
2011.16Sdbj#if defined(M68030) || defined(M68020)
2021.16Sdbj#define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
2031.16Sdbj			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
2041.16Sdbj#define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
2051.68Smhitch			 (((c) & SSW_DF) != 0 && \
2061.68Smhitch			 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0))))
2071.1Sdbj#else
2081.16Sdbj#define	KDFAULT_OTH(c)	0
2091.16Sdbj#define	WRFAULT_OTH(c)	0
2101.1Sdbj#endif
2111.1Sdbj
2121.16Sdbj#define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
2131.16Sdbj#define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
2141.16Sdbj
2151.1Sdbj#ifdef DEBUG
2161.1Sdbjint mmudebug = 0;
2171.1Sdbjint mmupid = -1;
2181.1Sdbj#define MDB_FOLLOW	1
2191.1Sdbj#define MDB_WBFOLLOW	2
2201.1Sdbj#define MDB_WBFAILED	4
2211.16Sdbj#define MDB_ISPID(p)	((p) == mmupid)
2221.1Sdbj#endif
2231.1Sdbj
2241.1Sdbj/*
2251.1Sdbj * trap and syscall both need the following work done before returning
2261.1Sdbj * to user mode.
2271.1Sdbj */
2281.1Sdbjstatic inline void
2291.53Schsuserret(struct lwp *l, struct frame *fp, u_quad_t oticks, u_int faultaddr,
2301.53Schs    int fromtrap)
2311.1Sdbj{
2321.39Sthorpej	struct proc *p = l->l_proc;
2331.48Scl#ifdef M68040
2341.20Sthorpej	int sig;
2351.1Sdbj	int beenhere = 0;
2361.1Sdbj
2371.1Sdbjagain:
2381.1Sdbj#endif
2391.47Scl	/* Invoke MI userret code */
2401.47Scl	mi_userret(l);
2411.1Sdbj
2421.1Sdbj	/*
2431.1Sdbj	 * If profiling, charge system time to the trapped pc.
2441.1Sdbj	 */
2451.62Sad	if (p->p_stflag & PST_PROFIL) {
2461.1Sdbj		extern int psratio;
2471.1Sdbj
2481.62Sad		addupc_task(l, fp->f_pc,
2491.1Sdbj			    (int)(p->p_sticks - oticks) * psratio);
2501.1Sdbj	}
2511.1Sdbj#ifdef M68040
2521.1Sdbj	/*
2531.1Sdbj	 * Deal with user mode writebacks (from trap, or from sigreturn).
2541.1Sdbj	 * If any writeback fails, go back and attempt signal delivery.
2551.1Sdbj	 * unless we have already been here and attempted the writeback
2561.1Sdbj	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
2571.40Swiz	 * we just return to the user without successfully completing
2581.1Sdbj	 * the writebacks.  Maybe we should just drop the sucker?
2591.1Sdbj	 */
2601.16Sdbj	if (cputype == CPU_68040 && fp->f_format == FMT7) {
2611.1Sdbj		if (beenhere) {
2621.1Sdbj#ifdef DEBUG
2631.1Sdbj			if (mmudebug & MDB_WBFAILED)
2641.1Sdbj				printf(fromtrap ?
2651.1Sdbj		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
2661.1Sdbj		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
2671.1Sdbj				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
2681.1Sdbj#endif
2691.16Sdbj		} else if ((sig = writeback(fp, fromtrap))) {
2701.45Scl			ksiginfo_t ksi;
2711.1Sdbj			beenhere = 1;
2721.1Sdbj			oticks = p->p_sticks;
2731.45Scl			(void)memset(&ksi, 0, sizeof(ksi));
2741.45Scl			ksi.ksi_signo = sig;
2751.45Scl			ksi.ksi_addr = (void *)faultaddr;
2761.45Scl			ksi.ksi_code = BUS_OBJERR;
2771.45Scl			trapsignal(l, &ksi);
2781.1Sdbj			goto again;
2791.1Sdbj		}
2801.1Sdbj	}
2811.1Sdbj#endif
2821.39Sthorpej	curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri;
2831.1Sdbj}
2841.1Sdbj
2851.1Sdbj/*
2861.28Sscw * Used by the common m68k syscall() and child_return() functions.
2871.28Sscw * XXX: Temporary until all m68k ports share common trap()/userret() code.
2881.28Sscw */
2891.39Sthorpejvoid machine_userret(struct lwp *, struct frame *, u_quad_t);
2901.28Sscw
2911.28Sscwvoid
2921.53Schsmachine_userret(struct lwp *l, struct frame *f, u_quad_t t)
2931.28Sscw{
2941.28Sscw
2951.39Sthorpej	userret(l, f, t, 0, 0);
2961.28Sscw}
2971.28Sscw
2981.28Sscw/*
2991.1Sdbj * Trap is called from locore to handle most types of processor traps,
3001.1Sdbj * including events such as simulated software interrupts/AST's.
3011.1Sdbj * System calls are broken out for efficiency.
3021.1Sdbj */
3031.1Sdbj/*ARGSUSED*/
3041.16Sdbjvoid
3051.67Smhitchtrap(struct frame *fp, int type, unsigned code, unsigned v)
3061.1Sdbj{
3071.1Sdbj	extern char fubail[], subail[];
3081.39Sthorpej	struct lwp *l;
3091.1Sdbj	struct proc *p;
3101.45Scl	ksiginfo_t ksi;
3111.45Scl	int s;
3121.16Sdbj	u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */;
3131.51Swiz	static int panicking = 0;
3141.1Sdbj
3151.7Sdbj	uvmexp.traps++;
3161.39Sthorpej	l = curlwp;
3171.45Scl
3181.46Sthorpej	KSI_INIT_TRAP(&ksi);
3191.45Scl	ksi.ksi_trap = type & ~T_USER;
3201.16Sdbj
3211.39Sthorpej	p = l->l_proc;
3221.39Sthorpej
3231.16Sdbj#ifdef DIAGNOSTIC
3241.39Sthorpej	if (l->l_addr == NULL)
3251.16Sdbj		panic("trap: no pcb");
3261.16Sdbj#endif
3271.16Sdbj
3281.67Smhitch	if (USERMODE(fp->f_sr)) {
3291.1Sdbj		type |= T_USER;
3301.1Sdbj		sticks = p->p_sticks;
3311.67Smhitch		l->l_md.md_regs = fp->f_regs;
3321.60Sad		LWP_CACHE_CREDS(l, p);
3331.1Sdbj	}
3341.1Sdbj	switch (type) {
3351.1Sdbj
3361.1Sdbj	default:
3371.14Sdbj	dopanic:
3381.14Sdbj		/*
3391.14Sdbj		 * Let the kernel debugger see the trap frame that
3401.14Sdbj		 * caused us to panic.  This is a convenience so
3411.14Sdbj		 * one can see registers at the point of failure.
3421.14Sdbj		 */
3431.16Sdbj		s = splhigh();
3441.51Swiz		panicking = 1;
3451.38Smycroft		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
3461.38Smycroft		printf("%s program counter = 0x%x\n",
3471.67Smhitch		    (type & T_USER) ? "user" : "kernel", fp->f_pc);
3481.14Sdbj#ifdef KGDB
3491.14Sdbj		/* If connected, step or cont returns 1 */
3501.67Smhitch		if (kgdb_trap(type, (db_regs_t *)fp))
3511.14Sdbj			goto kgdb_cont;
3521.14Sdbj#endif
3531.16Sdbj#ifdef DDB
3541.67Smhitch		(void)kdb_trap(type, (db_regs_t *)fp);
3551.1Sdbj#endif
3561.14Sdbj#ifdef KGDB
3571.14Sdbj	kgdb_cont:
3581.14Sdbj#endif
3591.16Sdbj		splx(s);
3601.14Sdbj		if (panicstr) {
3611.16Sdbj			printf("trap during panic!\n");
3621.16Sdbj#ifdef DEBUG
3631.16Sdbj			/* XXX should be a machine-dependent hook */
3641.16Sdbj			printf("(press a key)\n"); (void)cngetc();
3651.16Sdbj#endif
3661.14Sdbj		}
3671.67Smhitch		regdump((struct trapframe *)fp, 128);
3681.1Sdbj		type &= ~T_USER;
3691.16Sdbj		if ((u_int)type < trap_types)
3701.1Sdbj			panic(trap_type[type]);
3711.1Sdbj		panic("trap");
3721.1Sdbj
3731.1Sdbj	case T_BUSERR:		/* kernel bus error */
3741.39Sthorpej		if (l->l_addr->u_pcb.pcb_onfault == 0)
3751.1Sdbj			goto dopanic;
3761.16Sdbj		/* FALLTHROUGH */
3771.16Sdbj
3781.16Sdbj	copyfault:
3791.1Sdbj		/*
3801.1Sdbj		 * If we have arranged to catch this fault in any of the
3811.1Sdbj		 * copy to/from user space routines, set PC to return to
3821.1Sdbj		 * indicated location and set flag informing buserror code
3831.1Sdbj		 * that it may need to clean up stack frame.
3841.1Sdbj		 */
3851.67Smhitch		fp->f_stackadj = exframesize[fp->f_format];
3861.67Smhitch		fp->f_format = fp->f_vector = 0;
3871.67Smhitch		fp->f_pc = (int) l->l_addr->u_pcb.pcb_onfault;
3881.1Sdbj		return;
3891.1Sdbj
3901.1Sdbj	case T_BUSERR|T_USER:	/* bus error */
3911.1Sdbj	case T_ADDRERR|T_USER:	/* address error */
3921.45Scl		ksi.ksi_addr = (void *)v;
3931.45Scl		ksi.ksi_signo = SIGBUS;
3941.45Scl		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
3951.45Scl			BUS_OBJERR : BUS_ADRERR;
3961.1Sdbj		break;
3971.1Sdbj
3981.1Sdbj	case T_COPERR:		/* kernel coprocessor violation */
3991.1Sdbj	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
4001.1Sdbj	case T_FMTERR:		/* ...just in case... */
4011.1Sdbj	/*
4021.1Sdbj	 * The user has most likely trashed the RTE or FP state info
4031.1Sdbj	 * in the stack frame of a signal handler.
4041.1Sdbj	 */
4051.1Sdbj		printf("pid %d: kernel %s exception\n", p->p_pid,
4061.1Sdbj		       type==T_COPERR ? "coprocessor" : "format");
4071.1Sdbj		type |= T_USER;
4081.62Sad
4091.62Sad		mutex_enter(&p->p_smutex);
4101.29Sjdolecek		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
4111.29Sjdolecek		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
4121.29Sjdolecek		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
4131.62Sad		sigdelset(&l->l_sigmask, SIGILL);
4141.62Sad		mutex_exit(&p->p_smutex);
4151.62Sad
4161.45Scl		ksi.ksi_signo = SIGILL;
4171.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
4181.45Scl				/* XXX was ILL_RESAD_FAULT */
4191.45Scl		ksi.ksi_code = (type == T_COPERR) ?
4201.45Scl			ILL_COPROC : ILL_ILLOPC;
4211.1Sdbj		break;
4221.1Sdbj
4231.1Sdbj	case T_COPERR|T_USER:	/* user coprocessor violation */
4241.1Sdbj	/* What is a proper response here? */
4251.45Scl		ksi.ksi_signo = SIGFPE;
4261.45Scl		ksi.ksi_code = FPE_FLTINV;
4271.1Sdbj		break;
4281.1Sdbj
4291.1Sdbj	case T_FPERR|T_USER:	/* 68881 exceptions */
4301.1Sdbj	/*
4311.7Sdbj	 * We pass along the 68881 status register which locore stashed
4321.1Sdbj	 * in code for us.  Note that there is a possibility that the
4331.7Sdbj	 * bit pattern of this register will conflict with one of the
4341.1Sdbj	 * FPE_* codes defined in signal.h.  Fortunately for us, the
4351.1Sdbj	 * only such codes we use are all in the range 1-7 and the low
4361.7Sdbj	 * 3 bits of the status register are defined as 0 so there is
4371.1Sdbj	 * no clash.
4381.1Sdbj	 */
4391.45Scl		ksi.ksi_signo = SIGFPE;
4401.45Scl		ksi.ksi_addr = (void *)code;
4411.1Sdbj		break;
4421.1Sdbj
4431.1Sdbj#ifdef M68040
4441.56Swiz	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
4451.1Sdbj	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
4461.1Sdbj		/* XXX need to FSAVE */
4471.1Sdbj		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
4481.1Sdbj		       p->p_pid, p->p_comm,
4491.67Smhitch		       fp->f_format == 2 ? "instruction" : "data type",
4501.67Smhitch		       fp->f_pc, fp->f_fmt2.f_iaddr);
4511.1Sdbj		/* XXX need to FRESTORE */
4521.45Scl		ksi.ksi_signo = SIGFPE;
4531.45Scl		ksi.ksi_code = FPE_FLTINV;
4541.1Sdbj		break;
4551.1Sdbj#endif
4561.1Sdbj
4571.1Sdbj	case T_ILLINST|T_USER:	/* illegal instruction fault */
4581.1Sdbj#ifdef COMPAT_HPUX
4591.1Sdbj		if (p->p_emul == &emul_hpux) {
4601.45Scl			ksi.ksi_addr = (void *)HPUX_ILL_ILLINST_TRAP;
4611.45Scl			ksi.ksi_signo = SIGILL;
4621.1Sdbj			break;
4631.1Sdbj		}
4641.1Sdbj		/* fall through */
4651.1Sdbj#endif
4661.1Sdbj	case T_PRIVINST|T_USER:	/* privileged instruction fault */
4671.1Sdbj#ifdef COMPAT_HPUX
4681.1Sdbj		if (p->p_emul == &emul_hpux)
4691.45Scl			ksi.ksi_addr = (void *)HPUX_ILL_PRIV_TRAP;
4701.1Sdbj		else
4711.1Sdbj#endif
4721.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
4731.45Scl				/* XXX was ILL_PRIVIN_FAULT */
4741.45Scl		ksi.ksi_signo = SIGILL;
4751.45Scl		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
4761.45Scl			ILL_PRVOPC : ILL_ILLOPC;
4771.1Sdbj		break;
4781.1Sdbj
4791.1Sdbj	case T_ZERODIV|T_USER:	/* Divide by zero */
4801.1Sdbj#ifdef COMPAT_HPUX
4811.1Sdbj		if (p->p_emul == &emul_hpux)
4821.45Scl			ksi.ksi_addr = (void *)HPUX_FPE_INTDIV_TRAP;
4831.1Sdbj		else
4841.1Sdbj#endif
4851.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
4861.45Scl				/* XXX was FPE_INTDIV_TRAP */
4871.45Scl		ksi.ksi_signo = SIGFPE;
4881.45Scl		ksi.ksi_code = FPE_FLTDIV;
4891.1Sdbj		break;
4901.1Sdbj
4911.1Sdbj	case T_CHKINST|T_USER:	/* CHK instruction trap */
4921.1Sdbj#ifdef COMPAT_HPUX
4931.1Sdbj		if (p->p_emul == &emul_hpux) {
4941.1Sdbj			/* handled differently under hp-ux */
4951.45Scl			ksi.ksi_signo = SIGILL;
4961.45Scl			ksi.ksi_addr = (void *)HPUX_ILL_CHK_TRAP;
4971.1Sdbj			break;
4981.1Sdbj		}
4991.1Sdbj#endif
5001.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
5011.45Scl				/* XXX was FPE_SUBRNG_TRAP */
5021.45Scl		ksi.ksi_signo = SIGFPE;
5031.1Sdbj		break;
5041.1Sdbj
5051.1Sdbj	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
5061.1Sdbj#ifdef COMPAT_HPUX
5071.1Sdbj		if (p->p_emul == &emul_hpux) {
5081.1Sdbj			/* handled differently under hp-ux */
5091.45Scl			ksi.ksi_signo = SIGILL;
5101.45Scl			ksi.ksi_addr = (void *)HPUX_ILL_TRAPV_TRAP;
5111.1Sdbj			break;
5121.1Sdbj		}
5131.1Sdbj#endif
5141.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
5151.45Scl				/* XXX was FPE_INTOVF_TRAP */
5161.45Scl		ksi.ksi_signo = SIGFPE;
5171.1Sdbj		break;
5181.1Sdbj
5191.1Sdbj	/*
5201.1Sdbj	 * XXX: Trace traps are a nightmare.
5211.1Sdbj	 *
5221.1Sdbj	 *	HP-UX uses trap #1 for breakpoints,
5231.16Sdbj	 *	NetBSD/m68k uses trap #2,
5241.1Sdbj	 *	SUN 3.x uses trap #15,
5251.16Sdbj	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
5261.16Sdbj	 *	handled elsewhere).
5271.1Sdbj	 *
5281.16Sdbj	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
5291.1Sdbj	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
5301.1Sdbj	 * supported yet.
5311.16Sdbj	 *
5321.17Sitohy	 * XXX: We should never get kernel-mode T_TRAP15
5331.16Sdbj	 * XXX: because locore.s now gives them special treatment.
5341.1Sdbj	 */
5351.16Sdbj	case T_TRAP15:		/* kernel breakpoint */
5361.16Sdbj#ifdef DEBUG
5371.16Sdbj		printf("unexpected kernel trace trap, type = %d\n", type);
5381.67Smhitch		printf("program counter = 0x%x\n", fp->f_pc);
5391.1Sdbj#endif
5401.67Smhitch		fp->f_sr &= ~PSL_T;
5411.16Sdbj		return;
5421.1Sdbj
5431.1Sdbj	case T_TRACE|T_USER:	/* user trace trap */
5441.1Sdbj#ifdef COMPAT_SUNOS
5451.1Sdbj		/*
5461.1Sdbj		 * SunOS uses Trap #2 for a "CPU cache flush".
5471.1Sdbj		 * Just flush the on-chip caches and return.
5481.1Sdbj		 */
5491.1Sdbj		if (p->p_emul == &emul_sunos) {
5501.1Sdbj			ICIA();
5511.1Sdbj			DCIU();
5521.1Sdbj			return;
5531.1Sdbj		}
5541.16Sdbj#endif
5551.17Sitohy		/* FALLTHROUGH */
5561.17Sitohy	case T_TRACE:		/* tracing a trap instruction */
5571.17Sitohy	case T_TRAP15|T_USER:	/* SUN user trace trap */
5581.67Smhitch		fp->f_sr &= ~PSL_T;
5591.45Scl		ksi.ksi_signo = SIGTRAP;
5601.1Sdbj		break;
5611.1Sdbj
5621.1Sdbj	case T_ASTFLT:		/* system async trap, cannot happen */
5631.1Sdbj		goto dopanic;
5641.1Sdbj
5651.1Sdbj	case T_ASTFLT|T_USER:	/* user async trap */
5661.1Sdbj		astpending = 0;
5671.1Sdbj		/*
5681.1Sdbj		 * We check for software interrupts first.  This is because
5691.1Sdbj		 * they are at a higher level than ASTs, and on a VAX would
5701.1Sdbj		 * interrupt the AST.  We assume that if we are processing
5711.1Sdbj		 * an AST that we must be at IPL0 so we don't bother to
5721.1Sdbj		 * check.  Note that we ensure that we are at least at SIR
5731.1Sdbj		 * IPL while processing the SIR.
5741.1Sdbj		 */
5751.1Sdbj		spl1();
5761.1Sdbj		/* fall into... */
5771.1Sdbj
5781.1Sdbj	case T_SSIR:		/* software interrupt */
5791.1Sdbj	case T_SSIR|T_USER:
5801.65Stsutsui
5811.65Stsutsui		softintr_dispatch();
5821.65Stsutsui
5831.1Sdbj		/*
5841.1Sdbj		 * If this was not an AST trap, we are all done.
5851.1Sdbj		 */
5861.1Sdbj		if (type != (T_ASTFLT|T_USER)) {
5871.16Sdbj			uvmexp.traps--;
5881.1Sdbj			return;
5891.1Sdbj		}
5901.1Sdbj		spl0();
5911.62Sad		if (l->l_pflag & LP_OWEUPC) {
5921.62Sad			l->l_pflag &= ~LP_OWEUPC;
5931.62Sad			ADDUPROF(l);
5941.1Sdbj		}
5951.66Stsutsui		if (curcpu()->ci_want_resched)
5961.62Sad			preempt();
5971.1Sdbj		goto out;
5981.1Sdbj
5991.1Sdbj	case T_MMUFLT:		/* kernel mode page fault */
6001.1Sdbj		/*
6011.1Sdbj		 * If we were doing profiling ticks or other user mode
6021.1Sdbj		 * stuff from interrupt code, Just Say No.
6031.1Sdbj		 */
6041.39Sthorpej		if (l->l_addr->u_pcb.pcb_onfault == fubail ||
6051.39Sthorpej		    l->l_addr->u_pcb.pcb_onfault == subail)
6061.1Sdbj			goto copyfault;
6071.1Sdbj		/* fall into ... */
6081.1Sdbj
6091.1Sdbj	case T_MMUFLT|T_USER:	/* page fault */
6101.1Sdbj	    {
6111.7Sdbj		vaddr_t va;
6121.1Sdbj		struct vmspace *vm = p->p_vmspace;
6131.34Schs		struct vm_map *map;
6141.1Sdbj		int rv;
6151.1Sdbj		vm_prot_t ftype;
6161.34Schs		extern struct vm_map *kernel_map;
6171.1Sdbj
6181.1Sdbj#ifdef DEBUG
6191.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
6201.1Sdbj		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
6211.67Smhitch		       p->p_pid, code, v, fp->f_pc, fp->f_sr);
6221.1Sdbj#endif
6231.1Sdbj		/*
6241.1Sdbj		 * It is only a kernel address space fault iff:
6251.1Sdbj		 * 	1. (type & T_USER) == 0  and
6261.1Sdbj		 * 	2. pcb_onfault not set or
6271.1Sdbj		 *	3. pcb_onfault set but supervisor space data fault
6281.1Sdbj		 * The last can occur during an exec() copyin where the
6291.1Sdbj		 * argument space is lazy-allocated.
6301.1Sdbj		 */
6311.16Sdbj		if ((type & T_USER) == 0 &&
6321.39Sthorpej		    ((l->l_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code)))
6331.1Sdbj			map = kernel_map;
6341.62Sad		else
6351.16Sdbj			map = vm ? &vm->vm_map : kernel_map;
6361.16Sdbj
6371.1Sdbj		if (WRFAULT(code))
6381.36Schs			ftype = VM_PROT_WRITE;
6391.1Sdbj		else
6401.1Sdbj			ftype = VM_PROT_READ;
6411.16Sdbj
6421.7Sdbj		va = trunc_page((vaddr_t)v);
6431.16Sdbj
6441.1Sdbj		if (map == kernel_map && va == 0) {
6451.16Sdbj			printf("trap: bad kernel %s access at 0x%x\n",
6461.16Sdbj			    (ftype & VM_PROT_WRITE) ? "read/write" :
6471.16Sdbj			    "read", v);
6481.1Sdbj			goto dopanic;
6491.1Sdbj		}
6501.16Sdbj
6511.38Smycroft#ifdef DIAGNOSTIC
6521.51Swiz		if (interrupt_depth && !panicking) {
6531.38Smycroft			printf("trap: calling uvm_fault() from interrupt!\n");
6541.38Smycroft			goto dopanic;
6551.38Smycroft		}
6561.38Smycroft#endif
6571.38Smycroft
6581.1Sdbj#ifdef COMPAT_HPUX
6591.1Sdbj		if (ISHPMMADDR(va)) {
6601.53Schs			int pmap_mapmulti(pmap_t, vaddr_t);
6611.7Sdbj			vaddr_t bva;
6621.1Sdbj
6631.1Sdbj			rv = pmap_mapmulti(map->pmap, va);
6641.31Schs			if (rv != 0) {
6651.1Sdbj				bva = HPMMBASEADDR(va);
6661.57Sdrochner				rv = uvm_fault(map, bva, ftype);
6671.31Schs				if (rv == 0)
6681.1Sdbj					(void) pmap_mapmulti(map->pmap, va);
6691.1Sdbj			}
6701.1Sdbj		} else
6711.1Sdbj#endif
6721.57Sdrochner		rv = uvm_fault(map, va, ftype);
6731.7Sdbj#ifdef DEBUG
6741.7Sdbj		if (rv && MDB_ISPID(p->p_pid))
6751.57Sdrochner			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
6761.16Sdbj			    map, va, ftype, rv);
6771.7Sdbj#endif
6781.1Sdbj		/*
6791.1Sdbj		 * If this was a stack access we keep track of the maximum
6801.1Sdbj		 * accessed stack size.  Also, if vm_fault gets a protection
6811.1Sdbj		 * failure it is due to accessing the stack region outside
6821.1Sdbj		 * the current limit and we need to reflect that as an access
6831.1Sdbj		 * error.
6841.1Sdbj		 */
6851.31Schs		if (rv == 0) {
6861.64Schristos			if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
6871.52Sjdolecek				uvm_grow(p, va);
6881.52Sjdolecek
6891.1Sdbj			if (type == T_MMUFLT) {
6901.16Sdbj#ifdef M68040
6911.16Sdbj				if (cputype == CPU_68040)
6921.67Smhitch					(void) writeback(fp, 1);
6931.1Sdbj#endif
6941.1Sdbj				return;
6951.1Sdbj			}
6961.1Sdbj			goto out;
6971.1Sdbj		}
6981.45Scl		if (rv == EACCES) {
6991.45Scl			ksi.ksi_code = SEGV_ACCERR;
7001.45Scl			rv = EFAULT;
7011.45Scl		} else
7021.45Scl			ksi.ksi_code = SEGV_MAPERR;
7031.1Sdbj		if (type == T_MMUFLT) {
7041.39Sthorpej			if (l->l_addr->u_pcb.pcb_onfault)
7051.1Sdbj				goto copyfault;
7061.57Sdrochner			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
7071.16Sdbj			    map, va, ftype, rv);
7081.1Sdbj			printf("  type %x, code [mmu,,ssw]: %x\n",
7091.1Sdbj			       type, code);
7101.1Sdbj			goto dopanic;
7111.1Sdbj		}
7121.45Scl		ksi.ksi_addr = (void *)v;
7131.31Schs		if (rv == ENOMEM) {
7141.11Schs			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
7151.11Schs			       p->p_pid, p->p_comm,
7161.61Sad			       l->l_cred ?
7171.61Sad			       kauth_cred_geteuid(l->l_cred) : -1);
7181.45Scl			ksi.ksi_signo = SIGKILL;
7191.11Schs		} else {
7201.45Scl			ksi.ksi_signo = SIGSEGV;
7211.11Schs		}
7221.1Sdbj		break;
7231.1Sdbj	    }
7241.1Sdbj	}
7251.45Scl	trapsignal(l, &ksi);
7261.1Sdbj	if ((type & T_USER) == 0)
7271.1Sdbj		return;
7281.1Sdbjout:
7291.67Smhitch	userret(l, fp, sticks, v, 1);
7301.1Sdbj}
7311.1Sdbj
7321.1Sdbj#ifdef M68040
7331.1Sdbj#ifdef DEBUG
7341.1Sdbjstruct writebackstats {
7351.1Sdbj	int calls;
7361.1Sdbj	int cpushes;
7371.1Sdbj	int move16s;
7381.1Sdbj	int wb1s, wb2s, wb3s;
7391.1Sdbj	int wbsize[4];
7401.1Sdbj} wbstats;
7411.1Sdbj
7421.54Sheconst char *f7sz[] = { "longword", "byte", "word", "line" };
7431.54Sheconst char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
7441.54Sheconst char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
7451.1Sdbj		 "M-code", "k-data", "k-code", "RES" };
7461.54Sheconst char wberrstr[] =
7471.16Sdbj    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
7481.1Sdbj#endif
7491.1Sdbj
7501.16Sdbjint
7511.53Schswriteback(struct frame *fp, int docachepush)
7521.1Sdbj{
7531.1Sdbj	struct fmt7 *f = &fp->f_fmt7;
7541.39Sthorpej	struct lwp *l = curlwp;
7551.39Sthorpej	struct proc *p = l->l_proc;
7561.1Sdbj	int err = 0;
7571.1Sdbj	u_int fa;
7581.64Schristos	void *oonfault = l->l_addr->u_pcb.pcb_onfault;
7591.15Sthorpej	paddr_t pa;
7601.1Sdbj
7611.1Sdbj#ifdef DEBUG
7621.1Sdbj	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
7631.1Sdbj		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
7641.1Sdbj		dumpssw(f->f_ssw);
7651.1Sdbj	}
7661.1Sdbj	wbstats.calls++;
7671.1Sdbj#endif
7681.1Sdbj	/*
7691.1Sdbj	 * Deal with special cases first.
7701.1Sdbj	 */
7711.1Sdbj	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
7721.1Sdbj		/*
7731.1Sdbj		 * Dcache push fault.
7741.1Sdbj		 * Line-align the address and write out the push data to
7751.1Sdbj		 * the indicated physical address.
7761.1Sdbj		 */
7771.1Sdbj#ifdef DEBUG
7781.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
7791.1Sdbj			printf(" pushing %s to PA %x, data %x",
7801.1Sdbj			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
7811.1Sdbj			       f->f_fa, f->f_pd0);
7821.1Sdbj			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
7831.1Sdbj				printf("/%x/%x/%x",
7841.1Sdbj				       f->f_pd1, f->f_pd2, f->f_pd3);
7851.1Sdbj			printf("\n");
7861.1Sdbj		}
7871.1Sdbj		if (f->f_wb1s & SSW4_WBSV)
7881.1Sdbj			panic("writeback: cache push with WB1S valid");
7891.1Sdbj		wbstats.cpushes++;
7901.1Sdbj#endif
7911.1Sdbj		/*
7921.1Sdbj		 * XXX there are security problems if we attempt to do a
7931.1Sdbj		 * cache push after a signal handler has been called.
7941.1Sdbj		 */
7951.1Sdbj		if (docachepush) {
7961.7Sdbj			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
7971.18Sthorpej			    trunc_page(f->f_fa), VM_PROT_WRITE,
7981.18Sthorpej			    VM_PROT_WRITE|PMAP_WIRED);
7991.35Schris			pmap_update(pmap_kernel());
8001.1Sdbj			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
8011.64Schristos			bcopy((void *)&f->f_pd0, (void *)fa, 16);
8021.15Sthorpej			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
8031.15Sthorpej			DCFL(pa);
8041.7Sdbj			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
8051.41Sthorpej				    (vaddr_t)&vmmap[PAGE_SIZE]);
8061.35Schris			pmap_update(pmap_kernel());
8071.1Sdbj		} else
8081.1Sdbj			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
8091.61Sad			       p->p_pid, p->p_comm, kauth_cred_geteuid(l->l_cred));
8101.1Sdbj	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
8111.1Sdbj		/*
8121.1Sdbj		 * MOVE16 fault.
8131.1Sdbj		 * Line-align the address and write out the push data to
8141.1Sdbj		 * the indicated virtual address.
8151.1Sdbj		 */
8161.1Sdbj#ifdef DEBUG
8171.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
8181.1Sdbj			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
8191.1Sdbj			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
8201.1Sdbj			       f->f_pd2, f->f_pd3);
8211.1Sdbj		if (f->f_wb1s & SSW4_WBSV)
8221.1Sdbj			panic("writeback: MOVE16 with WB1S valid");
8231.1Sdbj		wbstats.move16s++;
8241.1Sdbj#endif
8251.1Sdbj		if (KDFAULT(f->f_wb1s))
8261.64Schristos			bcopy((void *)&f->f_pd0, (void *)(f->f_fa & ~0xF), 16);
8271.1Sdbj		else
8281.64Schristos			err = suline((void *)(f->f_fa & ~0xF), (void *)&f->f_pd0);
8291.1Sdbj		if (err) {
8301.1Sdbj			fa = f->f_fa & ~0xF;
8311.1Sdbj#ifdef DEBUG
8321.1Sdbj			if (mmudebug & MDB_WBFAILED)
8331.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8341.1Sdbj				       "MOVE16", fp->f_pc, f->f_fa,
8351.1Sdbj				       f->f_fa & ~0xF, f->f_pd0);
8361.1Sdbj#endif
8371.1Sdbj		}
8381.1Sdbj	} else if (f->f_wb1s & SSW4_WBSV) {
8391.1Sdbj		/*
8401.1Sdbj		 * Writeback #1.
8411.1Sdbj		 * Position the "memory-aligned" data and write it out.
8421.1Sdbj		 */
8431.1Sdbj		u_int wb1d = f->f_wb1d;
8441.1Sdbj		int off;
8451.1Sdbj
8461.1Sdbj#ifdef DEBUG
8471.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
8481.1Sdbj			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
8491.1Sdbj		wbstats.wb1s++;
8501.1Sdbj		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
8511.1Sdbj#endif
8521.1Sdbj		off = (f->f_wb1a & 3) * 8;
8531.1Sdbj		switch (f->f_wb1s & SSW4_SZMASK) {
8541.1Sdbj		case SSW4_SZLW:
8551.1Sdbj			if (off)
8561.1Sdbj				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
8571.1Sdbj			if (KDFAULT(f->f_wb1s))
8581.1Sdbj				*(long *)f->f_wb1a = wb1d;
8591.1Sdbj			else
8601.64Schristos				err = suword((void *)f->f_wb1a, wb1d);
8611.1Sdbj			break;
8621.1Sdbj		case SSW4_SZB:
8631.1Sdbj			off = 24 - off;
8641.1Sdbj			if (off)
8651.1Sdbj				wb1d >>= off;
8661.1Sdbj			if (KDFAULT(f->f_wb1s))
8671.1Sdbj				*(char *)f->f_wb1a = wb1d;
8681.1Sdbj			else
8691.64Schristos				err = subyte((void *)f->f_wb1a, wb1d);
8701.1Sdbj			break;
8711.1Sdbj		case SSW4_SZW:
8721.1Sdbj			off = (off + 16) % 32;
8731.1Sdbj			if (off)
8741.1Sdbj				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
8751.1Sdbj			if (KDFAULT(f->f_wb1s))
8761.1Sdbj				*(short *)f->f_wb1a = wb1d;
8771.1Sdbj			else
8781.64Schristos				err = susword((void *)f->f_wb1a, wb1d);
8791.1Sdbj			break;
8801.1Sdbj		}
8811.1Sdbj		if (err) {
8821.1Sdbj			fa = f->f_wb1a;
8831.1Sdbj#ifdef DEBUG
8841.1Sdbj			if (mmudebug & MDB_WBFAILED)
8851.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8861.1Sdbj				       "#1", fp->f_pc, f->f_fa,
8871.1Sdbj				       f->f_wb1a, f->f_wb1d);
8881.1Sdbj#endif
8891.1Sdbj		}
8901.1Sdbj	}
8911.1Sdbj	/*
8921.1Sdbj	 * Deal with the "normal" writebacks.
8931.1Sdbj	 *
8941.1Sdbj	 * XXX writeback2 is known to reflect a LINE size writeback after
8951.1Sdbj	 * a MOVE16 was already dealt with above.  Ignore it.
8961.1Sdbj	 */
8971.1Sdbj	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
8981.1Sdbj	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
8991.1Sdbj#ifdef DEBUG
9001.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
9011.1Sdbj			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
9021.1Sdbj		wbstats.wb2s++;
9031.1Sdbj		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
9041.1Sdbj#endif
9051.1Sdbj		switch (f->f_wb2s & SSW4_SZMASK) {
9061.1Sdbj		case SSW4_SZLW:
9071.1Sdbj			if (KDFAULT(f->f_wb2s))
9081.1Sdbj				*(long *)f->f_wb2a = f->f_wb2d;
9091.1Sdbj			else
9101.64Schristos				err = suword((void *)f->f_wb2a, f->f_wb2d);
9111.1Sdbj			break;
9121.1Sdbj		case SSW4_SZB:
9131.1Sdbj			if (KDFAULT(f->f_wb2s))
9141.1Sdbj				*(char *)f->f_wb2a = f->f_wb2d;
9151.1Sdbj			else
9161.64Schristos				err = subyte((void *)f->f_wb2a, f->f_wb2d);
9171.1Sdbj			break;
9181.1Sdbj		case SSW4_SZW:
9191.1Sdbj			if (KDFAULT(f->f_wb2s))
9201.1Sdbj				*(short *)f->f_wb2a = f->f_wb2d;
9211.1Sdbj			else
9221.64Schristos				err = susword((void *)f->f_wb2a, f->f_wb2d);
9231.1Sdbj			break;
9241.1Sdbj		}
9251.1Sdbj		if (err) {
9261.1Sdbj			fa = f->f_wb2a;
9271.1Sdbj#ifdef DEBUG
9281.1Sdbj			if (mmudebug & MDB_WBFAILED) {
9291.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
9301.1Sdbj				       "#2", fp->f_pc, f->f_fa,
9311.1Sdbj				       f->f_wb2a, f->f_wb2d);
9321.1Sdbj				dumpssw(f->f_ssw);
9331.1Sdbj				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
9341.1Sdbj			}
9351.1Sdbj#endif
9361.1Sdbj		}
9371.1Sdbj	}
9381.1Sdbj	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
9391.1Sdbj#ifdef DEBUG
9401.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
9411.1Sdbj			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
9421.1Sdbj		wbstats.wb3s++;
9431.1Sdbj		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
9441.1Sdbj#endif
9451.1Sdbj		switch (f->f_wb3s & SSW4_SZMASK) {
9461.1Sdbj		case SSW4_SZLW:
9471.1Sdbj			if (KDFAULT(f->f_wb3s))
9481.1Sdbj				*(long *)f->f_wb3a = f->f_wb3d;
9491.1Sdbj			else
9501.64Schristos				err = suword((void *)f->f_wb3a, f->f_wb3d);
9511.1Sdbj			break;
9521.1Sdbj		case SSW4_SZB:
9531.1Sdbj			if (KDFAULT(f->f_wb3s))
9541.1Sdbj				*(char *)f->f_wb3a = f->f_wb3d;
9551.1Sdbj			else
9561.64Schristos				err = subyte((void *)f->f_wb3a, f->f_wb3d);
9571.1Sdbj			break;
9581.1Sdbj		case SSW4_SZW:
9591.1Sdbj			if (KDFAULT(f->f_wb3s))
9601.1Sdbj				*(short *)f->f_wb3a = f->f_wb3d;
9611.1Sdbj			else
9621.64Schristos				err = susword((void *)f->f_wb3a, f->f_wb3d);
9631.1Sdbj			break;
9641.1Sdbj#ifdef DEBUG
9651.1Sdbj		case SSW4_SZLN:
9661.1Sdbj			panic("writeback: wb3s indicates LINE write");
9671.1Sdbj#endif
9681.1Sdbj		}
9691.1Sdbj		if (err) {
9701.1Sdbj			fa = f->f_wb3a;
9711.1Sdbj#ifdef DEBUG
9721.1Sdbj			if (mmudebug & MDB_WBFAILED)
9731.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
9741.1Sdbj				       "#3", fp->f_pc, f->f_fa,
9751.1Sdbj				       f->f_wb3a, f->f_wb3d);
9761.1Sdbj#endif
9771.1Sdbj		}
9781.1Sdbj	}
9791.39Sthorpej	l->l_addr->u_pcb.pcb_onfault = oonfault;
9801.1Sdbj	if (err)
9811.1Sdbj		err = SIGSEGV;
9821.16Sdbj	return (err);
9831.1Sdbj}
9841.1Sdbj
9851.1Sdbj#ifdef DEBUG
9861.16Sdbjvoid
9871.53Schsdumpssw(u_short ssw)
9881.1Sdbj{
9891.1Sdbj	printf(" SSW: %x: ", ssw);
9901.1Sdbj	if (ssw & SSW4_CP)
9911.1Sdbj		printf("CP,");
9921.1Sdbj	if (ssw & SSW4_CU)
9931.1Sdbj		printf("CU,");
9941.1Sdbj	if (ssw & SSW4_CT)
9951.1Sdbj		printf("CT,");
9961.1Sdbj	if (ssw & SSW4_CM)
9971.1Sdbj		printf("CM,");
9981.1Sdbj	if (ssw & SSW4_MA)
9991.1Sdbj		printf("MA,");
10001.1Sdbj	if (ssw & SSW4_ATC)
10011.1Sdbj		printf("ATC,");
10021.1Sdbj	if (ssw & SSW4_LK)
10031.1Sdbj		printf("LK,");
10041.1Sdbj	if (ssw & SSW4_RW)
10051.1Sdbj		printf("RW,");
10061.1Sdbj	printf(" SZ=%s, TT=%s, TM=%s\n",
10071.1Sdbj	       f7sz[(ssw & SSW4_SZMASK) >> 5],
10081.1Sdbj	       f7tt[(ssw & SSW4_TTMASK) >> 3],
10091.1Sdbj	       f7tm[ssw & SSW4_TMMASK]);
10101.1Sdbj}
10111.1Sdbj
10121.16Sdbjvoid
10131.53Schsdumpwb(int num, u_short s, u_int a, u_int d)
10141.1Sdbj{
10151.1Sdbj	struct proc *p = curproc;
10161.7Sdbj	paddr_t pa;
10171.1Sdbj
10181.1Sdbj	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
10191.1Sdbj	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
10201.1Sdbj	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
10211.16Sdbj	printf("               PA ");
10221.63Sthorpej	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == false)
10231.1Sdbj		printf("<invalid address>");
10241.1Sdbj	else
10251.64Schristos		printf("%lx, current value %lx", pa, fuword((void *)a));
10261.1Sdbj	printf("\n");
10271.1Sdbj}
10281.1Sdbj#endif
10291.1Sdbj#endif
1030