xref: /freebsd/sys/cddl/dev/dtrace/amd64/dtrace_asm.S (revision 91eaf3e1831d805c9cffd85818a70213d9007e07)
191eaf3e1SJohn Birrell/*
291eaf3e1SJohn Birrell * CDDL HEADER START
391eaf3e1SJohn Birrell *
491eaf3e1SJohn Birrell * The contents of this file are subject to the terms of the
591eaf3e1SJohn Birrell * Common Development and Distribution License (the "License").
691eaf3e1SJohn Birrell * You may not use this file except in compliance with the License.
791eaf3e1SJohn Birrell *
891eaf3e1SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
991eaf3e1SJohn Birrell * or http://www.opensolaris.org/os/licensing.
1091eaf3e1SJohn Birrell * See the License for the specific language governing permissions
1191eaf3e1SJohn Birrell * and limitations under the License.
1291eaf3e1SJohn Birrell *
1391eaf3e1SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each
1491eaf3e1SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1591eaf3e1SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the
1691eaf3e1SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying
1791eaf3e1SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner]
1891eaf3e1SJohn Birrell *
1991eaf3e1SJohn Birrell * CDDL HEADER END
2091eaf3e1SJohn Birrell *
2191eaf3e1SJohn Birrell * Portions Copyright 2008 John Birrell <jb@freebsd.org>
2291eaf3e1SJohn Birrell *
2391eaf3e1SJohn Birrell * $FreeBSD$
2491eaf3e1SJohn Birrell *
2591eaf3e1SJohn Birrell */
2691eaf3e1SJohn Birrell/*
2791eaf3e1SJohn Birrell * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2891eaf3e1SJohn Birrell * Use is subject to license terms.
2991eaf3e1SJohn Birrell */
3091eaf3e1SJohn Birrell
3191eaf3e1SJohn Birrell#define _ASM
3291eaf3e1SJohn Birrell
3391eaf3e1SJohn Birrell#include <machine/asmacros.h>
3491eaf3e1SJohn Birrell#include <sys/cpuvar_defs.h>
3591eaf3e1SJohn Birrell#include <sys/dtrace.h>
3691eaf3e1SJohn Birrell
3791eaf3e1SJohn Birrell#include "assym.s"
3891eaf3e1SJohn Birrell
3991eaf3e1SJohn Birrell#define INTR_POP				\
4091eaf3e1SJohn Birrell	MEXITCOUNT;				\
4191eaf3e1SJohn Birrell	movq	TF_RDI(%rsp),%rdi;		\
4291eaf3e1SJohn Birrell	movq	TF_RSI(%rsp),%rsi;		\
4391eaf3e1SJohn Birrell	movq	TF_RDX(%rsp),%rdx;		\
4491eaf3e1SJohn Birrell	movq	TF_RCX(%rsp),%rcx;		\
4591eaf3e1SJohn Birrell	movq	TF_R8(%rsp),%r8;		\
4691eaf3e1SJohn Birrell	movq	TF_R9(%rsp),%r9;		\
4791eaf3e1SJohn Birrell	movq	TF_RAX(%rsp),%rax;		\
4891eaf3e1SJohn Birrell	movq	TF_RBX(%rsp),%rbx;		\
4991eaf3e1SJohn Birrell	movq	TF_RBP(%rsp),%rbp;		\
5091eaf3e1SJohn Birrell	movq	TF_R10(%rsp),%r10;		\
5191eaf3e1SJohn Birrell	movq	TF_R11(%rsp),%r11;		\
5291eaf3e1SJohn Birrell	movq	TF_R12(%rsp),%r12;		\
5391eaf3e1SJohn Birrell	movq	TF_R13(%rsp),%r13;		\
5491eaf3e1SJohn Birrell	movq	TF_R14(%rsp),%r14;		\
5591eaf3e1SJohn Birrell	movq	TF_R15(%rsp),%r15;		\
5691eaf3e1SJohn Birrell	testb	$SEL_RPL_MASK,TF_CS(%rsp);	\
5791eaf3e1SJohn Birrell	jz	1f;				\
5891eaf3e1SJohn Birrell	cli;					\
5991eaf3e1SJohn Birrell	swapgs;					\
6091eaf3e1SJohn Birrell1:	addq	$TF_RIP,%rsp;
6191eaf3e1SJohn Birrell
6291eaf3e1SJohn Birrell
6391eaf3e1SJohn Birrell	.globl	calltrap
6491eaf3e1SJohn Birrell	.type	calltrap,@function
6591eaf3e1SJohn Birrell	ENTRY(dtrace_invop_start)
6691eaf3e1SJohn Birrell
6791eaf3e1SJohn Birrell	/*
6891eaf3e1SJohn Birrell	 * #BP traps with %rip set to the next address. We need to decrement
6991eaf3e1SJohn Birrell	 * the value to indicate the address of the int3 (0xcc) instruction
7091eaf3e1SJohn Birrell	 * that we substituted.
7191eaf3e1SJohn Birrell	 */
7291eaf3e1SJohn Birrell	movq	TF_RIP(%rsp), %rdi
7391eaf3e1SJohn Birrell	decq	%rdi
7491eaf3e1SJohn Birrell	movq	TF_RSP(%rsp), %rsi
7591eaf3e1SJohn Birrell	movq	TF_RAX(%rsp), %rdx
7691eaf3e1SJohn Birrell	pushq	(%rsi)
7791eaf3e1SJohn Birrell	movq	%rsp, %rsi
7891eaf3e1SJohn Birrell	call	dtrace_invop
7991eaf3e1SJohn Birrell	ALTENTRY(dtrace_invop_callsite)
8091eaf3e1SJohn Birrell	addq	$8, %rsp
8191eaf3e1SJohn Birrell	cmpl	$DTRACE_INVOP_PUSHL_EBP, %eax
8291eaf3e1SJohn Birrell	je	bp_push
8391eaf3e1SJohn Birrell	cmpl	$DTRACE_INVOP_LEAVE, %eax
8491eaf3e1SJohn Birrell	je	bp_leave
8591eaf3e1SJohn Birrell	cmpl	$DTRACE_INVOP_NOP, %eax
8691eaf3e1SJohn Birrell	je	bp_nop
8791eaf3e1SJohn Birrell	cmpl	$DTRACE_INVOP_RET, %eax
8891eaf3e1SJohn Birrell	je	bp_ret
8991eaf3e1SJohn Birrell
9091eaf3e1SJohn Birrell	/* When all else fails handle the trap in the usual way. */
9191eaf3e1SJohn Birrell	jmpq	*dtrace_invop_calltrap_addr
9291eaf3e1SJohn Birrell
9391eaf3e1SJohn Birrellbp_push:
9491eaf3e1SJohn Birrell	/*
9591eaf3e1SJohn Birrell	 * We must emulate a "pushq %rbp".  To do this, we pull the stack
9691eaf3e1SJohn Birrell	 * down 8 bytes, and then store the base pointer.
9791eaf3e1SJohn Birrell	 */
9891eaf3e1SJohn Birrell	INTR_POP
9991eaf3e1SJohn Birrell	subq	$16, %rsp		/* make room for %rbp */
10091eaf3e1SJohn Birrell	pushq	%rax			/* push temp */
10191eaf3e1SJohn Birrell	movq	24(%rsp), %rax		/* load calling RIP */
10291eaf3e1SJohn Birrell	movq	%rax, 8(%rsp)		/* store calling RIP */
10391eaf3e1SJohn Birrell	movq	32(%rsp), %rax		/* load calling CS */
10491eaf3e1SJohn Birrell	movq	%rax, 16(%rsp)		/* store calling CS */
10591eaf3e1SJohn Birrell	movq	40(%rsp), %rax		/* load calling RFLAGS */
10691eaf3e1SJohn Birrell	movq	%rax, 24(%rsp)		/* store calling RFLAGS */
10791eaf3e1SJohn Birrell	movq	48(%rsp), %rax		/* load calling RSP */
10891eaf3e1SJohn Birrell	subq	$8, %rax		/* make room for %rbp */
10991eaf3e1SJohn Birrell	movq	%rax, 32(%rsp)		/* store calling RSP */
11091eaf3e1SJohn Birrell	movq	56(%rsp), %rax		/* load calling SS */
11191eaf3e1SJohn Birrell	movq	%rax, 40(%rsp)		/* store calling SS */
11291eaf3e1SJohn Birrell	movq	32(%rsp), %rax		/* reload calling RSP */
11391eaf3e1SJohn Birrell	movq	%rbp, (%rax)		/* store %rbp there */
11491eaf3e1SJohn Birrell	popq	%rax			/* pop off temp */
11591eaf3e1SJohn Birrell	iretq				/* return from interrupt */
11691eaf3e1SJohn Birrell	/*NOTREACHED*/
11791eaf3e1SJohn Birrell
11891eaf3e1SJohn Birrellbp_leave:
11991eaf3e1SJohn Birrell	/*
12091eaf3e1SJohn Birrell	 * We must emulate a "leave", which is the same as a "movq %rbp, %rsp"
12191eaf3e1SJohn Birrell	 * followed by a "popq %rbp".  This is quite a bit simpler on amd64
12291eaf3e1SJohn Birrell	 * than it is on i386 -- we can exploit the fact that the %rsp is
12391eaf3e1SJohn Birrell	 * explicitly saved to effect the pop without having to reshuffle
12491eaf3e1SJohn Birrell	 * the other data pushed for the trap.
12591eaf3e1SJohn Birrell	 */
12691eaf3e1SJohn Birrell	INTR_POP
12791eaf3e1SJohn Birrell	pushq	%rax			/* push temp */
12891eaf3e1SJohn Birrell	movq	8(%rsp), %rax		/* load calling RIP */
12991eaf3e1SJohn Birrell	movq	%rax, 8(%rsp)		/* store calling RIP */
13091eaf3e1SJohn Birrell	movq	(%rbp), %rax		/* get new %rbp */
13191eaf3e1SJohn Birrell	addq	$8, %rbp		/* adjust new %rsp */
13291eaf3e1SJohn Birrell	movq	%rbp, 32(%rsp)		/* store new %rsp */
13391eaf3e1SJohn Birrell	movq	%rax, %rbp		/* set new %rbp */
13491eaf3e1SJohn Birrell	popq	%rax			/* pop off temp */
13591eaf3e1SJohn Birrell	iretq				/* return from interrupt */
13691eaf3e1SJohn Birrell	/*NOTREACHED*/
13791eaf3e1SJohn Birrell
13891eaf3e1SJohn Birrellbp_nop:
13991eaf3e1SJohn Birrell	/* We must emulate a "nop". */
14091eaf3e1SJohn Birrell	INTR_POP
14191eaf3e1SJohn Birrell	iretq
14291eaf3e1SJohn Birrell	/*NOTREACHED*/
14391eaf3e1SJohn Birrell
14491eaf3e1SJohn Birrellbp_ret:
14591eaf3e1SJohn Birrell	INTR_POP
14691eaf3e1SJohn Birrell	pushq	%rax			/* push temp */
14791eaf3e1SJohn Birrell	movq	32(%rsp), %rax		/* load %rsp */
14891eaf3e1SJohn Birrell	movq	(%rax), %rax		/* load calling RIP */
14991eaf3e1SJohn Birrell	movq	%rax, 8(%rsp)		/* store calling RIP */
15091eaf3e1SJohn Birrell	addq	$8, 32(%rsp)		/* adjust new %rsp */
15191eaf3e1SJohn Birrell	popq	%rax			/* pop off temp */
15291eaf3e1SJohn Birrell	iretq				/* return from interrupt */
15391eaf3e1SJohn Birrell	/*NOTREACHED*/
15491eaf3e1SJohn Birrell
15591eaf3e1SJohn Birrell	END(dtrace_invop_start)
15691eaf3e1SJohn Birrell
15791eaf3e1SJohn Birrell/*
15891eaf3e1SJohn Birrellvoid dtrace_invop_init(void)
15991eaf3e1SJohn Birrell*/
16091eaf3e1SJohn Birrell	ENTRY(dtrace_invop_init)
16191eaf3e1SJohn Birrell	movq	$dtrace_invop_start, dtrace_invop_jump_addr(%rip)
16291eaf3e1SJohn Birrell	ret
16391eaf3e1SJohn Birrell	END(dtrace_invop_init)
16491eaf3e1SJohn Birrell
16591eaf3e1SJohn Birrell/*
16691eaf3e1SJohn Birrellvoid dtrace_invop_uninit(void)
16791eaf3e1SJohn Birrell*/
16891eaf3e1SJohn Birrell	ENTRY(dtrace_invop_uninit)
16991eaf3e1SJohn Birrell	movq	$0, dtrace_invop_jump_addr(%rip)
17091eaf3e1SJohn Birrell	ret
17191eaf3e1SJohn Birrell	END(dtrace_invop_uninit)
17291eaf3e1SJohn Birrell
17391eaf3e1SJohn Birrell/*
17491eaf3e1SJohn Birrellgreg_t dtrace_getfp(void)
17591eaf3e1SJohn Birrell*/
17691eaf3e1SJohn Birrell	ENTRY(dtrace_getfp)
17791eaf3e1SJohn Birrell	movq	%rbp, %rax
17891eaf3e1SJohn Birrell	ret
17991eaf3e1SJohn Birrell	END(dtrace_getfp)
18091eaf3e1SJohn Birrell
18191eaf3e1SJohn Birrell/*
18291eaf3e1SJohn Birrelluint32_t
18391eaf3e1SJohn Birrelldtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
18491eaf3e1SJohn Birrell*/
18591eaf3e1SJohn Birrell	ENTRY(dtrace_cas32)
18691eaf3e1SJohn Birrell	movl	%esi, %eax
18791eaf3e1SJohn Birrell	lock
18891eaf3e1SJohn Birrell	cmpxchgl %edx, (%rdi)
18991eaf3e1SJohn Birrell	ret
19091eaf3e1SJohn Birrell	END(dtrace_cas32)
19191eaf3e1SJohn Birrell
19291eaf3e1SJohn Birrell/*
19391eaf3e1SJohn Birrellvoid *
19491eaf3e1SJohn Birrelldtrace_casptr(void *target, void *cmp, void *new)
19591eaf3e1SJohn Birrell*/
19691eaf3e1SJohn Birrell	ENTRY(dtrace_casptr)
19791eaf3e1SJohn Birrell	movq	%rsi, %rax
19891eaf3e1SJohn Birrell	lock
19991eaf3e1SJohn Birrell	cmpxchgq %rdx, (%rdi)
20091eaf3e1SJohn Birrell	ret
20191eaf3e1SJohn Birrell	END(dtrace_casptr)
20291eaf3e1SJohn Birrell
20391eaf3e1SJohn Birrell/*
20491eaf3e1SJohn Birrelluintptr_t
20591eaf3e1SJohn Birrelldtrace_caller(int aframes)
20691eaf3e1SJohn Birrell*/
20791eaf3e1SJohn Birrell	ENTRY(dtrace_caller)
20891eaf3e1SJohn Birrell	movq	$-1, %rax
20991eaf3e1SJohn Birrell	ret
21091eaf3e1SJohn Birrell	END(dtrace_caller)
21191eaf3e1SJohn Birrell
21291eaf3e1SJohn Birrell/*
21391eaf3e1SJohn Birrellvoid
21491eaf3e1SJohn Birrelldtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
21591eaf3e1SJohn Birrell*/
21691eaf3e1SJohn Birrell	ENTRY(dtrace_copy)
21791eaf3e1SJohn Birrell	pushq	%rbp
21891eaf3e1SJohn Birrell	movq	%rsp, %rbp
21991eaf3e1SJohn Birrell
22091eaf3e1SJohn Birrell	xchgq	%rdi, %rsi		/* make %rsi source, %rdi dest */
22191eaf3e1SJohn Birrell	movq	%rdx, %rcx		/* load count */
22291eaf3e1SJohn Birrell	repz				/* repeat for count ... */
22391eaf3e1SJohn Birrell	smovb				/*   move from %ds:rsi to %ed:rdi */
22491eaf3e1SJohn Birrell	leave
22591eaf3e1SJohn Birrell	ret
22691eaf3e1SJohn Birrell	END(dtrace_copy)
22791eaf3e1SJohn Birrell
22891eaf3e1SJohn Birrell/*
22991eaf3e1SJohn Birrellvoid
23091eaf3e1SJohn Birrelldtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
23191eaf3e1SJohn Birrell    volatile uint16_t *flags)
23291eaf3e1SJohn Birrell*/
23391eaf3e1SJohn Birrell	ENTRY(dtrace_copystr)
23491eaf3e1SJohn Birrell	pushq	%rbp
23591eaf3e1SJohn Birrell	movq	%rsp, %rbp
23691eaf3e1SJohn Birrell
23791eaf3e1SJohn Birrell0:
23891eaf3e1SJohn Birrell	movb	(%rdi), %al		/* load from source */
23991eaf3e1SJohn Birrell	movb	%al, (%rsi)		/* store to destination */
24091eaf3e1SJohn Birrell	addq	$1, %rdi		/* increment source pointer */
24191eaf3e1SJohn Birrell	addq	$1, %rsi		/* increment destination pointer */
24291eaf3e1SJohn Birrell	subq	$1, %rdx		/* decrement remaining count */
24391eaf3e1SJohn Birrell	cmpb	$0, %al
24491eaf3e1SJohn Birrell	je	2f
24591eaf3e1SJohn Birrell	testq	$0xfff, %rdx		/* test if count is 4k-aligned */
24691eaf3e1SJohn Birrell	jnz	1f			/* if not, continue with copying */
24791eaf3e1SJohn Birrell	testq	$CPU_DTRACE_BADADDR, (%rcx) /* load and test dtrace flags */
24891eaf3e1SJohn Birrell	jnz	2f
24991eaf3e1SJohn Birrell1:
25091eaf3e1SJohn Birrell	cmpq	$0, %rdx
25191eaf3e1SJohn Birrell	jne	0b
25291eaf3e1SJohn Birrell2:
25391eaf3e1SJohn Birrell	leave
25491eaf3e1SJohn Birrell	ret
25591eaf3e1SJohn Birrell
25691eaf3e1SJohn Birrell	END(dtrace_copystr)
25791eaf3e1SJohn Birrell
25891eaf3e1SJohn Birrell/*
25991eaf3e1SJohn Birrelluintptr_t
26091eaf3e1SJohn Birrelldtrace_fulword(void *addr)
26191eaf3e1SJohn Birrell*/
26291eaf3e1SJohn Birrell	ENTRY(dtrace_fulword)
26391eaf3e1SJohn Birrell	movq	(%rdi), %rax
26491eaf3e1SJohn Birrell	ret
26591eaf3e1SJohn Birrell	END(dtrace_fulword)
26691eaf3e1SJohn Birrell
26791eaf3e1SJohn Birrell/*
26891eaf3e1SJohn Birrelluint8_t
26991eaf3e1SJohn Birrelldtrace_fuword8_nocheck(void *addr)
27091eaf3e1SJohn Birrell*/
27191eaf3e1SJohn Birrell	ENTRY(dtrace_fuword8_nocheck)
27291eaf3e1SJohn Birrell	xorq	%rax, %rax
27391eaf3e1SJohn Birrell	movb	(%rdi), %al
27491eaf3e1SJohn Birrell	ret
27591eaf3e1SJohn Birrell	END(dtrace_fuword8_nocheck)
27691eaf3e1SJohn Birrell
27791eaf3e1SJohn Birrell/*
27891eaf3e1SJohn Birrelluint16_t
27991eaf3e1SJohn Birrelldtrace_fuword16_nocheck(void *addr)
28091eaf3e1SJohn Birrell*/
28191eaf3e1SJohn Birrell	ENTRY(dtrace_fuword16_nocheck)
28291eaf3e1SJohn Birrell	xorq	%rax, %rax
28391eaf3e1SJohn Birrell	movw	(%rdi), %ax
28491eaf3e1SJohn Birrell	ret
28591eaf3e1SJohn Birrell	END(dtrace_fuword16_nocheck)
28691eaf3e1SJohn Birrell
28791eaf3e1SJohn Birrell/*
28891eaf3e1SJohn Birrelluint32_t
28991eaf3e1SJohn Birrelldtrace_fuword32_nocheck(void *addr)
29091eaf3e1SJohn Birrell*/
29191eaf3e1SJohn Birrell	ENTRY(dtrace_fuword32_nocheck)
29291eaf3e1SJohn Birrell	xorq	%rax, %rax
29391eaf3e1SJohn Birrell	movl	(%rdi), %eax
29491eaf3e1SJohn Birrell	ret
29591eaf3e1SJohn Birrell	END(dtrace_fuword32_nocheck)
29691eaf3e1SJohn Birrell
29791eaf3e1SJohn Birrell/*
29891eaf3e1SJohn Birrelluint64_t
29991eaf3e1SJohn Birrelldtrace_fuword64_nocheck(void *addr)
30091eaf3e1SJohn Birrell*/
30191eaf3e1SJohn Birrell	ENTRY(dtrace_fuword64_nocheck)
30291eaf3e1SJohn Birrell	movq	(%rdi), %rax
30391eaf3e1SJohn Birrell	ret
30491eaf3e1SJohn Birrell	END(dtrace_fuword64_nocheck)
30591eaf3e1SJohn Birrell
30691eaf3e1SJohn Birrell/*
30791eaf3e1SJohn Birrellvoid
30891eaf3e1SJohn Birrelldtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
30991eaf3e1SJohn Birrell    int fault, int fltoffs, uintptr_t illval)
31091eaf3e1SJohn Birrell*/
31191eaf3e1SJohn Birrell	ENTRY(dtrace_probe_error)
31291eaf3e1SJohn Birrell	pushq	%rbp
31391eaf3e1SJohn Birrell	movq	%rsp, %rbp
31491eaf3e1SJohn Birrell	subq	$0x8, %rsp
31591eaf3e1SJohn Birrell	movq	%r9, (%rsp)
31691eaf3e1SJohn Birrell	movq	%r8, %r9
31791eaf3e1SJohn Birrell	movq	%rcx, %r8
31891eaf3e1SJohn Birrell	movq	%rdx, %rcx
31991eaf3e1SJohn Birrell	movq	%rsi, %rdx
32091eaf3e1SJohn Birrell	movq	%rdi, %rsi
32191eaf3e1SJohn Birrell	movl	dtrace_probeid_error(%rip), %edi
32291eaf3e1SJohn Birrell	call	dtrace_probe
32391eaf3e1SJohn Birrell	addq	$0x8, %rsp
32491eaf3e1SJohn Birrell	leave
32591eaf3e1SJohn Birrell	ret
32691eaf3e1SJohn Birrell	END(dtrace_probe_error)
32791eaf3e1SJohn Birrell
32891eaf3e1SJohn Birrell/*
32991eaf3e1SJohn Birrellvoid
33091eaf3e1SJohn Birrelldtrace_membar_producer(void)
33191eaf3e1SJohn Birrell*/
33291eaf3e1SJohn Birrell	ENTRY(dtrace_membar_producer)
33391eaf3e1SJohn Birrell	rep;	ret	/* use 2 byte return instruction when branch target */
33491eaf3e1SJohn Birrell			/* AMD Software Optimization Guide - Section 6.2 */
33591eaf3e1SJohn Birrell	END(dtrace_membar_producer)
33691eaf3e1SJohn Birrell
33791eaf3e1SJohn Birrell/*
33891eaf3e1SJohn Birrellvoid
33991eaf3e1SJohn Birrelldtrace_membar_consumer(void)
34091eaf3e1SJohn Birrell*/
34191eaf3e1SJohn Birrell	ENTRY(dtrace_membar_consumer)
34291eaf3e1SJohn Birrell	rep;	ret	/* use 2 byte return instruction when branch target */
34391eaf3e1SJohn Birrell			/* AMD Software Optimization Guide - Section 6.2 */
34491eaf3e1SJohn Birrell	END(dtrace_membar_consumer)
34591eaf3e1SJohn Birrell
34691eaf3e1SJohn Birrell/*
34791eaf3e1SJohn Birrelldtrace_icookie_t
34891eaf3e1SJohn Birrelldtrace_interrupt_disable(void)
34991eaf3e1SJohn Birrell*/
35091eaf3e1SJohn Birrell	ENTRY(dtrace_interrupt_disable)
35191eaf3e1SJohn Birrell	pushfq
35291eaf3e1SJohn Birrell	popq	%rax
35391eaf3e1SJohn Birrell	cli
35491eaf3e1SJohn Birrell	ret
35591eaf3e1SJohn Birrell	END(dtrace_interrupt_disable)
35691eaf3e1SJohn Birrell
35791eaf3e1SJohn Birrell/*
35891eaf3e1SJohn Birrellvoid
35991eaf3e1SJohn Birrelldtrace_interrupt_enable(dtrace_icookie_t cookie)
36091eaf3e1SJohn Birrell*/
36191eaf3e1SJohn Birrell	ENTRY(dtrace_interrupt_enable)
36291eaf3e1SJohn Birrell	pushq	%rdi
36391eaf3e1SJohn Birrell	popfq
36491eaf3e1SJohn Birrell	ret
36591eaf3e1SJohn Birrell	END(dtrace_interrupt_enable)
36691eaf3e1SJohn Birrell
36791eaf3e1SJohn Birrell/*
36891eaf3e1SJohn Birrell * The panic() and cmn_err() functions invoke vpanic() as a common entry point
36991eaf3e1SJohn Birrell * into the panic code implemented in panicsys().  vpanic() is responsible
37091eaf3e1SJohn Birrell * for passing through the format string and arguments, and constructing a
37191eaf3e1SJohn Birrell * regs structure on the stack into which it saves the current register
37291eaf3e1SJohn Birrell * values.  If we are not dying due to a fatal trap, these registers will
37391eaf3e1SJohn Birrell * then be preserved in panicbuf as the current processor state.  Before
37491eaf3e1SJohn Birrell * invoking panicsys(), vpanic() activates the first panic trigger (see
37591eaf3e1SJohn Birrell * common/os/panic.c) and switches to the panic_stack if successful.  Note that
37691eaf3e1SJohn Birrell * DTrace takes a slightly different panic path if it must panic from probe
37791eaf3e1SJohn Birrell * context.  Instead of calling panic, it calls into dtrace_vpanic(), which
37891eaf3e1SJohn Birrell * sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and
37991eaf3e1SJohn Birrell * branches back into vpanic().
38091eaf3e1SJohn Birrell */
38191eaf3e1SJohn Birrell
38291eaf3e1SJohn Birrell/*
38391eaf3e1SJohn Birrellvoid
38491eaf3e1SJohn Birrellvpanic(const char *format, va_list alist)
38591eaf3e1SJohn Birrell*/
38691eaf3e1SJohn Birrell	ENTRY(vpanic)				/* Initial stack layout: */
38791eaf3e1SJohn Birrell
38891eaf3e1SJohn Birrell	pushq	%rbp				/* | %rip | 	0x60	*/
38991eaf3e1SJohn Birrell	movq	%rsp, %rbp			/* | %rbp |	0x58	*/
39091eaf3e1SJohn Birrell	pushfq					/* | rfl  |	0x50	*/
39191eaf3e1SJohn Birrell	pushq	%r11				/* | %r11 |	0x48	*/
39291eaf3e1SJohn Birrell	pushq	%r10				/* | %r10 |	0x40	*/
39391eaf3e1SJohn Birrell	pushq	%rbx				/* | %rbx |	0x38	*/
39491eaf3e1SJohn Birrell	pushq	%rax				/* | %rax |	0x30	*/
39591eaf3e1SJohn Birrell	pushq	%r9				/* | %r9  |	0x28	*/
39691eaf3e1SJohn Birrell	pushq	%r8				/* | %r8  |	0x20	*/
39791eaf3e1SJohn Birrell	pushq	%rcx				/* | %rcx |	0x18	*/
39891eaf3e1SJohn Birrell	pushq	%rdx				/* | %rdx |	0x10	*/
39991eaf3e1SJohn Birrell	pushq	%rsi				/* | %rsi |	0x8 alist */
40091eaf3e1SJohn Birrell	pushq	%rdi				/* | %rdi |	0x0 format */
40191eaf3e1SJohn Birrell
40291eaf3e1SJohn Birrell	movq	%rsp, %rbx			/* %rbx = current %rsp */
40391eaf3e1SJohn Birrell
40491eaf3e1SJohn Birrell	leaq	panic_quiesce(%rip), %rdi	/* %rdi = &panic_quiesce */
40591eaf3e1SJohn Birrell	call	panic_trigger			/* %eax = panic_trigger() */
40691eaf3e1SJohn Birrell
40791eaf3e1SJohn Birrellvpanic_common:
40891eaf3e1SJohn Birrell	/*
40991eaf3e1SJohn Birrell	 * The panic_trigger result is in %eax from the call above, and
41091eaf3e1SJohn Birrell	 * dtrace_panic places it in %eax before branching here.
41191eaf3e1SJohn Birrell	 * The rdmsr instructions that follow below will clobber %eax so
41291eaf3e1SJohn Birrell	 * we stash the panic_trigger result in %r11d.
41391eaf3e1SJohn Birrell	 */
41491eaf3e1SJohn Birrell	movl	%eax, %r11d
41591eaf3e1SJohn Birrell	cmpl	$0, %r11d
41691eaf3e1SJohn Birrell	je	0f
41791eaf3e1SJohn Birrell
41891eaf3e1SJohn Birrell	/*
41991eaf3e1SJohn Birrell	 * If panic_trigger() was successful, we are the first to initiate a
42091eaf3e1SJohn Birrell	 * panic: we now switch to the reserved panic_stack before continuing.
42191eaf3e1SJohn Birrell	 */
42291eaf3e1SJohn Birrell	leaq	panic_stack(%rip), %rsp
42391eaf3e1SJohn Birrell	addq	$PANICSTKSIZE, %rsp
42491eaf3e1SJohn Birrell0:	subq	$REGSIZE, %rsp
42591eaf3e1SJohn Birrell	/*
42691eaf3e1SJohn Birrell	 * Now that we've got everything set up, store the register values as
42791eaf3e1SJohn Birrell	 * they were when we entered vpanic() to the designated location in
42891eaf3e1SJohn Birrell	 * the regs structure we allocated on the stack.
42991eaf3e1SJohn Birrell	 */
43091eaf3e1SJohn Birrell#ifdef notyet
43191eaf3e1SJohn Birrell	movq	0x0(%rbx), %rcx
43291eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RDI(%rsp)
43391eaf3e1SJohn Birrell	movq	0x8(%rbx), %rcx
43491eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RSI(%rsp)
43591eaf3e1SJohn Birrell	movq	0x10(%rbx), %rcx
43691eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RDX(%rsp)
43791eaf3e1SJohn Birrell	movq	0x18(%rbx), %rcx
43891eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RCX(%rsp)
43991eaf3e1SJohn Birrell	movq	0x20(%rbx), %rcx
44091eaf3e1SJohn Birrell
44191eaf3e1SJohn Birrell	movq	%rcx, REGOFF_R8(%rsp)
44291eaf3e1SJohn Birrell	movq	0x28(%rbx), %rcx
44391eaf3e1SJohn Birrell	movq	%rcx, REGOFF_R9(%rsp)
44491eaf3e1SJohn Birrell	movq	0x30(%rbx), %rcx
44591eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RAX(%rsp)
44691eaf3e1SJohn Birrell	movq	0x38(%rbx), %rcx
44791eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RBX(%rsp)
44891eaf3e1SJohn Birrell	movq	0x58(%rbx), %rcx
44991eaf3e1SJohn Birrell
45091eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RBP(%rsp)
45191eaf3e1SJohn Birrell	movq	0x40(%rbx), %rcx
45291eaf3e1SJohn Birrell	movq	%rcx, REGOFF_R10(%rsp)
45391eaf3e1SJohn Birrell	movq	0x48(%rbx), %rcx
45491eaf3e1SJohn Birrell	movq	%rcx, REGOFF_R11(%rsp)
45591eaf3e1SJohn Birrell	movq	%r12, REGOFF_R12(%rsp)
45691eaf3e1SJohn Birrell
45791eaf3e1SJohn Birrell	movq	%r13, REGOFF_R13(%rsp)
45891eaf3e1SJohn Birrell	movq	%r14, REGOFF_R14(%rsp)
45991eaf3e1SJohn Birrell	movq	%r15, REGOFF_R15(%rsp)
46091eaf3e1SJohn Birrell
46191eaf3e1SJohn Birrell	xorl	%ecx, %ecx
46291eaf3e1SJohn Birrell	movw	%ds, %cx
46391eaf3e1SJohn Birrell	movq	%rcx, REGOFF_DS(%rsp)
46491eaf3e1SJohn Birrell	movw	%es, %cx
46591eaf3e1SJohn Birrell	movq	%rcx, REGOFF_ES(%rsp)
46691eaf3e1SJohn Birrell	movw	%fs, %cx
46791eaf3e1SJohn Birrell	movq	%rcx, REGOFF_FS(%rsp)
46891eaf3e1SJohn Birrell	movw	%gs, %cx
46991eaf3e1SJohn Birrell	movq	%rcx, REGOFF_GS(%rsp)
47091eaf3e1SJohn Birrell
47191eaf3e1SJohn Birrell	movq	$0, REGOFF_TRAPNO(%rsp)
47291eaf3e1SJohn Birrell
47391eaf3e1SJohn Birrell	movq	$0, REGOFF_ERR(%rsp)
47491eaf3e1SJohn Birrell	leaq	vpanic(%rip), %rcx
47591eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RIP(%rsp)
47691eaf3e1SJohn Birrell	movw	%cs, %cx
47791eaf3e1SJohn Birrell	movzwq	%cx, %rcx
47891eaf3e1SJohn Birrell	movq	%rcx, REGOFF_CS(%rsp)
47991eaf3e1SJohn Birrell	movq	0x50(%rbx), %rcx
48091eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RFL(%rsp)
48191eaf3e1SJohn Birrell	movq	%rbx, %rcx
48291eaf3e1SJohn Birrell	addq	$0x60, %rcx
48391eaf3e1SJohn Birrell	movq	%rcx, REGOFF_RSP(%rsp)
48491eaf3e1SJohn Birrell	movw	%ss, %cx
48591eaf3e1SJohn Birrell	movzwq	%cx, %rcx
48691eaf3e1SJohn Birrell	movq	%rcx, REGOFF_SS(%rsp)
48791eaf3e1SJohn Birrell
48891eaf3e1SJohn Birrell	/*
48991eaf3e1SJohn Birrell	 * panicsys(format, alist, rp, on_panic_stack)
49091eaf3e1SJohn Birrell	 */
49191eaf3e1SJohn Birrell	movq	REGOFF_RDI(%rsp), %rdi		/* format */
49291eaf3e1SJohn Birrell	movq	REGOFF_RSI(%rsp), %rsi		/* alist */
49391eaf3e1SJohn Birrell	movq	%rsp, %rdx			/* struct regs */
49491eaf3e1SJohn Birrell	movl	%r11d, %ecx			/* on_panic_stack */
49591eaf3e1SJohn Birrell	call	panicsys
49691eaf3e1SJohn Birrell	addq	$REGSIZE, %rsp
49791eaf3e1SJohn Birrell#endif
49891eaf3e1SJohn Birrell	popq	%rdi
49991eaf3e1SJohn Birrell	popq	%rsi
50091eaf3e1SJohn Birrell	popq	%rdx
50191eaf3e1SJohn Birrell	popq	%rcx
50291eaf3e1SJohn Birrell	popq	%r8
50391eaf3e1SJohn Birrell	popq	%r9
50491eaf3e1SJohn Birrell	popq	%rax
50591eaf3e1SJohn Birrell	popq	%rbx
50691eaf3e1SJohn Birrell	popq	%r10
50791eaf3e1SJohn Birrell	popq	%r11
50891eaf3e1SJohn Birrell	popfq
50991eaf3e1SJohn Birrell	leave
51091eaf3e1SJohn Birrell	ret
51191eaf3e1SJohn Birrell	END(vpanic)
51291eaf3e1SJohn Birrell
51391eaf3e1SJohn Birrell/*
51491eaf3e1SJohn Birrellvoid
51591eaf3e1SJohn Birrelldtrace_vpanic(const char *format, va_list alist)
51691eaf3e1SJohn Birrell*/
51791eaf3e1SJohn Birrell	ENTRY(dtrace_vpanic)			/* Initial stack layout: */
51891eaf3e1SJohn Birrell
51991eaf3e1SJohn Birrell	pushq	%rbp				/* | %rip | 	0x60	*/
52091eaf3e1SJohn Birrell	movq	%rsp, %rbp			/* | %rbp |	0x58	*/
52191eaf3e1SJohn Birrell	pushfq					/* | rfl  |	0x50	*/
52291eaf3e1SJohn Birrell	pushq	%r11				/* | %r11 |	0x48	*/
52391eaf3e1SJohn Birrell	pushq	%r10				/* | %r10 |	0x40	*/
52491eaf3e1SJohn Birrell	pushq	%rbx				/* | %rbx |	0x38	*/
52591eaf3e1SJohn Birrell	pushq	%rax				/* | %rax |	0x30	*/
52691eaf3e1SJohn Birrell	pushq	%r9				/* | %r9  |	0x28	*/
52791eaf3e1SJohn Birrell	pushq	%r8				/* | %r8  |	0x20	*/
52891eaf3e1SJohn Birrell	pushq	%rcx				/* | %rcx |	0x18	*/
52991eaf3e1SJohn Birrell	pushq	%rdx				/* | %rdx |	0x10	*/
53091eaf3e1SJohn Birrell	pushq	%rsi				/* | %rsi |	0x8 alist */
53191eaf3e1SJohn Birrell	pushq	%rdi				/* | %rdi |	0x0 format */
53291eaf3e1SJohn Birrell
53391eaf3e1SJohn Birrell	movq	%rsp, %rbx			/* %rbx = current %rsp */
53491eaf3e1SJohn Birrell
53591eaf3e1SJohn Birrell	leaq	panic_quiesce(%rip), %rdi	/* %rdi = &panic_quiesce */
53691eaf3e1SJohn Birrell	call	dtrace_panic_trigger	/* %eax = dtrace_panic_trigger() */
53791eaf3e1SJohn Birrell	jmp	vpanic_common
53891eaf3e1SJohn Birrell
53991eaf3e1SJohn Birrell	END(dtrace_vpanic)
54091eaf3e1SJohn Birrell
54191eaf3e1SJohn Birrell/*
54291eaf3e1SJohn Birrellint
54391eaf3e1SJohn Birrellpanic_trigger(int *tp)
54491eaf3e1SJohn Birrell*/
54591eaf3e1SJohn Birrell	ENTRY(panic_trigger)
54691eaf3e1SJohn Birrell	xorl	%eax, %eax
54791eaf3e1SJohn Birrell	movl	$0xdefacedd, %edx
54891eaf3e1SJohn Birrell	lock
54991eaf3e1SJohn Birrell	  xchgl	%edx, (%rdi)
55091eaf3e1SJohn Birrell	cmpl	$0, %edx
55191eaf3e1SJohn Birrell	je	0f
55291eaf3e1SJohn Birrell	movl	$0, %eax
55391eaf3e1SJohn Birrell	ret
55491eaf3e1SJohn Birrell0:	movl	$1, %eax
55591eaf3e1SJohn Birrell	ret
55691eaf3e1SJohn Birrell	END(panic_trigger)
55791eaf3e1SJohn Birrell
55891eaf3e1SJohn Birrell/*
55991eaf3e1SJohn Birrellint
56091eaf3e1SJohn Birrelldtrace_panic_trigger(int *tp)
56191eaf3e1SJohn Birrell*/
56291eaf3e1SJohn Birrell	ENTRY(dtrace_panic_trigger)
56391eaf3e1SJohn Birrell	xorl	%eax, %eax
56491eaf3e1SJohn Birrell	movl	$0xdefacedd, %edx
56591eaf3e1SJohn Birrell	lock
56691eaf3e1SJohn Birrell	  xchgl	%edx, (%rdi)
56791eaf3e1SJohn Birrell	cmpl	$0, %edx
56891eaf3e1SJohn Birrell	je	0f
56991eaf3e1SJohn Birrell	movl	$0, %eax
57091eaf3e1SJohn Birrell	ret
57191eaf3e1SJohn Birrell0:	movl	$1, %eax
57291eaf3e1SJohn Birrell	ret
57391eaf3e1SJohn Birrell	END(dtrace_panic_trigger)
574