xref: /freebsd/sys/powerpc/powerpc/trap.c (revision be2bd024)
128cbb9b1SJustin Hibbits /*-
228cbb9b1SJustin Hibbits  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
328cbb9b1SJustin Hibbits  * Copyright (C) 1995, 1996 TooLs GmbH.
428cbb9b1SJustin Hibbits  * All rights reserved.
528cbb9b1SJustin Hibbits  *
628cbb9b1SJustin Hibbits  * Redistribution and use in source and binary forms, with or without
728cbb9b1SJustin Hibbits  * modification, are permitted provided that the following conditions
828cbb9b1SJustin Hibbits  * are met:
928cbb9b1SJustin Hibbits  * 1. Redistributions of source code must retain the above copyright
1028cbb9b1SJustin Hibbits  *    notice, this list of conditions and the following disclaimer.
1128cbb9b1SJustin Hibbits  * 2. Redistributions in binary form must reproduce the above copyright
1228cbb9b1SJustin Hibbits  *    notice, this list of conditions and the following disclaimer in the
1328cbb9b1SJustin Hibbits  *    documentation and/or other materials provided with the distribution.
1428cbb9b1SJustin Hibbits  * 3. All advertising materials mentioning features or use of this software
1528cbb9b1SJustin Hibbits  *    must display the following acknowledgement:
1628cbb9b1SJustin Hibbits  *	This product includes software developed by TooLs GmbH.
1728cbb9b1SJustin Hibbits  * 4. The name of TooLs GmbH may not be used to endorse or promote products
1828cbb9b1SJustin Hibbits  *    derived from this software without specific prior written permission.
1928cbb9b1SJustin Hibbits  *
2028cbb9b1SJustin Hibbits  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2128cbb9b1SJustin Hibbits  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2228cbb9b1SJustin Hibbits  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2328cbb9b1SJustin Hibbits  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2428cbb9b1SJustin Hibbits  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2528cbb9b1SJustin Hibbits  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2628cbb9b1SJustin Hibbits  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2728cbb9b1SJustin Hibbits  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2828cbb9b1SJustin Hibbits  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2928cbb9b1SJustin Hibbits  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3028cbb9b1SJustin Hibbits  *
3128cbb9b1SJustin Hibbits  * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $
3228cbb9b1SJustin Hibbits  */
3328cbb9b1SJustin Hibbits 
3428cbb9b1SJustin Hibbits #include <sys/cdefs.h>
3528cbb9b1SJustin Hibbits __FBSDID("$FreeBSD$");
3628cbb9b1SJustin Hibbits 
3728cbb9b1SJustin Hibbits #include <sys/param.h>
3828cbb9b1SJustin Hibbits #include <sys/kdb.h>
3928cbb9b1SJustin Hibbits #include <sys/proc.h>
4028cbb9b1SJustin Hibbits #include <sys/ktr.h>
4128cbb9b1SJustin Hibbits #include <sys/lock.h>
4228cbb9b1SJustin Hibbits #include <sys/mutex.h>
4328cbb9b1SJustin Hibbits #include <sys/pioctl.h>
4428cbb9b1SJustin Hibbits #include <sys/ptrace.h>
4528cbb9b1SJustin Hibbits #include <sys/reboot.h>
4628cbb9b1SJustin Hibbits #include <sys/syscall.h>
4728cbb9b1SJustin Hibbits #include <sys/sysent.h>
4828cbb9b1SJustin Hibbits #include <sys/systm.h>
4928cbb9b1SJustin Hibbits #include <sys/kernel.h>
5028cbb9b1SJustin Hibbits #include <sys/uio.h>
5128cbb9b1SJustin Hibbits #include <sys/signalvar.h>
5228cbb9b1SJustin Hibbits #include <sys/vmmeter.h>
5328cbb9b1SJustin Hibbits 
5428cbb9b1SJustin Hibbits #include <security/audit/audit.h>
5528cbb9b1SJustin Hibbits 
5628cbb9b1SJustin Hibbits #include <vm/vm.h>
5728cbb9b1SJustin Hibbits #include <vm/pmap.h>
5828cbb9b1SJustin Hibbits #include <vm/vm_extern.h>
5928cbb9b1SJustin Hibbits #include <vm/vm_param.h>
6028cbb9b1SJustin Hibbits #include <vm/vm_kern.h>
6128cbb9b1SJustin Hibbits #include <vm/vm_map.h>
6228cbb9b1SJustin Hibbits #include <vm/vm_page.h>
6328cbb9b1SJustin Hibbits 
6428cbb9b1SJustin Hibbits #include <machine/_inttypes.h>
6528cbb9b1SJustin Hibbits #include <machine/altivec.h>
6628cbb9b1SJustin Hibbits #include <machine/cpu.h>
6728cbb9b1SJustin Hibbits #include <machine/db_machdep.h>
6828cbb9b1SJustin Hibbits #include <machine/fpu.h>
6928cbb9b1SJustin Hibbits #include <machine/frame.h>
7028cbb9b1SJustin Hibbits #include <machine/pcb.h>
7128cbb9b1SJustin Hibbits #include <machine/psl.h>
7228cbb9b1SJustin Hibbits #include <machine/trap.h>
7328cbb9b1SJustin Hibbits #include <machine/spr.h>
7428cbb9b1SJustin Hibbits #include <machine/sr.h>
7528cbb9b1SJustin Hibbits 
76a18c313eSNathan Whitehorn /* Below matches setjmp.S */
77a18c313eSNathan Whitehorn #define	FAULTBUF_LR	21
7828cbb9b1SJustin Hibbits #define	FAULTBUF_R1	1
7928cbb9b1SJustin Hibbits #define	FAULTBUF_R2	2
80a18c313eSNathan Whitehorn #define	FAULTBUF_CR	22
81a18c313eSNathan Whitehorn #define	FAULTBUF_R14	3
8228cbb9b1SJustin Hibbits 
833e7e31bdSJustin Hibbits #define	MOREARGS(sp)	((caddr_t)((uintptr_t)(sp) + \
843e7e31bdSJustin Hibbits     sizeof(struct callframe) - 3*sizeof(register_t))) /* more args go here */
853e7e31bdSJustin Hibbits 
8628cbb9b1SJustin Hibbits static void	trap_fatal(struct trapframe *frame);
8728cbb9b1SJustin Hibbits static void	printtrap(u_int vector, struct trapframe *frame, int isfatal,
8828cbb9b1SJustin Hibbits 		    int user);
8928cbb9b1SJustin Hibbits static int	trap_pfault(struct trapframe *frame, int user);
9028cbb9b1SJustin Hibbits static int	fix_unaligned(struct thread *td, struct trapframe *frame);
9128cbb9b1SJustin Hibbits static int	handle_onfault(struct trapframe *frame);
9228cbb9b1SJustin Hibbits static void	syscall(struct trapframe *frame);
9328cbb9b1SJustin Hibbits 
94d5a30121SJustin Hibbits #if defined(__powerpc64__) && defined(AIM)
9528cbb9b1SJustin Hibbits        void	handle_kernel_slb_spill(int, register_t, register_t);
9628cbb9b1SJustin Hibbits static int	handle_user_slb_spill(pmap_t pm, vm_offset_t addr);
9728cbb9b1SJustin Hibbits extern int	n_slbs;
98be2bd024SLeandro Lupori static void	normalize_inputs(void);
9928cbb9b1SJustin Hibbits #endif
10028cbb9b1SJustin Hibbits 
101ec75f647SNathan Whitehorn extern vm_offset_t __startkernel;
102ec75f647SNathan Whitehorn 
10315fc4ab7SJustin Hibbits #ifdef KDB
10415fc4ab7SJustin Hibbits int db_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
10515fc4ab7SJustin Hibbits #endif
10615fc4ab7SJustin Hibbits 
10728cbb9b1SJustin Hibbits struct powerpc_exception {
10828cbb9b1SJustin Hibbits 	u_int	vector;
10928cbb9b1SJustin Hibbits 	char	*name;
11028cbb9b1SJustin Hibbits };
11128cbb9b1SJustin Hibbits 
11228cbb9b1SJustin Hibbits #ifdef KDTRACE_HOOKS
11328cbb9b1SJustin Hibbits #include <sys/dtrace_bsd.h>
11428cbb9b1SJustin Hibbits 
11528cbb9b1SJustin Hibbits int (*dtrace_invop_jump_addr)(struct trapframe *);
11628cbb9b1SJustin Hibbits #endif
11728cbb9b1SJustin Hibbits 
11828cbb9b1SJustin Hibbits static struct powerpc_exception powerpc_exceptions[] = {
11928cbb9b1SJustin Hibbits 	{ EXC_CRIT,	"critical input" },
12028cbb9b1SJustin Hibbits 	{ EXC_RST,	"system reset" },
12128cbb9b1SJustin Hibbits 	{ EXC_MCHK,	"machine check" },
12228cbb9b1SJustin Hibbits 	{ EXC_DSI,	"data storage interrupt" },
12328cbb9b1SJustin Hibbits 	{ EXC_DSE,	"data segment exception" },
12428cbb9b1SJustin Hibbits 	{ EXC_ISI,	"instruction storage interrupt" },
12528cbb9b1SJustin Hibbits 	{ EXC_ISE,	"instruction segment exception" },
12628cbb9b1SJustin Hibbits 	{ EXC_EXI,	"external interrupt" },
12728cbb9b1SJustin Hibbits 	{ EXC_ALI,	"alignment" },
12828cbb9b1SJustin Hibbits 	{ EXC_PGM,	"program" },
129ec75f647SNathan Whitehorn 	{ EXC_HEA,	"hypervisor emulation assistance" },
13028cbb9b1SJustin Hibbits 	{ EXC_FPU,	"floating-point unavailable" },
13128cbb9b1SJustin Hibbits 	{ EXC_APU,	"auxiliary proc unavailable" },
13228cbb9b1SJustin Hibbits 	{ EXC_DECR,	"decrementer" },
13328cbb9b1SJustin Hibbits 	{ EXC_FIT,	"fixed-interval timer" },
13428cbb9b1SJustin Hibbits 	{ EXC_WDOG,	"watchdog timer" },
13528cbb9b1SJustin Hibbits 	{ EXC_SC,	"system call" },
13628cbb9b1SJustin Hibbits 	{ EXC_TRC,	"trace" },
13728cbb9b1SJustin Hibbits 	{ EXC_FPA,	"floating-point assist" },
13828cbb9b1SJustin Hibbits 	{ EXC_DEBUG,	"debug" },
13928cbb9b1SJustin Hibbits 	{ EXC_PERF,	"performance monitoring" },
14028cbb9b1SJustin Hibbits 	{ EXC_VEC,	"altivec unavailable" },
14128cbb9b1SJustin Hibbits 	{ EXC_VSX,	"vsx unavailable" },
1427cd4e55cSJustin Hibbits 	{ EXC_FAC,	"facility unavailable" },
14328cbb9b1SJustin Hibbits 	{ EXC_ITMISS,	"instruction tlb miss" },
14428cbb9b1SJustin Hibbits 	{ EXC_DLMISS,	"data load tlb miss" },
14528cbb9b1SJustin Hibbits 	{ EXC_DSMISS,	"data store tlb miss" },
14628cbb9b1SJustin Hibbits 	{ EXC_BPT,	"instruction breakpoint" },
14728cbb9b1SJustin Hibbits 	{ EXC_SMI,	"system management" },
14828cbb9b1SJustin Hibbits 	{ EXC_VECAST_G4,	"altivec assist" },
14928cbb9b1SJustin Hibbits 	{ EXC_THRM,	"thermal management" },
15028cbb9b1SJustin Hibbits 	{ EXC_RUNMODETRC,	"run mode/trace" },
151be2bd024SLeandro Lupori 	{ EXC_SOFT_PATCH, "soft patch exception" },
15228cbb9b1SJustin Hibbits 	{ EXC_LAST,	NULL }
15328cbb9b1SJustin Hibbits };
15428cbb9b1SJustin Hibbits 
155bf1b9296SJustin Hibbits #define ESR_BITMASK							\
156bf1b9296SJustin Hibbits     "\20"								\
157bf1b9296SJustin Hibbits     "\040b0\037b1\036b2\035b3\034PIL\033PRR\032PTR\031FP"		\
158bf1b9296SJustin Hibbits     "\030ST\027b9\026DLK\025ILK\024b12\023b13\022BO\021PIE"		\
159bf1b9296SJustin Hibbits     "\020b16\017b17\016b18\015b19\014b20\013b21\012b22\011b23"		\
160bf1b9296SJustin Hibbits     "\010SPE\007EPID\006b26\005b27\004b28\003b29\002b30\001b31"
161bf1b9296SJustin Hibbits #define	MCSR_BITMASK							\
162bf1b9296SJustin Hibbits     "\20"								\
163bf1b9296SJustin Hibbits     "\040MCP\037ICERR\036DCERR\035TLBPERR\034L2MMU_MHIT\033b5\032b6\031b7"	\
164bf1b9296SJustin Hibbits     "\030b8\027b9\026b10\025NMI\024MAV\023MEA\022b14\021IF"		\
165bf1b9296SJustin Hibbits     "\020LD\017ST\016LDG\015b19\014b20\013b21\012b22\011b23"		\
166bf1b9296SJustin Hibbits     "\010b24\007b25\006b26\005b27\004b28\003b29\002TLBSYNC\001BSL2_ERR"
167bf1b9296SJustin Hibbits #define	MSSSR_BITMASK							\
168bf1b9296SJustin Hibbits     "\20"								\
169bf1b9296SJustin Hibbits     "\040b0\037b1\036b2\035b3\034b4\033b5\032b6\031b7"			\
170bf1b9296SJustin Hibbits     "\030b8\027b9\026b10\025b11\024b12\023L2TAG\022L2DAT\021L3TAG"	\
171bf1b9296SJustin Hibbits     "\020L3DAT\017APE\016DPE\015TEA\014b20\013b21\012b22\011b23"	\
172bf1b9296SJustin Hibbits     "\010b24\007b25\006b26\005b27\004b28\003b29\002b30\001b31"
173bf1b9296SJustin Hibbits 
174bf1b9296SJustin Hibbits 
17528cbb9b1SJustin Hibbits static const char *
17628cbb9b1SJustin Hibbits trapname(u_int vector)
17728cbb9b1SJustin Hibbits {
17828cbb9b1SJustin Hibbits 	struct	powerpc_exception *pe;
17928cbb9b1SJustin Hibbits 
18028cbb9b1SJustin Hibbits 	for (pe = powerpc_exceptions; pe->vector != EXC_LAST; pe++) {
18128cbb9b1SJustin Hibbits 		if (pe->vector == vector)
18228cbb9b1SJustin Hibbits 			return (pe->name);
18328cbb9b1SJustin Hibbits 	}
18428cbb9b1SJustin Hibbits 
18528cbb9b1SJustin Hibbits 	return ("unknown");
18628cbb9b1SJustin Hibbits }
18728cbb9b1SJustin Hibbits 
188a72b9513SJustin Hibbits static inline bool
189a72b9513SJustin Hibbits frame_is_trap_inst(struct trapframe *frame)
190a72b9513SJustin Hibbits {
191a72b9513SJustin Hibbits #ifdef AIM
192a72b9513SJustin Hibbits 	return (frame->exc == EXC_PGM && frame->srr1 & EXC_PGM_TRAP);
193a72b9513SJustin Hibbits #else
1949ae2eed9SJustin Hibbits 	return ((frame->cpu.booke.esr & ESR_PTR) != 0);
195a72b9513SJustin Hibbits #endif
196a72b9513SJustin Hibbits }
197a72b9513SJustin Hibbits 
19828cbb9b1SJustin Hibbits void
19928cbb9b1SJustin Hibbits trap(struct trapframe *frame)
20028cbb9b1SJustin Hibbits {
20128cbb9b1SJustin Hibbits 	struct thread	*td;
20228cbb9b1SJustin Hibbits 	struct proc	*p;
20328cbb9b1SJustin Hibbits #ifdef KDTRACE_HOOKS
20428cbb9b1SJustin Hibbits 	uint32_t inst;
20528cbb9b1SJustin Hibbits #endif
20628cbb9b1SJustin Hibbits 	int		sig, type, user;
20728cbb9b1SJustin Hibbits 	u_int		ucode;
20828cbb9b1SJustin Hibbits 	ksiginfo_t	ksi;
209ac2605b1SJustin Hibbits 	register_t 	fscr;
21028cbb9b1SJustin Hibbits 
21183c9dea1SGleb Smirnoff 	VM_CNT_INC(v_trap);
21228cbb9b1SJustin Hibbits 
213bda8aa77SJustin Hibbits #ifdef KDB
214bda8aa77SJustin Hibbits 	if (kdb_active) {
215bda8aa77SJustin Hibbits 		kdb_reenter();
216bda8aa77SJustin Hibbits 		return;
217bda8aa77SJustin Hibbits 	}
218bda8aa77SJustin Hibbits #endif
219bda8aa77SJustin Hibbits 
22028cbb9b1SJustin Hibbits 	td = curthread;
22128cbb9b1SJustin Hibbits 	p = td->td_proc;
22228cbb9b1SJustin Hibbits 
22328cbb9b1SJustin Hibbits 	type = ucode = frame->exc;
22428cbb9b1SJustin Hibbits 	sig = 0;
22528cbb9b1SJustin Hibbits 	user = frame->srr1 & PSL_PR;
22628cbb9b1SJustin Hibbits 
22728cbb9b1SJustin Hibbits 	CTR3(KTR_TRAP, "trap: %s type=%s (%s)", td->td_name,
22828cbb9b1SJustin Hibbits 	    trapname(type), user ? "user" : "kernel");
22928cbb9b1SJustin Hibbits 
23028cbb9b1SJustin Hibbits #ifdef KDTRACE_HOOKS
23128cbb9b1SJustin Hibbits 	/*
23228cbb9b1SJustin Hibbits 	 * A trap can occur while DTrace executes a probe. Before
23328cbb9b1SJustin Hibbits 	 * executing the probe, DTrace blocks re-scheduling and sets
23428cbb9b1SJustin Hibbits 	 * a flag in its per-cpu flags to indicate that it doesn't
23528cbb9b1SJustin Hibbits 	 * want to fault. On returning from the probe, the no-fault
23628cbb9b1SJustin Hibbits 	 * flag is cleared and finally re-scheduling is enabled.
23728cbb9b1SJustin Hibbits 	 *
23828cbb9b1SJustin Hibbits 	 * If the DTrace kernel module has registered a trap handler,
23928cbb9b1SJustin Hibbits 	 * call it and if it returns non-zero, assume that it has
24028cbb9b1SJustin Hibbits 	 * handled the trap and modified the trap frame so that this
24128cbb9b1SJustin Hibbits 	 * function can return normally.
24228cbb9b1SJustin Hibbits 	 */
24328cbb9b1SJustin Hibbits 	if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type) != 0)
24428cbb9b1SJustin Hibbits 		return;
24528cbb9b1SJustin Hibbits #endif
24628cbb9b1SJustin Hibbits 
24728cbb9b1SJustin Hibbits 	if (user) {
24828cbb9b1SJustin Hibbits 		td->td_pticks = 0;
24928cbb9b1SJustin Hibbits 		td->td_frame = frame;
2504ea6a9a2SMateusz Guzik 		if (td->td_cowgen != p->p_cowgen)
2514ea6a9a2SMateusz Guzik 			thread_cow_update(td);
25228cbb9b1SJustin Hibbits 
25328cbb9b1SJustin Hibbits 		/* User Mode Traps */
25428cbb9b1SJustin Hibbits 		switch (type) {
25528cbb9b1SJustin Hibbits 		case EXC_RUNMODETRC:
25628cbb9b1SJustin Hibbits 		case EXC_TRC:
25728cbb9b1SJustin Hibbits 			frame->srr1 &= ~PSL_SE;
25828cbb9b1SJustin Hibbits 			sig = SIGTRAP;
25928cbb9b1SJustin Hibbits 			ucode = TRAP_TRACE;
26028cbb9b1SJustin Hibbits 			break;
26128cbb9b1SJustin Hibbits 
262d5a30121SJustin Hibbits #if defined(__powerpc64__) && defined(AIM)
26328cbb9b1SJustin Hibbits 		case EXC_ISE:
26428cbb9b1SJustin Hibbits 		case EXC_DSE:
26528cbb9b1SJustin Hibbits 			if (handle_user_slb_spill(&p->p_vmspace->vm_pmap,
26628cbb9b1SJustin Hibbits 			    (type == EXC_ISE) ? frame->srr0 : frame->dar) != 0){
26728cbb9b1SJustin Hibbits 				sig = SIGSEGV;
26828cbb9b1SJustin Hibbits 				ucode = SEGV_MAPERR;
26928cbb9b1SJustin Hibbits 			}
27028cbb9b1SJustin Hibbits 			break;
27128cbb9b1SJustin Hibbits #endif
27228cbb9b1SJustin Hibbits 		case EXC_DSI:
27328cbb9b1SJustin Hibbits 		case EXC_ISI:
27428cbb9b1SJustin Hibbits 			sig = trap_pfault(frame, 1);
27528cbb9b1SJustin Hibbits 			if (sig == SIGSEGV)
27628cbb9b1SJustin Hibbits 				ucode = SEGV_MAPERR;
27728cbb9b1SJustin Hibbits 			break;
27828cbb9b1SJustin Hibbits 
27928cbb9b1SJustin Hibbits 		case EXC_SC:
28028cbb9b1SJustin Hibbits 			syscall(frame);
28128cbb9b1SJustin Hibbits 			break;
28228cbb9b1SJustin Hibbits 
28328cbb9b1SJustin Hibbits 		case EXC_FPU:
28428cbb9b1SJustin Hibbits 			KASSERT((td->td_pcb->pcb_flags & PCB_FPU) != PCB_FPU,
28528cbb9b1SJustin Hibbits 			    ("FPU already enabled for thread"));
28628cbb9b1SJustin Hibbits 			enable_fpu(td);
28728cbb9b1SJustin Hibbits 			break;
28828cbb9b1SJustin Hibbits 
28928cbb9b1SJustin Hibbits 		case EXC_VEC:
29028cbb9b1SJustin Hibbits 			KASSERT((td->td_pcb->pcb_flags & PCB_VEC) != PCB_VEC,
29128cbb9b1SJustin Hibbits 			    ("Altivec already enabled for thread"));
29228cbb9b1SJustin Hibbits 			enable_vec(td);
29328cbb9b1SJustin Hibbits 			break;
29428cbb9b1SJustin Hibbits 
29528cbb9b1SJustin Hibbits 		case EXC_VSX:
29628cbb9b1SJustin Hibbits 			KASSERT((td->td_pcb->pcb_flags & PCB_VSX) != PCB_VSX,
29728cbb9b1SJustin Hibbits 			    ("VSX already enabled for thread"));
29828cbb9b1SJustin Hibbits 			if (!(td->td_pcb->pcb_flags & PCB_VEC))
29928cbb9b1SJustin Hibbits 				enable_vec(td);
30028cbb9b1SJustin Hibbits 			if (!(td->td_pcb->pcb_flags & PCB_FPU))
30128cbb9b1SJustin Hibbits 				save_fpu(td);
30228cbb9b1SJustin Hibbits 			td->td_pcb->pcb_flags |= PCB_VSX;
30328cbb9b1SJustin Hibbits 			enable_fpu(td);
30428cbb9b1SJustin Hibbits 			break;
30528cbb9b1SJustin Hibbits 
3067cd4e55cSJustin Hibbits 		case EXC_FAC:
307ac2605b1SJustin Hibbits 			fscr = mfspr(SPR_FSCR);
308ac2605b1SJustin Hibbits 			if ((fscr & FSCR_IC_MASK) == FSCR_IC_HTM) {
309ac2605b1SJustin Hibbits 				CTR0(KTR_TRAP, "Hardware Transactional Memory subsystem disabled");
310ac2605b1SJustin Hibbits 			}
311ac2605b1SJustin Hibbits 			sig = SIGILL;
312ac2605b1SJustin Hibbits 			ucode =	ILL_ILLOPC;
313ac2605b1SJustin Hibbits 			break;
314838070d5SWojciech Macek 		case EXC_HEA:
3157cd4e55cSJustin Hibbits 			sig = SIGILL;
3167cd4e55cSJustin Hibbits 			ucode =	ILL_ILLOPC;
3177cd4e55cSJustin Hibbits 			break;
3187cd4e55cSJustin Hibbits 
319541c5806SJustin Hibbits 		case EXC_VECAST_E:
32028cbb9b1SJustin Hibbits 		case EXC_VECAST_G4:
32128cbb9b1SJustin Hibbits 		case EXC_VECAST_G5:
32228cbb9b1SJustin Hibbits 			/*
32328cbb9b1SJustin Hibbits 			 * We get a VPU assist exception for IEEE mode
32428cbb9b1SJustin Hibbits 			 * vector operations on denormalized floats.
32528cbb9b1SJustin Hibbits 			 * Emulating this is a giant pain, so for now,
32628cbb9b1SJustin Hibbits 			 * just switch off IEEE mode and treat them as
32728cbb9b1SJustin Hibbits 			 * zero.
32828cbb9b1SJustin Hibbits 			 */
32928cbb9b1SJustin Hibbits 
33028cbb9b1SJustin Hibbits 			save_vec(td);
33128cbb9b1SJustin Hibbits 			td->td_pcb->pcb_vec.vscr |= ALTIVEC_VSCR_NJ;
33228cbb9b1SJustin Hibbits 			enable_vec(td);
33328cbb9b1SJustin Hibbits 			break;
33428cbb9b1SJustin Hibbits 
33528cbb9b1SJustin Hibbits 		case EXC_ALI:
33628cbb9b1SJustin Hibbits 			if (fix_unaligned(td, frame) != 0) {
33728cbb9b1SJustin Hibbits 				sig = SIGBUS;
33828cbb9b1SJustin Hibbits 				ucode = BUS_ADRALN;
33928cbb9b1SJustin Hibbits 			}
34028cbb9b1SJustin Hibbits 			else
34128cbb9b1SJustin Hibbits 				frame->srr0 += 4;
34228cbb9b1SJustin Hibbits 			break;
34328cbb9b1SJustin Hibbits 
34428cbb9b1SJustin Hibbits 		case EXC_DEBUG:	/* Single stepping */
34528cbb9b1SJustin Hibbits 			mtspr(SPR_DBSR, mfspr(SPR_DBSR));
34628cbb9b1SJustin Hibbits 			frame->srr1 &= ~PSL_DE;
347fa133b6bSJustin Hibbits 			frame->cpu.booke.dbcr0 &= ~(DBCR0_IDM | DBCR0_IC);
34828cbb9b1SJustin Hibbits 			sig = SIGTRAP;
34928cbb9b1SJustin Hibbits 			ucode = TRAP_TRACE;
35028cbb9b1SJustin Hibbits 			break;
35128cbb9b1SJustin Hibbits 
35228cbb9b1SJustin Hibbits 		case EXC_PGM:
35328cbb9b1SJustin Hibbits 			/* Identify the trap reason */
354a72b9513SJustin Hibbits 			if (frame_is_trap_inst(frame)) {
35528cbb9b1SJustin Hibbits #ifdef KDTRACE_HOOKS
35628cbb9b1SJustin Hibbits 				inst = fuword32((const void *)frame->srr0);
35728cbb9b1SJustin Hibbits 				if (inst == 0x0FFFDDDD &&
35828cbb9b1SJustin Hibbits 				    dtrace_pid_probe_ptr != NULL) {
3595bab6234SMark Johnston 					(*dtrace_pid_probe_ptr)(frame);
36028cbb9b1SJustin Hibbits 					break;
36128cbb9b1SJustin Hibbits 				}
36228cbb9b1SJustin Hibbits #endif
36328cbb9b1SJustin Hibbits  				sig = SIGTRAP;
36428cbb9b1SJustin Hibbits 				ucode = TRAP_BRKPT;
36528cbb9b1SJustin Hibbits 			} else {
36628cbb9b1SJustin Hibbits 				sig = ppc_instr_emulate(frame, td->td_pcb);
36728cbb9b1SJustin Hibbits 				if (sig == SIGILL) {
36828cbb9b1SJustin Hibbits 					if (frame->srr1 & EXC_PGM_PRIV)
36928cbb9b1SJustin Hibbits 						ucode = ILL_PRVOPC;
37028cbb9b1SJustin Hibbits 					else if (frame->srr1 & EXC_PGM_ILLEGAL)
37128cbb9b1SJustin Hibbits 						ucode = ILL_ILLOPC;
37228cbb9b1SJustin Hibbits 				} else if (sig == SIGFPE)
37328cbb9b1SJustin Hibbits 					ucode = FPE_FLTINV;	/* Punt for now, invalid operation. */
37428cbb9b1SJustin Hibbits 			}
37528cbb9b1SJustin Hibbits 			break;
37628cbb9b1SJustin Hibbits 
37728cbb9b1SJustin Hibbits 		case EXC_MCHK:
37828cbb9b1SJustin Hibbits 			/*
37928cbb9b1SJustin Hibbits 			 * Note that this may not be recoverable for the user
38028cbb9b1SJustin Hibbits 			 * process, depending on the type of machine check,
38128cbb9b1SJustin Hibbits 			 * but it at least prevents the kernel from dying.
38228cbb9b1SJustin Hibbits 			 */
38328cbb9b1SJustin Hibbits 			sig = SIGBUS;
38428cbb9b1SJustin Hibbits 			ucode = BUS_OBJERR;
38528cbb9b1SJustin Hibbits 			break;
38628cbb9b1SJustin Hibbits 
387be2bd024SLeandro Lupori #if defined(__powerpc64__) && defined(AIM)
388be2bd024SLeandro Lupori 		case EXC_SOFT_PATCH:
389be2bd024SLeandro Lupori 			/*
390be2bd024SLeandro Lupori 			 * Point to the instruction that generated the exception to execute it again,
391be2bd024SLeandro Lupori 			 * and normalize the register values.
392be2bd024SLeandro Lupori 			 */
393be2bd024SLeandro Lupori 			frame->srr0 -= 4;
394be2bd024SLeandro Lupori 			normalize_inputs();
395be2bd024SLeandro Lupori 			break;
396be2bd024SLeandro Lupori #endif
397be2bd024SLeandro Lupori 
39828cbb9b1SJustin Hibbits 		default:
39928cbb9b1SJustin Hibbits 			trap_fatal(frame);
40028cbb9b1SJustin Hibbits 		}
40128cbb9b1SJustin Hibbits 	} else {
40228cbb9b1SJustin Hibbits 		/* Kernel Mode Traps */
40328cbb9b1SJustin Hibbits 
40428cbb9b1SJustin Hibbits 		KASSERT(cold || td->td_ucred != NULL,
40528cbb9b1SJustin Hibbits 		    ("kernel trap doesn't have ucred"));
40628cbb9b1SJustin Hibbits 		switch (type) {
40728cbb9b1SJustin Hibbits 		case EXC_PGM:
40815fc4ab7SJustin Hibbits #ifdef KDTRACE_HOOKS
409a72b9513SJustin Hibbits 			if (frame_is_trap_inst(frame)) {
41028cbb9b1SJustin Hibbits 				if (*(uint32_t *)frame->srr0 == EXC_DTRACE) {
41128cbb9b1SJustin Hibbits 					if (dtrace_invop_jump_addr != NULL) {
41228cbb9b1SJustin Hibbits 						dtrace_invop_jump_addr(frame);
41328cbb9b1SJustin Hibbits 						return;
41428cbb9b1SJustin Hibbits 					}
41528cbb9b1SJustin Hibbits 				}
41628cbb9b1SJustin Hibbits 			}
41728cbb9b1SJustin Hibbits #endif
41815fc4ab7SJustin Hibbits #ifdef KDB
41915fc4ab7SJustin Hibbits 			if (db_trap_glue(frame))
42015fc4ab7SJustin Hibbits 				return;
42115fc4ab7SJustin Hibbits #endif
42215fc4ab7SJustin Hibbits 			break;
423d5a30121SJustin Hibbits #if defined(__powerpc64__) && defined(AIM)
42428cbb9b1SJustin Hibbits 		case EXC_DSE:
425eb1baf72SNathan Whitehorn 			if (td->td_pcb->pcb_cpu.aim.usr_vsid != 0 &&
426eb1baf72SNathan Whitehorn 			    (frame->dar & SEGMENT_MASK) == USER_ADDR) {
42728cbb9b1SJustin Hibbits 				__asm __volatile ("slbmte %0, %1" ::
42828cbb9b1SJustin Hibbits 					"r"(td->td_pcb->pcb_cpu.aim.usr_vsid),
42928cbb9b1SJustin Hibbits 					"r"(USER_SLB_SLBE));
43028cbb9b1SJustin Hibbits 				return;
43128cbb9b1SJustin Hibbits 			}
43228cbb9b1SJustin Hibbits 			break;
43328cbb9b1SJustin Hibbits #endif
43428cbb9b1SJustin Hibbits 		case EXC_DSI:
43528cbb9b1SJustin Hibbits 			if (trap_pfault(frame, 0) == 0)
43628cbb9b1SJustin Hibbits  				return;
43728cbb9b1SJustin Hibbits 			break;
43828cbb9b1SJustin Hibbits 		case EXC_MCHK:
43928cbb9b1SJustin Hibbits 			if (handle_onfault(frame))
44028cbb9b1SJustin Hibbits  				return;
44128cbb9b1SJustin Hibbits 			break;
44228cbb9b1SJustin Hibbits 		default:
44328cbb9b1SJustin Hibbits 			break;
44428cbb9b1SJustin Hibbits 		}
44528cbb9b1SJustin Hibbits 		trap_fatal(frame);
44628cbb9b1SJustin Hibbits 	}
44728cbb9b1SJustin Hibbits 
44828cbb9b1SJustin Hibbits 	if (sig != 0) {
44928cbb9b1SJustin Hibbits 		if (p->p_sysent->sv_transtrap != NULL)
45028cbb9b1SJustin Hibbits 			sig = (p->p_sysent->sv_transtrap)(sig, type);
45128cbb9b1SJustin Hibbits 		ksiginfo_init_trap(&ksi);
45228cbb9b1SJustin Hibbits 		ksi.ksi_signo = sig;
45328cbb9b1SJustin Hibbits 		ksi.ksi_code = (int) ucode; /* XXX, not POSIX */
45424dd643dSJustin Hibbits 		ksi.ksi_addr = (void *)frame->srr0;
45528cbb9b1SJustin Hibbits 		ksi.ksi_trapno = type;
45628cbb9b1SJustin Hibbits 		trapsignal(td, &ksi);
45728cbb9b1SJustin Hibbits 	}
45828cbb9b1SJustin Hibbits 
45928cbb9b1SJustin Hibbits 	userret(td, frame);
46028cbb9b1SJustin Hibbits }
46128cbb9b1SJustin Hibbits 
46228cbb9b1SJustin Hibbits static void
46328cbb9b1SJustin Hibbits trap_fatal(struct trapframe *frame)
46428cbb9b1SJustin Hibbits {
465f3f6ecb4SAndriy Gapon #ifdef KDB
466f3f6ecb4SAndriy Gapon 	bool handled;
467f3f6ecb4SAndriy Gapon #endif
46828cbb9b1SJustin Hibbits 
46928cbb9b1SJustin Hibbits 	printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR));
47028cbb9b1SJustin Hibbits #ifdef KDB
471b317cfd4SJohn Baldwin 	if (debugger_on_trap) {
472f3f6ecb4SAndriy Gapon 		kdb_why = KDB_WHY_TRAP;
473f3f6ecb4SAndriy Gapon 		handled = kdb_trap(frame->exc, 0, frame);
474f3f6ecb4SAndriy Gapon 		kdb_why = KDB_WHY_UNSET;
475f3f6ecb4SAndriy Gapon 		if (handled)
47628cbb9b1SJustin Hibbits 			return;
477f3f6ecb4SAndriy Gapon 	}
47828cbb9b1SJustin Hibbits #endif
47928cbb9b1SJustin Hibbits 	panic("%s trap", trapname(frame->exc));
48028cbb9b1SJustin Hibbits }
48128cbb9b1SJustin Hibbits 
48228cbb9b1SJustin Hibbits static void
483fcc491a3SJustin Hibbits cpu_printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
484fcc491a3SJustin Hibbits {
485fcc491a3SJustin Hibbits #ifdef AIM
486fcc491a3SJustin Hibbits 	uint16_t ver;
487fcc491a3SJustin Hibbits 
488fcc491a3SJustin Hibbits 	switch (vector) {
489fcc491a3SJustin Hibbits 	case EXC_DSE:
490fcc491a3SJustin Hibbits 	case EXC_DSI:
491fcc491a3SJustin Hibbits 	case EXC_DTMISS:
492fcc491a3SJustin Hibbits 		printf("   dsisr           = 0x%lx\n",
493fcc491a3SJustin Hibbits 		    (u_long)frame->cpu.aim.dsisr);
494fcc491a3SJustin Hibbits 		break;
495fcc491a3SJustin Hibbits 	case EXC_MCHK:
496fcc491a3SJustin Hibbits 		ver = mfpvr() >> 16;
497fcc491a3SJustin Hibbits 		if (MPC745X_P(ver))
498fcc491a3SJustin Hibbits 			printf("    msssr0         = 0x%b\n",
499fcc491a3SJustin Hibbits 			    (int)mfspr(SPR_MSSSR0), MSSSR_BITMASK);
500fcc491a3SJustin Hibbits 		break;
501fcc491a3SJustin Hibbits 	}
502fcc491a3SJustin Hibbits #elif defined(BOOKE)
503fcc491a3SJustin Hibbits 	vm_paddr_t pa;
504fcc491a3SJustin Hibbits 
505fcc491a3SJustin Hibbits 	switch (vector) {
506fcc491a3SJustin Hibbits 	case EXC_MCHK:
507fcc491a3SJustin Hibbits 		pa = mfspr(SPR_MCARU);
508fcc491a3SJustin Hibbits 		pa = (pa << 32) | (u_register_t)mfspr(SPR_MCAR);
509fcc491a3SJustin Hibbits 		printf("   mcsr            = 0x%b\n",
510fcc491a3SJustin Hibbits 		    (int)mfspr(SPR_MCSR), MCSR_BITMASK);
511fcc491a3SJustin Hibbits 		printf("   mcar            = 0x%jx\n", (uintmax_t)pa);
512fcc491a3SJustin Hibbits 	}
513fcc491a3SJustin Hibbits 	printf("   esr             = 0x%b\n",
514fcc491a3SJustin Hibbits 	    (int)frame->cpu.booke.esr, ESR_BITMASK);
515fcc491a3SJustin Hibbits #endif
516fcc491a3SJustin Hibbits }
517fcc491a3SJustin Hibbits 
518fcc491a3SJustin Hibbits static void
51928cbb9b1SJustin Hibbits printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
52028cbb9b1SJustin Hibbits {
52128cbb9b1SJustin Hibbits 
52228cbb9b1SJustin Hibbits 	printf("\n");
52328cbb9b1SJustin Hibbits 	printf("%s %s trap:\n", isfatal ? "fatal" : "handled",
52428cbb9b1SJustin Hibbits 	    user ? "user" : "kernel");
52528cbb9b1SJustin Hibbits 	printf("\n");
52628cbb9b1SJustin Hibbits 	printf("   exception       = 0x%x (%s)\n", vector, trapname(vector));
52728cbb9b1SJustin Hibbits 	switch (vector) {
52828cbb9b1SJustin Hibbits 	case EXC_DSE:
52928cbb9b1SJustin Hibbits 	case EXC_DSI:
53039a4b70fSJustin Hibbits 	case EXC_DTMISS:
53128cbb9b1SJustin Hibbits 		printf("   virtual address = 0x%" PRIxPTR "\n", frame->dar);
53228cbb9b1SJustin Hibbits 		break;
53328cbb9b1SJustin Hibbits 	case EXC_ISE:
53428cbb9b1SJustin Hibbits 	case EXC_ISI:
53539a4b70fSJustin Hibbits 	case EXC_ITMISS:
53628cbb9b1SJustin Hibbits 		printf("   virtual address = 0x%" PRIxPTR "\n", frame->srr0);
53728cbb9b1SJustin Hibbits 		break;
538398973f8SJustin Hibbits 	case EXC_MCHK:
539398973f8SJustin Hibbits 		break;
54028cbb9b1SJustin Hibbits 	}
541fcc491a3SJustin Hibbits 	cpu_printtrap(vector, frame, isfatal, user);
542ec75f647SNathan Whitehorn 	printf("   srr0            = 0x%" PRIxPTR " (0x%" PRIxPTR ")\n",
5434e05ac24SNathan Whitehorn 	    frame->srr0, frame->srr0 - (register_t)(__startkernel - KERNBASE));
544cf5aa326SJustin Hibbits 	printf("   srr1            = 0x%lx\n", (u_long)frame->srr1);
5453762bafaSJustin Hibbits 	printf("   current msr     = 0x%" PRIxPTR "\n", mfmsr());
546ec75f647SNathan Whitehorn 	printf("   lr              = 0x%" PRIxPTR " (0x%" PRIxPTR ")\n",
5474e05ac24SNathan Whitehorn 	    frame->lr, frame->lr - (register_t)(__startkernel - KERNBASE));
54828cbb9b1SJustin Hibbits 	printf("   curthread       = %p\n", curthread);
54928cbb9b1SJustin Hibbits 	if (curthread != NULL)
55028cbb9b1SJustin Hibbits 		printf("          pid = %d, comm = %s\n",
55128cbb9b1SJustin Hibbits 		    curthread->td_proc->p_pid, curthread->td_name);
55228cbb9b1SJustin Hibbits 	printf("\n");
55328cbb9b1SJustin Hibbits }
55428cbb9b1SJustin Hibbits 
55528cbb9b1SJustin Hibbits /*
55628cbb9b1SJustin Hibbits  * Handles a fatal fault when we have onfault state to recover.  Returns
55728cbb9b1SJustin Hibbits  * non-zero if there was onfault recovery state available.
55828cbb9b1SJustin Hibbits  */
55928cbb9b1SJustin Hibbits static int
56028cbb9b1SJustin Hibbits handle_onfault(struct trapframe *frame)
56128cbb9b1SJustin Hibbits {
56228cbb9b1SJustin Hibbits 	struct		thread *td;
563a18c313eSNathan Whitehorn 	jmp_buf		*fb;
56428cbb9b1SJustin Hibbits 
56528cbb9b1SJustin Hibbits 	td = curthread;
56628cbb9b1SJustin Hibbits 	fb = td->td_pcb->pcb_onfault;
56728cbb9b1SJustin Hibbits 	if (fb != NULL) {
568a18c313eSNathan Whitehorn 		frame->srr0 = (*fb)->_jb[FAULTBUF_LR];
569a18c313eSNathan Whitehorn 		frame->fixreg[1] = (*fb)->_jb[FAULTBUF_R1];
570a18c313eSNathan Whitehorn 		frame->fixreg[2] = (*fb)->_jb[FAULTBUF_R2];
57128cbb9b1SJustin Hibbits 		frame->fixreg[3] = 1;
572a18c313eSNathan Whitehorn 		frame->cr = (*fb)->_jb[FAULTBUF_CR];
573a18c313eSNathan Whitehorn 		bcopy(&(*fb)->_jb[FAULTBUF_R14], &frame->fixreg[14],
574a18c313eSNathan Whitehorn 		    18 * sizeof(register_t));
575a18c313eSNathan Whitehorn 		td->td_pcb->pcb_onfault = NULL; /* Returns twice, not thrice */
57628cbb9b1SJustin Hibbits 		return (1);
57728cbb9b1SJustin Hibbits 	}
57828cbb9b1SJustin Hibbits 	return (0);
57928cbb9b1SJustin Hibbits }
58028cbb9b1SJustin Hibbits 
58128cbb9b1SJustin Hibbits int
5822d88da2fSKonstantin Belousov cpu_fetch_syscall_args(struct thread *td)
58328cbb9b1SJustin Hibbits {
58428cbb9b1SJustin Hibbits 	struct proc *p;
58528cbb9b1SJustin Hibbits 	struct trapframe *frame;
5862d88da2fSKonstantin Belousov 	struct syscall_args *sa;
58728cbb9b1SJustin Hibbits 	caddr_t	params;
58828cbb9b1SJustin Hibbits 	size_t argsz;
58928cbb9b1SJustin Hibbits 	int error, n, i;
59028cbb9b1SJustin Hibbits 
59128cbb9b1SJustin Hibbits 	p = td->td_proc;
59228cbb9b1SJustin Hibbits 	frame = td->td_frame;
5932d88da2fSKonstantin Belousov 	sa = &td->td_sa;
59428cbb9b1SJustin Hibbits 
59528cbb9b1SJustin Hibbits 	sa->code = frame->fixreg[0];
59628cbb9b1SJustin Hibbits 	params = (caddr_t)(frame->fixreg + FIRSTARG);
59728cbb9b1SJustin Hibbits 	n = NARGREG;
59828cbb9b1SJustin Hibbits 
59928cbb9b1SJustin Hibbits 	if (sa->code == SYS_syscall) {
60028cbb9b1SJustin Hibbits 		/*
60128cbb9b1SJustin Hibbits 		 * code is first argument,
60228cbb9b1SJustin Hibbits 		 * followed by actual args.
60328cbb9b1SJustin Hibbits 		 */
60428cbb9b1SJustin Hibbits 		sa->code = *(register_t *) params;
60528cbb9b1SJustin Hibbits 		params += sizeof(register_t);
60628cbb9b1SJustin Hibbits 		n -= 1;
60728cbb9b1SJustin Hibbits 	} else if (sa->code == SYS___syscall) {
60828cbb9b1SJustin Hibbits 		/*
60928cbb9b1SJustin Hibbits 		 * Like syscall, but code is a quad,
61028cbb9b1SJustin Hibbits 		 * so as to maintain quad alignment
61128cbb9b1SJustin Hibbits 		 * for the rest of the args.
61228cbb9b1SJustin Hibbits 		 */
61328cbb9b1SJustin Hibbits 		if (SV_PROC_FLAG(p, SV_ILP32)) {
61428cbb9b1SJustin Hibbits 			params += sizeof(register_t);
61528cbb9b1SJustin Hibbits 			sa->code = *(register_t *) params;
61628cbb9b1SJustin Hibbits 			params += sizeof(register_t);
61728cbb9b1SJustin Hibbits 			n -= 2;
61828cbb9b1SJustin Hibbits 		} else {
61928cbb9b1SJustin Hibbits 			sa->code = *(register_t *) params;
62028cbb9b1SJustin Hibbits 			params += sizeof(register_t);
62128cbb9b1SJustin Hibbits 			n -= 1;
62228cbb9b1SJustin Hibbits 		}
62328cbb9b1SJustin Hibbits 	}
62428cbb9b1SJustin Hibbits 
62528cbb9b1SJustin Hibbits  	if (p->p_sysent->sv_mask)
62628cbb9b1SJustin Hibbits 		sa->code &= p->p_sysent->sv_mask;
62728cbb9b1SJustin Hibbits 	if (sa->code >= p->p_sysent->sv_size)
62828cbb9b1SJustin Hibbits 		sa->callp = &p->p_sysent->sv_table[0];
62928cbb9b1SJustin Hibbits 	else
63028cbb9b1SJustin Hibbits 		sa->callp = &p->p_sysent->sv_table[sa->code];
63128cbb9b1SJustin Hibbits 
63228cbb9b1SJustin Hibbits 	sa->narg = sa->callp->sy_narg;
63328cbb9b1SJustin Hibbits 
63428cbb9b1SJustin Hibbits 	if (SV_PROC_FLAG(p, SV_ILP32)) {
63528cbb9b1SJustin Hibbits 		argsz = sizeof(uint32_t);
63628cbb9b1SJustin Hibbits 
63728cbb9b1SJustin Hibbits 		for (i = 0; i < n; i++)
63828cbb9b1SJustin Hibbits 			sa->args[i] = ((u_register_t *)(params))[i] &
63928cbb9b1SJustin Hibbits 			    0xffffffff;
64028cbb9b1SJustin Hibbits 	} else {
64128cbb9b1SJustin Hibbits 		argsz = sizeof(uint64_t);
64228cbb9b1SJustin Hibbits 
64328cbb9b1SJustin Hibbits 		for (i = 0; i < n; i++)
64428cbb9b1SJustin Hibbits 			sa->args[i] = ((u_register_t *)(params))[i];
64528cbb9b1SJustin Hibbits 	}
64628cbb9b1SJustin Hibbits 
64728cbb9b1SJustin Hibbits 	if (sa->narg > n)
64828cbb9b1SJustin Hibbits 		error = copyin(MOREARGS(frame->fixreg[1]), sa->args + n,
64928cbb9b1SJustin Hibbits 			       (sa->narg - n) * argsz);
65028cbb9b1SJustin Hibbits 	else
65128cbb9b1SJustin Hibbits 		error = 0;
65228cbb9b1SJustin Hibbits 
65328cbb9b1SJustin Hibbits #ifdef __powerpc64__
65428cbb9b1SJustin Hibbits 	if (SV_PROC_FLAG(p, SV_ILP32) && sa->narg > n) {
65528cbb9b1SJustin Hibbits 		/* Expand the size of arguments copied from the stack */
65628cbb9b1SJustin Hibbits 
65728cbb9b1SJustin Hibbits 		for (i = sa->narg; i >= n; i--)
65828cbb9b1SJustin Hibbits 			sa->args[i] = ((uint32_t *)(&sa->args[n]))[i-n];
65928cbb9b1SJustin Hibbits 	}
66028cbb9b1SJustin Hibbits #endif
66128cbb9b1SJustin Hibbits 
66228cbb9b1SJustin Hibbits 	if (error == 0) {
66328cbb9b1SJustin Hibbits 		td->td_retval[0] = 0;
66428cbb9b1SJustin Hibbits 		td->td_retval[1] = frame->fixreg[FIRSTARG + 1];
66528cbb9b1SJustin Hibbits 	}
66628cbb9b1SJustin Hibbits 	return (error);
66728cbb9b1SJustin Hibbits }
66828cbb9b1SJustin Hibbits 
66928cbb9b1SJustin Hibbits #include "../../kern/subr_syscall.c"
67028cbb9b1SJustin Hibbits 
67128cbb9b1SJustin Hibbits void
67228cbb9b1SJustin Hibbits syscall(struct trapframe *frame)
67328cbb9b1SJustin Hibbits {
67428cbb9b1SJustin Hibbits 	struct thread *td;
67528cbb9b1SJustin Hibbits 	int error;
67628cbb9b1SJustin Hibbits 
67728cbb9b1SJustin Hibbits 	td = curthread;
67828cbb9b1SJustin Hibbits 	td->td_frame = frame;
67928cbb9b1SJustin Hibbits 
680d5a30121SJustin Hibbits #if defined(__powerpc64__) && defined(AIM)
68128cbb9b1SJustin Hibbits 	/*
68228cbb9b1SJustin Hibbits 	 * Speculatively restore last user SLB segment, which we know is
68328cbb9b1SJustin Hibbits 	 * invalid already, since we are likely to do copyin()/copyout().
68428cbb9b1SJustin Hibbits 	 */
685e649493cSNathan Whitehorn 	if (td->td_pcb->pcb_cpu.aim.usr_vsid != 0)
68628cbb9b1SJustin Hibbits 		__asm __volatile ("slbmte %0, %1; isync" ::
68728cbb9b1SJustin Hibbits 		    "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), "r"(USER_SLB_SLBE));
68828cbb9b1SJustin Hibbits #endif
68928cbb9b1SJustin Hibbits 
6902d88da2fSKonstantin Belousov 	error = syscallenter(td);
6912d88da2fSKonstantin Belousov 	syscallret(td, error);
69228cbb9b1SJustin Hibbits }
69328cbb9b1SJustin Hibbits 
694d5a30121SJustin Hibbits #if defined(__powerpc64__) && defined(AIM)
69528cbb9b1SJustin Hibbits /* Handle kernel SLB faults -- runs in real mode, all seat belts off */
69628cbb9b1SJustin Hibbits void
69728cbb9b1SJustin Hibbits handle_kernel_slb_spill(int type, register_t dar, register_t srr0)
69828cbb9b1SJustin Hibbits {
69928cbb9b1SJustin Hibbits 	struct slb *slbcache;
70028cbb9b1SJustin Hibbits 	uint64_t slbe, slbv;
70128cbb9b1SJustin Hibbits 	uint64_t esid, addr;
70228cbb9b1SJustin Hibbits 	int i;
70328cbb9b1SJustin Hibbits 
70428cbb9b1SJustin Hibbits 	addr = (type == EXC_ISE) ? srr0 : dar;
705bce6d88bSJustin Hibbits 	slbcache = PCPU_GET(aim.slb);
70628cbb9b1SJustin Hibbits 	esid = (uintptr_t)addr >> ADDR_SR_SHFT;
70728cbb9b1SJustin Hibbits 	slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID;
70828cbb9b1SJustin Hibbits 
70928cbb9b1SJustin Hibbits 	/* See if the hardware flushed this somehow (can happen in LPARs) */
71028cbb9b1SJustin Hibbits 	for (i = 0; i < n_slbs; i++)
71128cbb9b1SJustin Hibbits 		if (slbcache[i].slbe == (slbe | (uint64_t)i))
71228cbb9b1SJustin Hibbits 			return;
71328cbb9b1SJustin Hibbits 
71428cbb9b1SJustin Hibbits 	/* Not in the map, needs to actually be added */
71528cbb9b1SJustin Hibbits 	slbv = kernel_va_to_slbv(addr);
71628cbb9b1SJustin Hibbits 	if (slbcache[USER_SLB_SLOT].slbe == 0) {
71728cbb9b1SJustin Hibbits 		for (i = 0; i < n_slbs; i++) {
71828cbb9b1SJustin Hibbits 			if (i == USER_SLB_SLOT)
71928cbb9b1SJustin Hibbits 				continue;
72028cbb9b1SJustin Hibbits 			if (!(slbcache[i].slbe & SLBE_VALID))
72128cbb9b1SJustin Hibbits 				goto fillkernslb;
72228cbb9b1SJustin Hibbits 		}
72328cbb9b1SJustin Hibbits 
72428cbb9b1SJustin Hibbits 		if (i == n_slbs)
72528cbb9b1SJustin Hibbits 			slbcache[USER_SLB_SLOT].slbe = 1;
72628cbb9b1SJustin Hibbits 	}
72728cbb9b1SJustin Hibbits 
72828cbb9b1SJustin Hibbits 	/* Sacrifice a random SLB entry that is not the user entry */
72928cbb9b1SJustin Hibbits 	i = mftb() % n_slbs;
73028cbb9b1SJustin Hibbits 	if (i == USER_SLB_SLOT)
73128cbb9b1SJustin Hibbits 		i = (i+1) % n_slbs;
73228cbb9b1SJustin Hibbits 
73328cbb9b1SJustin Hibbits fillkernslb:
73428cbb9b1SJustin Hibbits 	/* Write new entry */
73528cbb9b1SJustin Hibbits 	slbcache[i].slbv = slbv;
73628cbb9b1SJustin Hibbits 	slbcache[i].slbe = slbe | (uint64_t)i;
73728cbb9b1SJustin Hibbits 
73828cbb9b1SJustin Hibbits 	/* Trap handler will restore from cache on exit */
73928cbb9b1SJustin Hibbits }
74028cbb9b1SJustin Hibbits 
74128cbb9b1SJustin Hibbits static int
74228cbb9b1SJustin Hibbits handle_user_slb_spill(pmap_t pm, vm_offset_t addr)
74328cbb9b1SJustin Hibbits {
74428cbb9b1SJustin Hibbits 	struct slb *user_entry;
74528cbb9b1SJustin Hibbits 	uint64_t esid;
74628cbb9b1SJustin Hibbits 	int i;
74728cbb9b1SJustin Hibbits 
748e649493cSNathan Whitehorn 	if (pm->pm_slb == NULL)
749e649493cSNathan Whitehorn 		return (-1);
750e649493cSNathan Whitehorn 
75128cbb9b1SJustin Hibbits 	esid = (uintptr_t)addr >> ADDR_SR_SHFT;
75228cbb9b1SJustin Hibbits 
75328cbb9b1SJustin Hibbits 	PMAP_LOCK(pm);
75428cbb9b1SJustin Hibbits 	user_entry = user_va_to_slb_entry(pm, addr);
75528cbb9b1SJustin Hibbits 
75628cbb9b1SJustin Hibbits 	if (user_entry == NULL) {
75728cbb9b1SJustin Hibbits 		/* allocate_vsid auto-spills it */
75828cbb9b1SJustin Hibbits 		(void)allocate_user_vsid(pm, esid, 0);
75928cbb9b1SJustin Hibbits 	} else {
76028cbb9b1SJustin Hibbits 		/*
76128cbb9b1SJustin Hibbits 		 * Check that another CPU has not already mapped this.
76228cbb9b1SJustin Hibbits 		 * XXX: Per-thread SLB caches would be better.
76328cbb9b1SJustin Hibbits 		 */
76428cbb9b1SJustin Hibbits 		for (i = 0; i < pm->pm_slb_len; i++)
76528cbb9b1SJustin Hibbits 			if (pm->pm_slb[i] == user_entry)
76628cbb9b1SJustin Hibbits 				break;
76728cbb9b1SJustin Hibbits 
76828cbb9b1SJustin Hibbits 		if (i == pm->pm_slb_len)
76928cbb9b1SJustin Hibbits 			slb_insert_user(pm, user_entry);
77028cbb9b1SJustin Hibbits 	}
77128cbb9b1SJustin Hibbits 	PMAP_UNLOCK(pm);
77228cbb9b1SJustin Hibbits 
77328cbb9b1SJustin Hibbits 	return (0);
77428cbb9b1SJustin Hibbits }
77528cbb9b1SJustin Hibbits #endif
77628cbb9b1SJustin Hibbits 
77728cbb9b1SJustin Hibbits static int
77828cbb9b1SJustin Hibbits trap_pfault(struct trapframe *frame, int user)
77928cbb9b1SJustin Hibbits {
78028cbb9b1SJustin Hibbits 	vm_offset_t	eva, va;
78128cbb9b1SJustin Hibbits 	struct		thread *td;
78228cbb9b1SJustin Hibbits 	struct		proc *p;
78328cbb9b1SJustin Hibbits 	vm_map_t	map;
78428cbb9b1SJustin Hibbits 	vm_prot_t	ftype;
785eb1baf72SNathan Whitehorn 	int		rv, is_user;
78628cbb9b1SJustin Hibbits 
78728cbb9b1SJustin Hibbits 	td = curthread;
78828cbb9b1SJustin Hibbits 	p = td->td_proc;
78928cbb9b1SJustin Hibbits 	if (frame->exc == EXC_ISI) {
79028cbb9b1SJustin Hibbits 		eva = frame->srr0;
79128cbb9b1SJustin Hibbits 		ftype = VM_PROT_EXECUTE;
79228cbb9b1SJustin Hibbits 		if (frame->srr1 & SRR1_ISI_PFAULT)
79328cbb9b1SJustin Hibbits 			ftype |= VM_PROT_READ;
79428cbb9b1SJustin Hibbits 	} else {
79528cbb9b1SJustin Hibbits 		eva = frame->dar;
79628cbb9b1SJustin Hibbits #ifdef BOOKE
79728cbb9b1SJustin Hibbits 		if (frame->cpu.booke.esr & ESR_ST)
79828cbb9b1SJustin Hibbits #else
79928cbb9b1SJustin Hibbits 		if (frame->cpu.aim.dsisr & DSISR_STORE)
80028cbb9b1SJustin Hibbits #endif
80128cbb9b1SJustin Hibbits 			ftype = VM_PROT_WRITE;
80228cbb9b1SJustin Hibbits 		else
80328cbb9b1SJustin Hibbits 			ftype = VM_PROT_READ;
80428cbb9b1SJustin Hibbits 	}
80528cbb9b1SJustin Hibbits 
80628cbb9b1SJustin Hibbits 	if (user) {
80728cbb9b1SJustin Hibbits 		KASSERT(p->p_vmspace != NULL, ("trap_pfault: vmspace  NULL"));
80828cbb9b1SJustin Hibbits 		map = &p->p_vmspace->vm_map;
80928cbb9b1SJustin Hibbits 	} else {
810eb1baf72SNathan Whitehorn 		rv = pmap_decode_kernel_ptr(eva, &is_user, &eva);
811eb1baf72SNathan Whitehorn 		if (rv != 0)
812eb1baf72SNathan Whitehorn 			return (SIGSEGV);
81328cbb9b1SJustin Hibbits 
814eb1baf72SNathan Whitehorn 		if (is_user)
815eb1baf72SNathan Whitehorn 			map = &p->p_vmspace->vm_map;
816eb1baf72SNathan Whitehorn 		else
81728cbb9b1SJustin Hibbits 			map = kernel_map;
81828cbb9b1SJustin Hibbits 	}
81928cbb9b1SJustin Hibbits 	va = trunc_page(eva);
82028cbb9b1SJustin Hibbits 
8211fa67124SKonstantin Belousov 	/* Fault in the page. */
82228cbb9b1SJustin Hibbits 	rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
82328cbb9b1SJustin Hibbits 	/*
82428cbb9b1SJustin Hibbits 	 * XXXDTRACE: add dtrace_doubletrap_func here?
82528cbb9b1SJustin Hibbits 	 */
82628cbb9b1SJustin Hibbits 
82728cbb9b1SJustin Hibbits 	if (rv == KERN_SUCCESS)
82828cbb9b1SJustin Hibbits 		return (0);
82928cbb9b1SJustin Hibbits 
83028cbb9b1SJustin Hibbits 	if (!user && handle_onfault(frame))
83128cbb9b1SJustin Hibbits 		return (0);
83228cbb9b1SJustin Hibbits 
83328cbb9b1SJustin Hibbits 	return (SIGSEGV);
83428cbb9b1SJustin Hibbits }
83528cbb9b1SJustin Hibbits 
83628cbb9b1SJustin Hibbits /*
83728cbb9b1SJustin Hibbits  * For now, this only deals with the particular unaligned access case
83828cbb9b1SJustin Hibbits  * that gcc tends to generate.  Eventually it should handle all of the
83928cbb9b1SJustin Hibbits  * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
84028cbb9b1SJustin Hibbits  */
84128cbb9b1SJustin Hibbits 
84228cbb9b1SJustin Hibbits static int
84328cbb9b1SJustin Hibbits fix_unaligned(struct thread *td, struct trapframe *frame)
84428cbb9b1SJustin Hibbits {
84528cbb9b1SJustin Hibbits 	struct thread	*fputhread;
846dc9b124dSJustin Hibbits #ifdef	__SPE__
847dc9b124dSJustin Hibbits 	uint32_t	inst;
848dc9b124dSJustin Hibbits #endif
84928cbb9b1SJustin Hibbits 	int		indicator, reg;
85028cbb9b1SJustin Hibbits 	double		*fpr;
85128cbb9b1SJustin Hibbits 
852dc9b124dSJustin Hibbits #ifdef __SPE__
853dc9b124dSJustin Hibbits 	indicator = (frame->cpu.booke.esr & (ESR_ST|ESR_SPE));
854dc9b124dSJustin Hibbits 	if (indicator & ESR_SPE) {
855dc9b124dSJustin Hibbits 		if (copyin((void *)frame->srr0, &inst, sizeof(inst)) != 0)
856dc9b124dSJustin Hibbits 			return (-1);
857dc9b124dSJustin Hibbits 		reg = EXC_ALI_SPE_REG(inst);
858dc9b124dSJustin Hibbits 		fpr = (double *)td->td_pcb->pcb_vec.vr[reg];
859dc9b124dSJustin Hibbits 		fputhread = PCPU_GET(vecthread);
860dc9b124dSJustin Hibbits 
86189965e70SJustin Hibbits 		/* Juggle the SPE to ensure that we've initialized
86289965e70SJustin Hibbits 		 * the registers, and that their current state is in
863dc9b124dSJustin Hibbits 		 * the PCB.
864dc9b124dSJustin Hibbits 		 */
865eaa5e396SJustin Hibbits 		if (fputhread != td) {
866eaa5e396SJustin Hibbits 			if (fputhread)
867eaa5e396SJustin Hibbits 				save_vec(fputhread);
868dc9b124dSJustin Hibbits 			enable_vec(td);
869dc9b124dSJustin Hibbits 		}
870dc9b124dSJustin Hibbits 		save_vec(td);
871dc9b124dSJustin Hibbits 
872dc9b124dSJustin Hibbits 		if (!(indicator & ESR_ST)) {
873dc9b124dSJustin Hibbits 			if (copyin((void *)frame->dar, fpr,
874dc9b124dSJustin Hibbits 			    sizeof(double)) != 0)
875dc9b124dSJustin Hibbits 				return (-1);
876dc9b124dSJustin Hibbits 			frame->fixreg[reg] = td->td_pcb->pcb_vec.vr[reg][1];
877dc9b124dSJustin Hibbits 			enable_vec(td);
878dc9b124dSJustin Hibbits 		} else {
879dc9b124dSJustin Hibbits 			td->td_pcb->pcb_vec.vr[reg][1] = frame->fixreg[reg];
880dc9b124dSJustin Hibbits 			if (copyout(fpr, (void *)frame->dar,
881dc9b124dSJustin Hibbits 			    sizeof(double)) != 0)
882dc9b124dSJustin Hibbits 				return (-1);
883dc9b124dSJustin Hibbits 		}
884dc9b124dSJustin Hibbits 		return (0);
885dc9b124dSJustin Hibbits 	}
886dc9b124dSJustin Hibbits #else
88728cbb9b1SJustin Hibbits 	indicator = EXC_ALI_OPCODE_INDICATOR(frame->cpu.aim.dsisr);
88828cbb9b1SJustin Hibbits 
88928cbb9b1SJustin Hibbits 	switch (indicator) {
89028cbb9b1SJustin Hibbits 	case EXC_ALI_LFD:
89128cbb9b1SJustin Hibbits 	case EXC_ALI_STFD:
89228cbb9b1SJustin Hibbits 		reg = EXC_ALI_RST(frame->cpu.aim.dsisr);
89328cbb9b1SJustin Hibbits 		fpr = &td->td_pcb->pcb_fpu.fpr[reg].fpr;
89428cbb9b1SJustin Hibbits 		fputhread = PCPU_GET(fputhread);
89528cbb9b1SJustin Hibbits 
89628cbb9b1SJustin Hibbits 		/* Juggle the FPU to ensure that we've initialized
89728cbb9b1SJustin Hibbits 		 * the FPRs, and that their current state is in
89828cbb9b1SJustin Hibbits 		 * the PCB.
89928cbb9b1SJustin Hibbits 		 */
90028cbb9b1SJustin Hibbits 		if (fputhread != td) {
90128cbb9b1SJustin Hibbits 			if (fputhread)
90228cbb9b1SJustin Hibbits 				save_fpu(fputhread);
90328cbb9b1SJustin Hibbits 			enable_fpu(td);
90428cbb9b1SJustin Hibbits 		}
90528cbb9b1SJustin Hibbits 		save_fpu(td);
90628cbb9b1SJustin Hibbits 
90728cbb9b1SJustin Hibbits 		if (indicator == EXC_ALI_LFD) {
90828cbb9b1SJustin Hibbits 			if (copyin((void *)frame->dar, fpr,
90928cbb9b1SJustin Hibbits 			    sizeof(double)) != 0)
91028cbb9b1SJustin Hibbits 				return (-1);
91128cbb9b1SJustin Hibbits 			enable_fpu(td);
91228cbb9b1SJustin Hibbits 		} else {
91328cbb9b1SJustin Hibbits 			if (copyout(fpr, (void *)frame->dar,
91428cbb9b1SJustin Hibbits 			    sizeof(double)) != 0)
91528cbb9b1SJustin Hibbits 				return (-1);
91628cbb9b1SJustin Hibbits 		}
91728cbb9b1SJustin Hibbits 		return (0);
91828cbb9b1SJustin Hibbits 		break;
91928cbb9b1SJustin Hibbits 	}
920dc9b124dSJustin Hibbits #endif
92128cbb9b1SJustin Hibbits 
92228cbb9b1SJustin Hibbits 	return (-1);
92328cbb9b1SJustin Hibbits }
92428cbb9b1SJustin Hibbits 
925be2bd024SLeandro Lupori #if defined(__powerpc64__) && defined(AIM)
926be2bd024SLeandro Lupori #define MSKNSHL(x, m, n) "(((" #x ") & " #m ") << " #n ")"
927be2bd024SLeandro Lupori #define MSKNSHR(x, m, n) "(((" #x ") & " #m ") >> " #n ")"
928be2bd024SLeandro Lupori 
929be2bd024SLeandro Lupori /* xvcpsgndp instruction, built in opcode format.
930be2bd024SLeandro Lupori  * This can be changed to use mnemonic after a toolchain update.
931be2bd024SLeandro Lupori  */
932be2bd024SLeandro Lupori #define XVCPSGNDP(xt, xa, xb) \
933be2bd024SLeandro Lupori 	__asm __volatile(".long (" \
934be2bd024SLeandro Lupori 		MSKNSHL(60, 0x3f, 26) " | " \
935be2bd024SLeandro Lupori 		MSKNSHL(xt, 0x1f, 21) " | " \
936be2bd024SLeandro Lupori 		MSKNSHL(xa, 0x1f, 16) " | " \
937be2bd024SLeandro Lupori 		MSKNSHL(xb, 0x1f, 11) " | " \
938be2bd024SLeandro Lupori 		MSKNSHL(240, 0xff, 3) " | " \
939be2bd024SLeandro Lupori 		MSKNSHR(xa,  0x20, 3) " | " \
940be2bd024SLeandro Lupori 		MSKNSHR(xa,  0x20, 4) " | " \
941be2bd024SLeandro Lupori 		MSKNSHR(xa,  0x20, 5) ")")
942be2bd024SLeandro Lupori 
943be2bd024SLeandro Lupori /* Macros to normalize 1 or 10 VSX registers */
944be2bd024SLeandro Lupori #define NORM(x)	XVCPSGNDP(x, x, x)
945be2bd024SLeandro Lupori #define NORM10(x) \
946be2bd024SLeandro Lupori 	NORM(x ## 0); NORM(x ## 1); NORM(x ## 2); NORM(x ## 3); NORM(x ## 4); \
947be2bd024SLeandro Lupori 	NORM(x ## 5); NORM(x ## 6); NORM(x ## 7); NORM(x ## 8); NORM(x ## 9)
948be2bd024SLeandro Lupori 
949be2bd024SLeandro Lupori static void
950be2bd024SLeandro Lupori normalize_inputs(void)
951be2bd024SLeandro Lupori {
952be2bd024SLeandro Lupori 	unsigned long msr;
953be2bd024SLeandro Lupori 
954be2bd024SLeandro Lupori 	/* enable VSX */
955be2bd024SLeandro Lupori 	msr = mfmsr();
956be2bd024SLeandro Lupori 	mtmsr(msr | PSL_VSX);
957be2bd024SLeandro Lupori 
958be2bd024SLeandro Lupori 	NORM(0);   NORM(1);   NORM(2);   NORM(3);   NORM(4);
959be2bd024SLeandro Lupori 	NORM(5);   NORM(6);   NORM(7);   NORM(8);   NORM(9);
960be2bd024SLeandro Lupori 	NORM10(1); NORM10(2); NORM10(3); NORM10(4); NORM10(5);
961be2bd024SLeandro Lupori 	NORM(60);  NORM(61);  NORM(62);  NORM(63);
962be2bd024SLeandro Lupori 
963be2bd024SLeandro Lupori 	/* restore MSR */
964be2bd024SLeandro Lupori 	mtmsr(msr);
965be2bd024SLeandro Lupori }
966be2bd024SLeandro Lupori #endif
967be2bd024SLeandro Lupori 
96828cbb9b1SJustin Hibbits #ifdef KDB
96928cbb9b1SJustin Hibbits int
97028cbb9b1SJustin Hibbits db_trap_glue(struct trapframe *frame)
97128cbb9b1SJustin Hibbits {
97215fc4ab7SJustin Hibbits 
97328cbb9b1SJustin Hibbits 	if (!(frame->srr1 & PSL_PR)
97428cbb9b1SJustin Hibbits 	    && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
975a72b9513SJustin Hibbits 	    	|| frame_is_trap_inst(frame)
97628cbb9b1SJustin Hibbits 		|| frame->exc == EXC_BPT
9779ae2eed9SJustin Hibbits 		|| frame->exc == EXC_DEBUG
97828cbb9b1SJustin Hibbits 		|| frame->exc == EXC_DSI)) {
97928cbb9b1SJustin Hibbits 		int type = frame->exc;
98028cbb9b1SJustin Hibbits 
98128cbb9b1SJustin Hibbits 		/* Ignore DTrace traps. */
98228cbb9b1SJustin Hibbits 		if (*(uint32_t *)frame->srr0 == EXC_DTRACE)
98328cbb9b1SJustin Hibbits 			return (0);
984a72b9513SJustin Hibbits 		if (frame_is_trap_inst(frame)) {
98528cbb9b1SJustin Hibbits 			type = T_BREAKPOINT;
98628cbb9b1SJustin Hibbits 		}
98728cbb9b1SJustin Hibbits 		return (kdb_trap(type, 0, frame));
98828cbb9b1SJustin Hibbits 	}
98928cbb9b1SJustin Hibbits 
99028cbb9b1SJustin Hibbits 	return (0);
99128cbb9b1SJustin Hibbits }
99228cbb9b1SJustin Hibbits #endif
993