trap.c revision 1.4
11.4Sthorpej/*	$NetBSD: trap.c,v 1.4 1998/06/25 23:58:48 thorpej Exp $	*/
21.1Sdbj
31.1Sdbj/*
41.1Sdbj * Copyright (c) 1988 University of Utah.
51.1Sdbj * Copyright (c) 1982, 1986, 1990, 1993
61.1Sdbj *	The Regents of the University of California.  All rights reserved.
71.1Sdbj *
81.1Sdbj * This code is derived from software contributed to Berkeley by
91.1Sdbj * the Systems Programming Group of the University of Utah Computer
101.1Sdbj * Science Department.
111.1Sdbj *
121.1Sdbj * Redistribution and use in source and binary forms, with or without
131.1Sdbj * modification, are permitted provided that the following conditions
141.1Sdbj * are met:
151.1Sdbj * 1. Redistributions of source code must retain the above copyright
161.1Sdbj *    notice, this list of conditions and the following disclaimer.
171.1Sdbj * 2. Redistributions in binary form must reproduce the above copyright
181.1Sdbj *    notice, this list of conditions and the following disclaimer in the
191.1Sdbj *    documentation and/or other materials provided with the distribution.
201.1Sdbj * 3. All advertising materials mentioning features or use of this software
211.1Sdbj *    must display the following acknowledgement:
221.1Sdbj *	This product includes software developed by the University of
231.1Sdbj *	California, Berkeley and its contributors.
241.1Sdbj * 4. Neither the name of the University nor the names of its contributors
251.1Sdbj *    may be used to endorse or promote products derived from this software
261.1Sdbj *    without specific prior written permission.
271.1Sdbj *
281.1Sdbj * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
291.1Sdbj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
301.1Sdbj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
311.1Sdbj * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
321.1Sdbj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
331.1Sdbj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
341.1Sdbj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
351.1Sdbj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
361.1Sdbj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
371.1Sdbj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
381.1Sdbj * SUCH DAMAGE.
391.1Sdbj *
401.1Sdbj * from: Utah $Hdr: trap.c 1.37 92/12/20$
411.1Sdbj *
421.1Sdbj *	@(#)trap.c	8.5 (Berkeley) 1/4/94
431.1Sdbj */
441.2Sthorpej
451.2Sthorpej#include "opt_ktrace.h"
461.3Sthorpej#include "opt_compat_sunos.h"
471.4Sthorpej#include "opt_compat_hpux.h"
481.1Sdbj
491.1Sdbj#if 0
501.1Sdbj#include <machine/hp300spu.h>	/* XXX param.h includes cpu.h */
511.1Sdbj#endif
521.1Sdbj
531.1Sdbj#include <sys/param.h>
541.1Sdbj#include <sys/systm.h>
551.1Sdbj#include <sys/proc.h>
561.1Sdbj#include <sys/acct.h>
571.1Sdbj#include <sys/kernel.h>
581.1Sdbj#include <sys/signalvar.h>
591.1Sdbj#include <sys/resourcevar.h>
601.1Sdbj#include <sys/syscall.h>
611.1Sdbj#include <sys/syslog.h>
621.1Sdbj#include <sys/user.h>
631.1Sdbj#ifdef KTRACE
641.1Sdbj#include <sys/ktrace.h>
651.1Sdbj#endif
661.1Sdbj
671.1Sdbj#include <m68k/frame.h>
681.1Sdbj
691.1Sdbj#include <machine/db_machdep.h>
701.1Sdbj#include <machine/psl.h>
711.1Sdbj#include <machine/trap.h>
721.1Sdbj#include <machine/cpu.h>
731.1Sdbj#include <machine/reg.h>
741.1Sdbj#include <machine/intr.h>
751.1Sdbj
761.1Sdbj#include <vm/vm.h>
771.1Sdbj#include <vm/pmap.h>
781.1Sdbj
791.1Sdbj#include <dev/cons.h>
801.1Sdbj
811.1Sdbj#ifdef COMPAT_HPUX
821.1Sdbj#include <compat/hpux/hpux.h>
831.1Sdbjextern struct emul emul_hpux;
841.1Sdbj#endif
851.1Sdbj
861.1Sdbj#ifdef COMPAT_SUNOS
871.1Sdbj#include <compat/sunos/sunos_syscall.h>
881.1Sdbjextern struct emul emul_sunos;
891.1Sdbj#endif
901.1Sdbj
911.1Sdbjint	writeback __P((struct frame *fp, int docachepush));
921.1Sdbjvoid	trap __P((int type, u_int code, u_int v, struct frame frame));
931.1Sdbjvoid	syscall __P((register_t code, struct frame frame));
941.1Sdbjvoid	child_return __P((struct proc *, struct frame));
951.1Sdbj
961.1Sdbj#ifdef DEBUG
971.1Sdbjvoid	dumpssw __P((u_short));
981.1Sdbjvoid	dumpwb __P((int, u_short, u_int, u_int));
991.1Sdbj#endif
1001.1Sdbj
1011.1Sdbjstatic inline void userret __P((struct proc *p, struct frame *fp,
1021.1Sdbj	    u_quad_t oticks, u_int faultaddr, int fromtrap));
1031.1Sdbj
1041.1Sdbjchar	*trap_type[] = {
1051.1Sdbj	"Bus error",
1061.1Sdbj	"Address error",
1071.1Sdbj	"Illegal instruction",
1081.1Sdbj	"Zero divide",
1091.1Sdbj	"CHK instruction",
1101.1Sdbj	"TRAPV instruction",
1111.1Sdbj	"Privilege violation",
1121.1Sdbj	"Trace trap",
1131.1Sdbj	"MMU fault",
1141.1Sdbj	"SSIR trap",
1151.1Sdbj	"Format error",
1161.1Sdbj	"68881 exception",
1171.1Sdbj	"Coprocessor violation",
1181.1Sdbj	"Async system trap"
1191.1Sdbj};
1201.1Sdbjint	trap_types = sizeof trap_type / sizeof trap_type[0];
1211.1Sdbj
1221.1Sdbj/*
1231.1Sdbj * Size of various exception stack frames (minus the standard 8 bytes)
1241.1Sdbj */
1251.1Sdbjshort	exframesize[] = {
1261.1Sdbj	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
1271.1Sdbj	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
1281.1Sdbj	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
1291.1Sdbj	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
1301.1Sdbj	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
1311.1Sdbj	-1, -1,		/* type 5-6 - undefined */
1321.1Sdbj	FMT7SIZE,	/* type 7 - access error (68040) */
1331.1Sdbj	58,		/* type 8 - bus fault (68010) */
1341.1Sdbj	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
1351.1Sdbj	FMTASIZE,	/* type A - short bus fault (68020/030) */
1361.1Sdbj	FMTBSIZE,	/* type B - long bus fault (68020/030) */
1371.1Sdbj	-1, -1, -1, -1	/* type C-F - undefined */
1381.1Sdbj};
1391.1Sdbj
1401.1Sdbj#ifdef M68060
1411.1Sdbj#define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
1421.1Sdbj#define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
1431.1Sdbj#else
1441.1Sdbj#define	KDFAULT_060(c)	0
1451.1Sdbj#define	WRFAULT_060(c)	0
1461.1Sdbj#endif
1471.1Sdbj
1481.1Sdbj#ifdef M68040
1491.1Sdbj#define	KDFAULT_040(c)	(cputype == CPU_68040 && \
1501.1Sdbj			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
1511.1Sdbj#define	WRFAULT_040(c)	(cputype == CPU_68040 && \
1521.1Sdbj			 ((c) & SSW4_RW) == 0)
1531.1Sdbj#else
1541.1Sdbj#define	KDFAULT_040(c)	0
1551.1Sdbj#define	WRFAULT_040(c)	0
1561.1Sdbj#endif
1571.1Sdbj
1581.1Sdbj#if defined(M68030) || defined(M68020)
1591.1Sdbj#define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
1601.1Sdbj			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
1611.1Sdbj#define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
1621.1Sdbj			 ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
1631.1Sdbj#else
1641.1Sdbj#define	KDFAULT_OTH(c)	0
1651.1Sdbj#define	WRFAULT_OTH(c)	0
1661.1Sdbj#endif
1671.1Sdbj
1681.1Sdbj#define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
1691.1Sdbj#define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
1701.1Sdbj
1711.1Sdbj#ifdef DEBUG
1721.1Sdbjint mmudebug = 0;
1731.1Sdbjint mmupid = -1;
1741.1Sdbj#define MDB_FOLLOW	1
1751.1Sdbj#define MDB_WBFOLLOW	2
1761.1Sdbj#define MDB_WBFAILED	4
1771.1Sdbj#define MDB_ISPID(p)	((p) == mmupid)
1781.1Sdbj#endif
1791.1Sdbj
1801.1Sdbj#define NSIR	32
1811.1Sdbjvoid (*sir_routines[NSIR])();
1821.1Sdbjvoid *sir_args[NSIR];
1831.1Sdbjint next_sir;
1841.1Sdbj
1851.1Sdbj/*
1861.1Sdbj * trap and syscall both need the following work done before returning
1871.1Sdbj * to user mode.
1881.1Sdbj */
1891.1Sdbjstatic inline void
1901.1Sdbjuserret(p, fp, oticks, faultaddr, fromtrap)
1911.1Sdbj	struct proc *p;
1921.1Sdbj	struct frame *fp;
1931.1Sdbj	u_quad_t oticks;
1941.1Sdbj	u_int faultaddr;
1951.1Sdbj	int fromtrap;
1961.1Sdbj{
1971.1Sdbj	int sig, s;
1981.1Sdbj#ifdef M68040
1991.1Sdbj	int beenhere = 0;
2001.1Sdbj
2011.1Sdbjagain:
2021.1Sdbj#endif
2031.1Sdbj	/* take pending signals */
2041.1Sdbj	while ((sig = CURSIG(p)) != 0)
2051.1Sdbj		postsig(sig);
2061.1Sdbj	p->p_priority = p->p_usrpri;
2071.1Sdbj	if (want_resched) {
2081.1Sdbj		/*
2091.1Sdbj		 * Since we are curproc, clock will normally just change
2101.1Sdbj		 * our priority without moving us from one queue to another
2111.1Sdbj		 * (since the running process is not on a queue.)
2121.1Sdbj		 * If that happened after we put ourselves on the run queue
2131.1Sdbj		 * but before we mi_switch()'ed, we might not be on the queue
2141.1Sdbj		 * indicated by our priority.
2151.1Sdbj		 */
2161.1Sdbj		s = splstatclock();
2171.1Sdbj		setrunqueue(p);
2181.1Sdbj		p->p_stats->p_ru.ru_nivcsw++;
2191.1Sdbj		mi_switch();
2201.1Sdbj		splx(s);
2211.1Sdbj		while ((sig = CURSIG(p)) != 0)
2221.1Sdbj			postsig(sig);
2231.1Sdbj	}
2241.1Sdbj
2251.1Sdbj	/*
2261.1Sdbj	 * If profiling, charge system time to the trapped pc.
2271.1Sdbj	 */
2281.1Sdbj	if (p->p_flag & P_PROFIL) {
2291.1Sdbj		extern int psratio;
2301.1Sdbj
2311.1Sdbj		addupc_task(p, fp->f_pc,
2321.1Sdbj			    (int)(p->p_sticks - oticks) * psratio);
2331.1Sdbj	}
2341.1Sdbj#ifdef M68040
2351.1Sdbj	/*
2361.1Sdbj	 * Deal with user mode writebacks (from trap, or from sigreturn).
2371.1Sdbj	 * If any writeback fails, go back and attempt signal delivery.
2381.1Sdbj	 * unless we have already been here and attempted the writeback
2391.1Sdbj	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
2401.1Sdbj	 * we just return to the user without sucessfully completing
2411.1Sdbj	 * the writebacks.  Maybe we should just drop the sucker?
2421.1Sdbj	 */
2431.1Sdbj	if (cputype == CPU_68040 && fp->f_format == FMT7) {
2441.1Sdbj		if (beenhere) {
2451.1Sdbj#ifdef DEBUG
2461.1Sdbj			if (mmudebug & MDB_WBFAILED)
2471.1Sdbj				printf(fromtrap ?
2481.1Sdbj		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
2491.1Sdbj		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
2501.1Sdbj				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
2511.1Sdbj#endif
2521.1Sdbj		} else if ((sig = writeback(fp, fromtrap))) {
2531.1Sdbj			beenhere = 1;
2541.1Sdbj			oticks = p->p_sticks;
2551.1Sdbj			trapsignal(p, sig, faultaddr);
2561.1Sdbj			goto again;
2571.1Sdbj		}
2581.1Sdbj	}
2591.1Sdbj#endif
2601.1Sdbj	curpriority = p->p_priority;
2611.1Sdbj}
2621.1Sdbj
2631.1Sdbj/*
2641.1Sdbj * Trap is called from locore to handle most types of processor traps,
2651.1Sdbj * including events such as simulated software interrupts/AST's.
2661.1Sdbj * System calls are broken out for efficiency.
2671.1Sdbj */
2681.1Sdbj/*ARGSUSED*/
2691.1Sdbjvoid
2701.1Sdbjtrap(type, code, v, frame)
2711.1Sdbj	int type;
2721.1Sdbj	unsigned code;
2731.1Sdbj	unsigned v;
2741.1Sdbj	struct frame frame;
2751.1Sdbj{
2761.1Sdbj	extern char fubail[], subail[];
2771.1Sdbj	struct proc *p;
2781.1Sdbj	int i, s;
2791.1Sdbj        int bit;
2801.1Sdbj	u_int ucode;
2811.1Sdbj	u_quad_t sticks = 0 /* XXX initializer works around compiler bug */;
2821.1Sdbj
2831.1Sdbj	cnt.v_trap++;
2841.1Sdbj	p = curproc;
2851.1Sdbj	ucode = 0;
2861.1Sdbj
2871.1Sdbj	/* I have verified that this DOES happen! -gwr */
2881.1Sdbj	if (p == NULL)
2891.1Sdbj		p = &proc0;
2901.1Sdbj#ifdef DIAGNOSTIC
2911.1Sdbj	if (p->p_addr == NULL)
2921.1Sdbj		panic("trap: no pcb");
2931.1Sdbj#endif
2941.1Sdbj
2951.1Sdbj	if (USERMODE(frame.f_sr)) {
2961.1Sdbj		type |= T_USER;
2971.1Sdbj		sticks = p->p_sticks;
2981.1Sdbj		p->p_md.md_regs = frame.f_regs;
2991.1Sdbj	}
3001.1Sdbj	switch (type) {
3011.1Sdbj
3021.1Sdbj	default:
3031.1Sdbj	dopanic:
3041.1Sdbj		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
3051.1Sdbj		printf("%s program counter = 0x%x\n",
3061.1Sdbj		    (type & T_USER) ? "user" : "kernel", frame.f_pc);
3071.1Sdbj		/*
3081.1Sdbj		 * Let the kernel debugger see the trap frame that
3091.1Sdbj		 * caused us to panic.  This is a convenience so
3101.1Sdbj		 * one can see registers at the point of failure.
3111.1Sdbj		 */
3121.1Sdbj		s = splhigh();
3131.1Sdbj#ifdef KGDB
3141.1Sdbj		/* If connected, step or cont returns 1 */
3151.1Sdbj		if (kgdb_trap(type, &frame))
3161.1Sdbj			goto kgdb_cont;
3171.1Sdbj#endif
3181.1Sdbj#ifdef DDB
3191.1Sdbj		(void)kdb_trap(type, (db_regs_t *)&frame);
3201.1Sdbj#endif
3211.1Sdbj#ifdef KGDB
3221.1Sdbj	kgdb_cont:
3231.1Sdbj#endif
3241.1Sdbj		splx(s);
3251.1Sdbj		if (panicstr) {
3261.1Sdbj			printf("trap during panic!\n");
3271.1Sdbj#ifdef DEBUG
3281.1Sdbj			/* XXX should be a machine-dependent hook */
3291.1Sdbj			printf("(press a key)\n"); (void)cngetc();
3301.1Sdbj#endif
3311.1Sdbj		}
3321.1Sdbj		regdump((struct trapframe *)&frame, 128);
3331.1Sdbj		type &= ~T_USER;
3341.1Sdbj		if ((u_int)type < trap_types)
3351.1Sdbj			panic(trap_type[type]);
3361.1Sdbj		panic("trap");
3371.1Sdbj
3381.1Sdbj	case T_BUSERR:		/* kernel bus error */
3391.1Sdbj		if (p->p_addr->u_pcb.pcb_onfault == 0)
3401.1Sdbj			goto dopanic;
3411.1Sdbj		/* FALLTHROUGH */
3421.1Sdbj
3431.1Sdbj	copyfault:
3441.1Sdbj		/*
3451.1Sdbj		 * If we have arranged to catch this fault in any of the
3461.1Sdbj		 * copy to/from user space routines, set PC to return to
3471.1Sdbj		 * indicated location and set flag informing buserror code
3481.1Sdbj		 * that it may need to clean up stack frame.
3491.1Sdbj		 */
3501.1Sdbj		frame.f_stackadj = exframesize[frame.f_format];
3511.1Sdbj		frame.f_format = frame.f_vector = 0;
3521.1Sdbj		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
3531.1Sdbj		return;
3541.1Sdbj
3551.1Sdbj	case T_BUSERR|T_USER:	/* bus error */
3561.1Sdbj	case T_ADDRERR|T_USER:	/* address error */
3571.1Sdbj		ucode = v;
3581.1Sdbj		i = SIGBUS;
3591.1Sdbj		break;
3601.1Sdbj
3611.1Sdbj	case T_COPERR:		/* kernel coprocessor violation */
3621.1Sdbj	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
3631.1Sdbj	case T_FMTERR:		/* ...just in case... */
3641.1Sdbj	/*
3651.1Sdbj	 * The user has most likely trashed the RTE or FP state info
3661.1Sdbj	 * in the stack frame of a signal handler.
3671.1Sdbj	 */
3681.1Sdbj		printf("pid %d: kernel %s exception\n", p->p_pid,
3691.1Sdbj		       type==T_COPERR ? "coprocessor" : "format");
3701.1Sdbj		type |= T_USER;
3711.1Sdbj		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
3721.1Sdbj		i = sigmask(SIGILL);
3731.1Sdbj		p->p_sigignore &= ~i;
3741.1Sdbj		p->p_sigcatch &= ~i;
3751.1Sdbj		p->p_sigmask &= ~i;
3761.1Sdbj		i = SIGILL;
3771.1Sdbj		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
3781.1Sdbj		break;
3791.1Sdbj
3801.1Sdbj	case T_COPERR|T_USER:	/* user coprocessor violation */
3811.1Sdbj	/* What is a proper response here? */
3821.1Sdbj		ucode = 0;
3831.1Sdbj		i = SIGFPE;
3841.1Sdbj		break;
3851.1Sdbj
3861.1Sdbj	case T_FPERR|T_USER:	/* 68881 exceptions */
3871.1Sdbj	/*
3881.1Sdbj	 * We pass along the 68881 status which locore stashed
3891.1Sdbj	 * in code for us.  Note that there is a possibility that the
3901.1Sdbj	 * bit pattern of this will conflict with one of the
3911.1Sdbj	 * FPE_* codes defined in signal.h.  Fortunately for us, the
3921.1Sdbj	 * only such codes we use are all in the range 1-7 and the low
3931.1Sdbj	 * 3 bits of the status are defined as 0 so there is
3941.1Sdbj	 * no clash.
3951.1Sdbj	 */
3961.1Sdbj		ucode = code;
3971.1Sdbj		i = SIGFPE;
3981.1Sdbj		break;
3991.1Sdbj
4001.1Sdbj#ifdef M68040
4011.1Sdbj	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
4021.1Sdbj	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
4031.1Sdbj		/* XXX need to FSAVE */
4041.1Sdbj		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
4051.1Sdbj		       p->p_pid, p->p_comm,
4061.1Sdbj		       frame.f_format == 2 ? "instruction" : "data type",
4071.1Sdbj		       frame.f_pc, frame.f_fmt2.f_iaddr);
4081.1Sdbj		/* XXX need to FRESTORE */
4091.1Sdbj		i = SIGFPE;
4101.1Sdbj		break;
4111.1Sdbj#endif
4121.1Sdbj
4131.1Sdbj	case T_ILLINST|T_USER:	/* illegal instruction fault */
4141.1Sdbj#ifdef COMPAT_HPUX
4151.1Sdbj		if (p->p_emul == &emul_hpux) {
4161.1Sdbj			ucode = HPUX_ILL_ILLINST_TRAP;
4171.1Sdbj			i = SIGILL;
4181.1Sdbj			break;
4191.1Sdbj		}
4201.1Sdbj		/* fall through */
4211.1Sdbj#endif
4221.1Sdbj	case T_PRIVINST|T_USER:	/* privileged instruction fault */
4231.1Sdbj#ifdef COMPAT_HPUX
4241.1Sdbj		if (p->p_emul == &emul_hpux)
4251.1Sdbj			ucode = HPUX_ILL_PRIV_TRAP;
4261.1Sdbj		else
4271.1Sdbj#endif
4281.1Sdbj		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
4291.1Sdbj		i = SIGILL;
4301.1Sdbj		break;
4311.1Sdbj
4321.1Sdbj	case T_ZERODIV|T_USER:	/* Divide by zero */
4331.1Sdbj#ifdef COMPAT_HPUX
4341.1Sdbj		if (p->p_emul == &emul_hpux)
4351.1Sdbj			ucode = HPUX_FPE_INTDIV_TRAP;
4361.1Sdbj		else
4371.1Sdbj#endif
4381.1Sdbj		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
4391.1Sdbj		i = SIGFPE;
4401.1Sdbj		break;
4411.1Sdbj
4421.1Sdbj	case T_CHKINST|T_USER:	/* CHK instruction trap */
4431.1Sdbj#ifdef COMPAT_HPUX
4441.1Sdbj		if (p->p_emul == &emul_hpux) {
4451.1Sdbj			/* handled differently under hp-ux */
4461.1Sdbj			i = SIGILL;
4471.1Sdbj			ucode = HPUX_ILL_CHK_TRAP;
4481.1Sdbj			break;
4491.1Sdbj		}
4501.1Sdbj#endif
4511.1Sdbj		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
4521.1Sdbj		i = SIGFPE;
4531.1Sdbj		break;
4541.1Sdbj
4551.1Sdbj	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
4561.1Sdbj#ifdef COMPAT_HPUX
4571.1Sdbj		if (p->p_emul == &emul_hpux) {
4581.1Sdbj			/* handled differently under hp-ux */
4591.1Sdbj			i = SIGILL;
4601.1Sdbj			ucode = HPUX_ILL_TRAPV_TRAP;
4611.1Sdbj			break;
4621.1Sdbj		}
4631.1Sdbj#endif
4641.1Sdbj		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
4651.1Sdbj		i = SIGFPE;
4661.1Sdbj		break;
4671.1Sdbj
4681.1Sdbj	/*
4691.1Sdbj	 * XXX: Trace traps are a nightmare.
4701.1Sdbj	 *
4711.1Sdbj	 *	HP-UX uses trap #1 for breakpoints,
4721.1Sdbj	 *	NetBSD/m68k uses trap #2,
4731.1Sdbj	 *	SUN 3.x uses trap #15,
4741.1Sdbj	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
4751.1Sdbj	 *	handled elsewhere).
4761.1Sdbj	 *
4771.1Sdbj	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
4781.1Sdbj	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
4791.1Sdbj	 * supported yet.
4801.1Sdbj	 *
4811.1Sdbj	 * XXX: We should never get kernel-mode T_TRACE or T_TRAP15
4821.1Sdbj	 * XXX: because locore.s now gives them special treatment.
4831.1Sdbj	 */
4841.1Sdbj	case T_TRACE:		/* kernel trace trap */
4851.1Sdbj	case T_TRAP15:		/* kernel breakpoint */
4861.1Sdbj#ifdef DEBUG
4871.1Sdbj		printf("unexpected kernel trace trap, type = %d\n", type);
4881.1Sdbj		printf("program counter = 0x%x\n", frame.f_pc);
4891.1Sdbj#endif
4901.1Sdbj		frame.f_sr &= ~PSL_T;
4911.1Sdbj		return;
4921.1Sdbj
4931.1Sdbj	case T_TRACE|T_USER:	/* user trace trap */
4941.1Sdbj	case T_TRAP15|T_USER:	/* SUN user trace trap */
4951.1Sdbj#ifdef COMPAT_SUNOS
4961.1Sdbj		/*
4971.1Sdbj		 * SunOS uses Trap #2 for a "CPU cache flush".
4981.1Sdbj		 * Just flush the on-chip caches and return.
4991.1Sdbj		 */
5001.1Sdbj		if (p->p_emul == &emul_sunos) {
5011.1Sdbj			ICIA();
5021.1Sdbj			DCIU();
5031.1Sdbj			return;
5041.1Sdbj		}
5051.1Sdbj#endif
5061.1Sdbj		frame.f_sr &= ~PSL_T;
5071.1Sdbj		i = SIGTRAP;
5081.1Sdbj		break;
5091.1Sdbj
5101.1Sdbj	case T_ASTFLT:		/* system async trap, cannot happen */
5111.1Sdbj		goto dopanic;
5121.1Sdbj
5131.1Sdbj	case T_ASTFLT|T_USER:	/* user async trap */
5141.1Sdbj		astpending = 0;
5151.1Sdbj		/*
5161.1Sdbj		 * We check for software interrupts first.  This is because
5171.1Sdbj		 * they are at a higher level than ASTs, and on a VAX would
5181.1Sdbj		 * interrupt the AST.  We assume that if we are processing
5191.1Sdbj		 * an AST that we must be at IPL0 so we don't bother to
5201.1Sdbj		 * check.  Note that we ensure that we are at least at SIR
5211.1Sdbj		 * IPL while processing the SIR.
5221.1Sdbj		 */
5231.1Sdbj		spl1();
5241.1Sdbj		/* fall into... */
5251.1Sdbj
5261.1Sdbj	case T_SSIR:		/* software interrupt */
5271.1Sdbj	case T_SSIR|T_USER:
5281.1Sdbj		while (bit = ffs(ssir)) {
5291.1Sdbj			--bit;
5301.1Sdbj			ssir &= ~(1 << bit);
5311.1Sdbj			cnt.v_soft++;
5321.1Sdbj			if (sir_routines[bit])
5331.1Sdbj				sir_routines[bit](sir_args[bit]);
5341.1Sdbj		}
5351.1Sdbj
5361.1Sdbj		/*
5371.1Sdbj		 * If this was not an AST trap, we are all done.
5381.1Sdbj		 */
5391.1Sdbj		if (type != (T_ASTFLT|T_USER)) {
5401.1Sdbj			cnt.v_trap--;
5411.1Sdbj			return;
5421.1Sdbj		}
5431.1Sdbj		spl0();
5441.1Sdbj		if (p->p_flag & P_OWEUPC) {
5451.1Sdbj			p->p_flag &= ~P_OWEUPC;
5461.1Sdbj			ADDUPROF(p);
5471.1Sdbj		}
5481.1Sdbj		goto out;
5491.1Sdbj
5501.1Sdbj	case T_MMUFLT:		/* kernel mode page fault */
5511.1Sdbj		/*
5521.1Sdbj		 * If we were doing profiling ticks or other user mode
5531.1Sdbj		 * stuff from interrupt code, Just Say No.
5541.1Sdbj		 */
5551.1Sdbj		if (p->p_addr->u_pcb.pcb_onfault == fubail ||
5561.1Sdbj		    p->p_addr->u_pcb.pcb_onfault == subail)
5571.1Sdbj			goto copyfault;
5581.1Sdbj		/* fall into ... */
5591.1Sdbj
5601.1Sdbj	case T_MMUFLT|T_USER:	/* page fault */
5611.1Sdbj	    {
5621.1Sdbj		vm_offset_t va;
5631.1Sdbj		struct vmspace *vm = p->p_vmspace;
5641.1Sdbj		vm_map_t map;
5651.1Sdbj		int rv;
5661.1Sdbj		vm_prot_t ftype;
5671.1Sdbj		extern vm_map_t kernel_map;
5681.1Sdbj
5691.1Sdbj#ifdef DEBUG
5701.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
5711.1Sdbj		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
5721.1Sdbj		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
5731.1Sdbj#endif
5741.1Sdbj		/*
5751.1Sdbj		 * It is only a kernel address space fault iff:
5761.1Sdbj		 * 	1. (type & T_USER) == 0  and
5771.1Sdbj		 * 	2. pcb_onfault not set or
5781.1Sdbj		 *	3. pcb_onfault set but supervisor space data fault
5791.1Sdbj		 * The last can occur during an exec() copyin where the
5801.1Sdbj		 * argument space is lazy-allocated.
5811.1Sdbj		 */
5821.1Sdbj		if ((type & T_USER) == 0 &&
5831.1Sdbj		    ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code)))
5841.1Sdbj			map = kernel_map;
5851.1Sdbj		else
5861.1Sdbj			map = vm ? &vm->vm_map : kernel_map;
5871.1Sdbj
5881.1Sdbj		if (WRFAULT(code))
5891.1Sdbj			ftype = VM_PROT_READ | VM_PROT_WRITE;
5901.1Sdbj		else
5911.1Sdbj			ftype = VM_PROT_READ;
5921.1Sdbj
5931.1Sdbj		va = trunc_page((vm_offset_t)v);
5941.1Sdbj
5951.1Sdbj		if (map == kernel_map && va == 0) {
5961.1Sdbj			printf("trap: bad kernel %s access at 0x%x\n",
5971.1Sdbj			    (ftype & VM_PROT_WRITE) ? "read/write" :
5981.1Sdbj			    "read", v);
5991.1Sdbj			goto dopanic;
6001.1Sdbj		}
6011.1Sdbj
6021.1Sdbj#ifdef COMPAT_HPUX
6031.1Sdbj		if (ISHPMMADDR(va)) {
6041.1Sdbj			int pmap_mapmulti __P((pmap_t, vm_offset_t));
6051.1Sdbj			vm_offset_t bva;
6061.1Sdbj
6071.1Sdbj			rv = pmap_mapmulti(map->pmap, va);
6081.1Sdbj			if (rv != KERN_SUCCESS) {
6091.1Sdbj				bva = HPMMBASEADDR(va);
6101.1Sdbj				rv = vm_fault(map, bva, ftype, FALSE);
6111.1Sdbj				if (rv == KERN_SUCCESS)
6121.1Sdbj					(void) pmap_mapmulti(map->pmap, va);
6131.1Sdbj			}
6141.1Sdbj		} else
6151.1Sdbj#endif
6161.1Sdbj		rv = vm_fault(map, va, ftype, FALSE);
6171.1Sdbj#ifdef DEBUG
6181.1Sdbj		if (rv && MDB_ISPID(p->p_pid))
6191.1Sdbj			printf("vm_fault(%p, %lx, %x, 0) -> %x\n",
6201.1Sdbj			       map, va, ftype, rv);
6211.1Sdbj#endif
6221.1Sdbj		/*
6231.1Sdbj		 * If this was a stack access we keep track of the maximum
6241.1Sdbj		 * accessed stack size.  Also, if vm_fault gets a protection
6251.1Sdbj		 * failure it is due to accessing the stack region outside
6261.1Sdbj		 * the current limit and we need to reflect that as an access
6271.1Sdbj		 * error.
6281.1Sdbj		 */
6291.1Sdbj		if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr)
6301.1Sdbj		    && map != kernel_map) {
6311.1Sdbj			if (rv == KERN_SUCCESS) {
6321.1Sdbj				unsigned nss;
6331.1Sdbj
6341.1Sdbj				nss = clrnd(btoc(USRSTACK-(unsigned)va));
6351.1Sdbj				if (nss > vm->vm_ssize)
6361.1Sdbj					vm->vm_ssize = nss;
6371.1Sdbj			} else if (rv == KERN_PROTECTION_FAILURE)
6381.1Sdbj				rv = KERN_INVALID_ADDRESS;
6391.1Sdbj		}
6401.1Sdbj		if (rv == KERN_SUCCESS) {
6411.1Sdbj			if (type == T_MMUFLT) {
6421.1Sdbj#ifdef M68040
6431.1Sdbj				if (cputype == CPU_68040)
6441.1Sdbj					(void) writeback(&frame, 1);
6451.1Sdbj#endif
6461.1Sdbj				return;
6471.1Sdbj			}
6481.1Sdbj			goto out;
6491.1Sdbj		}
6501.1Sdbj		if (type == T_MMUFLT) {
6511.1Sdbj			if (p->p_addr->u_pcb.pcb_onfault)
6521.1Sdbj				goto copyfault;
6531.1Sdbj			printf("vm_fault(%p, %lx, %x, 0) -> %x\n",
6541.1Sdbj			       map, va, ftype, rv);
6551.1Sdbj			printf("  type %x, code [mmu,,ssw]: %x\n",
6561.1Sdbj			       type, code);
6571.1Sdbj			goto dopanic;
6581.1Sdbj		}
6591.1Sdbj		ucode = v;
6601.1Sdbj		i = SIGSEGV;
6611.1Sdbj		break;
6621.1Sdbj	    }
6631.1Sdbj	}
6641.1Sdbj	trapsignal(p, i, ucode);
6651.1Sdbj	if ((type & T_USER) == 0)
6661.1Sdbj		return;
6671.1Sdbjout:
6681.1Sdbj	userret(p, &frame, sticks, v, 1);
6691.1Sdbj}
6701.1Sdbj
6711.1Sdbj#ifdef M68040
6721.1Sdbj#ifdef DEBUG
6731.1Sdbjstruct writebackstats {
6741.1Sdbj	int calls;
6751.1Sdbj	int cpushes;
6761.1Sdbj	int move16s;
6771.1Sdbj	int wb1s, wb2s, wb3s;
6781.1Sdbj	int wbsize[4];
6791.1Sdbj} wbstats;
6801.1Sdbj
6811.1Sdbjchar *f7sz[] = { "longword", "byte", "word", "line" };
6821.1Sdbjchar *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
6831.1Sdbjchar *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
6841.1Sdbj		 "M-code", "k-data", "k-code", "RES" };
6851.1Sdbjchar wberrstr[] =
6861.1Sdbj    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
6871.1Sdbj#endif
6881.1Sdbj
6891.1Sdbjint
6901.1Sdbjwriteback(fp, docachepush)
6911.1Sdbj	struct frame *fp;
6921.1Sdbj	int docachepush;
6931.1Sdbj{
6941.1Sdbj	struct fmt7 *f = &fp->f_fmt7;
6951.1Sdbj	struct proc *p = curproc;
6961.1Sdbj	int err = 0;
6971.1Sdbj	u_int fa;
6981.1Sdbj	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
6991.1Sdbj
7001.1Sdbj#ifdef DEBUG
7011.1Sdbj	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
7021.1Sdbj		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
7031.1Sdbj		dumpssw(f->f_ssw);
7041.1Sdbj	}
7051.1Sdbj	wbstats.calls++;
7061.1Sdbj#endif
7071.1Sdbj	/*
7081.1Sdbj	 * Deal with special cases first.
7091.1Sdbj	 */
7101.1Sdbj	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
7111.1Sdbj		/*
7121.1Sdbj		 * Dcache push fault.
7131.1Sdbj		 * Line-align the address and write out the push data to
7141.1Sdbj		 * the indicated physical address.
7151.1Sdbj		 */
7161.1Sdbj#ifdef DEBUG
7171.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
7181.1Sdbj			printf(" pushing %s to PA %x, data %x",
7191.1Sdbj			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
7201.1Sdbj			       f->f_fa, f->f_pd0);
7211.1Sdbj			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
7221.1Sdbj				printf("/%x/%x/%x",
7231.1Sdbj				       f->f_pd1, f->f_pd2, f->f_pd3);
7241.1Sdbj			printf("\n");
7251.1Sdbj		}
7261.1Sdbj		if (f->f_wb1s & SSW4_WBSV)
7271.1Sdbj			panic("writeback: cache push with WB1S valid");
7281.1Sdbj		wbstats.cpushes++;
7291.1Sdbj#endif
7301.1Sdbj		/*
7311.1Sdbj		 * XXX there are security problems if we attempt to do a
7321.1Sdbj		 * cache push after a signal handler has been called.
7331.1Sdbj		 */
7341.1Sdbj		if (docachepush) {
7351.1Sdbj			pmap_enter(pmap_kernel(), (vm_offset_t)vmmap,
7361.1Sdbj				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
7371.1Sdbj			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
7381.1Sdbj			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
7391.1Sdbj			DCFL(pmap_extract(pmap_kernel(), (vm_offset_t)fa));
7401.1Sdbj			pmap_remove(pmap_kernel(), (vm_offset_t)vmmap,
7411.1Sdbj				    (vm_offset_t)&vmmap[NBPG]);
7421.1Sdbj		} else
7431.1Sdbj			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
7441.1Sdbj			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
7451.1Sdbj	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
7461.1Sdbj		/*
7471.1Sdbj		 * MOVE16 fault.
7481.1Sdbj		 * Line-align the address and write out the push data to
7491.1Sdbj		 * the indicated virtual address.
7501.1Sdbj		 */
7511.1Sdbj#ifdef DEBUG
7521.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
7531.1Sdbj			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
7541.1Sdbj			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
7551.1Sdbj			       f->f_pd2, f->f_pd3);
7561.1Sdbj		if (f->f_wb1s & SSW4_WBSV)
7571.1Sdbj			panic("writeback: MOVE16 with WB1S valid");
7581.1Sdbj		wbstats.move16s++;
7591.1Sdbj#endif
7601.1Sdbj		if (KDFAULT(f->f_wb1s))
7611.1Sdbj			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
7621.1Sdbj		else
7631.1Sdbj			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
7641.1Sdbj		if (err) {
7651.1Sdbj			fa = f->f_fa & ~0xF;
7661.1Sdbj#ifdef DEBUG
7671.1Sdbj			if (mmudebug & MDB_WBFAILED)
7681.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
7691.1Sdbj				       "MOVE16", fp->f_pc, f->f_fa,
7701.1Sdbj				       f->f_fa & ~0xF, f->f_pd0);
7711.1Sdbj#endif
7721.1Sdbj		}
7731.1Sdbj	} else if (f->f_wb1s & SSW4_WBSV) {
7741.1Sdbj		/*
7751.1Sdbj		 * Writeback #1.
7761.1Sdbj		 * Position the "memory-aligned" data and write it out.
7771.1Sdbj		 */
7781.1Sdbj		u_int wb1d = f->f_wb1d;
7791.1Sdbj		int off;
7801.1Sdbj
7811.1Sdbj#ifdef DEBUG
7821.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
7831.1Sdbj			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
7841.1Sdbj		wbstats.wb1s++;
7851.1Sdbj		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
7861.1Sdbj#endif
7871.1Sdbj		off = (f->f_wb1a & 3) * 8;
7881.1Sdbj		switch (f->f_wb1s & SSW4_SZMASK) {
7891.1Sdbj		case SSW4_SZLW:
7901.1Sdbj			if (off)
7911.1Sdbj				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
7921.1Sdbj			if (KDFAULT(f->f_wb1s))
7931.1Sdbj				*(long *)f->f_wb1a = wb1d;
7941.1Sdbj			else
7951.1Sdbj				err = suword((caddr_t)f->f_wb1a, wb1d);
7961.1Sdbj			break;
7971.1Sdbj		case SSW4_SZB:
7981.1Sdbj			off = 24 - off;
7991.1Sdbj			if (off)
8001.1Sdbj				wb1d >>= off;
8011.1Sdbj			if (KDFAULT(f->f_wb1s))
8021.1Sdbj				*(char *)f->f_wb1a = wb1d;
8031.1Sdbj			else
8041.1Sdbj				err = subyte((caddr_t)f->f_wb1a, wb1d);
8051.1Sdbj			break;
8061.1Sdbj		case SSW4_SZW:
8071.1Sdbj			off = (off + 16) % 32;
8081.1Sdbj			if (off)
8091.1Sdbj				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
8101.1Sdbj			if (KDFAULT(f->f_wb1s))
8111.1Sdbj				*(short *)f->f_wb1a = wb1d;
8121.1Sdbj			else
8131.1Sdbj				err = susword((caddr_t)f->f_wb1a, wb1d);
8141.1Sdbj			break;
8151.1Sdbj		}
8161.1Sdbj		if (err) {
8171.1Sdbj			fa = f->f_wb1a;
8181.1Sdbj#ifdef DEBUG
8191.1Sdbj			if (mmudebug & MDB_WBFAILED)
8201.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8211.1Sdbj				       "#1", fp->f_pc, f->f_fa,
8221.1Sdbj				       f->f_wb1a, f->f_wb1d);
8231.1Sdbj#endif
8241.1Sdbj		}
8251.1Sdbj	}
8261.1Sdbj	/*
8271.1Sdbj	 * Deal with the "normal" writebacks.
8281.1Sdbj	 *
8291.1Sdbj	 * XXX writeback2 is known to reflect a LINE size writeback after
8301.1Sdbj	 * a MOVE16 was already dealt with above.  Ignore it.
8311.1Sdbj	 */
8321.1Sdbj	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
8331.1Sdbj	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
8341.1Sdbj#ifdef DEBUG
8351.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
8361.1Sdbj			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
8371.1Sdbj		wbstats.wb2s++;
8381.1Sdbj		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
8391.1Sdbj#endif
8401.1Sdbj		switch (f->f_wb2s & SSW4_SZMASK) {
8411.1Sdbj		case SSW4_SZLW:
8421.1Sdbj			if (KDFAULT(f->f_wb2s))
8431.1Sdbj				*(long *)f->f_wb2a = f->f_wb2d;
8441.1Sdbj			else
8451.1Sdbj				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
8461.1Sdbj			break;
8471.1Sdbj		case SSW4_SZB:
8481.1Sdbj			if (KDFAULT(f->f_wb2s))
8491.1Sdbj				*(char *)f->f_wb2a = f->f_wb2d;
8501.1Sdbj			else
8511.1Sdbj				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
8521.1Sdbj			break;
8531.1Sdbj		case SSW4_SZW:
8541.1Sdbj			if (KDFAULT(f->f_wb2s))
8551.1Sdbj				*(short *)f->f_wb2a = f->f_wb2d;
8561.1Sdbj			else
8571.1Sdbj				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
8581.1Sdbj			break;
8591.1Sdbj		}
8601.1Sdbj		if (err) {
8611.1Sdbj			fa = f->f_wb2a;
8621.1Sdbj#ifdef DEBUG
8631.1Sdbj			if (mmudebug & MDB_WBFAILED) {
8641.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8651.1Sdbj				       "#2", fp->f_pc, f->f_fa,
8661.1Sdbj				       f->f_wb2a, f->f_wb2d);
8671.1Sdbj				dumpssw(f->f_ssw);
8681.1Sdbj				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
8691.1Sdbj			}
8701.1Sdbj#endif
8711.1Sdbj		}
8721.1Sdbj	}
8731.1Sdbj	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
8741.1Sdbj#ifdef DEBUG
8751.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
8761.1Sdbj			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
8771.1Sdbj		wbstats.wb3s++;
8781.1Sdbj		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
8791.1Sdbj#endif
8801.1Sdbj		switch (f->f_wb3s & SSW4_SZMASK) {
8811.1Sdbj		case SSW4_SZLW:
8821.1Sdbj			if (KDFAULT(f->f_wb3s))
8831.1Sdbj				*(long *)f->f_wb3a = f->f_wb3d;
8841.1Sdbj			else
8851.1Sdbj				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
8861.1Sdbj			break;
8871.1Sdbj		case SSW4_SZB:
8881.1Sdbj			if (KDFAULT(f->f_wb3s))
8891.1Sdbj				*(char *)f->f_wb3a = f->f_wb3d;
8901.1Sdbj			else
8911.1Sdbj				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
8921.1Sdbj			break;
8931.1Sdbj		case SSW4_SZW:
8941.1Sdbj			if (KDFAULT(f->f_wb3s))
8951.1Sdbj				*(short *)f->f_wb3a = f->f_wb3d;
8961.1Sdbj			else
8971.1Sdbj				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
8981.1Sdbj			break;
8991.1Sdbj#ifdef DEBUG
9001.1Sdbj		case SSW4_SZLN:
9011.1Sdbj			panic("writeback: wb3s indicates LINE write");
9021.1Sdbj#endif
9031.1Sdbj		}
9041.1Sdbj		if (err) {
9051.1Sdbj			fa = f->f_wb3a;
9061.1Sdbj#ifdef DEBUG
9071.1Sdbj			if (mmudebug & MDB_WBFAILED)
9081.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
9091.1Sdbj				       "#3", fp->f_pc, f->f_fa,
9101.1Sdbj				       f->f_wb3a, f->f_wb3d);
9111.1Sdbj#endif
9121.1Sdbj		}
9131.1Sdbj	}
9141.1Sdbj	p->p_addr->u_pcb.pcb_onfault = oonfault;
9151.1Sdbj	if (err)
9161.1Sdbj		err = SIGSEGV;
9171.1Sdbj	return (err);
9181.1Sdbj}
9191.1Sdbj
9201.1Sdbj#ifdef DEBUG
9211.1Sdbjvoid
9221.1Sdbjdumpssw(ssw)
9231.1Sdbj	u_short ssw;
9241.1Sdbj{
9251.1Sdbj	printf(" SSW: %x: ", ssw);
9261.1Sdbj	if (ssw & SSW4_CP)
9271.1Sdbj		printf("CP,");
9281.1Sdbj	if (ssw & SSW4_CU)
9291.1Sdbj		printf("CU,");
9301.1Sdbj	if (ssw & SSW4_CT)
9311.1Sdbj		printf("CT,");
9321.1Sdbj	if (ssw & SSW4_CM)
9331.1Sdbj		printf("CM,");
9341.1Sdbj	if (ssw & SSW4_MA)
9351.1Sdbj		printf("MA,");
9361.1Sdbj	if (ssw & SSW4_ATC)
9371.1Sdbj		printf("ATC,");
9381.1Sdbj	if (ssw & SSW4_LK)
9391.1Sdbj		printf("LK,");
9401.1Sdbj	if (ssw & SSW4_RW)
9411.1Sdbj		printf("RW,");
9421.1Sdbj	printf(" SZ=%s, TT=%s, TM=%s\n",
9431.1Sdbj	       f7sz[(ssw & SSW4_SZMASK) >> 5],
9441.1Sdbj	       f7tt[(ssw & SSW4_TTMASK) >> 3],
9451.1Sdbj	       f7tm[ssw & SSW4_TMMASK]);
9461.1Sdbj}
9471.1Sdbj
9481.1Sdbjvoid
9491.1Sdbjdumpwb(num, s, a, d)
9501.1Sdbj	int num;
9511.1Sdbj	u_short s;
9521.1Sdbj	u_int a, d;
9531.1Sdbj{
9541.1Sdbj	struct proc *p = curproc;
9551.1Sdbj	vm_offset_t pa;
9561.1Sdbj
9571.1Sdbj	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
9581.1Sdbj	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
9591.1Sdbj	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
9601.1Sdbj	printf("               PA ");
9611.1Sdbj	pa = pmap_extract(p->p_vmspace->vm_map.pmap, (vm_offset_t)a);
9621.1Sdbj	if (pa == 0)
9631.1Sdbj		printf("<invalid address>");
9641.1Sdbj	else
9651.1Sdbj		printf("%lx, current value %lx", pa, fuword((caddr_t)a));
9661.1Sdbj	printf("\n");
9671.1Sdbj}
9681.1Sdbj#endif
9691.1Sdbj#endif
9701.1Sdbj
9711.1Sdbj/*
9721.1Sdbj * Process a system call.
9731.1Sdbj */
9741.1Sdbjvoid
9751.1Sdbjsyscall(code, frame)
9761.1Sdbj	register_t code;
9771.1Sdbj	struct frame frame;
9781.1Sdbj{
9791.1Sdbj	caddr_t params;
9801.1Sdbj	struct sysent *callp;
9811.1Sdbj	struct proc *p;
9821.1Sdbj	int error, opc, nsys;
9831.1Sdbj	size_t argsize;
9841.1Sdbj	register_t args[8], rval[2];
9851.1Sdbj	u_quad_t sticks;
9861.1Sdbj
9871.1Sdbj	cnt.v_syscall++;
9881.1Sdbj	if (!USERMODE(frame.f_sr))
9891.1Sdbj		panic("syscall");
9901.1Sdbj	p = curproc;
9911.1Sdbj	sticks = p->p_sticks;
9921.1Sdbj	p->p_md.md_regs = frame.f_regs;
9931.1Sdbj	opc = frame.f_pc;
9941.1Sdbj
9951.1Sdbj	nsys = p->p_emul->e_nsysent;
9961.1Sdbj	callp = p->p_emul->e_sysent;
9971.1Sdbj
9981.1Sdbj#ifdef COMPAT_SUNOS
9991.1Sdbj	if (p->p_emul == &emul_sunos) {
10001.1Sdbj		/*
10011.1Sdbj		 * SunOS passes the syscall-number on the stack, whereas
10021.1Sdbj		 * BSD passes it in D0. So, we have to get the real "code"
10031.1Sdbj		 * from the stack, and clean up the stack, as SunOS glue
10041.1Sdbj		 * code assumes the kernel pops the syscall argument the
10051.1Sdbj		 * glue pushed on the stack. Sigh...
10061.1Sdbj		 */
10071.1Sdbj		code = fuword((caddr_t)frame.f_regs[SP]);
10081.1Sdbj
10091.1Sdbj		/*
10101.1Sdbj		 * XXX
10111.1Sdbj		 * Don't do this for sunos_sigreturn, as there's no stored pc
10121.1Sdbj		 * on the stack to skip, the argument follows the syscall
10131.1Sdbj		 * number without a gap.
10141.1Sdbj		 */
10151.1Sdbj		if (code != SUNOS_SYS_sigreturn) {
10161.1Sdbj			frame.f_regs[SP] += sizeof (int);
10171.1Sdbj			/*
10181.1Sdbj			 * remember that we adjusted the SP,
10191.1Sdbj			 * might have to undo this if the system call
10201.1Sdbj			 * returns ERESTART.
10211.1Sdbj			 */
10221.1Sdbj			p->p_md.md_flags |= MDP_STACKADJ;
10231.1Sdbj		} else
10241.1Sdbj			p->p_md.md_flags &= ~MDP_STACKADJ;
10251.1Sdbj	}
10261.1Sdbj#endif
10271.1Sdbj
10281.1Sdbj	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
10291.1Sdbj
10301.1Sdbj	switch (code) {
10311.1Sdbj	case SYS_syscall:
10321.1Sdbj		/*
10331.1Sdbj		 * Code is first argument, followed by actual args.
10341.1Sdbj		 */
10351.1Sdbj		code = fuword(params);
10361.1Sdbj		params += sizeof(int);
10371.1Sdbj		/*
10381.1Sdbj		 * XXX sigreturn requires special stack manipulation
10391.1Sdbj		 * that is only done if entered via the sigreturn
10401.1Sdbj		 * trap.  Cannot allow it here so make sure we fail.
10411.1Sdbj		 */
10421.1Sdbj		if (code == SYS_sigreturn)
10431.1Sdbj			code = nsys;
10441.1Sdbj		break;
10451.1Sdbj	case SYS___syscall:
10461.1Sdbj		/*
10471.1Sdbj		 * Like syscall, but code is a quad, so as to maintain
10481.1Sdbj		 * quad alignment for the rest of the arguments.
10491.1Sdbj		 */
10501.1Sdbj		if (callp != sysent)
10511.1Sdbj			break;
10521.1Sdbj		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
10531.1Sdbj		params += sizeof(quad_t);
10541.1Sdbj		break;
10551.1Sdbj	default:
10561.1Sdbj		break;
10571.1Sdbj	}
10581.1Sdbj	if (code < 0 || code >= nsys)
10591.1Sdbj		callp += p->p_emul->e_nosys;		/* illegal */
10601.1Sdbj	else
10611.1Sdbj		callp += code;
10621.1Sdbj	argsize = callp->sy_argsize;
10631.1Sdbj	if (argsize)
10641.1Sdbj		error = copyin(params, (caddr_t)args, argsize);
10651.1Sdbj	else
10661.1Sdbj		error = 0;
10671.1Sdbj#ifdef SYSCALL_DEBUG
10681.1Sdbj	scdebug_call(p, code, args);
10691.1Sdbj#endif
10701.1Sdbj#ifdef KTRACE
10711.1Sdbj	if (KTRPOINT(p, KTR_SYSCALL))
10721.1Sdbj		ktrsyscall(p->p_tracep, code, argsize, args);
10731.1Sdbj#endif
10741.1Sdbj	if (error)
10751.1Sdbj		goto bad;
10761.1Sdbj	rval[0] = 0;
10771.1Sdbj	rval[1] = frame.f_regs[D1];
10781.1Sdbj	error = (*callp->sy_call)(p, args, rval);
10791.1Sdbj	switch (error) {
10801.1Sdbj	case 0:
10811.1Sdbj		frame.f_regs[D0] = rval[0];
10821.1Sdbj		frame.f_regs[D1] = rval[1];
10831.1Sdbj		frame.f_sr &= ~PSL_C;	/* carry bit */
10841.1Sdbj		break;
10851.1Sdbj	case ERESTART:
10861.1Sdbj		/*
10871.1Sdbj		 * We always enter through a `trap' instruction, which is 2
10881.1Sdbj		 * bytes, so adjust the pc by that amount.
10891.1Sdbj		 */
10901.1Sdbj		frame.f_pc = opc - 2;
10911.1Sdbj		break;
10921.1Sdbj	case EJUSTRETURN:
10931.1Sdbj		/* nothing to do */
10941.1Sdbj		break;
10951.1Sdbj	default:
10961.1Sdbj	bad:
10971.1Sdbj		if (p->p_emul->e_errno)
10981.1Sdbj			error = p->p_emul->e_errno[error];
10991.1Sdbj		frame.f_regs[D0] = error;
11001.1Sdbj		frame.f_sr |= PSL_C;	/* carry bit */
11011.1Sdbj		break;
11021.1Sdbj	}
11031.1Sdbj
11041.1Sdbj#ifdef SYSCALL_DEBUG
11051.1Sdbj	scdebug_ret(p, code, error, rval);
11061.1Sdbj#endif
11071.1Sdbj#ifdef COMPAT_SUNOS
11081.1Sdbj	/* need new p-value for this */
11091.1Sdbj	if (error == ERESTART && (p->p_md.md_flags & MDP_STACKADJ))
11101.1Sdbj		frame.f_regs[SP] -= sizeof (int);
11111.1Sdbj#endif
11121.1Sdbj	userret(p, &frame, sticks, (u_int)0, 0);
11131.1Sdbj#ifdef KTRACE
11141.1Sdbj	if (KTRPOINT(p, KTR_SYSRET))
11151.1Sdbj		ktrsysret(p->p_tracep, code, error, rval[0]);
11161.1Sdbj#endif
11171.1Sdbj}
11181.1Sdbj
11191.1Sdbjvoid
11201.1Sdbjchild_return(p, frame)
11211.1Sdbj	struct proc *p;
11221.1Sdbj	struct frame frame;
11231.1Sdbj{
11241.1Sdbj
11251.1Sdbj	frame.f_regs[D0] = 0;
11261.1Sdbj	frame.f_sr &= ~PSL_C;
11271.1Sdbj	frame.f_format = FMT0;
11281.1Sdbj
11291.1Sdbj	userret(p, &frame, 0, (u_int)0, 0);
11301.1Sdbj#ifdef KTRACE
11311.1Sdbj	if (KTRPOINT(p, KTR_SYSRET))
11321.1Sdbj		ktrsysret(p->p_tracep, SYS_fork, 0, 0);
11331.1Sdbj#endif
11341.1Sdbj}
11351.1Sdbj
11361.1Sdbj/*
11371.1Sdbj * Allocation routines for software interrupts.
11381.1Sdbj */
11391.1Sdbju_long
11401.1Sdbjallocate_sir(proc, arg)
11411.1Sdbj	void (*proc)();
11421.1Sdbj	void *arg;
11431.1Sdbj{
11441.1Sdbj	int bit;
11451.1Sdbj
11461.1Sdbj	if( next_sir >= NSIR )
11471.1Sdbj		panic("allocate_sir: none left");
11481.1Sdbj	bit = next_sir++;
11491.1Sdbj	sir_routines[bit] = proc;
11501.1Sdbj	sir_args[bit] = arg;
11511.1Sdbj	return (1 << bit);
11521.1Sdbj}
11531.1Sdbj
11541.1Sdbjvoid
11551.1Sdbjinit_sir()
11561.1Sdbj{
11571.1Sdbj	extern void netintr();
11581.1Sdbj
11591.1Sdbj	sir_routines[0] = netintr;
11601.1Sdbj	sir_routines[1] = softclock;
11611.1Sdbj	next_sir = 2;
11621.1Sdbj}
1163