trap.c revision 1.38
11.38Smycroft/*	$NetBSD: trap.c,v 1.38 2002/09/11 01:46:35 mycroft 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) 1988 University of Utah.
121.1Sdbj * Copyright (c) 1982, 1986, 1990, 1993
131.1Sdbj *	The Regents of the University of California.  All rights reserved.
141.1Sdbj *
151.1Sdbj * This code is derived from software contributed to Berkeley by
161.1Sdbj * the Systems Programming Group of the University of Utah Computer
171.1Sdbj * Science Department.
181.1Sdbj *
191.1Sdbj * Redistribution and use in source and binary forms, with or without
201.1Sdbj * modification, are permitted provided that the following conditions
211.1Sdbj * are met:
221.1Sdbj * 1. Redistributions of source code must retain the above copyright
231.1Sdbj *    notice, this list of conditions and the following disclaimer.
241.1Sdbj * 2. Redistributions in binary form must reproduce the above copyright
251.1Sdbj *    notice, this list of conditions and the following disclaimer in the
261.1Sdbj *    documentation and/or other materials provided with the distribution.
271.1Sdbj * 3. All advertising materials mentioning features or use of this software
281.1Sdbj *    must display the following acknowledgement:
291.1Sdbj *	This product includes software developed by the University of
301.1Sdbj *	California, Berkeley and its contributors.
311.1Sdbj * 4. Neither the name of the University nor the names of its contributors
321.1Sdbj *    may be used to endorse or promote products derived from this software
331.1Sdbj *    without specific prior written permission.
341.1Sdbj *
351.1Sdbj * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
361.1Sdbj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
371.1Sdbj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
381.1Sdbj * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
391.1Sdbj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
401.1Sdbj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
411.1Sdbj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
421.1Sdbj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
431.1Sdbj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
441.1Sdbj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
451.1Sdbj * SUCH DAMAGE.
461.1Sdbj *
471.1Sdbj * from: Utah $Hdr: trap.c 1.37 92/12/20$
481.1Sdbj *
491.1Sdbj *	@(#)trap.c	8.5 (Berkeley) 1/4/94
501.1Sdbj */
511.2Sthorpej
521.5Sjonathan#include "opt_ddb.h"
531.9Sitohy#include "opt_execfmt.h"
541.33Slukem#include "opt_kgdb.h"
551.3Sthorpej#include "opt_compat_sunos.h"
561.4Sthorpej#include "opt_compat_hpux.h"
571.1Sdbj
581.1Sdbj#include <sys/param.h>
591.1Sdbj#include <sys/systm.h>
601.1Sdbj#include <sys/proc.h>
611.1Sdbj#include <sys/acct.h>
621.1Sdbj#include <sys/kernel.h>
631.1Sdbj#include <sys/signalvar.h>
641.1Sdbj#include <sys/resourcevar.h>
651.1Sdbj#include <sys/syscall.h>
661.1Sdbj#include <sys/syslog.h>
671.1Sdbj#include <sys/user.h>
681.16Sdbj
691.16Sdbj#ifdef DEBUG
701.16Sdbj#include <dev/cons.h>
711.14Sdbj#endif
721.1Sdbj
731.16Sdbj#include <machine/db_machdep.h>
741.1Sdbj#include <machine/psl.h>
751.1Sdbj#include <machine/trap.h>
761.1Sdbj#include <machine/cpu.h>
771.1Sdbj#include <machine/reg.h>
781.1Sdbj
791.16Sdbj#include <m68k/cacheops.h>
801.16Sdbj
811.7Sdbj#include <uvm/uvm_extern.h>
821.1Sdbj
831.1Sdbj#ifdef COMPAT_HPUX
841.1Sdbj#include <compat/hpux/hpux.h>
851.1Sdbj#endif
861.1Sdbj
871.1Sdbj#ifdef COMPAT_SUNOS
881.1Sdbj#include <compat/sunos/sunos_syscall.h>
891.1Sdbjextern struct emul emul_sunos;
901.1Sdbj#endif
911.1Sdbj
921.37Sjdolecek#ifdef KGDB
931.37Sjdolecek#include <sys/kgdb.h>
941.37Sjdolecek#endif
951.37Sjdolecek
961.16Sdbjint	writeback __P((struct frame *fp, int docachepush));
971.16Sdbjvoid	trap __P((int type, u_int code, u_int v, struct frame frame));
981.16Sdbj
991.16Sdbj#ifdef DEBUG
1001.16Sdbjvoid	dumpssw __P((u_short));
1011.16Sdbjvoid	dumpwb __P((int, u_short, u_int, u_int));
1021.16Sdbj#endif
1031.16Sdbj
1041.16Sdbjstatic inline void userret __P((struct proc *p, struct frame *fp,
1051.16Sdbj	    u_quad_t oticks, u_int faultaddr, int fromtrap));
1061.1Sdbj
1071.7Sdbjint	astpending;
1081.1Sdbj
1091.1Sdbjchar	*trap_type[] = {
1101.1Sdbj	"Bus error",
1111.1Sdbj	"Address error",
1121.1Sdbj	"Illegal instruction",
1131.1Sdbj	"Zero divide",
1141.1Sdbj	"CHK instruction",
1151.1Sdbj	"TRAPV instruction",
1161.1Sdbj	"Privilege violation",
1171.1Sdbj	"Trace trap",
1181.1Sdbj	"MMU fault",
1191.1Sdbj	"SSIR trap",
1201.1Sdbj	"Format error",
1211.1Sdbj	"68881 exception",
1221.1Sdbj	"Coprocessor violation",
1231.1Sdbj	"Async system trap"
1241.1Sdbj};
1251.1Sdbjint	trap_types = sizeof trap_type / sizeof trap_type[0];
1261.1Sdbj
1271.1Sdbj/*
1281.1Sdbj * Size of various exception stack frames (minus the standard 8 bytes)
1291.1Sdbj */
1301.1Sdbjshort	exframesize[] = {
1311.16Sdbj	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
1321.1Sdbj	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
1331.16Sdbj	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
1341.16Sdbj	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
1351.16Sdbj	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
1361.16Sdbj	-1, -1,		/* type 5-6 - undefined */
1371.1Sdbj	FMT7SIZE,	/* type 7 - access error (68040) */
1381.1Sdbj	58,		/* type 8 - bus fault (68010) */
1391.1Sdbj	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
1401.1Sdbj	FMTASIZE,	/* type A - short bus fault (68020/030) */
1411.1Sdbj	FMTBSIZE,	/* type B - long bus fault (68020/030) */
1421.1Sdbj	-1, -1, -1, -1	/* type C-F - undefined */
1431.1Sdbj};
1441.1Sdbj
1451.16Sdbj#ifdef M68060
1461.16Sdbj#define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
1471.16Sdbj#define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
1481.16Sdbj#else
1491.16Sdbj#define	KDFAULT_060(c)	0
1501.16Sdbj#define	WRFAULT_060(c)	0
1511.16Sdbj#endif
1521.16Sdbj
1531.1Sdbj#ifdef M68040
1541.16Sdbj#define	KDFAULT_040(c)	(cputype == CPU_68040 && \
1551.16Sdbj			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
1561.16Sdbj#define	WRFAULT_040(c)	(cputype == CPU_68040 && \
1571.16Sdbj			 ((c) & SSW4_RW) == 0)
1581.16Sdbj#else
1591.16Sdbj#define	KDFAULT_040(c)	0
1601.16Sdbj#define	WRFAULT_040(c)	0
1611.16Sdbj#endif
1621.16Sdbj
1631.16Sdbj#if defined(M68030) || defined(M68020)
1641.16Sdbj#define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
1651.16Sdbj			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
1661.16Sdbj#define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
1671.16Sdbj			 ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
1681.1Sdbj#else
1691.16Sdbj#define	KDFAULT_OTH(c)	0
1701.16Sdbj#define	WRFAULT_OTH(c)	0
1711.1Sdbj#endif
1721.1Sdbj
1731.16Sdbj#define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
1741.16Sdbj#define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
1751.16Sdbj
1761.1Sdbj#ifdef DEBUG
1771.1Sdbjint mmudebug = 0;
1781.1Sdbjint mmupid = -1;
1791.1Sdbj#define MDB_FOLLOW	1
1801.1Sdbj#define MDB_WBFOLLOW	2
1811.1Sdbj#define MDB_WBFAILED	4
1821.16Sdbj#define MDB_ISPID(p)	((p) == mmupid)
1831.1Sdbj#endif
1841.1Sdbj
1851.16Sdbj
1861.1Sdbj#define NSIR	32
1871.16Sdbjvoid (*sir_routines[NSIR])(void *);
1881.1Sdbjvoid *sir_args[NSIR];
1891.1Sdbjint next_sir;
1901.1Sdbj
1911.1Sdbj/*
1921.1Sdbj * trap and syscall both need the following work done before returning
1931.1Sdbj * to user mode.
1941.1Sdbj */
1951.1Sdbjstatic inline void
1961.1Sdbjuserret(p, fp, oticks, faultaddr, fromtrap)
1971.1Sdbj	struct proc *p;
1981.1Sdbj	struct frame *fp;
1991.1Sdbj	u_quad_t oticks;
2001.1Sdbj	u_int faultaddr;
2011.1Sdbj	int fromtrap;
2021.1Sdbj{
2031.20Sthorpej	int sig;
2041.1Sdbj#ifdef M68040
2051.1Sdbj	int beenhere = 0;
2061.1Sdbj
2071.1Sdbjagain:
2081.1Sdbj#endif
2091.1Sdbj	/* take pending signals */
2101.1Sdbj	while ((sig = CURSIG(p)) != 0)
2111.1Sdbj		postsig(sig);
2121.1Sdbj	p->p_priority = p->p_usrpri;
2131.1Sdbj	if (want_resched) {
2141.1Sdbj		/*
2151.20Sthorpej		 * We are being preempted.
2161.1Sdbj		 */
2171.20Sthorpej		preempt(NULL);
2181.1Sdbj		while ((sig = CURSIG(p)) != 0)
2191.1Sdbj			postsig(sig);
2201.1Sdbj	}
2211.1Sdbj
2221.1Sdbj	/*
2231.1Sdbj	 * If profiling, charge system time to the trapped pc.
2241.1Sdbj	 */
2251.1Sdbj	if (p->p_flag & P_PROFIL) {
2261.1Sdbj		extern int psratio;
2271.1Sdbj
2281.1Sdbj		addupc_task(p, fp->f_pc,
2291.1Sdbj			    (int)(p->p_sticks - oticks) * psratio);
2301.1Sdbj	}
2311.1Sdbj#ifdef M68040
2321.1Sdbj	/*
2331.1Sdbj	 * Deal with user mode writebacks (from trap, or from sigreturn).
2341.1Sdbj	 * If any writeback fails, go back and attempt signal delivery.
2351.1Sdbj	 * unless we have already been here and attempted the writeback
2361.1Sdbj	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
2371.1Sdbj	 * we just return to the user without sucessfully completing
2381.1Sdbj	 * the writebacks.  Maybe we should just drop the sucker?
2391.1Sdbj	 */
2401.16Sdbj	if (cputype == CPU_68040 && fp->f_format == FMT7) {
2411.1Sdbj		if (beenhere) {
2421.1Sdbj#ifdef DEBUG
2431.1Sdbj			if (mmudebug & MDB_WBFAILED)
2441.1Sdbj				printf(fromtrap ?
2451.1Sdbj		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
2461.1Sdbj		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
2471.1Sdbj				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
2481.1Sdbj#endif
2491.16Sdbj		} else if ((sig = writeback(fp, fromtrap))) {
2501.1Sdbj			beenhere = 1;
2511.1Sdbj			oticks = p->p_sticks;
2521.1Sdbj			trapsignal(p, sig, faultaddr);
2531.1Sdbj			goto again;
2541.1Sdbj		}
2551.1Sdbj	}
2561.1Sdbj#endif
2571.21Sthorpej	curcpu()->ci_schedstate.spc_curpriority = p->p_priority;
2581.1Sdbj}
2591.1Sdbj
2601.1Sdbj/*
2611.28Sscw * Used by the common m68k syscall() and child_return() functions.
2621.28Sscw * XXX: Temporary until all m68k ports share common trap()/userret() code.
2631.28Sscw */
2641.28Sscwvoid machine_userret(struct proc *, struct frame *, u_quad_t);
2651.28Sscw
2661.28Sscwvoid
2671.28Sscwmachine_userret(p, f, t)
2681.28Sscw	struct proc *p;
2691.28Sscw	struct frame *f;
2701.28Sscw	u_quad_t t;
2711.28Sscw{
2721.28Sscw
2731.28Sscw	userret(p, f, t, 0, 0);
2741.28Sscw}
2751.28Sscw
2761.28Sscw/*
2771.1Sdbj * Trap is called from locore to handle most types of processor traps,
2781.1Sdbj * including events such as simulated software interrupts/AST's.
2791.1Sdbj * System calls are broken out for efficiency.
2801.1Sdbj */
2811.1Sdbj/*ARGSUSED*/
2821.16Sdbjvoid
2831.1Sdbjtrap(type, code, v, frame)
2841.1Sdbj	int type;
2851.1Sdbj	unsigned code;
2861.1Sdbj	unsigned v;
2871.1Sdbj	struct frame frame;
2881.1Sdbj{
2891.1Sdbj	extern char fubail[], subail[];
2901.1Sdbj	struct proc *p;
2911.16Sdbj	int i, s;
2921.1Sdbj	u_int ucode;
2931.16Sdbj	u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */;
2941.7Sdbj	int bit;
2951.38Smycroft	static int panicing = 0;
2961.1Sdbj
2971.7Sdbj	uvmexp.traps++;
2981.1Sdbj	p = curproc;
2991.1Sdbj	ucode = 0;
3001.16Sdbj
3011.16Sdbj	/* I have verified that this DOES happen! -gwr */
3021.16Sdbj	if (p == NULL)
3031.16Sdbj		p = &proc0;
3041.16Sdbj#ifdef DIAGNOSTIC
3051.16Sdbj	if (p->p_addr == NULL)
3061.16Sdbj		panic("trap: no pcb");
3071.16Sdbj#endif
3081.16Sdbj
3091.1Sdbj	if (USERMODE(frame.f_sr)) {
3101.1Sdbj		type |= T_USER;
3111.1Sdbj		sticks = p->p_sticks;
3121.1Sdbj		p->p_md.md_regs = frame.f_regs;
3131.1Sdbj	}
3141.1Sdbj	switch (type) {
3151.1Sdbj
3161.1Sdbj	default:
3171.14Sdbj	dopanic:
3181.14Sdbj		/*
3191.14Sdbj		 * Let the kernel debugger see the trap frame that
3201.14Sdbj		 * caused us to panic.  This is a convenience so
3211.14Sdbj		 * one can see registers at the point of failure.
3221.14Sdbj		 */
3231.16Sdbj		s = splhigh();
3241.38Smycroft		panicing = 1;
3251.38Smycroft		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
3261.38Smycroft		printf("%s program counter = 0x%x\n",
3271.38Smycroft		    (type & T_USER) ? "user" : "kernel", frame.f_pc);
3281.14Sdbj#ifdef KGDB
3291.14Sdbj		/* If connected, step or cont returns 1 */
3301.37Sjdolecek		if (kgdb_trap(type, (db_regs_t *)&frame))
3311.14Sdbj			goto kgdb_cont;
3321.14Sdbj#endif
3331.16Sdbj#ifdef DDB
3341.16Sdbj		(void)kdb_trap(type, (db_regs_t *)&frame);
3351.1Sdbj#endif
3361.14Sdbj#ifdef KGDB
3371.14Sdbj	kgdb_cont:
3381.14Sdbj#endif
3391.16Sdbj		splx(s);
3401.14Sdbj		if (panicstr) {
3411.16Sdbj			printf("trap during panic!\n");
3421.16Sdbj#ifdef DEBUG
3431.16Sdbj			/* XXX should be a machine-dependent hook */
3441.16Sdbj			printf("(press a key)\n"); (void)cngetc();
3451.16Sdbj#endif
3461.14Sdbj		}
3471.1Sdbj		regdump((struct trapframe *)&frame, 128);
3481.1Sdbj		type &= ~T_USER;
3491.16Sdbj		if ((u_int)type < trap_types)
3501.1Sdbj			panic(trap_type[type]);
3511.1Sdbj		panic("trap");
3521.1Sdbj
3531.1Sdbj	case T_BUSERR:		/* kernel bus error */
3541.16Sdbj		if (p->p_addr->u_pcb.pcb_onfault == 0)
3551.1Sdbj			goto dopanic;
3561.16Sdbj		/* FALLTHROUGH */
3571.16Sdbj
3581.16Sdbj	copyfault:
3591.1Sdbj		/*
3601.1Sdbj		 * If we have arranged to catch this fault in any of the
3611.1Sdbj		 * copy to/from user space routines, set PC to return to
3621.1Sdbj		 * indicated location and set flag informing buserror code
3631.1Sdbj		 * that it may need to clean up stack frame.
3641.1Sdbj		 */
3651.1Sdbj		frame.f_stackadj = exframesize[frame.f_format];
3661.1Sdbj		frame.f_format = frame.f_vector = 0;
3671.1Sdbj		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
3681.1Sdbj		return;
3691.1Sdbj
3701.1Sdbj	case T_BUSERR|T_USER:	/* bus error */
3711.1Sdbj	case T_ADDRERR|T_USER:	/* address error */
3721.1Sdbj		ucode = v;
3731.1Sdbj		i = SIGBUS;
3741.1Sdbj		break;
3751.1Sdbj
3761.1Sdbj	case T_COPERR:		/* kernel coprocessor violation */
3771.1Sdbj	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
3781.1Sdbj	case T_FMTERR:		/* ...just in case... */
3791.1Sdbj	/*
3801.1Sdbj	 * The user has most likely trashed the RTE or FP state info
3811.1Sdbj	 * in the stack frame of a signal handler.
3821.1Sdbj	 */
3831.1Sdbj		printf("pid %d: kernel %s exception\n", p->p_pid,
3841.1Sdbj		       type==T_COPERR ? "coprocessor" : "format");
3851.1Sdbj		type |= T_USER;
3861.29Sjdolecek		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
3871.29Sjdolecek		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
3881.29Sjdolecek		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
3891.29Sjdolecek		sigdelset(&p->p_sigctx.ps_sigmask, SIGILL);
3901.1Sdbj		i = SIGILL;
3911.1Sdbj		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
3921.1Sdbj		break;
3931.1Sdbj
3941.1Sdbj	case T_COPERR|T_USER:	/* user coprocessor violation */
3951.1Sdbj	/* What is a proper response here? */
3961.1Sdbj		ucode = 0;
3971.1Sdbj		i = SIGFPE;
3981.1Sdbj		break;
3991.1Sdbj
4001.1Sdbj	case T_FPERR|T_USER:	/* 68881 exceptions */
4011.1Sdbj	/*
4021.7Sdbj	 * We pass along the 68881 status register which locore stashed
4031.1Sdbj	 * in code for us.  Note that there is a possibility that the
4041.7Sdbj	 * bit pattern of this register will conflict with one of the
4051.1Sdbj	 * FPE_* codes defined in signal.h.  Fortunately for us, the
4061.1Sdbj	 * only such codes we use are all in the range 1-7 and the low
4071.7Sdbj	 * 3 bits of the status register are defined as 0 so there is
4081.1Sdbj	 * no clash.
4091.1Sdbj	 */
4101.1Sdbj		ucode = code;
4111.1Sdbj		i = SIGFPE;
4121.1Sdbj		break;
4131.1Sdbj
4141.1Sdbj#ifdef M68040
4151.1Sdbj	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
4161.1Sdbj	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
4171.1Sdbj		/* XXX need to FSAVE */
4181.1Sdbj		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
4191.1Sdbj		       p->p_pid, p->p_comm,
4201.1Sdbj		       frame.f_format == 2 ? "instruction" : "data type",
4211.1Sdbj		       frame.f_pc, frame.f_fmt2.f_iaddr);
4221.1Sdbj		/* XXX need to FRESTORE */
4231.1Sdbj		i = SIGFPE;
4241.1Sdbj		break;
4251.1Sdbj#endif
4261.1Sdbj
4271.1Sdbj	case T_ILLINST|T_USER:	/* illegal instruction fault */
4281.1Sdbj#ifdef COMPAT_HPUX
4291.1Sdbj		if (p->p_emul == &emul_hpux) {
4301.1Sdbj			ucode = HPUX_ILL_ILLINST_TRAP;
4311.1Sdbj			i = SIGILL;
4321.1Sdbj			break;
4331.1Sdbj		}
4341.1Sdbj		/* fall through */
4351.1Sdbj#endif
4361.1Sdbj	case T_PRIVINST|T_USER:	/* privileged instruction fault */
4371.1Sdbj#ifdef COMPAT_HPUX
4381.1Sdbj		if (p->p_emul == &emul_hpux)
4391.1Sdbj			ucode = HPUX_ILL_PRIV_TRAP;
4401.1Sdbj		else
4411.1Sdbj#endif
4421.1Sdbj		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
4431.1Sdbj		i = SIGILL;
4441.1Sdbj		break;
4451.1Sdbj
4461.1Sdbj	case T_ZERODIV|T_USER:	/* Divide by zero */
4471.1Sdbj#ifdef COMPAT_HPUX
4481.1Sdbj		if (p->p_emul == &emul_hpux)
4491.1Sdbj			ucode = HPUX_FPE_INTDIV_TRAP;
4501.1Sdbj		else
4511.1Sdbj#endif
4521.1Sdbj		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
4531.1Sdbj		i = SIGFPE;
4541.1Sdbj		break;
4551.1Sdbj
4561.1Sdbj	case T_CHKINST|T_USER:	/* CHK instruction trap */
4571.1Sdbj#ifdef COMPAT_HPUX
4581.1Sdbj		if (p->p_emul == &emul_hpux) {
4591.1Sdbj			/* handled differently under hp-ux */
4601.1Sdbj			i = SIGILL;
4611.1Sdbj			ucode = HPUX_ILL_CHK_TRAP;
4621.1Sdbj			break;
4631.1Sdbj		}
4641.1Sdbj#endif
4651.1Sdbj		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
4661.1Sdbj		i = SIGFPE;
4671.1Sdbj		break;
4681.1Sdbj
4691.1Sdbj	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
4701.1Sdbj#ifdef COMPAT_HPUX
4711.1Sdbj		if (p->p_emul == &emul_hpux) {
4721.1Sdbj			/* handled differently under hp-ux */
4731.1Sdbj			i = SIGILL;
4741.1Sdbj			ucode = HPUX_ILL_TRAPV_TRAP;
4751.1Sdbj			break;
4761.1Sdbj		}
4771.1Sdbj#endif
4781.1Sdbj		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
4791.1Sdbj		i = SIGFPE;
4801.1Sdbj		break;
4811.1Sdbj
4821.1Sdbj	/*
4831.1Sdbj	 * XXX: Trace traps are a nightmare.
4841.1Sdbj	 *
4851.1Sdbj	 *	HP-UX uses trap #1 for breakpoints,
4861.16Sdbj	 *	NetBSD/m68k uses trap #2,
4871.1Sdbj	 *	SUN 3.x uses trap #15,
4881.16Sdbj	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
4891.16Sdbj	 *	handled elsewhere).
4901.1Sdbj	 *
4911.16Sdbj	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
4921.1Sdbj	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
4931.1Sdbj	 * supported yet.
4941.16Sdbj	 *
4951.17Sitohy	 * XXX: We should never get kernel-mode T_TRAP15
4961.16Sdbj	 * XXX: because locore.s now gives them special treatment.
4971.1Sdbj	 */
4981.16Sdbj	case T_TRAP15:		/* kernel breakpoint */
4991.16Sdbj#ifdef DEBUG
5001.16Sdbj		printf("unexpected kernel trace trap, type = %d\n", type);
5011.16Sdbj		printf("program counter = 0x%x\n", frame.f_pc);
5021.1Sdbj#endif
5031.1Sdbj		frame.f_sr &= ~PSL_T;
5041.16Sdbj		return;
5051.1Sdbj
5061.1Sdbj	case T_TRACE|T_USER:	/* user trace trap */
5071.1Sdbj#ifdef COMPAT_SUNOS
5081.1Sdbj		/*
5091.1Sdbj		 * SunOS uses Trap #2 for a "CPU cache flush".
5101.1Sdbj		 * Just flush the on-chip caches and return.
5111.1Sdbj		 */
5121.1Sdbj		if (p->p_emul == &emul_sunos) {
5131.1Sdbj			ICIA();
5141.1Sdbj			DCIU();
5151.1Sdbj			return;
5161.1Sdbj		}
5171.16Sdbj#endif
5181.17Sitohy		/* FALLTHROUGH */
5191.17Sitohy	case T_TRACE:		/* tracing a trap instruction */
5201.17Sitohy	case T_TRAP15|T_USER:	/* SUN user trace trap */
5211.1Sdbj		frame.f_sr &= ~PSL_T;
5221.1Sdbj		i = SIGTRAP;
5231.1Sdbj		break;
5241.1Sdbj
5251.1Sdbj	case T_ASTFLT:		/* system async trap, cannot happen */
5261.1Sdbj		goto dopanic;
5271.1Sdbj
5281.1Sdbj	case T_ASTFLT|T_USER:	/* user async trap */
5291.1Sdbj		astpending = 0;
5301.1Sdbj		/*
5311.1Sdbj		 * We check for software interrupts first.  This is because
5321.1Sdbj		 * they are at a higher level than ASTs, and on a VAX would
5331.1Sdbj		 * interrupt the AST.  We assume that if we are processing
5341.1Sdbj		 * an AST that we must be at IPL0 so we don't bother to
5351.1Sdbj		 * check.  Note that we ensure that we are at least at SIR
5361.1Sdbj		 * IPL while processing the SIR.
5371.1Sdbj		 */
5381.1Sdbj		spl1();
5391.1Sdbj		/* fall into... */
5401.1Sdbj
5411.1Sdbj	case T_SSIR:		/* software interrupt */
5421.1Sdbj	case T_SSIR|T_USER:
5431.16Sdbj		while ((bit = ffs(ssir))) {
5441.1Sdbj			--bit;
5451.1Sdbj			ssir &= ~(1 << bit);
5461.7Sdbj			uvmexp.softs++;
5471.1Sdbj			if (sir_routines[bit])
5481.1Sdbj				sir_routines[bit](sir_args[bit]);
5491.1Sdbj		}
5501.1Sdbj		/*
5511.1Sdbj		 * If this was not an AST trap, we are all done.
5521.1Sdbj		 */
5531.1Sdbj		if (type != (T_ASTFLT|T_USER)) {
5541.16Sdbj			uvmexp.traps--;
5551.1Sdbj			return;
5561.1Sdbj		}
5571.1Sdbj		spl0();
5581.1Sdbj		if (p->p_flag & P_OWEUPC) {
5591.1Sdbj			p->p_flag &= ~P_OWEUPC;
5601.1Sdbj			ADDUPROF(p);
5611.1Sdbj		}
5621.1Sdbj		goto out;
5631.1Sdbj
5641.1Sdbj	case T_MMUFLT:		/* kernel mode page fault */
5651.1Sdbj		/*
5661.1Sdbj		 * If we were doing profiling ticks or other user mode
5671.1Sdbj		 * stuff from interrupt code, Just Say No.
5681.1Sdbj		 */
5691.1Sdbj		if (p->p_addr->u_pcb.pcb_onfault == fubail ||
5701.1Sdbj		    p->p_addr->u_pcb.pcb_onfault == subail)
5711.1Sdbj			goto copyfault;
5721.1Sdbj		/* fall into ... */
5731.1Sdbj
5741.1Sdbj	case T_MMUFLT|T_USER:	/* page fault */
5751.1Sdbj	    {
5761.7Sdbj		vaddr_t va;
5771.1Sdbj		struct vmspace *vm = p->p_vmspace;
5781.34Schs		struct vm_map *map;
5791.1Sdbj		int rv;
5801.1Sdbj		vm_prot_t ftype;
5811.34Schs		extern struct vm_map *kernel_map;
5821.1Sdbj
5831.1Sdbj#ifdef DEBUG
5841.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
5851.1Sdbj		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
5861.1Sdbj		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
5871.1Sdbj#endif
5881.1Sdbj		/*
5891.1Sdbj		 * It is only a kernel address space fault iff:
5901.1Sdbj		 * 	1. (type & T_USER) == 0  and
5911.1Sdbj		 * 	2. pcb_onfault not set or
5921.1Sdbj		 *	3. pcb_onfault set but supervisor space data fault
5931.1Sdbj		 * The last can occur during an exec() copyin where the
5941.1Sdbj		 * argument space is lazy-allocated.
5951.1Sdbj		 */
5961.16Sdbj		if ((type & T_USER) == 0 &&
5971.16Sdbj		    ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code)))
5981.1Sdbj			map = kernel_map;
5991.1Sdbj		else
6001.16Sdbj			map = vm ? &vm->vm_map : kernel_map;
6011.16Sdbj
6021.1Sdbj		if (WRFAULT(code))
6031.36Schs			ftype = VM_PROT_WRITE;
6041.1Sdbj		else
6051.1Sdbj			ftype = VM_PROT_READ;
6061.16Sdbj
6071.7Sdbj		va = trunc_page((vaddr_t)v);
6081.16Sdbj
6091.1Sdbj		if (map == kernel_map && va == 0) {
6101.16Sdbj			printf("trap: bad kernel %s access at 0x%x\n",
6111.16Sdbj			    (ftype & VM_PROT_WRITE) ? "read/write" :
6121.16Sdbj			    "read", v);
6131.1Sdbj			goto dopanic;
6141.1Sdbj		}
6151.16Sdbj
6161.38Smycroft#ifdef DIAGNOSTIC
6171.38Smycroft		if (interrupt_depth && !panicing) {
6181.38Smycroft			printf("trap: calling uvm_fault() from interrupt!\n");
6191.38Smycroft			goto dopanic;
6201.38Smycroft		}
6211.38Smycroft#endif
6221.38Smycroft
6231.1Sdbj#ifdef COMPAT_HPUX
6241.1Sdbj		if (ISHPMMADDR(va)) {
6251.16Sdbj			int pmap_mapmulti __P((pmap_t, vaddr_t));
6261.7Sdbj			vaddr_t bva;
6271.1Sdbj
6281.1Sdbj			rv = pmap_mapmulti(map->pmap, va);
6291.31Schs			if (rv != 0) {
6301.1Sdbj				bva = HPMMBASEADDR(va);
6311.7Sdbj				rv = uvm_fault(map, bva, 0, ftype);
6321.31Schs				if (rv == 0)
6331.1Sdbj					(void) pmap_mapmulti(map->pmap, va);
6341.1Sdbj			}
6351.1Sdbj		} else
6361.1Sdbj#endif
6371.7Sdbj		rv = uvm_fault(map, va, 0, ftype);
6381.7Sdbj#ifdef DEBUG
6391.7Sdbj		if (rv && MDB_ISPID(p->p_pid))
6401.7Sdbj			printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
6411.16Sdbj			    map, va, ftype, rv);
6421.7Sdbj#endif
6431.1Sdbj		/*
6441.1Sdbj		 * If this was a stack access we keep track of the maximum
6451.1Sdbj		 * accessed stack size.  Also, if vm_fault gets a protection
6461.1Sdbj		 * failure it is due to accessing the stack region outside
6471.1Sdbj		 * the current limit and we need to reflect that as an access
6481.1Sdbj		 * error.
6491.1Sdbj		 */
6501.16Sdbj		if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr)
6511.16Sdbj		    && map != kernel_map) {
6521.31Schs			if (rv == 0) {
6531.1Sdbj				unsigned nss;
6541.1Sdbj
6551.19Sragge				nss = btoc(USRSTACK-(unsigned)va);
6561.1Sdbj				if (nss > vm->vm_ssize)
6571.1Sdbj					vm->vm_ssize = nss;
6581.31Schs			} else if (rv == EACCES)
6591.31Schs				rv = EFAULT;
6601.1Sdbj		}
6611.31Schs		if (rv == 0) {
6621.1Sdbj			if (type == T_MMUFLT) {
6631.16Sdbj#ifdef M68040
6641.16Sdbj				if (cputype == CPU_68040)
6651.1Sdbj					(void) writeback(&frame, 1);
6661.1Sdbj#endif
6671.1Sdbj				return;
6681.1Sdbj			}
6691.1Sdbj			goto out;
6701.1Sdbj		}
6711.1Sdbj		if (type == T_MMUFLT) {
6721.1Sdbj			if (p->p_addr->u_pcb.pcb_onfault)
6731.1Sdbj				goto copyfault;
6741.7Sdbj			printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
6751.16Sdbj			    map, va, ftype, rv);
6761.1Sdbj			printf("  type %x, code [mmu,,ssw]: %x\n",
6771.1Sdbj			       type, code);
6781.1Sdbj			goto dopanic;
6791.1Sdbj		}
6801.1Sdbj		ucode = v;
6811.31Schs		if (rv == ENOMEM) {
6821.11Schs			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
6831.11Schs			       p->p_pid, p->p_comm,
6841.11Schs			       p->p_cred && p->p_ucred ?
6851.11Schs			       p->p_ucred->cr_uid : -1);
6861.11Schs			i = SIGKILL;
6871.11Schs		} else {
6881.11Schs			i = SIGSEGV;
6891.11Schs		}
6901.1Sdbj		break;
6911.1Sdbj	    }
6921.1Sdbj	}
6931.1Sdbj	trapsignal(p, i, ucode);
6941.1Sdbj	if ((type & T_USER) == 0)
6951.1Sdbj		return;
6961.1Sdbjout:
6971.1Sdbj	userret(p, &frame, sticks, v, 1);
6981.1Sdbj}
6991.1Sdbj
7001.1Sdbj#ifdef M68040
7011.1Sdbj#ifdef DEBUG
7021.1Sdbjstruct writebackstats {
7031.1Sdbj	int calls;
7041.1Sdbj	int cpushes;
7051.1Sdbj	int move16s;
7061.1Sdbj	int wb1s, wb2s, wb3s;
7071.1Sdbj	int wbsize[4];
7081.1Sdbj} wbstats;
7091.1Sdbj
7101.1Sdbjchar *f7sz[] = { "longword", "byte", "word", "line" };
7111.1Sdbjchar *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
7121.1Sdbjchar *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
7131.1Sdbj		 "M-code", "k-data", "k-code", "RES" };
7141.1Sdbjchar wberrstr[] =
7151.16Sdbj    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
7161.1Sdbj#endif
7171.1Sdbj
7181.16Sdbjint
7191.1Sdbjwriteback(fp, docachepush)
7201.1Sdbj	struct frame *fp;
7211.1Sdbj	int docachepush;
7221.1Sdbj{
7231.1Sdbj	struct fmt7 *f = &fp->f_fmt7;
7241.1Sdbj	struct proc *p = curproc;
7251.1Sdbj	int err = 0;
7261.1Sdbj	u_int fa;
7271.1Sdbj	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
7281.15Sthorpej	paddr_t pa;
7291.1Sdbj
7301.1Sdbj#ifdef DEBUG
7311.1Sdbj	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
7321.1Sdbj		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
7331.1Sdbj		dumpssw(f->f_ssw);
7341.1Sdbj	}
7351.1Sdbj	wbstats.calls++;
7361.1Sdbj#endif
7371.1Sdbj	/*
7381.1Sdbj	 * Deal with special cases first.
7391.1Sdbj	 */
7401.1Sdbj	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
7411.1Sdbj		/*
7421.1Sdbj		 * Dcache push fault.
7431.1Sdbj		 * Line-align the address and write out the push data to
7441.1Sdbj		 * the indicated physical address.
7451.1Sdbj		 */
7461.1Sdbj#ifdef DEBUG
7471.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
7481.1Sdbj			printf(" pushing %s to PA %x, data %x",
7491.1Sdbj			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
7501.1Sdbj			       f->f_fa, f->f_pd0);
7511.1Sdbj			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
7521.1Sdbj				printf("/%x/%x/%x",
7531.1Sdbj				       f->f_pd1, f->f_pd2, f->f_pd3);
7541.1Sdbj			printf("\n");
7551.1Sdbj		}
7561.1Sdbj		if (f->f_wb1s & SSW4_WBSV)
7571.1Sdbj			panic("writeback: cache push with WB1S valid");
7581.1Sdbj		wbstats.cpushes++;
7591.1Sdbj#endif
7601.1Sdbj		/*
7611.1Sdbj		 * XXX there are security problems if we attempt to do a
7621.1Sdbj		 * cache push after a signal handler has been called.
7631.1Sdbj		 */
7641.1Sdbj		if (docachepush) {
7651.7Sdbj			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
7661.18Sthorpej			    trunc_page(f->f_fa), VM_PROT_WRITE,
7671.18Sthorpej			    VM_PROT_WRITE|PMAP_WIRED);
7681.35Schris			pmap_update(pmap_kernel());
7691.1Sdbj			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
7701.1Sdbj			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
7711.15Sthorpej			(void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa);
7721.15Sthorpej			DCFL(pa);
7731.7Sdbj			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
7741.7Sdbj				    (vaddr_t)&vmmap[NBPG]);
7751.35Schris			pmap_update(pmap_kernel());
7761.1Sdbj		} else
7771.1Sdbj			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
7781.1Sdbj			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
7791.1Sdbj	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
7801.1Sdbj		/*
7811.1Sdbj		 * MOVE16 fault.
7821.1Sdbj		 * Line-align the address and write out the push data to
7831.1Sdbj		 * the indicated virtual address.
7841.1Sdbj		 */
7851.1Sdbj#ifdef DEBUG
7861.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
7871.1Sdbj			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
7881.1Sdbj			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
7891.1Sdbj			       f->f_pd2, f->f_pd3);
7901.1Sdbj		if (f->f_wb1s & SSW4_WBSV)
7911.1Sdbj			panic("writeback: MOVE16 with WB1S valid");
7921.1Sdbj		wbstats.move16s++;
7931.1Sdbj#endif
7941.1Sdbj		if (KDFAULT(f->f_wb1s))
7951.1Sdbj			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
7961.1Sdbj		else
7971.1Sdbj			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
7981.1Sdbj		if (err) {
7991.1Sdbj			fa = f->f_fa & ~0xF;
8001.1Sdbj#ifdef DEBUG
8011.1Sdbj			if (mmudebug & MDB_WBFAILED)
8021.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8031.1Sdbj				       "MOVE16", fp->f_pc, f->f_fa,
8041.1Sdbj				       f->f_fa & ~0xF, f->f_pd0);
8051.1Sdbj#endif
8061.1Sdbj		}
8071.1Sdbj	} else if (f->f_wb1s & SSW4_WBSV) {
8081.1Sdbj		/*
8091.1Sdbj		 * Writeback #1.
8101.1Sdbj		 * Position the "memory-aligned" data and write it out.
8111.1Sdbj		 */
8121.1Sdbj		u_int wb1d = f->f_wb1d;
8131.1Sdbj		int off;
8141.1Sdbj
8151.1Sdbj#ifdef DEBUG
8161.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
8171.1Sdbj			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
8181.1Sdbj		wbstats.wb1s++;
8191.1Sdbj		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
8201.1Sdbj#endif
8211.1Sdbj		off = (f->f_wb1a & 3) * 8;
8221.1Sdbj		switch (f->f_wb1s & SSW4_SZMASK) {
8231.1Sdbj		case SSW4_SZLW:
8241.1Sdbj			if (off)
8251.1Sdbj				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
8261.1Sdbj			if (KDFAULT(f->f_wb1s))
8271.1Sdbj				*(long *)f->f_wb1a = wb1d;
8281.1Sdbj			else
8291.1Sdbj				err = suword((caddr_t)f->f_wb1a, wb1d);
8301.1Sdbj			break;
8311.1Sdbj		case SSW4_SZB:
8321.1Sdbj			off = 24 - off;
8331.1Sdbj			if (off)
8341.1Sdbj				wb1d >>= off;
8351.1Sdbj			if (KDFAULT(f->f_wb1s))
8361.1Sdbj				*(char *)f->f_wb1a = wb1d;
8371.1Sdbj			else
8381.1Sdbj				err = subyte((caddr_t)f->f_wb1a, wb1d);
8391.1Sdbj			break;
8401.1Sdbj		case SSW4_SZW:
8411.1Sdbj			off = (off + 16) % 32;
8421.1Sdbj			if (off)
8431.1Sdbj				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
8441.1Sdbj			if (KDFAULT(f->f_wb1s))
8451.1Sdbj				*(short *)f->f_wb1a = wb1d;
8461.1Sdbj			else
8471.1Sdbj				err = susword((caddr_t)f->f_wb1a, wb1d);
8481.1Sdbj			break;
8491.1Sdbj		}
8501.1Sdbj		if (err) {
8511.1Sdbj			fa = f->f_wb1a;
8521.1Sdbj#ifdef DEBUG
8531.1Sdbj			if (mmudebug & MDB_WBFAILED)
8541.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8551.1Sdbj				       "#1", fp->f_pc, f->f_fa,
8561.1Sdbj				       f->f_wb1a, f->f_wb1d);
8571.1Sdbj#endif
8581.1Sdbj		}
8591.1Sdbj	}
8601.1Sdbj	/*
8611.1Sdbj	 * Deal with the "normal" writebacks.
8621.1Sdbj	 *
8631.1Sdbj	 * XXX writeback2 is known to reflect a LINE size writeback after
8641.1Sdbj	 * a MOVE16 was already dealt with above.  Ignore it.
8651.1Sdbj	 */
8661.1Sdbj	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
8671.1Sdbj	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
8681.1Sdbj#ifdef DEBUG
8691.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
8701.1Sdbj			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
8711.1Sdbj		wbstats.wb2s++;
8721.1Sdbj		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
8731.1Sdbj#endif
8741.1Sdbj		switch (f->f_wb2s & SSW4_SZMASK) {
8751.1Sdbj		case SSW4_SZLW:
8761.1Sdbj			if (KDFAULT(f->f_wb2s))
8771.1Sdbj				*(long *)f->f_wb2a = f->f_wb2d;
8781.1Sdbj			else
8791.1Sdbj				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
8801.1Sdbj			break;
8811.1Sdbj		case SSW4_SZB:
8821.1Sdbj			if (KDFAULT(f->f_wb2s))
8831.1Sdbj				*(char *)f->f_wb2a = f->f_wb2d;
8841.1Sdbj			else
8851.1Sdbj				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
8861.1Sdbj			break;
8871.1Sdbj		case SSW4_SZW:
8881.1Sdbj			if (KDFAULT(f->f_wb2s))
8891.1Sdbj				*(short *)f->f_wb2a = f->f_wb2d;
8901.1Sdbj			else
8911.1Sdbj				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
8921.1Sdbj			break;
8931.1Sdbj		}
8941.1Sdbj		if (err) {
8951.1Sdbj			fa = f->f_wb2a;
8961.1Sdbj#ifdef DEBUG
8971.1Sdbj			if (mmudebug & MDB_WBFAILED) {
8981.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8991.1Sdbj				       "#2", fp->f_pc, f->f_fa,
9001.1Sdbj				       f->f_wb2a, f->f_wb2d);
9011.1Sdbj				dumpssw(f->f_ssw);
9021.1Sdbj				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
9031.1Sdbj			}
9041.1Sdbj#endif
9051.1Sdbj		}
9061.1Sdbj	}
9071.1Sdbj	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
9081.1Sdbj#ifdef DEBUG
9091.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
9101.1Sdbj			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
9111.1Sdbj		wbstats.wb3s++;
9121.1Sdbj		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
9131.1Sdbj#endif
9141.1Sdbj		switch (f->f_wb3s & SSW4_SZMASK) {
9151.1Sdbj		case SSW4_SZLW:
9161.1Sdbj			if (KDFAULT(f->f_wb3s))
9171.1Sdbj				*(long *)f->f_wb3a = f->f_wb3d;
9181.1Sdbj			else
9191.1Sdbj				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
9201.1Sdbj			break;
9211.1Sdbj		case SSW4_SZB:
9221.1Sdbj			if (KDFAULT(f->f_wb3s))
9231.1Sdbj				*(char *)f->f_wb3a = f->f_wb3d;
9241.1Sdbj			else
9251.1Sdbj				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
9261.1Sdbj			break;
9271.1Sdbj		case SSW4_SZW:
9281.1Sdbj			if (KDFAULT(f->f_wb3s))
9291.1Sdbj				*(short *)f->f_wb3a = f->f_wb3d;
9301.1Sdbj			else
9311.1Sdbj				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
9321.1Sdbj			break;
9331.1Sdbj#ifdef DEBUG
9341.1Sdbj		case SSW4_SZLN:
9351.1Sdbj			panic("writeback: wb3s indicates LINE write");
9361.1Sdbj#endif
9371.1Sdbj		}
9381.1Sdbj		if (err) {
9391.1Sdbj			fa = f->f_wb3a;
9401.1Sdbj#ifdef DEBUG
9411.1Sdbj			if (mmudebug & MDB_WBFAILED)
9421.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
9431.1Sdbj				       "#3", fp->f_pc, f->f_fa,
9441.1Sdbj				       f->f_wb3a, f->f_wb3d);
9451.1Sdbj#endif
9461.1Sdbj		}
9471.1Sdbj	}
9481.1Sdbj	p->p_addr->u_pcb.pcb_onfault = oonfault;
9491.1Sdbj	if (err)
9501.1Sdbj		err = SIGSEGV;
9511.16Sdbj	return (err);
9521.1Sdbj}
9531.1Sdbj
9541.1Sdbj#ifdef DEBUG
9551.16Sdbjvoid
9561.1Sdbjdumpssw(ssw)
9571.1Sdbj	u_short ssw;
9581.1Sdbj{
9591.1Sdbj	printf(" SSW: %x: ", ssw);
9601.1Sdbj	if (ssw & SSW4_CP)
9611.1Sdbj		printf("CP,");
9621.1Sdbj	if (ssw & SSW4_CU)
9631.1Sdbj		printf("CU,");
9641.1Sdbj	if (ssw & SSW4_CT)
9651.1Sdbj		printf("CT,");
9661.1Sdbj	if (ssw & SSW4_CM)
9671.1Sdbj		printf("CM,");
9681.1Sdbj	if (ssw & SSW4_MA)
9691.1Sdbj		printf("MA,");
9701.1Sdbj	if (ssw & SSW4_ATC)
9711.1Sdbj		printf("ATC,");
9721.1Sdbj	if (ssw & SSW4_LK)
9731.1Sdbj		printf("LK,");
9741.1Sdbj	if (ssw & SSW4_RW)
9751.1Sdbj		printf("RW,");
9761.1Sdbj	printf(" SZ=%s, TT=%s, TM=%s\n",
9771.1Sdbj	       f7sz[(ssw & SSW4_SZMASK) >> 5],
9781.1Sdbj	       f7tt[(ssw & SSW4_TTMASK) >> 3],
9791.1Sdbj	       f7tm[ssw & SSW4_TMMASK]);
9801.1Sdbj}
9811.1Sdbj
9821.16Sdbjvoid
9831.1Sdbjdumpwb(num, s, a, d)
9841.1Sdbj	int num;
9851.1Sdbj	u_short s;
9861.1Sdbj	u_int a, d;
9871.1Sdbj{
9881.1Sdbj	struct proc *p = curproc;
9891.7Sdbj	paddr_t pa;
9901.1Sdbj
9911.1Sdbj	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
9921.1Sdbj	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
9931.1Sdbj	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
9941.16Sdbj	printf("               PA ");
9951.15Sthorpej	if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE)
9961.1Sdbj		printf("<invalid address>");
9971.1Sdbj	else
9981.16Sdbj		printf("%lx, current value %lx", pa, fuword((caddr_t)a));
9991.1Sdbj	printf("\n");
10001.1Sdbj}
10011.1Sdbj#endif
10021.1Sdbj#endif
10031.1Sdbj
10041.1Sdbj/*
10051.1Sdbj * Allocation routines for software interrupts.
10061.1Sdbj */
10071.1Sdbju_long
10081.1Sdbjallocate_sir(proc, arg)
10091.16Sdbj	void (*proc)(void *);
10101.1Sdbj	void *arg;
10111.1Sdbj{
10121.1Sdbj	int bit;
10131.1Sdbj
10141.1Sdbj	if( next_sir >= NSIR )
10151.1Sdbj		panic("allocate_sir: none left");
10161.1Sdbj	bit = next_sir++;
10171.1Sdbj	sir_routines[bit] = proc;
10181.1Sdbj	sir_args[bit] = arg;
10191.1Sdbj	return (1 << bit);
10201.1Sdbj}
10211.1Sdbj
10221.1Sdbjvoid
10231.1Sdbjinit_sir()
10241.1Sdbj{
10251.16Sdbj	extern void netintr(void);
10261.1Sdbj
10271.16Sdbj	sir_routines[0] = (void (*)(void *))netintr;
10281.30Sthorpej	sir_routines[1] = softclock;
10291.1Sdbj	next_sir = 2;
10301.1Sdbj}
1031