17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5d8aa0f5sudheer * Common Development and Distribution License (the "License").
6d8aa0f5sudheer * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
2197eda13raf
227c478bdstevel@tonic-gate/*
235cd376eJimmy Vetayases * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bdstevel@tonic-gate */
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate/*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
277c478bdstevel@tonic-gate/*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T   */
2858b4950Hans Rosenfeld/*		All Rights Reserved				*/
297c478bdstevel@tonic-gate/*								*/
3058b4950Hans Rosenfeld/*	Copyright (c) 1987, 1988 Microsoft Corporation		*/
3158b4950Hans Rosenfeld/*		All Rights Reserved				*/
327c478bdstevel@tonic-gate/*								*/
337c478bdstevel@tonic-gate
34f16a0f4Robert Mustacchi/*
3574ecdb5John Levon * Copyright 2018 Joyent, Inc.
36f16a0f4Robert Mustacchi */
37f16a0f4Robert Mustacchi
387c478bdstevel@tonic-gate#include <sys/types.h>
397c478bdstevel@tonic-gate#include <sys/sysmacros.h>
407c478bdstevel@tonic-gate#include <sys/param.h>
417c478bdstevel@tonic-gate#include <sys/signal.h>
427c478bdstevel@tonic-gate#include <sys/systm.h>
437c478bdstevel@tonic-gate#include <sys/user.h>
447c478bdstevel@tonic-gate#include <sys/proc.h>
457c478bdstevel@tonic-gate#include <sys/disp.h>
467c478bdstevel@tonic-gate#include <sys/class.h>
477c478bdstevel@tonic-gate#include <sys/core.h>
487c478bdstevel@tonic-gate#include <sys/syscall.h>
497c478bdstevel@tonic-gate#include <sys/cpuvar.h>
507c478bdstevel@tonic-gate#include <sys/vm.h>
517c478bdstevel@tonic-gate#include <sys/sysinfo.h>
527c478bdstevel@tonic-gate#include <sys/fault.h>
537c478bdstevel@tonic-gate#include <sys/stack.h>
547c478bdstevel@tonic-gate#include <sys/psw.h>
557c478bdstevel@tonic-gate#include <sys/regset.h>
567c478bdstevel@tonic-gate#include <sys/fp.h>
577c478bdstevel@tonic-gate#include <sys/trap.h>
587c478bdstevel@tonic-gate#include <sys/kmem.h>
597c478bdstevel@tonic-gate#include <sys/vtrace.h>
607c478bdstevel@tonic-gate#include <sys/cmn_err.h>
617c478bdstevel@tonic-gate#include <sys/prsystm.h>
627c478bdstevel@tonic-gate#include <sys/mutex_impl.h>
637c478bdstevel@tonic-gate#include <sys/machsystm.h>
647c478bdstevel@tonic-gate#include <sys/archsystm.h>
657c478bdstevel@tonic-gate#include <sys/sdt.h>
667c478bdstevel@tonic-gate#include <sys/avintr.h>
677c478bdstevel@tonic-gate#include <sys/kobj.h>
687c478bdstevel@tonic-gate
697c478bdstevel@tonic-gate#include <vm/hat.h>
707c478bdstevel@tonic-gate
717c478bdstevel@tonic-gate#include <vm/seg_kmem.h>
727c478bdstevel@tonic-gate#include <vm/as.h>
737c478bdstevel@tonic-gate#include <vm/seg.h>
747c478bdstevel@tonic-gate#include <vm/hat_pte.h>
75ae115bcmrj#include <vm/hat_i86.h>
767c478bdstevel@tonic-gate
777c478bdstevel@tonic-gate#include <sys/procfs.h>
787c478bdstevel@tonic-gate
797c478bdstevel@tonic-gate#include <sys/reboot.h>
807c478bdstevel@tonic-gate#include <sys/debug.h>
817c478bdstevel@tonic-gate#include <sys/debugreg.h>
827c478bdstevel@tonic-gate#include <sys/modctl.h>
837c478bdstevel@tonic-gate#include <sys/aio_impl.h>
847c478bdstevel@tonic-gate#include <sys/tnf.h>
857c478bdstevel@tonic-gate#include <sys/tnf_probe.h>
867c478bdstevel@tonic-gate#include <sys/cred.h>
877c478bdstevel@tonic-gate#include <sys/mman.h>
887c478bdstevel@tonic-gate#include <sys/x86_archext.h>
897c478bdstevel@tonic-gate#include <sys/copyops.h>
907c478bdstevel@tonic-gate#include <c2/audit.h>
917c478bdstevel@tonic-gate#include <sys/ftrace.h>
927c478bdstevel@tonic-gate#include <sys/panic.h>
937c478bdstevel@tonic-gate#include <sys/traptrace.h>
947c478bdstevel@tonic-gate#include <sys/ontrap.h>
957c478bdstevel@tonic-gate#include <sys/cpc_impl.h>
96ae115bcmrj#include <sys/bootconf.h>
97ae115bcmrj#include <sys/bootinfo.h>
98ae115bcmrj#include <sys/promif.h>
99ae115bcmrj#include <sys/mach_mmu.h>
100843e198johnlev#if defined(__xpv)
101843e198johnlev#include <sys/hypervisor.h>
102843e198johnlev#endif
10320c794bgavinm#include <sys/contract/process_impl.h>
1047c478bdstevel@tonic-gate
1057c478bdstevel@tonic-gate#define	USER	0x10000		/* user-mode flag added to trap type */
1067c478bdstevel@tonic-gate
1077c478bdstevel@tonic-gatestatic const char *trap_type_mnemonic[] = {
1087c478bdstevel@tonic-gate	"de",	"db",	"2",	"bp",
1097c478bdstevel@tonic-gate	"of",	"br",	"ud",	"nm",
1107c478bdstevel@tonic-gate	"df",	"9",	"ts",	"np",
1117c478bdstevel@tonic-gate	"ss",	"gp",	"pf",	"15",
1127c478bdstevel@tonic-gate	"mf",	"ac",	"mc",	"xf"
1137c478bdstevel@tonic-gate};
1147c478bdstevel@tonic-gate
1157c478bdstevel@tonic-gatestatic const char *trap_type[] = {
11658b4950Hans Rosenfeld	"Divide error",				/* trap id 0	*/
1177c478bdstevel@tonic-gate	"Debug",				/* trap id 1	*/
1187c478bdstevel@tonic-gate	"NMI interrupt",			/* trap id 2	*/
11958b4950Hans Rosenfeld	"Breakpoint",				/* trap id 3	*/
12058b4950Hans Rosenfeld	"Overflow",				/* trap id 4	*/
12158b4950Hans Rosenfeld	"BOUND range exceeded",			/* trap id 5	*/
12258b4950Hans Rosenfeld	"Invalid opcode",			/* trap id 6	*/
12358b4950Hans Rosenfeld	"Device not available",			/* trap id 7	*/
12458b4950Hans Rosenfeld	"Double fault",				/* trap id 8	*/
12558b4950Hans Rosenfeld	"Coprocessor segment overrun",		/* trap id 9	*/
12658b4950Hans Rosenfeld	"Invalid TSS",				/* trap id 10	*/
12758b4950Hans Rosenfeld	"Segment not present",			/* trap id 11	*/
12858b4950Hans Rosenfeld	"Stack segment fault",			/* trap id 12	*/
12958b4950Hans Rosenfeld	"General protection",			/* trap id 13	*/
13058b4950Hans Rosenfeld	"Page fault",				/* trap id 14	*/
13158b4950Hans Rosenfeld	"Reserved",				/* trap id 15	*/
13258b4950Hans Rosenfeld	"x87 floating point error",		/* trap id 16	*/
13358b4950Hans Rosenfeld	"Alignment check",			/* trap id 17	*/
1347c478bdstevel@tonic-gate	"Machine check",			/* trap id 18	*/
1357c478bdstevel@tonic-gate	"SIMD floating point exception",	/* trap id 19	*/
1367c478bdstevel@tonic-gate};
1377c478bdstevel@tonic-gate
1387c478bdstevel@tonic-gate#define	TRAP_TYPES	(sizeof (trap_type) / sizeof (trap_type[0]))
1397c478bdstevel@tonic-gate
140ddece0bsethg#define	SLOW_SCALL_SIZE	2
141ddece0bsethg#define	FAST_SCALL_SIZE	2
142ddece0bsethg
1437c478bdstevel@tonic-gateint tudebug = 0;
1447c478bdstevel@tonic-gateint tudebugbpt = 0;
1457c478bdstevel@tonic-gateint tudebugfpe = 0;
1467c478bdstevel@tonic-gateint tudebugsse = 0;
1477c478bdstevel@tonic-gate
1487c478bdstevel@tonic-gate#if defined(TRAPDEBUG) || defined(lint)
1497c478bdstevel@tonic-gateint tdebug = 0;
1507c478bdstevel@tonic-gateint lodebug = 0;
1517c478bdstevel@tonic-gateint faultdebug = 0;
1527c478bdstevel@tonic-gate#else
1537c478bdstevel@tonic-gate#define	tdebug	0
1547c478bdstevel@tonic-gate#define	lodebug	0
1557c478bdstevel@tonic-gate#define	faultdebug	0
1567c478bdstevel@tonic-gate#endif /* defined(TRAPDEBUG) || defined(lint) */
1577c478bdstevel@tonic-gate
1587c478bdstevel@tonic-gate#if defined(TRAPTRACE)
159a563a03bholler/*
160a563a03bholler * trap trace record for cpu0 is allocated here.
161a563a03bholler * trap trace records for non-boot cpus are allocated in mp_startup_init().
162a563a03bholler */
163a563a03bhollerstatic trap_trace_rec_t trap_tr0[TRAPTR_NENT];
164a563a03bhollertrap_trace_ctl_t trap_trace_ctl[NCPU] = {
165a563a03bholler	{
166a563a03bholler	    (uintptr_t)trap_tr0,			/* next record */
167a563a03bholler	    (uintptr_t)trap_tr0,			/* first record */
168a563a03bholler	    (uintptr_t)(trap_tr0 + TRAPTR_NENT),	/* limit */
169a563a03bholler	    (uintptr_t)0				/* current */
170a563a03bholler	},
171a563a03bholler};
172a563a03bholler
173a563a03bholler/*
174a563a03bholler * default trap buffer size
175a563a03bholler */
176a563a03bhollersize_t trap_trace_bufsize = TRAPTR_NENT * sizeof (trap_trace_rec_t);
177a563a03bhollerint trap_trace_freeze = 0;
178a563a03bhollerint trap_trace_off = 0;
179a563a03bholler
180a563a03bholler/*
181a563a03bholler * A dummy TRAPTRACE entry to use after death.
182a563a03bholler */
183a563a03bhollertrap_trace_rec_t trap_trace_postmort;
184a563a03bholler
1857c478bdstevel@tonic-gatestatic void dump_ttrace(void);
1867c478bdstevel@tonic-gate#endif	/* TRAPTRACE */
1877c478bdstevel@tonic-gatestatic void dumpregs(struct regs *);
1887c478bdstevel@tonic-gatestatic void showregs(uint_t, struct regs *, caddr_t);
1897c478bdstevel@tonic-gatestatic int kern_gpfault(struct regs *);
1907c478bdstevel@tonic-gate
1917c478bdstevel@tonic-gate/*ARGSUSED*/
1927c478bdstevel@tonic-gatestatic int
1937c478bdstevel@tonic-gatedie(uint_t type, struct regs *rp, caddr_t addr, processorid_t cpuid)
1947c478bdstevel@tonic-gate{
195843e198johnlev	struct panic_trap_info ti;
1967c478bdstevel@tonic-gate	const char *trap_name, *trap_mnemonic;
1977c478bdstevel@tonic-gate
1987c478bdstevel@tonic-gate	if (type < TRAP_TYPES) {
1997c478bdstevel@tonic-gate		trap_name = trap_type[type];
2007c478bdstevel@tonic-gate		trap_mnemonic = trap_type_mnemonic[type];
2017c478bdstevel@tonic-gate	} else {
2027c478bdstevel@tonic-gate		trap_name = "trap";
2037c478bdstevel@tonic-gate		trap_mnemonic = "-";
2047c478bdstevel@tonic-gate	}
2057c478bdstevel@tonic-gate
2067c478bdstevel@tonic-gate#ifdef TRAPTRACE
2077c478bdstevel@tonic-gate	TRAPTRACE_FREEZE;
2087c478bdstevel@tonic-gate#endif
2097c478bdstevel@tonic-gate
2107c478bdstevel@tonic-gate	ti.trap_regs = rp;
2117c478bdstevel@tonic-gate	ti.trap_type = type & ~USER;
2127c478bdstevel@tonic-gate	ti.trap_addr = addr;
2137c478bdstevel@tonic-gate
2147c478bdstevel@tonic-gate	curthread->t_panic_trap = &ti;
2157c478bdstevel@tonic-gate
216086dcf7Patrick Mooney	if (type == T_PGFLT && addr < (caddr_t)kernelbase) {
2177c478bdstevel@tonic-gate		panic("BAD TRAP: type=%x (#%s %s) rp=%p addr=%p "
2187c478bdstevel@tonic-gate		    "occurred in module \"%s\" due to %s",
2197c478bdstevel@tonic-gate		    type, trap_mnemonic, trap_name, (void *)rp, (void *)addr,
2207c478bdstevel@tonic-gate		    mod_containing_pc((caddr_t)rp->r_pc),
2217c478bdstevel@tonic-gate		    addr < (caddr_t)PAGESIZE ?
2227c478bdstevel@tonic-gate		    "a NULL pointer dereference" :
2237c478bdstevel@tonic-gate		    "an illegal access to a user address");
2247c478bdstevel@tonic-gate	} else
2257c478bdstevel@tonic-gate		panic("BAD TRAP: type=%x (#%s %s) rp=%p addr=%p",
2267c478bdstevel@tonic-gate		    type, trap_mnemonic, trap_name, (void *)rp, (void *)addr);
2277c478bdstevel@tonic-gate	return (0);
2287c478bdstevel@tonic-gate}
2297c478bdstevel@tonic-gate
2307c478bdstevel@tonic-gate/*
2317c478bdstevel@tonic-gate * Rewrite the instruction at pc to be an int $T_SYSCALLINT instruction.
2327c478bdstevel@tonic-gate *
2337c478bdstevel@tonic-gate * int <vector> is two bytes: 0xCD <vector>
2347c478bdstevel@tonic-gate */
2357c478bdstevel@tonic-gate
2367c478bdstevel@tonic-gatestatic int
2377c478bdstevel@tonic-gaterewrite_syscall(caddr_t pc)
2387c478bdstevel@tonic-gate{
2397c478bdstevel@tonic-gate	uchar_t instr[SLOW_SCALL_SIZE] = { 0xCD, T_SYSCALLINT };
2407c478bdstevel@tonic-gate
2417c478bdstevel@tonic-gate	if (uwrite(curthread->t_procp, instr, SLOW_SCALL_SIZE,
2427c478bdstevel@tonic-gate	    (uintptr_t)pc) != 0)
2437c478bdstevel@tonic-gate		return (1);
2447c478bdstevel@tonic-gate
2457c478bdstevel@tonic-gate	return (0);
2467c478bdstevel@tonic-gate}
2477c478bdstevel@tonic-gate
2487c478bdstevel@tonic-gate/*
2497c478bdstevel@tonic-gate * Test to see if the instruction at pc is sysenter or syscall. The second
2507c478bdstevel@tonic-gate * argument should be the x86 feature flag corresponding to the expected
2517c478bdstevel@tonic-gate * instruction.
2527c478bdstevel@tonic-gate *
2537c478bdstevel@tonic-gate * sysenter is two bytes: 0x0F 0x34
2547c478bdstevel@tonic-gate * syscall is two bytes:  0x0F 0x05
255ddece0bsethg * int $T_SYSCALLINT is two bytes: 0xCD 0x91
2567c478bdstevel@tonic-gate */
2577c478bdstevel@tonic-gate
2587c478bdstevel@tonic-gatestatic int
259ddece0bsethginstr_is_other_syscall(caddr_t pc, int which)
2607c478bdstevel@tonic-gate{
2617c478bdstevel@tonic-gate	uchar_t instr[FAST_SCALL_SIZE];
2627c478bdstevel@tonic-gate
2637417cfdKuriakose Kuruvilla	ASSERT(which == X86FSET_SEP || which == X86FSET_ASYSC || which == 0xCD);
2647c478bdstevel@tonic-gate
265ddece0bsethg	if (copyin_nowatch(pc, (caddr_t)instr, FAST_SCALL_SIZE) != 0)
2667c478bdstevel@tonic-gate		return (0);
2677c478bdstevel@tonic-gate
268ddece0bsethg	switch (which) {
2697417cfdKuriakose Kuruvilla	case X86FSET_SEP:
270ddece0bsethg		if (instr[0] == 0x0F && instr[1] == 0x34)
271ddece0bsethg			return (1);
272ddece0bsethg		break;
2737417cfdKuriakose Kuruvilla	case X86FSET_ASYSC:
274ddece0bsethg		if (instr[0] == 0x0F && instr[1] == 0x05)
275ddece0bsethg			return (1);
276ddece0bsethg		break;
277ddece0bsethg	case 0xCD:
278ddece0bsethg		if (instr[0] == 0xCD && instr[1] == T_SYSCALLINT)
279ddece0bsethg			return (1);
280ddece0bsethg		break;
281ddece0bsethg	}
2827c478bdstevel@tonic-gate
2837c478bdstevel@tonic-gate	return (0);
2847c478bdstevel@tonic-gate}
2857c478bdstevel@tonic-gate
286ddece0bsethgstatic const char *
287ddece0bsethgsyscall_insn_string(int syscall_insn)
288ddece0bsethg{
289ddece0bsethg	switch (syscall_insn) {
2907417cfdKuriakose Kuruvilla	case X86FSET_SEP:
291ddece0bsethg		return ("sysenter");
2927417cfdKuriakose Kuruvilla	case X86FSET_ASYSC:
293ddece0bsethg		return ("syscall");
294ddece0bsethg	case 0xCD:
295ddece0bsethg		return ("int");
296ddece0bsethg	default:
297ddece0bsethg		return ("Unknown");
298ddece0bsethg	}
299ddece0bsethg}
300ddece0bsethg
301ddece0bsethgstatic int
302ddece0bsethgldt_rewrite_syscall(struct regs *rp, proc_t *p, int syscall_insn)
303ddece0bsethg{
304ddece0bsethg	caddr_t	linearpc;
305ddece0bsethg	int return_code = 0;
306ddece0bsethg
307ddece0bsethg	mutex_enter(&p->p_ldtlock);	/* Must be held across linear_pc() */
308ddece0bsethg
309ddece0bsethg	if (linear_pc(rp, p, &linearpc) == 0) {
310ddece0bsethg
311ddece0bsethg		/*
312ddece0bsethg		 * If another thread beat us here, it already changed
313ddece0bsethg		 * this site to the slower (int) syscall instruction.
314ddece0bsethg		 */
315ddece0bsethg		if (instr_is_other_syscall(linearpc, 0xCD)) {
316ddece0bsethg			return_code = 1;
317ddece0bsethg		} else if (instr_is_other_syscall(linearpc, syscall_insn)) {
318ddece0bsethg
319ddece0bsethg			if (rewrite_syscall(linearpc) == 0) {
320ddece0bsethg				return_code = 1;
321ddece0bsethg			}
322ddece0bsethg#ifdef DEBUG
323ddece0bsethg			else
324ddece0bsethg				cmn_err(CE_WARN, "failed to rewrite %s "
325ddece0bsethg				    "instruction in process %d",
326ddece0bsethg				    syscall_insn_string(syscall_insn),
327ddece0bsethg				    p->p_pid);
328ddece0bsethg#endif /* DEBUG */
329ddece0bsethg		}
330ddece0bsethg	}
331ddece0bsethg
332ddece0bsethg	mutex_exit(&p->p_ldtlock);	/* Must be held across linear_pc() */
333ddece0bsethg
334ddece0bsethg	return (return_code);
335ddece0bsethg}
336ddece0bsethg
3377c478bdstevel@tonic-gate/*
3387c478bdstevel@tonic-gate * Test to see if the instruction at pc is a system call instruction.
3397c478bdstevel@tonic-gate *
3407c478bdstevel@tonic-gate * The bytes of an lcall instruction used for the syscall trap.
3417c478bdstevel@tonic-gate * static uchar_t lcall[7] = { 0x9a, 0, 0, 0, 0, 0x7, 0 };
3427c478bdstevel@tonic-gate * static uchar_t lcallalt[7] = { 0x9a, 0, 0, 0, 0, 0x27, 0 };
3437c478bdstevel@tonic-gate */
3447c478bdstevel@tonic-gate
3457c478bdstevel@tonic-gate#define	LCALLSIZE	7
3467c478bdstevel@tonic-gate
3477c478bdstevel@tonic-gatestatic int
348ddece0bsethginstr_is_lcall_syscall(caddr_t pc)
3497c478bdstevel@tonic-gate{
3507c478bdstevel@tonic-gate	uchar_t instr[LCALLSIZE];
3517c478bdstevel@tonic-gate
3527c478bdstevel@tonic-gate	if (copyin_nowatch(pc, (caddr_t)instr, LCALLSIZE) == 0 &&
3537c478bdstevel@tonic-gate	    instr[0] == 0x9a &&
3547c478bdstevel@tonic-gate	    instr[1] == 0 &&
3557c478bdstevel@tonic-gate	    instr[2] == 0 &&
3567c478bdstevel@tonic-gate	    instr[3] == 0 &&
3577c478bdstevel@tonic-gate	    instr[4] == 0 &&
3587c478bdstevel@tonic-gate	    (instr[5] == 0x7 || instr[5] == 0x27) &&
3597c478bdstevel@tonic-gate	    instr[6] == 0)
3607c478bdstevel@tonic-gate		return (1);
3617c478bdstevel@tonic-gate
3627c478bdstevel@tonic-gate	return (0);
3637c478bdstevel@tonic-gate}
3647c478bdstevel@tonic-gate
365130a12bfvdl#ifdef __amd64
366130a12bfvdl
367130a12bfvdl/*
368ae115bcmrj * In the first revisions of amd64 CPUs produced by AMD, the LAHF and
369ae115bcmrj * SAHF instructions were not implemented in 64-bit mode. Later revisions
370130a12bfvdl * did implement these instructions. An extension to the cpuid instruction
371130a12bfvdl * was added to check for the capability of executing these instructions
372ae115bcmrj * in 64-bit mode.
373130a12bfvdl *
374130a12bfvdl * Intel originally did not implement these instructions in EM64T either,
375130a12bfvdl * but added them in later revisions.
376130a12bfvdl *
377130a12bfvdl * So, there are different chip revisions by both vendors out there that
378130a12bfvdl * may or may not implement these instructions. The easy solution is to
379130a12bfvdl * just always emulate these instructions on demand.
380130a12bfvdl *
381130a12bfvdl * SAHF == store %ah in the lower 8 bits of %rflags (opcode 0x9e)
382130a12bfvdl * LAHF == load the lower 8 bits of %rflags into %ah (opcode 0x9f)
383130a12bfvdl */
384130a12bfvdl
385130a12bfvdl#define	LSAHFSIZE 1
386130a12bfvdl
387130a12bfvdlstatic int
388130a12bfvdlinstr_is_lsahf(caddr_t pc, uchar_t *instr)
389130a12bfvdl{
390130a12bfvdl	if (copyin_nowatch(pc, (caddr_t)instr, LSAHFSIZE) == 0 &&
391130a12bfvdl	    (*instr == 0x9e || *instr == 0x9f))
392130a12bfvdl		return (1);
393130a12bfvdl	return (0);
394130a12bfvdl}
395130a12bfvdl
396130a12bfvdl/*
397130a12bfvdl * Emulate the LAHF and SAHF instructions. The reference manuals define
398130a12bfvdl * these instructions to always load/store bit 1 as a 1, and bits 3 and 5
399130a12bfvdl * as a 0. The other, defined, bits are copied (the PS_ICC bits and PS_P).
400130a12bfvdl *
401130a12bfvdl * Note that %ah is bits 8-15 of %rax.
402130a12bfvdl */
403130a12bfvdlstatic void
404130a12bfvdlemulate_lsahf(struct regs *rp, uchar_t instr)
405130a12bfvdl{
406130a12bfvdl	if (instr == 0x9e) {
407130a12bfvdl		/* sahf. Copy bits from %ah to flags. */
408130a12bfvdl		rp->r_ps = (rp->r_ps & ~0xff) |
409130a12bfvdl		    ((rp->r_rax >> 8) & PSL_LSAHFMASK) | PS_MB1;
410130a12bfvdl	} else {
411130a12bfvdl		/* lahf. Copy bits from flags to %ah. */
412130a12bfvdl		rp->r_rax = (rp->r_rax & ~0xff00) |
413130a12bfvdl		    (((rp->r_ps & PSL_LSAHFMASK) | PS_MB1) << 8);
414130a12bfvdl	}
415130a12bfvdl	rp->r_pc += LSAHFSIZE;
416130a12bfvdl}
417130a12bfvdl#endif /* __amd64 */
418130a12bfvdl
4197c478bdstevel@tonic-gate#ifdef OPTERON_ERRATUM_91
4207c478bdstevel@tonic-gate
4217c478bdstevel@tonic-gate/*
4227c478bdstevel@tonic-gate * Test to see if the instruction at pc is a prefetch instruction.
4237c478bdstevel@tonic-gate *
4247c478bdstevel@tonic-gate * The first byte of prefetch instructions is always 0x0F.
4257c478bdstevel@tonic-gate * The second byte is 0x18 for regular prefetch or 0x0D for AMD 3dnow prefetch.
426d32b573George Wilson * The third byte (ModRM) contains the register field bits (bits 3-5).
427d32b573George Wilson * These bits must be between 0 and 3 inclusive for regular prefetch and
428d32b573George Wilson * 0 and 1 inclusive for AMD 3dnow prefetch.
4298ad4d6dJeff Bonwick *
4308ad4d6dJeff Bonwick * In 64-bit mode, there may be a one-byte REX prefex (0x40-0x4F).
4317c478bdstevel@tonic-gate */
4327c478bdstevel@tonic-gate
4337c478bdstevel@tonic-gatestatic int
4347c478bdstevel@tonic-gatecmp_to_prefetch(uchar_t *p)
4357c478bdstevel@tonic-gate{
4368ad4d6dJeff Bonwick#ifdef _LP64
4378ad4d6dJeff Bonwick	if ((p[0] & 0xF0) == 0x40)	/* 64-bit REX prefix */
4388ad4d6dJeff Bonwick		p++;
4398ad4d6dJeff Bonwick#endif
440d32b573George Wilson	return ((p[0] == 0x0F && p[1] == 0x18 && ((p[2] >> 3) & 7) <= 3) ||
441d32b573George Wilson	    (p[0] == 0x0F && p[1] == 0x0D && ((p[2] >> 3) & 7) <= 1));
4427c478bdstevel@tonic-gate}
4437c478bdstevel@tonic-gate
4447c478bdstevel@tonic-gatestatic int
4457c478bdstevel@tonic-gateinstr_is_prefetch(caddr_t pc)
4467c478bdstevel@tonic-gate{
4478ad4d6dJeff Bonwick	uchar_t instr[4];	/* optional REX prefix plus 3-byte opcode */
4487c478bdstevel@tonic-gate
4498ad4d6dJeff Bonwick	return (copyin_nowatch(pc, instr, sizeof (instr)) == 0 &&
4508ad4d6dJeff Bonwick	    cmp_to_prefetch(instr));
4517c478bdstevel@tonic-gate}
4527c478bdstevel@tonic-gate
4537c478bdstevel@tonic-gate#endif /* OPTERON_ERRATUM_91 */
4547c478bdstevel@tonic-gate
4557c478bdstevel@tonic-gate/*
4567c478bdstevel@tonic-gate * Called from the trap handler when a processor trap occurs.
4577c478bdstevel@tonic-gate *
4587c478bdstevel@tonic-gate * Note: All user-level traps that might call stop() must exit
4597c478bdstevel@tonic-gate * trap() by 'goto out' or by falling through.
460ae115bcmrj * Note Also: trap() is usually called with interrupts enabled, (PS_IE == 1)
461ae115bcmrj * however, there are paths that arrive here with PS_IE == 0 so special care
462ae115bcmrj * must be taken in those cases.
4637c478bdstevel@tonic-gate */
4647c478bdstevel@tonic-gatevoid
4657c478bdstevel@tonic-gatetrap(struct regs *rp, caddr_t addr, processorid_t cpuid)
4667c478bdstevel@tonic-gate{
467