aboutsummaryrefslogtreecommitdiff
path: root/sys/cddl/dev/dtrace/amd64/dtrace_asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cddl/dev/dtrace/amd64/dtrace_asm.S')
-rw-r--r--sys/cddl/dev/dtrace/amd64/dtrace_asm.S53
1 files changed, 49 insertions, 4 deletions
diff --git a/sys/cddl/dev/dtrace/amd64/dtrace_asm.S b/sys/cddl/dev/dtrace/amd64/dtrace_asm.S
index 9a83c87dda02..0c8cd9a83d01 100644
--- a/sys/cddl/dev/dtrace/amd64/dtrace_asm.S
+++ b/sys/cddl/dev/dtrace/amd64/dtrace_asm.S
@@ -20,8 +20,6 @@
*
* Portions Copyright 2008 John Birrell <jb@freebsd.org>
*
- * $FreeBSD$
- *
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
@@ -58,6 +56,8 @@
swapgs; \
1: addq $TF_RIP,%rsp;
+.globl dtrace_invop_callsite
+.type dtrace_invop_callsite,@function
ENTRY(dtrace_invop_start)
@@ -69,11 +69,22 @@
movq TF_RIP(%rsp), %rdi
decq %rdi
movq %rsp, %rsi
- movq TF_RAX(%rsp), %rdx
+
+ /*
+ * Allocate some scratch space to let the invop handler return a value.
+ * This is needed when emulating "call" instructions.
+ */
+ subq $16, %rsp
+ movq %rsp, %rdx
+
call dtrace_invop
- ENTRY(dtrace_invop_callsite)
+dtrace_invop_callsite:
+ addq $16, %rsp
+
cmpl $DTRACE_INVOP_PUSHL_EBP, %eax
je bp_push
+ cmpl $DTRACE_INVOP_CALL, %eax
+ je bp_call
cmpl $DTRACE_INVOP_LEAVE, %eax
je bp_leave
cmpl $DTRACE_INVOP_NOP, %eax
@@ -109,6 +120,40 @@ bp_push:
iretq /* return from interrupt */
/*NOTREACHED*/
+bp_call:
+ /*
+ * Emulate a "call" instruction. The invop handler must have already
+ * updated the saved copy of %rip in the register set. It's our job to
+ * pull the hardware-saved registers down to make space for the return
+ * address, which is provided by the invop handler in our scratch
+ * space.
+ */
+ INTR_POP
+ subq $16, %rsp /* make room for %rbp */
+ pushq %rax /* push temp */
+ pushq %rbx /* push temp */
+
+ movq 32(%rsp), %rax /* load calling RIP */
+ movq %rax, 16(%rsp) /* store calling RIP */
+ movq 40(%rsp), %rax /* load calling CS */
+ movq %rax, 24(%rsp) /* store calling CS */
+ movq 48(%rsp), %rax /* load calling RFLAGS */
+ movq %rax, 32(%rsp) /* store calling RFLAGS */
+ movq 56(%rsp), %rax /* load calling RSP */
+ subq $8, %rax /* make room for return address */
+ movq %rax, 40(%rsp) /* store calling RSP */
+ movq 64(%rsp), %rax /* load calling SS */
+ movq %rax, 48(%rsp) /* store calling SS */
+
+ movq -(TF_RIP - 16)(%rsp), %rax /* load return address */
+ movq 40(%rsp), %rbx /* reload calling RSP */
+ movq %rax, (%rbx) /* store return address */
+
+ popq %rbx /* pop temp */
+ popq %rax /* pop temp */
+ iretq /* return from interrupt */
+ /*NOTREACHED*/
+
bp_leave:
/*
* We must emulate a "leave", which is the same as a "movq %rbp, %rsp"