11.97Sthorpej/*	$NetBSD: trap.c,v 1.97 2024/01/20 00:15:32 thorpej 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.93Stsutsui * original cvs id: NetBSD: trap.c,v 1.32 1999/08/03 10:52:06 dbj Exp
81.7Sdbj */
91.1Sdbj
101.1Sdbj/*
111.84Srmind * 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.43Sagc * 3. Neither the name of the University nor the names of its contributors
281.43Sagc *    may be used to endorse or promote products derived from this software
291.43Sagc *    without specific prior written permission.
301.43Sagc *
311.43Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
321.43Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
331.43Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
341.43Sagc * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
351.43Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
361.43Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
371.43Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
381.43Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
391.43Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
401.43Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
411.43Sagc * SUCH DAMAGE.
421.43Sagc *
431.43Sagc * from: Utah $Hdr: trap.c 1.37 92/12/20$
441.43Sagc *
451.43Sagc *	@(#)trap.c	8.5 (Berkeley) 1/4/94
461.43Sagc */
471.42Slukem
481.42Slukem#include <sys/cdefs.h>
491.97Sthorpej__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.97 2024/01/20 00:15:32 thorpej Exp $");
501.2Sthorpej
511.5Sjonathan#include "opt_ddb.h"
521.9Sitohy#include "opt_execfmt.h"
531.33Slukem#include "opt_kgdb.h"
541.3Sthorpej#include "opt_compat_sunos.h"
551.80Smrg#include "opt_m68k_arch.h"
561.1Sdbj
571.1Sdbj#include <sys/param.h>
581.1Sdbj#include <sys/systm.h>
591.1Sdbj#include <sys/proc.h>
601.1Sdbj#include <sys/acct.h>
611.1Sdbj#include <sys/kernel.h>
621.1Sdbj#include <sys/signalvar.h>
631.1Sdbj#include <sys/resourcevar.h>
641.1Sdbj#include <sys/syscall.h>
651.1Sdbj#include <sys/syslog.h>
661.47Scl#include <sys/userret.h>
671.59Syamt#include <sys/kauth.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.83Stsutsui#include <machine/pcb.h>
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.16Sdbj#include <m68k/cacheops.h>
811.16Sdbj
821.7Sdbj#include <uvm/uvm_extern.h>
831.1Sdbj
841.1Sdbj#ifdef COMPAT_SUNOS
851.1Sdbj#include <compat/sunos/sunos_syscall.h>
861.1Sdbjextern struct emul emul_sunos;
871.1Sdbj#endif
881.1Sdbj
891.37Sjdolecek#ifdef KGDB
901.37Sjdolecek#include <sys/kgdb.h>
911.37Sjdolecek#endif
921.37Sjdolecek
931.67Smhitchvoid	trap(struct frame *, int, u_int, u_int);
941.16Sdbj
951.16Sdbj#ifdef DEBUG
961.53Schsvoid	dumpssw(u_short);
971.53Schsvoid	dumpwb(int, u_short, u_int, u_int);
981.16Sdbj#endif
991.16Sdbj
1001.53Schsstatic inline void userret(struct lwp *, struct frame *, u_quad_t, u_int, int);
1011.1Sdbj
1021.54Sheconst char *trap_type[] = {
1031.1Sdbj	"Bus error",
1041.1Sdbj	"Address error",
1051.1Sdbj	"Illegal instruction",
1061.1Sdbj	"Zero divide",
1071.1Sdbj	"CHK instruction",
1081.1Sdbj	"TRAPV instruction",
1091.1Sdbj	"Privilege violation",
1101.1Sdbj	"Trace trap",
1111.1Sdbj	"MMU fault",
1121.1Sdbj	"SSIR trap",
1131.1Sdbj	"Format error",
1141.1Sdbj	"68881 exception",
1151.1Sdbj	"Coprocessor violation",
1161.1Sdbj	"Async system trap"
1171.1Sdbj};
1181.1Sdbjint	trap_types = sizeof trap_type / sizeof trap_type[0];
1191.1Sdbj
1201.1Sdbj/*
1211.1Sdbj * Size of various exception stack frames (minus the standard 8 bytes)
1221.1Sdbj */
1231.1Sdbjshort	exframesize[] = {
1241.16Sdbj	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
1251.1Sdbj	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
1261.16Sdbj	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
1271.16Sdbj	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
1281.16Sdbj	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
1291.16Sdbj	-1, -1,		/* type 5-6 - undefined */
1301.1Sdbj	FMT7SIZE,	/* type 7 - access error (68040) */
1311.1Sdbj	58,		/* type 8 - bus fault (68010) */
1321.1Sdbj	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
1331.1Sdbj	FMTASIZE,	/* type A - short bus fault (68020/030) */
1341.1Sdbj	FMTBSIZE,	/* type B - long bus fault (68020/030) */
1351.1Sdbj	-1, -1, -1, -1	/* type C-F - undefined */
1361.1Sdbj};
1371.1Sdbj
1381.16Sdbj#ifdef M68060
1391.16Sdbj#define	KDFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_TM_SV))
1401.16Sdbj#define	WRFAULT_060(c)	(cputype == CPU_68060 && ((c) & FSLW_RW_W))
1411.16Sdbj#else
1421.16Sdbj#define	KDFAULT_060(c)	0
1431.16Sdbj#define	WRFAULT_060(c)	0
1441.16Sdbj#endif
1451.16Sdbj
1461.1Sdbj#ifdef M68040
1471.16Sdbj#define	KDFAULT_040(c)	(cputype == CPU_68040 && \
1481.16Sdbj			 ((c) & SSW4_TMMASK) == SSW4_TMKD)
1491.16Sdbj#define	WRFAULT_040(c)	(cputype == CPU_68040 && \
1501.68Smhitch			 ((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW)
1511.16Sdbj#else
1521.16Sdbj#define	KDFAULT_040(c)	0
1531.16Sdbj#define	WRFAULT_040(c)	0
1541.16Sdbj#endif
1551.16Sdbj
1561.16Sdbj#if defined(M68030) || defined(M68020)
1571.16Sdbj#define	KDFAULT_OTH(c)	(cputype <= CPU_68030 && \
1581.16Sdbj			 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
1591.16Sdbj#define	WRFAULT_OTH(c)	(cputype <= CPU_68030 && \
1601.68Smhitch			 (((c) & SSW_DF) != 0 && \
1611.68Smhitch			 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0))))
1621.1Sdbj#else
1631.16Sdbj#define	KDFAULT_OTH(c)	0
1641.16Sdbj#define	WRFAULT_OTH(c)	0
1651.1Sdbj#endif
1661.1Sdbj
1671.16Sdbj#define	KDFAULT(c)	(KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
1681.16Sdbj#define	WRFAULT(c)	(WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
1691.16Sdbj
1701.1Sdbj#ifdef DEBUG
1711.1Sdbjint mmudebug = 0;
1721.1Sdbjint mmupid = -1;
1731.1Sdbj#define MDB_FOLLOW	1
1741.1Sdbj#define MDB_WBFOLLOW	2
1751.1Sdbj#define MDB_WBFAILED	4
1761.16Sdbj#define MDB_ISPID(p)	((p) == mmupid)
1771.1Sdbj#endif
1781.1Sdbj
1791.1Sdbj/*
1801.1Sdbj * trap and syscall both need the following work done before returning
1811.1Sdbj * to user mode.
1821.1Sdbj */
1831.1Sdbjstatic inline void
1841.53Schsuserret(struct lwp *l, struct frame *fp, u_quad_t oticks, u_int faultaddr,
1851.53Schs    int fromtrap)
1861.1Sdbj{
1871.39Sthorpej	struct proc *p = l->l_proc;
1881.48Scl#ifdef M68040
1891.20Sthorpej	int sig;
1901.1Sdbj	int beenhere = 0;
1911.1Sdbj
1921.1Sdbjagain:
1931.1Sdbj#endif
1941.47Scl	/* Invoke MI userret code */
1951.47Scl	mi_userret(l);
1961.1Sdbj
1971.1Sdbj	/*
1981.1Sdbj	 * If profiling, charge system time to the trapped pc.
1991.1Sdbj	 */
2001.62Sad	if (p->p_stflag & PST_PROFIL) {
2011.1Sdbj		extern int psratio;
2021.1Sdbj
2031.62Sad		addupc_task(l, fp->f_pc,
2041.1Sdbj			    (int)(p->p_sticks - oticks) * psratio);
2051.1Sdbj	}
2061.1Sdbj#ifdef M68040
2071.1Sdbj	/*
2081.1Sdbj	 * Deal with user mode writebacks (from trap, or from sigreturn).
2091.1Sdbj	 * If any writeback fails, go back and attempt signal delivery.
2101.1Sdbj	 * unless we have already been here and attempted the writeback
2111.1Sdbj	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
2121.40Swiz	 * we just return to the user without successfully completing
2131.1Sdbj	 * the writebacks.  Maybe we should just drop the sucker?
2141.1Sdbj	 */
2151.16Sdbj	if (cputype == CPU_68040 && fp->f_format == FMT7) {
2161.1Sdbj		if (beenhere) {
2171.1Sdbj#ifdef DEBUG
2181.1Sdbj			if (mmudebug & MDB_WBFAILED)
2191.1Sdbj				printf(fromtrap ?
2201.1Sdbj		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
2211.1Sdbj		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
2221.1Sdbj				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
2231.1Sdbj#endif
2241.89Sthorpej		} else if ((sig = m68040_writeback(fp, fromtrap))) {
2251.45Scl			ksiginfo_t ksi;
2261.1Sdbj			beenhere = 1;
2271.1Sdbj			oticks = p->p_sticks;
2281.45Scl			(void)memset(&ksi, 0, sizeof(ksi));
2291.45Scl			ksi.ksi_signo = sig;
2301.45Scl			ksi.ksi_addr = (void *)faultaddr;
2311.45Scl			ksi.ksi_code = BUS_OBJERR;
2321.45Scl			trapsignal(l, &ksi);
2331.1Sdbj			goto again;
2341.1Sdbj		}
2351.1Sdbj	}
2361.1Sdbj#endif
2371.1Sdbj}
2381.1Sdbj
2391.1Sdbj/*
2401.28Sscw * Used by the common m68k syscall() and child_return() functions.
2411.28Sscw * XXX: Temporary until all m68k ports share common trap()/userret() code.
2421.28Sscw */
2431.39Sthorpejvoid machine_userret(struct lwp *, struct frame *, u_quad_t);
2441.28Sscw
2451.28Sscwvoid
2461.53Schsmachine_userret(struct lwp *l, struct frame *f, u_quad_t t)
2471.28Sscw{
2481.28Sscw
2491.39Sthorpej	userret(l, f, t, 0, 0);
2501.28Sscw}
2511.28Sscw
2521.28Sscw/*
2531.1Sdbj * Trap is called from locore to handle most types of processor traps,
2541.1Sdbj * including events such as simulated software interrupts/AST's.
2551.1Sdbj * System calls are broken out for efficiency.
2561.1Sdbj */
2571.1Sdbj/*ARGSUSED*/
2581.16Sdbjvoid
2591.67Smhitchtrap(struct frame *fp, int type, unsigned code, unsigned v)
2601.1Sdbj{
2611.39Sthorpej	struct lwp *l;
2621.1Sdbj	struct proc *p;
2631.78Srmind	struct pcb *pcb;
2641.79Schs	void *onfault;
2651.45Scl	ksiginfo_t ksi;
2661.45Scl	int s;
2671.79Schs	int rv;
2681.16Sdbj	u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */;
2691.87Schristos	static int panicking __diagused;
2701.1Sdbj
2711.82Smatt	curcpu()->ci_data.cpu_ntrap++;
2721.39Sthorpej	l = curlwp;
2731.79Schs	p = l->l_proc;
2741.79Schs	pcb = lwp_getpcb(l);
2751.45Scl
2761.46Sthorpej	KSI_INIT_TRAP(&ksi);
2771.45Scl	ksi.ksi_trap = type & ~T_USER;
2781.16Sdbj
2791.67Smhitch	if (USERMODE(fp->f_sr)) {
2801.1Sdbj		type |= T_USER;
2811.1Sdbj		sticks = p->p_sticks;
2821.67Smhitch		l->l_md.md_regs = fp->f_regs;
2831.1Sdbj	}
2841.1Sdbj	switch (type) {
2851.1Sdbj
2861.1Sdbj	default:
2871.14Sdbj	dopanic:
2881.14Sdbj		/*
2891.14Sdbj		 * Let the kernel debugger see the trap frame that
2901.14Sdbj		 * caused us to panic.  This is a convenience so
2911.14Sdbj		 * one can see registers at the point of failure.
2921.14Sdbj		 */
2931.16Sdbj		s = splhigh();
2941.51Swiz		panicking = 1;
2951.38Smycroft		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
2961.38Smycroft		printf("%s program counter = 0x%x\n",
2971.67Smhitch		    (type & T_USER) ? "user" : "kernel", fp->f_pc);
2981.14Sdbj#ifdef KGDB
2991.14Sdbj		/* If connected, step or cont returns 1 */
3001.67Smhitch		if (kgdb_trap(type, (db_regs_t *)fp))
3011.14Sdbj			goto kgdb_cont;
3021.14Sdbj#endif
3031.16Sdbj#ifdef DDB
3041.67Smhitch		(void)kdb_trap(type, (db_regs_t *)fp);
3051.1Sdbj#endif
3061.14Sdbj#ifdef KGDB
3071.14Sdbj	kgdb_cont:
3081.14Sdbj#endif
3091.16Sdbj		splx(s);
3101.14Sdbj		if (panicstr) {
3111.16Sdbj			printf("trap during panic!\n");
3121.16Sdbj#ifdef DEBUG
3131.16Sdbj			/* XXX should be a machine-dependent hook */
3141.92Stsutsui			printf("(press a key)\n");
3151.92Stsutsui			cnpollc(1);
3161.92Stsutsui			(void)cngetc();
3171.92Stsutsui			cnpollc(0);
3181.16Sdbj#endif
3191.14Sdbj		}
3201.67Smhitch		regdump((struct trapframe *)fp, 128);
3211.1Sdbj		type &= ~T_USER;
3221.16Sdbj		if ((u_int)type < trap_types)
3231.1Sdbj			panic(trap_type[type]);
3241.1Sdbj		panic("trap");
3251.1Sdbj
3261.1Sdbj	case T_BUSERR:		/* kernel bus error */
3271.79Schs		onfault = pcb->pcb_onfault;
3281.79Schs		if (onfault == NULL)
3291.1Sdbj			goto dopanic;
3301.79Schs		rv = EFAULT;
3311.16Sdbj		/* FALLTHROUGH */
3321.16Sdbj
3331.16Sdbj	copyfault:
3341.1Sdbj		/*
3351.1Sdbj		 * If we have arranged to catch this fault in any of the
3361.1Sdbj		 * copy to/from user space routines, set PC to return to
3371.1Sdbj		 * indicated location and set flag informing buserror code
3381.1Sdbj		 * that it may need to clean up stack frame.
3391.1Sdbj		 */
3401.67Smhitch		fp->f_stackadj = exframesize[fp->f_format];
3411.67Smhitch		fp->f_format = fp->f_vector = 0;
3421.79Schs		fp->f_pc = (int)onfault;
3431.79Schs		fp->f_regs[D0] = rv;
3441.1Sdbj		return;
3451.1Sdbj
3461.1Sdbj	case T_BUSERR|T_USER:	/* bus error */
3471.1Sdbj	case T_ADDRERR|T_USER:	/* address error */
3481.45Scl		ksi.ksi_addr = (void *)v;
3491.45Scl		ksi.ksi_signo = SIGBUS;
3501.45Scl		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
3511.45Scl			BUS_OBJERR : BUS_ADRERR;
3521.1Sdbj		break;
3531.1Sdbj
3541.1Sdbj	case T_COPERR:		/* kernel coprocessor violation */
3551.1Sdbj	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
3561.1Sdbj	case T_FMTERR:		/* ...just in case... */
3571.1Sdbj	/*
3581.1Sdbj	 * The user has most likely trashed the RTE or FP state info
3591.1Sdbj	 * in the stack frame of a signal handler.
3601.1Sdbj	 */
3611.1Sdbj		printf("pid %d: kernel %s exception\n", p->p_pid,
3621.1Sdbj		       type==T_COPERR ? "coprocessor" : "format");
3631.1Sdbj		type |= T_USER;
3641.62Sad
3651.73Sad		mutex_enter(p->p_lock);
3661.29Sjdolecek		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
3671.29Sjdolecek		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
3681.29Sjdolecek		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
3691.62Sad		sigdelset(&l->l_sigmask, SIGILL);
3701.73Sad		mutex_exit(p->p_lock);
3711.62Sad
3721.45Scl		ksi.ksi_signo = SIGILL;
3731.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
3741.45Scl				/* XXX was ILL_RESAD_FAULT */
3751.45Scl		ksi.ksi_code = (type == T_COPERR) ?
3761.45Scl			ILL_COPROC : ILL_ILLOPC;
3771.1Sdbj		break;
3781.1Sdbj
3791.1Sdbj	case T_COPERR|T_USER:	/* user coprocessor violation */
3801.1Sdbj	/* What is a proper response here? */
3811.45Scl		ksi.ksi_signo = SIGFPE;
3821.45Scl		ksi.ksi_code = FPE_FLTINV;
3831.1Sdbj		break;
3841.1Sdbj
3851.1Sdbj	case T_FPERR|T_USER:	/* 68881 exceptions */
3861.1Sdbj	/*
3871.7Sdbj	 * We pass along the 68881 status register which locore stashed
3881.75Smartin	 * in code for us.
3891.1Sdbj	 */
3901.45Scl		ksi.ksi_signo = SIGFPE;
3911.75Smartin		ksi.ksi_code = fpsr2siginfocode(code);
3921.1Sdbj		break;
3931.1Sdbj
3941.1Sdbj#ifdef M68040
3951.56Swiz	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
3961.1Sdbj	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
3971.1Sdbj		/* XXX need to FSAVE */
3981.1Sdbj		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
3991.1Sdbj		       p->p_pid, p->p_comm,
4001.67Smhitch		       fp->f_format == 2 ? "instruction" : "data type",
4011.67Smhitch		       fp->f_pc, fp->f_fmt2.f_iaddr);
4021.1Sdbj		/* XXX need to FRESTORE */
4031.45Scl		ksi.ksi_signo = SIGFPE;
4041.45Scl		ksi.ksi_code = FPE_FLTINV;
4051.1Sdbj		break;
4061.1Sdbj#endif
4071.1Sdbj
4081.1Sdbj	case T_ILLINST|T_USER:	/* illegal instruction fault */
4091.1Sdbj	case T_PRIVINST|T_USER:	/* privileged instruction fault */
4101.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
4111.45Scl				/* XXX was ILL_PRIVIN_FAULT */
4121.45Scl		ksi.ksi_signo = SIGILL;
4131.45Scl		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
4141.45Scl			ILL_PRVOPC : ILL_ILLOPC;
4151.1Sdbj		break;
4161.1Sdbj
4171.1Sdbj	case T_ZERODIV|T_USER:	/* Divide by zero */
4181.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
4191.45Scl				/* XXX was FPE_INTDIV_TRAP */
4201.45Scl		ksi.ksi_signo = SIGFPE;
4211.45Scl		ksi.ksi_code = FPE_FLTDIV;
4221.1Sdbj		break;
4231.1Sdbj
4241.1Sdbj	case T_CHKINST|T_USER:	/* CHK instruction trap */
4251.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
4261.45Scl				/* XXX was FPE_SUBRNG_TRAP */
4271.45Scl		ksi.ksi_signo = SIGFPE;
4281.1Sdbj		break;
4291.1Sdbj
4301.1Sdbj	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
4311.67Smhitch		ksi.ksi_addr = (void *)(int)fp->f_format;
4321.45Scl				/* XXX was FPE_INTOVF_TRAP */
4331.45Scl		ksi.ksi_signo = SIGFPE;
4341.1Sdbj		break;
4351.1Sdbj
4361.1Sdbj	/*
4371.1Sdbj	 * XXX: Trace traps are a nightmare.
4381.1Sdbj	 *
4391.1Sdbj	 *	HP-UX uses trap #1 for breakpoints,
4401.16Sdbj	 *	NetBSD/m68k uses trap #2,
4411.1Sdbj	 *	SUN 3.x uses trap #15,
4421.16Sdbj	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
4431.16Sdbj	 *	handled elsewhere).
4441.1Sdbj	 *
4451.16Sdbj	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
4461.1Sdbj	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
4471.1Sdbj	 * supported yet.
4481.16Sdbj	 *
4491.17Sitohy	 * XXX: We should never get kernel-mode T_TRAP15
4501.16Sdbj	 * XXX: because locore.s now gives them special treatment.
4511.1Sdbj	 */
4521.16Sdbj	case T_TRAP15:		/* kernel breakpoint */
4531.16Sdbj#ifdef DEBUG
4541.16Sdbj		printf("unexpected kernel trace trap, type = %d\n", type);
4551.67Smhitch		printf("program counter = 0x%x\n", fp->f_pc);
4561.1Sdbj#endif
4571.67Smhitch		fp->f_sr &= ~PSL_T;
4581.16Sdbj		return;
4591.1Sdbj
4601.1Sdbj	case T_TRACE|T_USER:	/* user trace trap */
4611.1Sdbj#ifdef COMPAT_SUNOS
4621.1Sdbj		/*
4631.1Sdbj		 * SunOS uses Trap #2 for a "CPU cache flush".
4641.1Sdbj		 * Just flush the on-chip caches and return.
4651.1Sdbj		 */
4661.1Sdbj		if (p->p_emul == &emul_sunos) {
4671.1Sdbj			ICIA();
4681.1Sdbj			DCIU();
4691.1Sdbj			return;
4701.1Sdbj		}
4711.16Sdbj#endif
4721.17Sitohy		/* FALLTHROUGH */
4731.17Sitohy	case T_TRACE:		/* tracing a trap instruction */
4741.17Sitohy	case T_TRAP15|T_USER:	/* SUN user trace trap */
4751.67Smhitch		fp->f_sr &= ~PSL_T;
4761.45Scl		ksi.ksi_signo = SIGTRAP;
4771.1Sdbj		break;
4781.1Sdbj
4791.1Sdbj	case T_ASTFLT:		/* system async trap, cannot happen */
4801.1Sdbj		goto dopanic;
4811.1Sdbj
4821.1Sdbj	case T_ASTFLT|T_USER:	/* user async trap */
4831.1Sdbj		astpending = 0;
4841.1Sdbj		/*
4851.1Sdbj		 * We check for software interrupts first.  This is because
4861.1Sdbj		 * they are at a higher level than ASTs, and on a VAX would
4871.1Sdbj		 * interrupt the AST.  We assume that if we are processing
4881.1Sdbj		 * an AST that we must be at IPL0 so we don't bother to
4891.1Sdbj		 * check.  Note that we ensure that we are at least at SIR
4901.1Sdbj		 * IPL while processing the SIR.
4911.1Sdbj		 */
4921.1Sdbj		spl1();
4931.1Sdbj		/* fall into... */
4941.1Sdbj
4951.1Sdbj	case T_SSIR:		/* software interrupt */
4961.1Sdbj	case T_SSIR|T_USER:
4971.1Sdbj		/*
4981.1Sdbj		 * If this was not an AST trap, we are all done.
4991.1Sdbj		 */
5001.1Sdbj		if (type != (T_ASTFLT|T_USER)) {
5011.82Smatt			curcpu()->ci_data.cpu_ntrap--;
5021.1Sdbj			return;
5031.1Sdbj		}
5041.1Sdbj		spl0();
5051.62Sad		if (l->l_pflag & LP_OWEUPC) {
5061.62Sad			l->l_pflag &= ~LP_OWEUPC;
5071.62Sad			ADDUPROF(l);
5081.1Sdbj		}
5091.1Sdbj		goto out;
5101.1Sdbj
5111.1Sdbj	case T_MMUFLT:		/* kernel mode page fault */
5121.1Sdbj	case T_MMUFLT|T_USER:	/* page fault */
5131.1Sdbj	    {
5141.7Sdbj		vaddr_t va;
5151.1Sdbj		struct vmspace *vm = p->p_vmspace;
5161.34Schs		struct vm_map *map;
5171.1Sdbj		vm_prot_t ftype;
5181.34Schs		extern struct vm_map *kernel_map;
5191.1Sdbj
5201.79Schs		onfault = pcb->pcb_onfault;
5211.79Schs
5221.1Sdbj#ifdef DEBUG
5231.1Sdbj		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
5241.1Sdbj		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
5251.67Smhitch		       p->p_pid, code, v, fp->f_pc, fp->f_sr);
5261.1Sdbj#endif
5271.1Sdbj		/*
5281.1Sdbj		 * It is only a kernel address space fault iff:
5291.1Sdbj		 * 	1. (type & T_USER) == 0  and
5301.1Sdbj		 * 	2. pcb_onfault not set or
5311.1Sdbj		 *	3. pcb_onfault set but supervisor space data fault
5321.1Sdbj		 * The last can occur during an exec() copyin where the
5331.1Sdbj		 * argument space is lazy-allocated.
5341.1Sdbj		 */
5351.79Schs		if ((type & T_USER) == 0 && (onfault == NULL || KDFAULT(code)))
5361.1Sdbj			map = kernel_map;
5371.74Swrstuden		else {
5381.16Sdbj			map = vm ? &vm->vm_map : kernel_map;
5391.74Swrstuden		}
5401.16Sdbj
5411.1Sdbj		if (WRFAULT(code))
5421.36Schs			ftype = VM_PROT_WRITE;
5431.1Sdbj		else
5441.1Sdbj			ftype = VM_PROT_READ;
5451.16Sdbj
5461.7Sdbj		va = trunc_page((vaddr_t)v);
5471.16Sdbj
5481.1Sdbj		if (map == kernel_map && va == 0) {
5491.16Sdbj			printf("trap: bad kernel %s access at 0x%x\n",
5501.16Sdbj			    (ftype & VM_PROT_WRITE) ? "read/write" :
5511.16Sdbj			    "read", v);
5521.1Sdbj			goto dopanic;
5531.1Sdbj		}
5541.16Sdbj
5551.38Smycroft#ifdef DIAGNOSTIC
5561.96Sthorpej		if (intr_depth && !panicking) {
5571.38Smycroft			printf("trap: calling uvm_fault() from interrupt!\n");
5581.38Smycroft			goto dopanic;
5591.38Smycroft		}
5601.38Smycroft#endif
5611.93Stsutsui
5621.79Schs		pcb->pcb_onfault = NULL;
5631.57Sdrochner		rv = uvm_fault(map, va, ftype);
5641.79Schs		pcb->pcb_onfault = onfault;
5651.7Sdbj#ifdef DEBUG
5661.7Sdbj		if (rv && MDB_ISPID(p->p_pid))
5671.57Sdrochner			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
5681.16Sdbj			    map, va, ftype, rv);
5691.7Sdbj#endif
5701.1Sdbj		/*
5711.1Sdbj		 * If this was a stack access we keep track of the maximum
5721.1Sdbj		 * accessed stack size.  Also, if vm_fault gets a protection
5731.1Sdbj		 * failure it is due to accessing the stack region outside
5741.1Sdbj		 * the current limit and we need to reflect that as an access
5751.1Sdbj		 * error.
5761.1Sdbj		 */
5771.31Schs		if (rv == 0) {
5781.64Schristos			if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
5791.52Sjdolecek				uvm_grow(p, va);
5801.52Sjdolecek
5811.1Sdbj			if (type == T_MMUFLT) {
5821.16Sdbj#ifdef M68040
5831.16Sdbj				if (cputype == CPU_68040)
5841.89Sthorpej					(void) m68040_writeback(fp, 1);
5851.1Sdbj#endif
5861.1Sdbj				return;
5871.1Sdbj			}
5881.1Sdbj			goto out;
5891.1Sdbj		}
5901.45Scl		if (rv == EACCES) {
5911.45Scl			ksi.ksi_code = SEGV_ACCERR;
5921.45Scl			rv = EFAULT;
5931.45Scl		} else
5941.45Scl			ksi.ksi_code = SEGV_MAPERR;
5951.1Sdbj		if (type == T_MMUFLT) {
5961.79Schs			if (onfault)
5971.1Sdbj				goto copyfault;
5981.57Sdrochner			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
5991.16Sdbj			    map, va, ftype, rv);
6001.1Sdbj			printf("  type %x, code [mmu,,ssw]: %x\n",
6011.1Sdbj			       type, code);
6021.1Sdbj			goto dopanic;
6031.1Sdbj		}
6041.45Scl		ksi.ksi_addr = (void *)v;
6051.88Smartin		switch (rv) {
6061.88Smartin		case ENOMEM:
6071.11Schs			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
6081.11Schs			       p->p_pid, p->p_comm,
6091.61Sad			       l->l_cred ?
6101.61Sad			       kauth_cred_geteuid(l->l_cred) : -1);
6111.45Scl			ksi.ksi_signo = SIGKILL;
6121.88Smartin			break;
6131.88Smartin		case EINVAL:
6141.88Smartin			ksi.ksi_signo = SIGBUS;
6151.88Smartin			ksi.ksi_code = BUS_ADRERR;
6161.88Smartin			break;
6171.88Smartin		case EACCES:
6181.45Scl			ksi.ksi_signo = SIGSEGV;
6191.88Smartin			ksi.ksi_code = SEGV_ACCERR;
6201.88Smartin			break;
6211.88Smartin		default:
6221.88Smartin			ksi.ksi_signo = SIGSEGV;
6231.88Smartin			ksi.ksi_code = SEGV_MAPERR;
6241.88Smartin			break;
6251.11Schs		}
6261.1Sdbj		break;
6271.1Sdbj	    }
6281.1Sdbj	}
6291.45Scl	trapsignal(l, &ksi);
6301.1Sdbj	if ((type & T_USER) == 0)
6311.1Sdbj		return;
6321.1Sdbjout:
6331.67Smhitch	userret(l, fp, sticks, v, 1);
6341.1Sdbj}
635