trap.c revision 1.9
11.9Sitohy/*	$NetBSD: trap.c,v 1.9 1998/12/15 19:37:08 itohy Exp $ */
21.7Sdbj
31.7Sdbj/*
41.7Sdbj * This file was taken from from mvme68k/mvme68k/trap.c
51.7Sdbj * should probably be re-synced when needed.
61.7Sdbj * Darrin B. Jewell <jewell@mit.edu>  Tue Nov 10 05:07:16 1998
71.7Sdbj * original cvs id: NetBSD: trap.c,v 1.24 1998/10/01 02:53:54 thorpej 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.2Sthorpej#include "opt_ktrace.h"
551.7Sdbj#include "opt_uvm.h"
561.6Sthorpej#include "opt_compat_netbsd.h"
571.3Sthorpej#include "opt_compat_sunos.h"
581.4Sthorpej#include "opt_compat_hpux.h"
591.9Sitohy#include "opt_compat_linux.h"
601.1Sdbj
611.1Sdbj#include <sys/param.h>
621.1Sdbj#include <sys/systm.h>
631.1Sdbj#include <sys/proc.h>
641.1Sdbj#include <sys/acct.h>
651.1Sdbj#include <sys/kernel.h>
661.1Sdbj#include <sys/signalvar.h>
671.1Sdbj#include <sys/resourcevar.h>
681.1Sdbj#include <sys/syscall.h>
691.1Sdbj#include <sys/syslog.h>
701.1Sdbj#include <sys/user.h>
711.1Sdbj#ifdef KTRACE
721.1Sdbj#include <sys/ktrace.h>
731.1Sdbj#endif
741.1Sdbj
751.1Sdbj#include <machine/psl.h>
761.1Sdbj#include <machine/trap.h>
771.1Sdbj#include <machine/cpu.h>
781.1Sdbj#include <machine/reg.h>
791.1Sdbj
801.1Sdbj#include <vm/vm.h>
811.1Sdbj#include <vm/pmap.h>
821.1Sdbj
831.7Sdbj#if defined(UVM)
841.7Sdbj#include <uvm/uvm_extern.h>
851.7Sdbj#endif
861.1Sdbj
871.1Sdbj#ifdef COMPAT_HPUX
881.1Sdbj#include <compat/hpux/hpux.h>
891.1Sdbj#endif
901.1Sdbj
911.1Sdbj#ifdef COMPAT_SUNOS
921.1Sdbj#include <compat/sunos/sunos_syscall.h>
931.1Sdbjextern struct emul emul_sunos;
941.1Sdbj#endif
951.1Sdbj
961.9Sitohy#ifdef COMPAT_LINUX
971.9Sitohy#ifdef EXEC_AOUT
981.9Sitohyextern struct emul emul_linux_aout;
991.9Sitohy#endif
1001.9Sitohy#ifdef EXEC_ELF32
1011.9Sitohyextern struct emul emul_linux_elf32;
1021.9Sitohy#endif
1031.9Sitohy#endif
1041.9Sitohy
1051.7Sdbj#include <m68k/cacheops.h>
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.7Sdbj	FMT0SIZE,	/* type 0 - normal (68020/030/040) */
1321.1Sdbj	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
1331.7Sdbj	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040) */
1341.7Sdbj	FMT3SIZE,	/* type 3 - FP post-instruction (68040) */
1351.7Sdbj	-1, -1, -1,	/* type 4-6 - undefined */
1361.1Sdbj	FMT7SIZE,	/* type 7 - access error (68040) */
1371.1Sdbj	58,		/* type 8 - bus fault (68010) */
1381.1Sdbj	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
1391.1Sdbj	FMTASIZE,	/* type A - short bus fault (68020/030) */
1401.1Sdbj	FMTBSIZE,	/* type B - long bus fault (68020/030) */
1411.1Sdbj	-1, -1, -1, -1	/* type C-F - undefined */
1421.1Sdbj};
1431.1Sdbj
1441.1Sdbj#ifdef M68040
1451.7Sdbj#define KDFAULT(c)    (mmutype == MMU_68040 ? \
1461.7Sdbj			    ((c) & SSW4_TMMASK) == SSW4_TMKD : \
1471.7Sdbj			    ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))
1481.7Sdbj#define WRFAULT(c)    (mmutype == MMU_68040 ? \
1491.7Sdbj			    ((c) & SSW4_RW) == 0 : \
1501.7Sdbj			    ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
1511.1Sdbj#else
1521.7Sdbj#define KDFAULT(c)	(((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
1531.7Sdbj#define WRFAULT(c)	(((c) & (SSW_DF|SSW_RW)) == SSW_DF)
1541.1Sdbj#endif
1551.1Sdbj
1561.1Sdbj#ifdef DEBUG
1571.1Sdbjint mmudebug = 0;
1581.1Sdbjint mmupid = -1;
1591.1Sdbj#define MDB_FOLLOW	1
1601.1Sdbj#define MDB_WBFOLLOW	2
1611.1Sdbj#define MDB_WBFAILED	4
1621.7Sdbj#define MDB_ISPID(p)	(p) == mmupid
1631.1Sdbj#endif
1641.1Sdbj
1651.1Sdbj#define NSIR	32
1661.1Sdbjvoid (*sir_routines[NSIR])();
1671.1Sdbjvoid *sir_args[NSIR];
1681.1Sdbjint next_sir;
1691.1Sdbj
1701.1Sdbj/*
1711.1Sdbj * trap and syscall both need the following work done before returning
1721.1Sdbj * to user mode.
1731.1Sdbj */
1741.1Sdbjstatic inline void
1751.1Sdbjuserret(p, fp, oticks, faultaddr, fromtrap)
1761.1Sdbj	struct proc *p;
1771.1Sdbj	struct frame *fp;
1781.1Sdbj	u_quad_t oticks;
1791.1Sdbj	u_int faultaddr;
1801.1Sdbj	int fromtrap;
1811.1Sdbj{
1821.1Sdbj	int sig, s;
1831.1Sdbj#ifdef M68040
1841.1Sdbj	int beenhere = 0;
1851.1Sdbj
1861.1Sdbjagain:
1871.1Sdbj#endif
1881.1Sdbj	/* take pending signals */
1891.1Sdbj	while ((sig = CURSIG(p)) != 0)
1901.1Sdbj		postsig(sig);
1911.1Sdbj	p->p_priority = p->p_usrpri;
1921.1Sdbj	if (want_resched) {
1931.1Sdbj		/*
1941.1Sdbj		 * Since we are curproc, clock will normally just change
1951.1Sdbj		 * our priority without moving us from one queue to another
1961.1Sdbj		 * (since the running process is not on a queue.)
1971.1Sdbj		 * If that happened after we put ourselves on the run queue
1981.1Sdbj		 * but before we mi_switch()'ed, we might not be on the queue
1991.1Sdbj		 * indicated by our priority.
2001.1Sdbj		 */
2011.1Sdbj		s = splstatclock();
2021.1Sdbj		setrunqueue(p);
2031.1Sdbj		p->p_stats->p_ru.ru_nivcsw++;
2041.1Sdbj		mi_switch();
2051.1Sdbj		splx(s);
2061.1Sdbj		while ((sig = CURSIG(p)) != 0)
2071.1Sdbj			postsig(sig);
2081.1Sdbj	}
2091.1Sdbj
2101.1Sdbj	/*
2111.1Sdbj	 * If profiling, charge system time to the trapped pc.
2121.1Sdbj	 */
2131.1Sdbj	if (p->p_flag & P_PROFIL) {
2141.1Sdbj		extern int psratio;
2151.1Sdbj
2161.1Sdbj		addupc_task(p, fp->f_pc,
2171.1Sdbj			    (int)(p->p_sticks - oticks) * psratio);
2181.1Sdbj	}
2191.1Sdbj#ifdef M68040
2201.1Sdbj	/*
2211.1Sdbj	 * Deal with user mode writebacks (from trap, or from sigreturn).
2221.1Sdbj	 * If any writeback fails, go back and attempt signal delivery.
2231.1Sdbj	 * unless we have already been here and attempted the writeback
2241.1Sdbj	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
2251.1Sdbj	 * we just return to the user without sucessfully completing
2261.1Sdbj	 * the writebacks.  Maybe we should just drop the sucker?
2271.1Sdbj	 */
2281.7Sdbj	if (mmutype == MMU_68040 && fp->f_format == FMT7) {
2291.1Sdbj		if (beenhere) {
2301.1Sdbj#ifdef DEBUG
2311.1Sdbj			if (mmudebug & MDB_WBFAILED)
2321.1Sdbj				printf(fromtrap ?
2331.1Sdbj		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
2341.1Sdbj		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
2351.1Sdbj				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
2361.1Sdbj#endif
2371.7Sdbj		} else if (sig = writeback(fp, fromtrap)) {
2381.1Sdbj			beenhere = 1;
2391.1Sdbj			oticks = p->p_sticks;
2401.1Sdbj			trapsignal(p, sig, faultaddr);
2411.1Sdbj			goto again;
2421.1Sdbj		}
2431.1Sdbj	}
2441.1Sdbj#endif
2451.1Sdbj	curpriority = p->p_priority;
2461.1Sdbj}
2471.1Sdbj
2481.1Sdbj/*
2491.1Sdbj * Trap is called from locore to handle most types of processor traps,
2501.1Sdbj * including events such as simulated software interrupts/AST's.
2511.1Sdbj * System calls are broken out for efficiency.
2521.1Sdbj */
2531.1Sdbj/*ARGSUSED*/
2541.1Sdbjtrap(type, code, v, frame)
2551.1Sdbj	int type;
2561.1Sdbj	unsigned code;
2571.1Sdbj	unsigned v;
2581.1Sdbj	struct frame frame;
2591.1Sdbj{
2601.1Sdbj	extern char fubail[], subail[];
2611.7Sdbj#ifdef DDB
2621.7Sdbj	extern char trap0[], trap1[], trap2[], trap12[], trap15[], illinst[];
2631.7Sdbj#endif
2641.1Sdbj	struct proc *p;
2651.7Sdbj	int i;
2661.1Sdbj	u_int ucode;
2671.7Sdbj	u_quad_t sticks;
2681.7Sdbj#ifdef COMPAT_HPUX
2691.7Sdbj	extern struct emul emul_hpux;
2701.7Sdbj#endif
2711.7Sdbj	int bit;
2721.1Sdbj
2731.7Sdbj#if defined(UVM)
2741.7Sdbj	uvmexp.traps++;
2751.7Sdbj#else
2761.1Sdbj	cnt.v_trap++;
2771.7Sdbj#endif
2781.1Sdbj	p = curproc;
2791.1Sdbj	ucode = 0;
2801.1Sdbj	if (USERMODE(frame.f_sr)) {
2811.1Sdbj		type |= T_USER;
2821.1Sdbj		sticks = p->p_sticks;
2831.1Sdbj		p->p_md.md_regs = frame.f_regs;
2841.1Sdbj	}
2851.1Sdbj	switch (type) {
2861.1Sdbj
2871.1Sdbj	default:
2881.7Sdbjdopanic:
2891.7Sdbj		printf("trap type %d, code = %x, v = %x\n", type, code, v);
2901.1Sdbj#ifdef DDB
2911.7Sdbj		if (kdb_trap(type, &frame))
2921.7Sdbj			return;
2931.1Sdbj#endif
2941.1Sdbj		regdump((struct trapframe *)&frame, 128);
2951.1Sdbj		type &= ~T_USER;
2961.7Sdbj		if ((unsigned)type < trap_types)
2971.1Sdbj			panic(trap_type[type]);
2981.1Sdbj		panic("trap");
2991.1Sdbj
3001.1Sdbj	case T_BUSERR:		/* kernel bus error */
3011.7Sdbj		if (!p->p_addr->u_pcb.pcb_onfault)
3021.1Sdbj			goto dopanic;
3031.1Sdbj		/*
3041.1Sdbj		 * If we have arranged to catch this fault in any of the
3051.1Sdbj		 * copy to/from user space routines, set PC to return to
3061.1Sdbj		 * indicated location and set flag informing buserror code
3071.1Sdbj		 * that it may need to clean up stack frame.
3081.1Sdbj		 */
3091.7Sdbjcopyfault:
3101.1Sdbj		frame.f_stackadj = exframesize[frame.f_format];
3111.1Sdbj		frame.f_format = frame.f_vector = 0;
3121.1Sdbj		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
3131.1Sdbj		return;
3141.1Sdbj
3151.1Sdbj	case T_BUSERR|T_USER:	/* bus error */
3161.1Sdbj	case T_ADDRERR|T_USER:	/* address error */
3171.1Sdbj		ucode = v;
3181.1Sdbj		i = SIGBUS;
3191.1Sdbj		break;
3201.1Sdbj
3211.1Sdbj	case T_COPERR:		/* kernel coprocessor violation */
3221.1Sdbj	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
3231.1Sdbj	case T_FMTERR:		/* ...just in case... */
3241.1Sdbj	/*
3251.1Sdbj	 * The user has most likely trashed the RTE or FP state info
3261.1Sdbj	 * in the stack frame of a signal handler.
3271.1Sdbj	 */
3281.1Sdbj		printf("pid %d: kernel %s exception\n", p->p_pid,
3291.1Sdbj		       type==T_COPERR ? "coprocessor" : "format");
3301.1Sdbj		type |= T_USER;
3311.6Sthorpej		p->p_sigacts->ps_sigact[SIGILL].sa_handler = SIG_DFL;
3321.6Sthorpej		sigdelset(&p->p_sigignore, SIGILL);
3331.6Sthorpej		sigdelset(&p->p_sigcatch, SIGILL);
3341.6Sthorpej		sigdelset(&p->p_sigmask, SIGILL);
3351.1Sdbj		i = SIGILL;
3361.1Sdbj		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
3371.1Sdbj		break;
3381.1Sdbj
3391.1Sdbj	case T_COPERR|T_USER:	/* user coprocessor violation */
3401.1Sdbj	/* What is a proper response here? */
3411.1Sdbj		ucode = 0;
3421.1Sdbj		i = SIGFPE;
3431.1Sdbj		break;
3441.1Sdbj
3451.1Sdbj	case T_FPERR|T_USER:	/* 68881 exceptions */
3461.1Sdbj	/*
3471.7Sdbj	 * We pass along the 68881 status register which locore stashed
3481.1Sdbj	 * in code for us.  Note that there is a possibility that the
3491.7Sdbj	 * bit pattern of this register will conflict with one of the
3501.1Sdbj	 * FPE_* codes defined in signal.h.  Fortunately for us, the
3511.1Sdbj	 * only such codes we use are all in the range 1-7 and the low
3521.7Sdbj	 * 3 bits of the status register are defined as 0 so there is
3531.1Sdbj	 * no clash.
3541.1Sdbj	 */
3551.1Sdbj		ucode = code;
3561.1Sdbj		i = SIGFPE;
3571.1Sdbj		break;
3581.1Sdbj
3591.1Sdbj#ifdef M68040
3601.1Sdbj	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
3611.1Sdbj	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
3621.1Sdbj		/* XXX need to FSAVE */
3631.1Sdbj		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
3641.1Sdbj		       p->p_pid, p->p_comm,
3651.1Sdbj		       frame.f_format == 2 ? "instruction" : "data type",
3661.1Sdbj		       frame.f_pc, frame.f_fmt2.f_iaddr);
3671.1Sdbj		/* XXX need to FRESTORE */
3681.1Sdbj		i = SIGFPE;
3691.1Sdbj		break;
3701.1Sdbj#endif
3711.1Sdbj
3721.1Sdbj	case T_ILLINST|T_USER:	/* illegal instruction fault */
3731.1Sdbj#ifdef COMPAT_HPUX
3741.1Sdbj		if (p->p_emul == &emul_hpux) {
3751.1Sdbj			ucode = HPUX_ILL_ILLINST_TRAP;
3761.1Sdbj			i = SIGILL;
3771.1Sdbj			break;
3781.1Sdbj		}
3791.1Sdbj		/* fall through */
3801.1Sdbj#endif
3811.1Sdbj	case T_PRIVINST|T_USER:	/* privileged instruction fault */
3821.1Sdbj#ifdef COMPAT_HPUX
3831.1Sdbj		if (p->p_emul == &emul_hpux)
3841.1Sdbj			ucode = HPUX_ILL_PRIV_TRAP;
3851.1Sdbj		else
3861.1Sdbj#endif
3871.1Sdbj		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
3881.1Sdbj		i = SIGILL;
3891.1Sdbj		break;
3901.1Sdbj
3911.1Sdbj	case T_ZERODIV|T_USER:	/* Divide by zero */
3921.1Sdbj#ifdef COMPAT_HPUX
3931.1Sdbj		if (p->p_emul == &emul_hpux)
3941.1Sdbj			ucode = HPUX_FPE_INTDIV_TRAP;
3951.1Sdbj		else
3961.1Sdbj#endif
3971.1Sdbj		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
3981.1Sdbj		i = SIGFPE;
3991.1Sdbj		break;
4001.1Sdbj
4011.1Sdbj	case T_CHKINST|T_USER:	/* CHK instruction trap */
4021.1Sdbj#ifdef COMPAT_HPUX
4031.1Sdbj		if (p->p_emul == &emul_hpux) {
4041.1Sdbj			/* handled differently under hp-ux */
4051.1Sdbj			i = SIGILL;
4061.1Sdbj			ucode = HPUX_ILL_CHK_TRAP;
4071.1Sdbj			break;
4081.1Sdbj		}
4091.1Sdbj#endif
4101.1Sdbj		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
4111.1Sdbj		i = SIGFPE;
4121.1Sdbj		break;
4131.1Sdbj
4141.1Sdbj	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
4151.1Sdbj#ifdef COMPAT_HPUX
4161.1Sdbj		if (p->p_emul == &emul_hpux) {
4171.1Sdbj			/* handled differently under hp-ux */
4181.1Sdbj			i = SIGILL;
4191.1Sdbj			ucode = HPUX_ILL_TRAPV_TRAP;
4201.1Sdbj			break;
4211.1Sdbj		}
4221.1Sdbj#endif
4231.1Sdbj		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
4241.1Sdbj		i = SIGFPE;
4251.1Sdbj		break;
4261.1Sdbj
4271.1Sdbj	/*
4281.1Sdbj	 * XXX: Trace traps are a nightmare.
4291.1Sdbj	 *
4301.1Sdbj	 *	HP-UX uses trap #1 for breakpoints,
4311.7Sdbj	 *	HPBSD uses trap #2,
4321.1Sdbj	 *	SUN 3.x uses trap #15,
4331.7Sdbj	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
4341.1Sdbj	 *
4351.7Sdbj	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
4361.1Sdbj	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
4371.1Sdbj	 * supported yet.
4381.1Sdbj	 */
4391.1Sdbj	case T_TRACE:		/* kernel trace trap */
4401.7Sdbj	case T_TRAP15:		/* SUN trace trap */
4411.7Sdbj#ifdef DDB
4421.7Sdbj		if (type == T_TRAP15 ||
4431.7Sdbj		    ((caddr_t)frame.f_pc != trap0 &&
4441.7Sdbj		     (caddr_t)frame.f_pc != trap1 &&
4451.7Sdbj		     (caddr_t)frame.f_pc != trap2 &&
4461.7Sdbj		     (caddr_t)frame.f_pc != trap12 &&
4471.7Sdbj		     (caddr_t)frame.f_pc != trap15 &&
4481.7Sdbj		     (caddr_t)frame.f_pc != illinst)) {
4491.7Sdbj			if (kdb_trap(type, &frame))
4501.7Sdbj				return;
4511.7Sdbj		}
4521.1Sdbj#endif
4531.1Sdbj		frame.f_sr &= ~PSL_T;
4541.7Sdbj		i = SIGTRAP;
4551.7Sdbj		break;
4561.1Sdbj
4571.1Sdbj	case T_TRACE|T_USER:	/* user trace trap */
4581.1Sdbj	case T_TRAP15|T_USER:	/* SUN user trace trap */
4591.1Sdbj#ifdef COMPAT_SUNOS
4601.1Sdbj		/*
4611.1Sdbj		 * SunOS uses Trap #2 for a "CPU cache flush".
4621.1Sdbj		 * Just flush the on-chip caches and return.
4631.1Sdbj		 */
4641.1Sdbj		if (p->p_emul == &emul_sunos) {
4651.1Sdbj			ICIA();
4661.1Sdbj			DCIU();
4671.1Sdbj			return;
4681.1Sdbj		}
4691.7Sdbj#endif COMPAT_SUNOS
4701.1Sdbj		frame.f_sr &= ~PSL_T;
4711.1Sdbj		i = SIGTRAP;
4721.1Sdbj		break;
4731.1Sdbj
4741.1Sdbj	case T_ASTFLT:		/* system async trap, cannot happen */
4751.1Sdbj		goto dopanic;
4761.1Sdbj
4771.1Sdbj	case T_ASTFLT|T_USER:	/* user async trap */
4781.1Sdbj		astpending = 0;
4791.1Sdbj		/*
4801.1Sdbj		 * We check for software interrupts first.  This is because
4811.1Sdbj		 * they are at a higher level than ASTs, and on a VAX would
4821.1Sdbj		 * interrupt the AST.  We assume that if we are processing
4831.1Sdbj		 * an AST that we must be at IPL0 so we don't bother to
4841.1Sdbj		 * check.  Note that we ensure that we are at least at SIR
4851.1Sdbj		 * IPL while processing the SIR.
4861.1Sdbj		 */
4871.1Sdbj		spl1();
4881.1Sdbj		/* fall into... */
4891.1Sdbj
4901.1Sdbj	case T_SSIR:		/* software interrupt */
4911.1Sdbj	case T_SSIR|T_USER:
4921.1Sdbj		while (bit = ffs(ssir)) {
4931.1Sdbj			--bit;
4941.1Sdbj			ssir &= ~(1 << bit);
4951.7Sdbj#if defined(UVM)
4961.7Sdbj			uvmexp.softs++;
4971.7Sdbj#else
4981.1Sdbj			cnt.v_soft++;
4991.7Sdbj#endif
5001.1Sdbj			if (sir_routines[bit])
5011.1Sdbj				sir_routines[bit](sir_args[bit]);
5021.1Sdbj		}
5031.1Sdbj
5041.1Sdbj		/*
5051.1Sdbj		 * If this was not an AST trap, we are all done.
5061.1Sdbj		 */
5071.1Sdbj		if (type != (T_ASTFLT|T_USER)) {
5081.7Sdbj#if defined(UVM)
5091.7Sdbj			uvmexp.traps++;
5101.7Sdbj#else
5111.1Sdbj			cnt.v_trap--;
5121.7Sdbj#endif
5131.1Sdbj			return;
5141.1Sdbj		}
5151.1Sdbj		spl0();
5161.1Sdbj		if (p->p_flag & P_OWEUPC) {
5171.1Sdbj			p->p_flag &= ~P_OWEUPC;
5181.1Sdbj			ADDUPROF(p);
5191.1Sdbj		}
5201.1Sdbj		goto out;
5211.1Sdbj
5221.1Sdbj	case T_MMUFLT:		/* kernel mode page fault */
5231.1Sdbj		/*
5241.1Sdbj		 * If we were doing profiling ticks or other user mode
5251.1Sdbj		 * stuff from interrupt code, Just Say No.
5261.1Sdbj		 */
5271.1Sdbj		if (p->p_addr->u_pcb.pcb_onfault == fubail ||
5281.1Sdbj		    p->p_addr->u_pcb.pcb_onfault == subail)
5291.1Sdbj			goto copyfault;
5301.1Sdbj		/* fall into ... */
5311.1Sdbj
5321.1Sdbj	case T_MMUFLT|T_USER:	/* page fault */
5331.1Sdbj	    {
5341.7Sdbj		vaddr_t va;
5351.1Sdbj		struct vmspace *vm = p->p_vmspace;
5361.1Sdbj		vm_map_t map;
5371.1Sdbj		int rv;
5381.1Sdbj		vm_prot_t ftype;
5391.1Sdbj		extern vm_map_t kernel_map;
5401.1Sdbj
5411.1Sdbj#ifdef DEBUG
5421.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
5431.1Sdbj		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
5441.1Sdbj		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
5451.1Sdbj#endif
5461.1Sdbj		/*
5471.1Sdbj		 * It is only a kernel address space fault iff:
5481.1Sdbj		 * 	1. (type & T_USER) == 0  and
5491.1Sdbj		 * 	2. pcb_onfault not set or
5501.1Sdbj		 *	3. pcb_onfault set but supervisor space data fault
5511.1Sdbj		 * The last can occur during an exec() copyin where the
5521.1Sdbj		 * argument space is lazy-allocated.
5531.1Sdbj		 */
5541.7Sdbj		if (type == T_MMUFLT &&
5551.7Sdbj		    (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
5561.1Sdbj			map = kernel_map;
5571.1Sdbj		else
5581.7Sdbj			map = &vm->vm_map;
5591.1Sdbj		if (WRFAULT(code))
5601.1Sdbj			ftype = VM_PROT_READ | VM_PROT_WRITE;
5611.1Sdbj		else
5621.1Sdbj			ftype = VM_PROT_READ;
5631.7Sdbj		va = trunc_page((vaddr_t)v);
5641.7Sdbj#ifdef DEBUG
5651.1Sdbj		if (map == kernel_map && va == 0) {
5661.7Sdbj			printf("trap: bad kernel access at %x\n", v);
5671.1Sdbj			goto dopanic;
5681.1Sdbj		}
5691.7Sdbj#endif
5701.1Sdbj#ifdef COMPAT_HPUX
5711.1Sdbj		if (ISHPMMADDR(va)) {
5721.7Sdbj			vaddr_t bva;
5731.1Sdbj
5741.1Sdbj			rv = pmap_mapmulti(map->pmap, va);
5751.1Sdbj			if (rv != KERN_SUCCESS) {
5761.1Sdbj				bva = HPMMBASEADDR(va);
5771.7Sdbj#if defined(UVM)
5781.7Sdbj				rv = uvm_fault(map, bva, 0, ftype);
5791.7Sdbj#else
5801.1Sdbj				rv = vm_fault(map, bva, ftype, FALSE);
5811.7Sdbj#endif
5821.1Sdbj				if (rv == KERN_SUCCESS)
5831.1Sdbj					(void) pmap_mapmulti(map->pmap, va);
5841.1Sdbj			}
5851.1Sdbj		} else
5861.1Sdbj#endif
5871.7Sdbj#if defined(UVM)
5881.7Sdbj		rv = uvm_fault(map, va, 0, ftype);
5891.7Sdbj#ifdef DEBUG
5901.7Sdbj		if (rv && MDB_ISPID(p->p_pid))
5911.7Sdbj			printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
5921.7Sdbj			       map, va, ftype, rv);
5931.7Sdbj#endif
5941.7Sdbj#else /* ! UVM */
5951.1Sdbj		rv = vm_fault(map, va, ftype, FALSE);
5961.1Sdbj#ifdef DEBUG
5971.1Sdbj		if (rv && MDB_ISPID(p->p_pid))
5981.7Sdbj			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
5991.1Sdbj			       map, va, ftype, rv);
6001.1Sdbj#endif
6011.7Sdbj#endif /* UVM */
6021.1Sdbj		/*
6031.1Sdbj		 * If this was a stack access we keep track of the maximum
6041.1Sdbj		 * accessed stack size.  Also, if vm_fault gets a protection
6051.1Sdbj		 * failure it is due to accessing the stack region outside
6061.1Sdbj		 * the current limit and we need to reflect that as an access
6071.1Sdbj		 * error.
6081.1Sdbj		 */
6091.7Sdbj		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
6101.1Sdbj			if (rv == KERN_SUCCESS) {
6111.1Sdbj				unsigned nss;
6121.1Sdbj
6131.1Sdbj				nss = clrnd(btoc(USRSTACK-(unsigned)va));
6141.1Sdbj				if (nss > vm->vm_ssize)
6151.1Sdbj					vm->vm_ssize = nss;
6161.1Sdbj			} else if (rv == KERN_PROTECTION_FAILURE)
6171.1Sdbj				rv = KERN_INVALID_ADDRESS;
6181.1Sdbj		}
6191.1Sdbj		if (rv == KERN_SUCCESS) {
6201.1Sdbj			if (type == T_MMUFLT) {
6211.7Sdbj#if defined(M68040)
6221.7Sdbj				if (mmutype == MMU_68040)
6231.1Sdbj					(void) writeback(&frame, 1);
6241.1Sdbj#endif
6251.1Sdbj				return;
6261.1Sdbj			}
6271.1Sdbj			goto out;
6281.1Sdbj		}
6291.1Sdbj		if (type == T_MMUFLT) {
6301.1Sdbj			if (p->p_addr->u_pcb.pcb_onfault)
6311.1Sdbj				goto copyfault;
6321.7Sdbj#if defined(UVM)
6331.7Sdbj			printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n",
6341.7Sdbj			       map, va, ftype, rv);
6351.7Sdbj#else
6361.7Sdbj			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
6371.1Sdbj			       map, va, ftype, rv);
6381.7Sdbj#endif
6391.1Sdbj			printf("  type %x, code [mmu,,ssw]: %x\n",
6401.1Sdbj			       type, code);
6411.1Sdbj			goto dopanic;
6421.1Sdbj		}
6431.1Sdbj		ucode = v;
6441.1Sdbj		i = SIGSEGV;
6451.1Sdbj		break;
6461.1Sdbj	    }
6471.1Sdbj	}
6481.1Sdbj	trapsignal(p, i, ucode);
6491.1Sdbj	if ((type & T_USER) == 0)
6501.1Sdbj		return;
6511.1Sdbjout:
6521.1Sdbj	userret(p, &frame, sticks, v, 1);
6531.1Sdbj}
6541.1Sdbj
6551.1Sdbj#ifdef M68040
6561.1Sdbj#ifdef DEBUG
6571.1Sdbjstruct writebackstats {
6581.1Sdbj	int calls;
6591.1Sdbj	int cpushes;
6601.1Sdbj	int move16s;
6611.1Sdbj	int wb1s, wb2s, wb3s;
6621.1Sdbj	int wbsize[4];
6631.1Sdbj} wbstats;
6641.1Sdbj
6651.1Sdbjchar *f7sz[] = { "longword", "byte", "word", "line" };
6661.1Sdbjchar *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
6671.1Sdbjchar *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
6681.1Sdbj		 "M-code", "k-data", "k-code", "RES" };
6691.1Sdbjchar wberrstr[] =
6701.7Sdbj	"WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
6711.1Sdbj#endif
6721.1Sdbj
6731.1Sdbjwriteback(fp, docachepush)
6741.1Sdbj	struct frame *fp;
6751.1Sdbj	int docachepush;
6761.1Sdbj{
6771.1Sdbj	struct fmt7 *f = &fp->f_fmt7;
6781.1Sdbj	struct proc *p = curproc;
6791.1Sdbj	int err = 0;
6801.1Sdbj	u_int fa;
6811.1Sdbj	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
6821.1Sdbj
6831.1Sdbj#ifdef DEBUG
6841.1Sdbj	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
6851.1Sdbj		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
6861.1Sdbj		dumpssw(f->f_ssw);
6871.1Sdbj	}
6881.1Sdbj	wbstats.calls++;
6891.1Sdbj#endif
6901.1Sdbj	/*
6911.1Sdbj	 * Deal with special cases first.
6921.1Sdbj	 */
6931.1Sdbj	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
6941.1Sdbj		/*
6951.1Sdbj		 * Dcache push fault.
6961.1Sdbj		 * Line-align the address and write out the push data to
6971.1Sdbj		 * the indicated physical address.
6981.1Sdbj		 */
6991.1Sdbj#ifdef DEBUG
7001.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
7011.1Sdbj			printf(" pushing %s to PA %x, data %x",
7021.1Sdbj			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
7031.1Sdbj			       f->f_fa, f->f_pd0);
7041.1Sdbj			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
7051.1Sdbj				printf("/%x/%x/%x",
7061.1Sdbj				       f->f_pd1, f->f_pd2, f->f_pd3);
7071.1Sdbj			printf("\n");
7081.1Sdbj		}
7091.1Sdbj		if (f->f_wb1s & SSW4_WBSV)
7101.1Sdbj			panic("writeback: cache push with WB1S valid");
7111.1Sdbj		wbstats.cpushes++;
7121.1Sdbj#endif
7131.1Sdbj		/*
7141.1Sdbj		 * XXX there are security problems if we attempt to do a
7151.1Sdbj		 * cache push after a signal handler has been called.
7161.1Sdbj		 */
7171.1Sdbj		if (docachepush) {
7181.7Sdbj			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
7191.1Sdbj				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
7201.1Sdbj			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
7211.1Sdbj			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
7221.7Sdbj			DCFL(pmap_extract(pmap_kernel(), (vaddr_t)fa));
7231.7Sdbj			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
7241.7Sdbj				    (vaddr_t)&vmmap[NBPG]);
7251.1Sdbj		} else
7261.1Sdbj			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
7271.1Sdbj			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
7281.1Sdbj	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
7291.1Sdbj		/*
7301.1Sdbj		 * MOVE16 fault.
7311.1Sdbj		 * Line-align the address and write out the push data to
7321.1Sdbj		 * the indicated virtual address.
7331.1Sdbj		 */
7341.1Sdbj#ifdef DEBUG
7351.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
7361.1Sdbj			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
7371.1Sdbj			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
7381.1Sdbj			       f->f_pd2, f->f_pd3);
7391.1Sdbj		if (f->f_wb1s & SSW4_WBSV)
7401.1Sdbj			panic("writeback: MOVE16 with WB1S valid");
7411.1Sdbj		wbstats.move16s++;
7421.1Sdbj#endif
7431.1Sdbj		if (KDFAULT(f->f_wb1s))
7441.1Sdbj			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
7451.1Sdbj		else
7461.1Sdbj			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
7471.1Sdbj		if (err) {
7481.1Sdbj			fa = f->f_fa & ~0xF;
7491.1Sdbj#ifdef DEBUG
7501.1Sdbj			if (mmudebug & MDB_WBFAILED)
7511.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
7521.1Sdbj				       "MOVE16", fp->f_pc, f->f_fa,
7531.1Sdbj				       f->f_fa & ~0xF, f->f_pd0);
7541.1Sdbj#endif
7551.1Sdbj		}
7561.1Sdbj	} else if (f->f_wb1s & SSW4_WBSV) {
7571.1Sdbj		/*
7581.1Sdbj		 * Writeback #1.
7591.1Sdbj		 * Position the "memory-aligned" data and write it out.
7601.1Sdbj		 */
7611.1Sdbj		u_int wb1d = f->f_wb1d;
7621.1Sdbj		int off;
7631.1Sdbj
7641.1Sdbj#ifdef DEBUG
7651.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
7661.1Sdbj			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
7671.1Sdbj		wbstats.wb1s++;
7681.1Sdbj		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
7691.1Sdbj#endif
7701.1Sdbj		off = (f->f_wb1a & 3) * 8;
7711.1Sdbj		switch (f->f_wb1s & SSW4_SZMASK) {
7721.1Sdbj		case SSW4_SZLW:
7731.1Sdbj			if (off)
7741.1Sdbj				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
7751.1Sdbj			if (KDFAULT(f->f_wb1s))
7761.1Sdbj				*(long *)f->f_wb1a = wb1d;
7771.1Sdbj			else
7781.1Sdbj				err = suword((caddr_t)f->f_wb1a, wb1d);
7791.1Sdbj			break;
7801.1Sdbj		case SSW4_SZB:
7811.1Sdbj			off = 24 - off;
7821.1Sdbj			if (off)
7831.1Sdbj				wb1d >>= off;
7841.1Sdbj			if (KDFAULT(f->f_wb1s))
7851.1Sdbj				*(char *)f->f_wb1a = wb1d;
7861.1Sdbj			else
7871.1Sdbj				err = subyte((caddr_t)f->f_wb1a, wb1d);
7881.1Sdbj			break;
7891.1Sdbj		case SSW4_SZW:
7901.1Sdbj			off = (off + 16) % 32;
7911.1Sdbj			if (off)
7921.1Sdbj				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
7931.1Sdbj			if (KDFAULT(f->f_wb1s))
7941.1Sdbj				*(short *)f->f_wb1a = wb1d;
7951.1Sdbj			else
7961.1Sdbj				err = susword((caddr_t)f->f_wb1a, wb1d);
7971.1Sdbj			break;
7981.1Sdbj		}
7991.1Sdbj		if (err) {
8001.1Sdbj			fa = f->f_wb1a;
8011.1Sdbj#ifdef DEBUG
8021.1Sdbj			if (mmudebug & MDB_WBFAILED)
8031.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8041.1Sdbj				       "#1", fp->f_pc, f->f_fa,
8051.1Sdbj				       f->f_wb1a, f->f_wb1d);
8061.1Sdbj#endif
8071.1Sdbj		}
8081.1Sdbj	}
8091.1Sdbj	/*
8101.1Sdbj	 * Deal with the "normal" writebacks.
8111.1Sdbj	 *
8121.1Sdbj	 * XXX writeback2 is known to reflect a LINE size writeback after
8131.1Sdbj	 * a MOVE16 was already dealt with above.  Ignore it.
8141.1Sdbj	 */
8151.1Sdbj	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
8161.1Sdbj	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
8171.1Sdbj#ifdef DEBUG
8181.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
8191.1Sdbj			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
8201.1Sdbj		wbstats.wb2s++;
8211.1Sdbj		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
8221.1Sdbj#endif
8231.1Sdbj		switch (f->f_wb2s & SSW4_SZMASK) {
8241.1Sdbj		case SSW4_SZLW:
8251.1Sdbj			if (KDFAULT(f->f_wb2s))
8261.1Sdbj				*(long *)f->f_wb2a = f->f_wb2d;
8271.1Sdbj			else
8281.1Sdbj				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
8291.1Sdbj			break;
8301.1Sdbj		case SSW4_SZB:
8311.1Sdbj			if (KDFAULT(f->f_wb2s))
8321.1Sdbj				*(char *)f->f_wb2a = f->f_wb2d;
8331.1Sdbj			else
8341.1Sdbj				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
8351.1Sdbj			break;
8361.1Sdbj		case SSW4_SZW:
8371.1Sdbj			if (KDFAULT(f->f_wb2s))
8381.1Sdbj				*(short *)f->f_wb2a = f->f_wb2d;
8391.1Sdbj			else
8401.1Sdbj				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
8411.1Sdbj			break;
8421.1Sdbj		}
8431.1Sdbj		if (err) {
8441.1Sdbj			fa = f->f_wb2a;
8451.1Sdbj#ifdef DEBUG
8461.1Sdbj			if (mmudebug & MDB_WBFAILED) {
8471.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8481.1Sdbj				       "#2", fp->f_pc, f->f_fa,
8491.1Sdbj				       f->f_wb2a, f->f_wb2d);
8501.1Sdbj				dumpssw(f->f_ssw);
8511.1Sdbj				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
8521.1Sdbj			}
8531.1Sdbj#endif
8541.1Sdbj		}
8551.1Sdbj	}
8561.1Sdbj	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
8571.1Sdbj#ifdef DEBUG
8581.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
8591.1Sdbj			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
8601.1Sdbj		wbstats.wb3s++;
8611.1Sdbj		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
8621.1Sdbj#endif
8631.1Sdbj		switch (f->f_wb3s & SSW4_SZMASK) {
8641.1Sdbj		case SSW4_SZLW:
8651.1Sdbj			if (KDFAULT(f->f_wb3s))
8661.1Sdbj				*(long *)f->f_wb3a = f->f_wb3d;
8671.1Sdbj			else
8681.1Sdbj				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
8691.1Sdbj			break;
8701.1Sdbj		case SSW4_SZB:
8711.1Sdbj			if (KDFAULT(f->f_wb3s))
8721.1Sdbj				*(char *)f->f_wb3a = f->f_wb3d;
8731.1Sdbj			else
8741.1Sdbj				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
8751.1Sdbj			break;
8761.1Sdbj		case SSW4_SZW:
8771.1Sdbj			if (KDFAULT(f->f_wb3s))
8781.1Sdbj				*(short *)f->f_wb3a = f->f_wb3d;
8791.1Sdbj			else
8801.1Sdbj				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
8811.1Sdbj			break;
8821.1Sdbj#ifdef DEBUG
8831.1Sdbj		case SSW4_SZLN:
8841.1Sdbj			panic("writeback: wb3s indicates LINE write");
8851.1Sdbj#endif
8861.1Sdbj		}
8871.1Sdbj		if (err) {
8881.1Sdbj			fa = f->f_wb3a;
8891.1Sdbj#ifdef DEBUG
8901.1Sdbj			if (mmudebug & MDB_WBFAILED)
8911.1Sdbj				printf(wberrstr, p->p_pid, p->p_comm,
8921.1Sdbj				       "#3", fp->f_pc, f->f_fa,
8931.1Sdbj				       f->f_wb3a, f->f_wb3d);
8941.1Sdbj#endif
8951.1Sdbj		}
8961.1Sdbj	}
8971.1Sdbj	p->p_addr->u_pcb.pcb_onfault = oonfault;
8981.1Sdbj	if (err)
8991.1Sdbj		err = SIGSEGV;
9001.7Sdbj	return(err);
9011.1Sdbj}
9021.1Sdbj
9031.1Sdbj#ifdef DEBUG
9041.1Sdbjdumpssw(ssw)
9051.1Sdbj	u_short ssw;
9061.1Sdbj{
9071.1Sdbj	printf(" SSW: %x: ", ssw);
9081.1Sdbj	if (ssw & SSW4_CP)
9091.1Sdbj		printf("CP,");
9101.1Sdbj	if (ssw & SSW4_CU)
9111.1Sdbj		printf("CU,");
9121.1Sdbj	if (ssw & SSW4_CT)
9131.1Sdbj		printf("CT,");
9141.1Sdbj	if (ssw & SSW4_CM)
9151.1Sdbj		printf("CM,");
9161.1Sdbj	if (ssw & SSW4_MA)
9171.1Sdbj		printf("MA,");
9181.1Sdbj	if (ssw & SSW4_ATC)
9191.1Sdbj		printf("ATC,");
9201.1Sdbj	if (ssw & SSW4_LK)
9211.1Sdbj		printf("LK,");
9221.1Sdbj	if (ssw & SSW4_RW)
9231.1Sdbj		printf("RW,");
9241.1Sdbj	printf(" SZ=%s, TT=%s, TM=%s\n",
9251.1Sdbj	       f7sz[(ssw & SSW4_SZMASK) >> 5],
9261.1Sdbj	       f7tt[(ssw & SSW4_TTMASK) >> 3],
9271.1Sdbj	       f7tm[ssw & SSW4_TMMASK]);
9281.1Sdbj}
9291.1Sdbj
9301.1Sdbjdumpwb(num, s, a, d)
9311.1Sdbj	int num;
9321.1Sdbj	u_short s;
9331.1Sdbj	u_int a, d;
9341.1Sdbj{
9351.1Sdbj	struct proc *p = curproc;
9361.7Sdbj	paddr_t pa;
9371.1Sdbj
9381.1Sdbj	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
9391.1Sdbj	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
9401.1Sdbj	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
9411.7Sdbj	printf("	       PA ");
9421.7Sdbj	pa = pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a);
9431.1Sdbj	if (pa == 0)
9441.1Sdbj		printf("<invalid address>");
9451.1Sdbj	else
9461.7Sdbj		printf("%x, current value %x", pa, fuword((caddr_t)a));
9471.1Sdbj	printf("\n");
9481.1Sdbj}
9491.1Sdbj#endif
9501.1Sdbj#endif
9511.1Sdbj
9521.1Sdbj/*
9531.1Sdbj * Process a system call.
9541.1Sdbj */
9551.1Sdbjsyscall(code, frame)
9561.7Sdbj	int code;
9571.1Sdbj	struct frame frame;
9581.1Sdbj{
9591.1Sdbj	caddr_t params;
9601.1Sdbj	struct sysent *callp;
9611.1Sdbj	struct proc *p;
9621.1Sdbj	int error, opc, nsys;
9631.1Sdbj	size_t argsize;
9641.7Sdbj	int args[8], rval[2];
9651.1Sdbj	u_quad_t sticks;
9661.1Sdbj
9671.7Sdbj#if defined(UVM)
9681.7Sdbj	uvmexp.syscalls++;
9691.7Sdbj#else
9701.1Sdbj	cnt.v_syscall++;
9711.7Sdbj#endif
9721.1Sdbj	if (!USERMODE(frame.f_sr))
9731.1Sdbj		panic("syscall");
9741.1Sdbj	p = curproc;
9751.1Sdbj	sticks = p->p_sticks;
9761.1Sdbj	p->p_md.md_regs = frame.f_regs;
9771.1Sdbj	opc = frame.f_pc;
9781.1Sdbj
9791.1Sdbj	nsys = p->p_emul->e_nsysent;
9801.1Sdbj	callp = p->p_emul->e_sysent;
9811.1Sdbj
9821.1Sdbj#ifdef COMPAT_SUNOS
9831.1Sdbj	if (p->p_emul == &emul_sunos) {
9841.1Sdbj		/*
9851.1Sdbj		 * SunOS passes the syscall-number on the stack, whereas
9861.1Sdbj		 * BSD passes it in D0. So, we have to get the real "code"
9871.1Sdbj		 * from the stack, and clean up the stack, as SunOS glue
9881.1Sdbj		 * code assumes the kernel pops the syscall argument the
9891.1Sdbj		 * glue pushed on the stack. Sigh...
9901.1Sdbj		 */
9911.1Sdbj		code = fuword((caddr_t)frame.f_regs[SP]);
9921.1Sdbj
9931.1Sdbj		/*
9941.1Sdbj		 * XXX
9951.1Sdbj		 * Don't do this for sunos_sigreturn, as there's no stored pc
9961.1Sdbj		 * on the stack to skip, the argument follows the syscall
9971.1Sdbj		 * number without a gap.
9981.1Sdbj		 */
9991.1Sdbj		if (code != SUNOS_SYS_sigreturn) {
10001.1Sdbj			frame.f_regs[SP] += sizeof (int);
10011.1Sdbj			/*
10021.7Sdbj			 * remember that we adjusted the SP,
10031.1Sdbj			 * might have to undo this if the system call
10041.1Sdbj			 * returns ERESTART.
10051.1Sdbj			 */
10061.1Sdbj			p->p_md.md_flags |= MDP_STACKADJ;
10071.1Sdbj		} else
10081.1Sdbj			p->p_md.md_flags &= ~MDP_STACKADJ;
10091.1Sdbj	}
10101.1Sdbj#endif
10111.1Sdbj
10121.1Sdbj	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
10131.1Sdbj
10141.1Sdbj	switch (code) {
10151.1Sdbj	case SYS_syscall:
10161.1Sdbj		/*
10171.1Sdbj		 * Code is first argument, followed by actual args.
10181.1Sdbj		 */
10191.1Sdbj		code = fuword(params);
10201.1Sdbj		params += sizeof(int);
10211.1Sdbj		/*
10221.1Sdbj		 * XXX sigreturn requires special stack manipulation
10231.1Sdbj		 * that is only done if entered via the sigreturn
10241.1Sdbj		 * trap.  Cannot allow it here so make sure we fail.
10251.1Sdbj		 */
10261.6Sthorpej		switch (code) {
10271.6Sthorpej#ifdef COMPAT_13
10281.6Sthorpej		case SYS_compat_13_sigreturn13:
10291.6Sthorpej#endif
10301.6Sthorpej		case SYS___sigreturn14:
10311.1Sdbj			code = nsys;
10321.6Sthorpej			break;
10331.6Sthorpej		}
10341.1Sdbj		break;
10351.1Sdbj	case SYS___syscall:
10361.1Sdbj		/*
10371.1Sdbj		 * Like syscall, but code is a quad, so as to maintain
10381.1Sdbj		 * quad alignment for the rest of the arguments.
10391.1Sdbj		 */
10401.1Sdbj		if (callp != sysent)
10411.1Sdbj			break;
10421.1Sdbj		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
10431.1Sdbj		params += sizeof(quad_t);
10441.1Sdbj		break;
10451.1Sdbj	default:
10461.1Sdbj		break;
10471.1Sdbj	}
10481.1Sdbj	if (code < 0 || code >= nsys)
10491.1Sdbj		callp += p->p_emul->e_nosys;		/* illegal */
10501.1Sdbj	else
10511.1Sdbj		callp += code;
10521.1Sdbj	argsize = callp->sy_argsize;
10531.9Sitohy#ifdef COMPAT_LINUX
10541.9Sitohy	if (0
10551.9Sitohy# ifdef EXEC_AOUT
10561.9Sitohy	    || p->p_emul == &emul_linux_aout
10571.9Sitohy# endif
10581.9Sitohy# ifdef EXEC_ELF32
10591.9Sitohy	    || p->p_emul == &emul_linux_elf32
10601.9Sitohy# endif
10611.9Sitohy	     ) {
10621.9Sitohy		/*
10631.9Sitohy		 * Linux passes the args in d1-d5
10641.9Sitohy		 */
10651.9Sitohy		switch (argsize) {
10661.9Sitohy		case 20:
10671.9Sitohy			args[4] = frame.f_regs[D5];
10681.9Sitohy		case 16:
10691.9Sitohy			args[3] = frame.f_regs[D4];
10701.9Sitohy		case 12:
10711.9Sitohy			args[2] = frame.f_regs[D3];
10721.9Sitohy		case 8:
10731.9Sitohy			args[1] = frame.f_regs[D2];
10741.9Sitohy		case 4:
10751.9Sitohy			args[0] = frame.f_regs[D1];
10761.9Sitohy		case 0:
10771.9Sitohy			error = 0;
10781.9Sitohy			break;
10791.9Sitohy		default:
10801.9Sitohy#ifdef DEBUG
10811.9Sitohy			panic("linux syscall %d weird argsize %d",
10821.9Sitohy				code, argsize);
10831.9Sitohy#else
10841.9Sitohy			error = EINVAL;
10851.9Sitohy#endif
10861.9Sitohy			break;
10871.9Sitohy		}
10881.9Sitohy	} else
10891.9Sitohy#endif
10901.1Sdbj	if (argsize)
10911.1Sdbj		error = copyin(params, (caddr_t)args, argsize);
10921.1Sdbj	else
10931.1Sdbj		error = 0;
10941.1Sdbj#ifdef SYSCALL_DEBUG
10951.1Sdbj	scdebug_call(p, code, args);
10961.1Sdbj#endif
10971.1Sdbj#ifdef KTRACE
10981.1Sdbj	if (KTRPOINT(p, KTR_SYSCALL))
10991.1Sdbj		ktrsyscall(p->p_tracep, code, argsize, args);
11001.1Sdbj#endif
11011.1Sdbj	if (error)
11021.1Sdbj		goto bad;
11031.1Sdbj	rval[0] = 0;
11041.1Sdbj	rval[1] = frame.f_regs[D1];
11051.1Sdbj	error = (*callp->sy_call)(p, args, rval);
11061.1Sdbj	switch (error) {
11071.1Sdbj	case 0:
11081.1Sdbj		frame.f_regs[D0] = rval[0];
11091.1Sdbj		frame.f_regs[D1] = rval[1];
11101.1Sdbj		frame.f_sr &= ~PSL_C;	/* carry bit */
11111.1Sdbj		break;
11121.1Sdbj	case ERESTART:
11131.1Sdbj		/*
11141.1Sdbj		 * We always enter through a `trap' instruction, which is 2
11151.1Sdbj		 * bytes, so adjust the pc by that amount.
11161.1Sdbj		 */
11171.1Sdbj		frame.f_pc = opc - 2;
11181.1Sdbj		break;
11191.1Sdbj	case EJUSTRETURN:
11201.1Sdbj		/* nothing to do */
11211.1Sdbj		break;
11221.1Sdbj	default:
11231.1Sdbj	bad:
11241.1Sdbj		if (p->p_emul->e_errno)
11251.1Sdbj			error = p->p_emul->e_errno[error];
11261.1Sdbj		frame.f_regs[D0] = error;
11271.1Sdbj		frame.f_sr |= PSL_C;	/* carry bit */
11281.1Sdbj		break;
11291.1Sdbj	}
11301.1Sdbj
11311.1Sdbj#ifdef SYSCALL_DEBUG
11321.1Sdbj	scdebug_ret(p, code, error, rval);
11331.1Sdbj#endif
11341.1Sdbj#ifdef COMPAT_SUNOS
11351.1Sdbj	/* need new p-value for this */
11361.1Sdbj	if (error == ERESTART && (p->p_md.md_flags & MDP_STACKADJ))
11371.1Sdbj		frame.f_regs[SP] -= sizeof (int);
11381.1Sdbj#endif
11391.1Sdbj	userret(p, &frame, sticks, (u_int)0, 0);
11401.1Sdbj#ifdef KTRACE
11411.1Sdbj	if (KTRPOINT(p, KTR_SYSRET))
11421.1Sdbj		ktrsysret(p->p_tracep, code, error, rval[0]);
11431.1Sdbj#endif
11441.1Sdbj}
11451.1Sdbj
11461.1Sdbjvoid
11471.8Sthorpejchild_return(arg)
11481.8Sthorpej	void *arg;
11491.1Sdbj{
11501.8Sthorpej	struct proc *p = arg;
11511.8Sthorpej	/* See cpu_fork() */
11521.8Sthorpej	struct frame *f = (struct frame *)p->p_md.md_regs;
11531.8Sthorpej
11541.8Sthorpej	f->f_regs[D0] = 0;
11551.8Sthorpej	f->f_sr &= ~PSL_C;
11561.8Sthorpej	f->f_format = FMT0;
11571.1Sdbj
11581.8Sthorpej	userret(p, f, p->p_sticks, (u_int)0, 0);
11591.1Sdbj#ifdef KTRACE
11601.1Sdbj	if (KTRPOINT(p, KTR_SYSRET))
11611.1Sdbj		ktrsysret(p->p_tracep, SYS_fork, 0, 0);
11621.1Sdbj#endif
11631.1Sdbj}
11641.1Sdbj
11651.1Sdbj/*
11661.1Sdbj * Allocation routines for software interrupts.
11671.1Sdbj */
11681.1Sdbju_long
11691.1Sdbjallocate_sir(proc, arg)
11701.1Sdbj	void (*proc)();
11711.1Sdbj	void *arg;
11721.1Sdbj{
11731.1Sdbj	int bit;
11741.1Sdbj
11751.1Sdbj	if( next_sir >= NSIR )
11761.1Sdbj		panic("allocate_sir: none left");
11771.1Sdbj	bit = next_sir++;
11781.1Sdbj	sir_routines[bit] = proc;
11791.1Sdbj	sir_args[bit] = arg;
11801.1Sdbj	return (1 << bit);
11811.1Sdbj}
11821.1Sdbj
11831.1Sdbjvoid
11841.1Sdbjinit_sir()
11851.1Sdbj{
11861.1Sdbj	extern void netintr();
11871.1Sdbj
11881.1Sdbj	sir_routines[0] = netintr;
11891.1Sdbj	sir_routines[1] = softclock;
11901.1Sdbj	next_sir = 2;
11911.1Sdbj}
1192