xref: /freebsd/sys/cddl/dev/dtrace/i386/dtrace_asm.S (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
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, Version 1.0 only
691eaf3e1SJohn Birrell * (the "License").  You may not use this file except in compliance
791eaf3e1SJohn Birrell * with the License.
891eaf3e1SJohn Birrell *
991eaf3e1SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1091eaf3e1SJohn Birrell * or http://www.opensolaris.org/os/licensing.
1191eaf3e1SJohn Birrell * See the License for the specific language governing permissions
1291eaf3e1SJohn Birrell * and limitations under the License.
1391eaf3e1SJohn Birrell *
1491eaf3e1SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each
1591eaf3e1SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1691eaf3e1SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the
1791eaf3e1SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying
1891eaf3e1SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner]
1991eaf3e1SJohn Birrell *
2091eaf3e1SJohn Birrell * CDDL HEADER END
2191eaf3e1SJohn Birrell */
2291eaf3e1SJohn Birrell/*
2391eaf3e1SJohn Birrell * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
2491eaf3e1SJohn Birrell * Use is subject to license terms.
2591eaf3e1SJohn Birrell */
2691eaf3e1SJohn Birrell
2791eaf3e1SJohn Birrell#define _ASM
2891eaf3e1SJohn Birrell
2991eaf3e1SJohn Birrell#include <machine/asmacros.h>
3091eaf3e1SJohn Birrell#include <sys/cpuvar_defs.h>
3191eaf3e1SJohn Birrell#include <sys/dtrace.h>
3291eaf3e1SJohn Birrell
33*fc2a8776SEd Maste#include "assym.inc"
3491eaf3e1SJohn Birrell
3591eaf3e1SJohn Birrell	ENTRY(dtrace_invop_start)
3691eaf3e1SJohn Birrell
3791eaf3e1SJohn Birrell	pushl	%eax			/* push %eax -- may be return value */
3891eaf3e1SJohn Birrell	pushl	%esp			/* push stack pointer */
396c280659SMark Johnston	subl	$8, (%esp)		/* skip first arg and segment regs */
4091eaf3e1SJohn Birrell	pushl	40(%esp)		/* push calling EIP */
4191eaf3e1SJohn Birrell
4291eaf3e1SJohn Birrell	/*
4391eaf3e1SJohn Birrell	 * Call dtrace_invop to let it check if the exception was
4491eaf3e1SJohn Birrell	 * a fbt one. The return value in %eax will tell us what
4591eaf3e1SJohn Birrell	 * dtrace_invop wants us to do.
4691eaf3e1SJohn Birrell	 */
4791eaf3e1SJohn Birrell	call	dtrace_invop
4891eaf3e1SJohn Birrell	ALTENTRY(dtrace_invop_callsite)
49efa1aff6SMark Johnston	addl	$12, %esp
5091eaf3e1SJohn Birrell	cmpl	$DTRACE_INVOP_PUSHL_EBP, %eax
5191eaf3e1SJohn Birrell	je	invop_push
5291eaf3e1SJohn Birrell	cmpl	$DTRACE_INVOP_POPL_EBP, %eax
5391eaf3e1SJohn Birrell	je	invop_pop
5491eaf3e1SJohn Birrell	cmpl	$DTRACE_INVOP_LEAVE, %eax
5591eaf3e1SJohn Birrell	je	invop_leave
5691eaf3e1SJohn Birrell	cmpl	$DTRACE_INVOP_NOP, %eax
5791eaf3e1SJohn Birrell	je	invop_nop
5891eaf3e1SJohn Birrell
5991eaf3e1SJohn Birrell	/* When all else fails handle the trap in the usual way. */
6091eaf3e1SJohn Birrell	jmpl	*dtrace_invop_calltrap_addr
6191eaf3e1SJohn Birrell
6291eaf3e1SJohn Birrellinvop_push:
6391eaf3e1SJohn Birrell	/*
6491eaf3e1SJohn Birrell	 * We must emulate a "pushl %ebp".  To do this, we pull the stack
6591eaf3e1SJohn Birrell	 * down 4 bytes, and then store the base pointer.
6691eaf3e1SJohn Birrell	 */
6791eaf3e1SJohn Birrell	popal
6891eaf3e1SJohn Birrell	subl	$4, %esp		/* make room for %ebp */
6991eaf3e1SJohn Birrell	pushl	%eax			/* push temp */
7091eaf3e1SJohn Birrell	movl	8(%esp), %eax		/* load calling EIP */
7191eaf3e1SJohn Birrell	incl	%eax			/* increment over LOCK prefix */
7291eaf3e1SJohn Birrell	movl	%eax, 4(%esp)		/* store calling EIP */
7391eaf3e1SJohn Birrell	movl	12(%esp), %eax		/* load calling CS */
7491eaf3e1SJohn Birrell	movl	%eax, 8(%esp)		/* store calling CS */
7591eaf3e1SJohn Birrell	movl	16(%esp), %eax		/* load calling EFLAGS */
7691eaf3e1SJohn Birrell	movl	%eax, 12(%esp)		/* store calling EFLAGS */
7791eaf3e1SJohn Birrell	movl	%ebp, 16(%esp)		/* push %ebp */
7891eaf3e1SJohn Birrell	popl	%eax			/* pop off temp */
7991eaf3e1SJohn Birrell	iret				/* Return from interrupt. */
8091eaf3e1SJohn Birrellinvop_pop:
8191eaf3e1SJohn Birrell	/*
8291eaf3e1SJohn Birrell	 * We must emulate a "popl %ebp".  To do this, we do the opposite of
8391eaf3e1SJohn Birrell	 * the above:  we remove the %ebp from the stack, and squeeze up the
8491eaf3e1SJohn Birrell	 * saved state from the trap.
8591eaf3e1SJohn Birrell	 */
8691eaf3e1SJohn Birrell	popal
8791eaf3e1SJohn Birrell	pushl	%eax			/* push temp */
8891eaf3e1SJohn Birrell	movl	16(%esp), %ebp		/* pop %ebp */
8991eaf3e1SJohn Birrell	movl	12(%esp), %eax		/* load calling EFLAGS */
9091eaf3e1SJohn Birrell	movl	%eax, 16(%esp)		/* store calling EFLAGS */
9191eaf3e1SJohn Birrell	movl	8(%esp), %eax		/* load calling CS */
9291eaf3e1SJohn Birrell	movl	%eax, 12(%esp)		/* store calling CS */
9391eaf3e1SJohn Birrell	movl	4(%esp), %eax		/* load calling EIP */
9491eaf3e1SJohn Birrell	incl	%eax			/* increment over LOCK prefix */
9591eaf3e1SJohn Birrell	movl	%eax, 8(%esp)		/* store calling EIP */
9691eaf3e1SJohn Birrell	popl	%eax			/* pop off temp */
9791eaf3e1SJohn Birrell	addl	$4, %esp		/* adjust stack pointer */
9891eaf3e1SJohn Birrell	iret				/* Return from interrupt. */
9991eaf3e1SJohn Birrellinvop_leave:
10091eaf3e1SJohn Birrell	/*
10191eaf3e1SJohn Birrell	 * We must emulate a "leave", which is the same as a "movl %ebp, %esp"
10291eaf3e1SJohn Birrell	 * followed by a "popl %ebp".  This looks similar to the above, but
10391eaf3e1SJohn Birrell	 * requires two temporaries:  one for the new base pointer, and one
10491eaf3e1SJohn Birrell	 * for the staging register.
10591eaf3e1SJohn Birrell	 */
10691eaf3e1SJohn Birrell	popa
10791eaf3e1SJohn Birrell	pushl	%eax			/* push temp */
10891eaf3e1SJohn Birrell	pushl	%ebx			/* push temp */
10991eaf3e1SJohn Birrell	movl	%ebp, %ebx		/* set temp to old %ebp */
11091eaf3e1SJohn Birrell	movl	(%ebx), %ebp		/* pop %ebp */
11191eaf3e1SJohn Birrell	movl	16(%esp), %eax		/* load calling EFLAGS */
11291eaf3e1SJohn Birrell	movl	%eax, (%ebx)		/* store calling EFLAGS */
11391eaf3e1SJohn Birrell	movl	12(%esp), %eax		/* load calling CS */
11491eaf3e1SJohn Birrell	movl	%eax, -4(%ebx)		/* store calling CS */
11591eaf3e1SJohn Birrell	movl	8(%esp), %eax		/* load calling EIP */
11691eaf3e1SJohn Birrell	incl	%eax			/* increment over LOCK prefix */
11791eaf3e1SJohn Birrell	movl	%eax, -8(%ebx)		/* store calling EIP */
118cddcb8b4SRyan Stone	subl	$8, %ebx		/* adjust for three pushes, one pop */
119cddcb8b4SRyan Stone	movl	%ebx, 8(%esp)		/* temporarily store new %esp */
12091eaf3e1SJohn Birrell	popl	%ebx			/* pop off temp */
12191eaf3e1SJohn Birrell	popl	%eax			/* pop off temp */
122cddcb8b4SRyan Stone	movl	(%esp), %esp		/* set stack pointer */
12391eaf3e1SJohn Birrell	iret				/* return from interrupt */
12491eaf3e1SJohn Birrellinvop_nop:
12591eaf3e1SJohn Birrell	/*
12691eaf3e1SJohn Birrell	 * We must emulate a "nop".  This is obviously not hard:  we need only
12791eaf3e1SJohn Birrell	 * advance the %eip by one.
12891eaf3e1SJohn Birrell	 */
12991eaf3e1SJohn Birrell	popa
13091eaf3e1SJohn Birrell	incl	(%esp)
13191eaf3e1SJohn Birrell	iret				/* return from interrupt */
13291eaf3e1SJohn Birrell
13391eaf3e1SJohn Birrell	END(dtrace_invop_start)
13491eaf3e1SJohn Birrell
13591eaf3e1SJohn Birrell/*
13691eaf3e1SJohn Birrellgreg_t dtrace_getfp(void)
13791eaf3e1SJohn Birrell*/
13891eaf3e1SJohn Birrell
13991eaf3e1SJohn Birrell	ENTRY(dtrace_getfp)
14091eaf3e1SJohn Birrell	movl	%ebp, %eax
14191eaf3e1SJohn Birrell	ret
14291eaf3e1SJohn Birrell	END(dtrace_getfp)
14391eaf3e1SJohn Birrell
14491eaf3e1SJohn Birrell/*
14591eaf3e1SJohn Birrelluint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
14691eaf3e1SJohn Birrell*/
14791eaf3e1SJohn Birrell
14891eaf3e1SJohn Birrell	ENTRY(dtrace_cas32)
14991eaf3e1SJohn Birrell	ALTENTRY(dtrace_casptr)
15091eaf3e1SJohn Birrell	movl	4(%esp), %edx
15191eaf3e1SJohn Birrell	movl	8(%esp), %eax
15291eaf3e1SJohn Birrell	movl	12(%esp), %ecx
15391eaf3e1SJohn Birrell	lock
15491eaf3e1SJohn Birrell	cmpxchgl %ecx, (%edx)
15591eaf3e1SJohn Birrell	ret
15691eaf3e1SJohn Birrell	END(dtrace_casptr)
15791eaf3e1SJohn Birrell	END(dtrace_cas32)
15891eaf3e1SJohn Birrell
15991eaf3e1SJohn Birrell/*
16091eaf3e1SJohn Birrelluintptr_t dtrace_caller(int aframes)
16191eaf3e1SJohn Birrell*/
16291eaf3e1SJohn Birrell
16391eaf3e1SJohn Birrell	ENTRY(dtrace_caller)
16491eaf3e1SJohn Birrell	movl	$-1, %eax
16591eaf3e1SJohn Birrell	ret
16691eaf3e1SJohn Birrell	END(dtrace_caller)
16791eaf3e1SJohn Birrell
16891eaf3e1SJohn Birrell/*
16991eaf3e1SJohn Birrellvoid dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
17091eaf3e1SJohn Birrell*/
17191eaf3e1SJohn Birrell
17291eaf3e1SJohn Birrell	ENTRY(dtrace_copy)
17391eaf3e1SJohn Birrell	pushl	%ebp
17491eaf3e1SJohn Birrell	movl	%esp, %ebp
17591eaf3e1SJohn Birrell	pushl	%esi
17691eaf3e1SJohn Birrell	pushl	%edi
17791eaf3e1SJohn Birrell
17891eaf3e1SJohn Birrell	movl	8(%ebp), %esi		/* Load source address */
17991eaf3e1SJohn Birrell	movl	12(%ebp), %edi		/* Load destination address */
18091eaf3e1SJohn Birrell	movl	16(%ebp), %ecx		/* Load count */
18191eaf3e1SJohn Birrell	repz				/* Repeat for count... */
18291eaf3e1SJohn Birrell	smovb				/*   move from %ds:si to %es:di */
18391eaf3e1SJohn Birrell
18491eaf3e1SJohn Birrell	popl	%edi
18591eaf3e1SJohn Birrell	popl	%esi
18691eaf3e1SJohn Birrell	movl	%ebp, %esp
18791eaf3e1SJohn Birrell	popl	%ebp
18891eaf3e1SJohn Birrell	ret
18991eaf3e1SJohn Birrell	END(dtrace_copy)
19091eaf3e1SJohn Birrell
19191eaf3e1SJohn Birrell/*
19291eaf3e1SJohn Birrellvoid dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size)
19391eaf3e1SJohn Birrell*/
19491eaf3e1SJohn Birrell
19591eaf3e1SJohn Birrell	ENTRY(dtrace_copystr)
19691eaf3e1SJohn Birrell
19791eaf3e1SJohn Birrell	pushl	%ebp			/* Setup stack frame */
19891eaf3e1SJohn Birrell	movl	%esp, %ebp
19991eaf3e1SJohn Birrell	pushl	%ebx			/* Save registers */
20091eaf3e1SJohn Birrell
20191eaf3e1SJohn Birrell	movl	8(%ebp), %ebx		/* Load source address */
20291eaf3e1SJohn Birrell	movl	12(%ebp), %edx		/* Load destination address */
20391eaf3e1SJohn Birrell	movl	16(%ebp), %ecx		/* Load count */
20491eaf3e1SJohn Birrell
20591eaf3e1SJohn Birrell0:
20691eaf3e1SJohn Birrell	movb	(%ebx), %al		/* Load from source */
20791eaf3e1SJohn Birrell	movb	%al, (%edx)		/* Store to destination */
20891eaf3e1SJohn Birrell	incl	%ebx			/* Increment source pointer */
20991eaf3e1SJohn Birrell	incl	%edx			/* Increment destination pointer */
21091eaf3e1SJohn Birrell	decl	%ecx			/* Decrement remaining count */
21191eaf3e1SJohn Birrell	cmpb	$0, %al
21291eaf3e1SJohn Birrell	je	1f
21391eaf3e1SJohn Birrell	cmpl	$0, %ecx
21491eaf3e1SJohn Birrell	jne	0b
21591eaf3e1SJohn Birrell
21691eaf3e1SJohn Birrell1:
21791eaf3e1SJohn Birrell	popl	%ebx
21891eaf3e1SJohn Birrell	movl	%ebp, %esp
21991eaf3e1SJohn Birrell	popl	%ebp
22091eaf3e1SJohn Birrell	ret
22191eaf3e1SJohn Birrell
22291eaf3e1SJohn Birrell	END(dtrace_copystr)
22391eaf3e1SJohn Birrell
22491eaf3e1SJohn Birrell/*
22591eaf3e1SJohn Birrelluintptr_t dtrace_fulword(void *addr)
22691eaf3e1SJohn Birrell*/
22791eaf3e1SJohn Birrell
22891eaf3e1SJohn Birrell	ENTRY(dtrace_fulword)
22991eaf3e1SJohn Birrell	movl	4(%esp), %ecx
23091eaf3e1SJohn Birrell	xorl	%eax, %eax
23191eaf3e1SJohn Birrell	movl	(%ecx), %eax
23291eaf3e1SJohn Birrell	ret
23391eaf3e1SJohn Birrell	END(dtrace_fulword)
23491eaf3e1SJohn Birrell
23591eaf3e1SJohn Birrell/*
23691eaf3e1SJohn Birrelluint8_t dtrace_fuword8_nocheck(void *addr)
23791eaf3e1SJohn Birrell*/
23891eaf3e1SJohn Birrell
23991eaf3e1SJohn Birrell	ENTRY(dtrace_fuword8_nocheck)
24091eaf3e1SJohn Birrell	movl	4(%esp), %ecx
24191eaf3e1SJohn Birrell	xorl	%eax, %eax
24291eaf3e1SJohn Birrell	movzbl	(%ecx), %eax
24391eaf3e1SJohn Birrell	ret
24491eaf3e1SJohn Birrell	END(dtrace_fuword8_nocheck)
24591eaf3e1SJohn Birrell
24691eaf3e1SJohn Birrell/*
24791eaf3e1SJohn Birrelluint16_t dtrace_fuword16_nocheck(void *addr)
24891eaf3e1SJohn Birrell*/
24991eaf3e1SJohn Birrell
25091eaf3e1SJohn Birrell	ENTRY(dtrace_fuword16_nocheck)
25191eaf3e1SJohn Birrell	movl	4(%esp), %ecx
25291eaf3e1SJohn Birrell	xorl	%eax, %eax
25391eaf3e1SJohn Birrell	movzwl	(%ecx), %eax
25491eaf3e1SJohn Birrell	ret
25591eaf3e1SJohn Birrell	END(dtrace_fuword16_nocheck)
25691eaf3e1SJohn Birrell
25791eaf3e1SJohn Birrell/*
25891eaf3e1SJohn Birrelluint32_t dtrace_fuword32_nocheck(void *addr)
25991eaf3e1SJohn Birrell*/
26091eaf3e1SJohn Birrell
26191eaf3e1SJohn Birrell	ENTRY(dtrace_fuword32_nocheck)
26291eaf3e1SJohn Birrell	movl	4(%esp), %ecx
26391eaf3e1SJohn Birrell	xorl	%eax, %eax
26491eaf3e1SJohn Birrell	movl	(%ecx), %eax
26591eaf3e1SJohn Birrell	ret
26691eaf3e1SJohn Birrell	END(dtrace_fuword32_nocheck)
26791eaf3e1SJohn Birrell
26891eaf3e1SJohn Birrell/*
26991eaf3e1SJohn Birrelluint64_t dtrace_fuword64_nocheck(void *addr)
27091eaf3e1SJohn Birrell*/
27191eaf3e1SJohn Birrell
27291eaf3e1SJohn Birrell	ENTRY(dtrace_fuword64_nocheck)
27391eaf3e1SJohn Birrell	movl	4(%esp), %ecx
27491eaf3e1SJohn Birrell	xorl	%eax, %eax
27591eaf3e1SJohn Birrell	xorl	%edx, %edx
27691eaf3e1SJohn Birrell	movl	(%ecx), %eax
27791eaf3e1SJohn Birrell	movl	4(%ecx), %edx
27891eaf3e1SJohn Birrell	ret
27991eaf3e1SJohn Birrell	END(dtrace_fuword64_nocheck)
28091eaf3e1SJohn Birrell
28191eaf3e1SJohn Birrell/*
28291eaf3e1SJohn Birrellvoid dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval)
28391eaf3e1SJohn Birrell*/
28491eaf3e1SJohn Birrell
28591eaf3e1SJohn Birrell	ENTRY(dtrace_probe_error)
28691eaf3e1SJohn Birrell	pushl	%ebp
28791eaf3e1SJohn Birrell	movl	%esp, %ebp
28891eaf3e1SJohn Birrell	pushl	0x1c(%ebp)
28991eaf3e1SJohn Birrell	pushl	0x18(%ebp)
29091eaf3e1SJohn Birrell	pushl	0x14(%ebp)
29191eaf3e1SJohn Birrell	pushl	0x10(%ebp)
29291eaf3e1SJohn Birrell	pushl	0xc(%ebp)
29391eaf3e1SJohn Birrell	pushl	0x8(%ebp)
29491eaf3e1SJohn Birrell	pushl	dtrace_probeid_error
29591eaf3e1SJohn Birrell	call	dtrace_probe
29691eaf3e1SJohn Birrell	movl	%ebp, %esp
29791eaf3e1SJohn Birrell	popl	%ebp
29891eaf3e1SJohn Birrell	ret
29991eaf3e1SJohn Birrell	END(dtrace_probe_error)
30091eaf3e1SJohn Birrell
30191eaf3e1SJohn Birrell/*
30291eaf3e1SJohn Birrellvoid dtrace_membar_producer(void)
30391eaf3e1SJohn Birrell*/
30491eaf3e1SJohn Birrell
30591eaf3e1SJohn Birrell	ENTRY(dtrace_membar_producer)
30691eaf3e1SJohn Birrell	rep;	ret	/* use 2 byte return instruction when branch target */
30791eaf3e1SJohn Birrell			/* AMD Software Optimization Guide - Section 6.2 */
30891eaf3e1SJohn Birrell	END(dtrace_membar_producer)
30991eaf3e1SJohn Birrell
31091eaf3e1SJohn Birrell/*
31191eaf3e1SJohn Birrellvoid dtrace_membar_consumer(void)
31291eaf3e1SJohn Birrell*/
31391eaf3e1SJohn Birrell
31491eaf3e1SJohn Birrell	ENTRY(dtrace_membar_consumer)
31591eaf3e1SJohn Birrell	rep;	ret	/* use 2 byte return instruction when branch target */
31691eaf3e1SJohn Birrell			/* AMD Software Optimization Guide - Section 6.2 */
31791eaf3e1SJohn Birrell	END(dtrace_membar_consumer)
31891eaf3e1SJohn Birrell
31991eaf3e1SJohn Birrell/*
32091eaf3e1SJohn Birrelldtrace_icookie_t dtrace_interrupt_disable(void)
32191eaf3e1SJohn Birrell*/
32291eaf3e1SJohn Birrell	ENTRY(dtrace_interrupt_disable)
32391eaf3e1SJohn Birrell	pushfl
32491eaf3e1SJohn Birrell	popl	%eax
32591eaf3e1SJohn Birrell	cli
32691eaf3e1SJohn Birrell	ret
32791eaf3e1SJohn Birrell	END(dtrace_interrupt_disable)
32891eaf3e1SJohn Birrell
32991eaf3e1SJohn Birrell/*
33091eaf3e1SJohn Birrellvoid dtrace_interrupt_enable(dtrace_icookie_t cookie)
33191eaf3e1SJohn Birrell*/
33291eaf3e1SJohn Birrell	ENTRY(dtrace_interrupt_enable)
33391eaf3e1SJohn Birrell	movl	4(%esp), %eax
33491eaf3e1SJohn Birrell	pushl	%eax
33591eaf3e1SJohn Birrell	popfl
33691eaf3e1SJohn Birrell	ret
33791eaf3e1SJohn Birrell	END(dtrace_interrupt_enable)
338