dtrace_asm.S revision 283676
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 *
22 * $FreeBSD: stable/10/sys/cddl/dev/dtrace/i386/dtrace_asm.S 283676 2015-05-29 04:01:39Z markj $
23 */
24/*
25 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
26 * Use is subject to license terms.
27 */
28
29#define _ASM
30
31#include <machine/asmacros.h>
32#include <sys/cpuvar_defs.h>
33#include <sys/dtrace.h>
34
35#include "assym.s"
36
37	.globl	calltrap
38	.type	calltrap,@function
39	ENTRY(dtrace_invop_start)
40
41	pushl	%eax			/* push %eax -- may be return value */
42	pushl	%esp			/* push stack pointer */
43	addl	$48, (%esp)		/* adjust to incoming args */
44	pushl	40(%esp)		/* push calling EIP */
45
46	/*
47	 * Call dtrace_invop to let it check if the exception was
48	 * a fbt one. The return value in %eax will tell us what
49	 * dtrace_invop wants us to do.
50	 */
51	call	dtrace_invop
52	ALTENTRY(dtrace_invop_callsite)
53	addl	$12, %esp
54	cmpl	$DTRACE_INVOP_PUSHL_EBP, %eax
55	je	invop_push
56	cmpl	$DTRACE_INVOP_POPL_EBP, %eax
57	je	invop_pop
58	cmpl	$DTRACE_INVOP_LEAVE, %eax
59	je	invop_leave
60	cmpl	$DTRACE_INVOP_NOP, %eax
61	je	invop_nop
62
63	/* When all else fails handle the trap in the usual way. */
64	jmpl	*dtrace_invop_calltrap_addr
65
66invop_push:
67	/*
68	 * We must emulate a "pushl %ebp".  To do this, we pull the stack
69	 * down 4 bytes, and then store the base pointer.
70	 */
71	popal
72	subl	$4, %esp		/* make room for %ebp */
73	pushl	%eax			/* push temp */
74	movl	8(%esp), %eax		/* load calling EIP */
75	incl	%eax			/* increment over LOCK prefix */
76	movl	%eax, 4(%esp)		/* store calling EIP */
77	movl	12(%esp), %eax		/* load calling CS */
78	movl	%eax, 8(%esp)		/* store calling CS */
79	movl	16(%esp), %eax		/* load calling EFLAGS */
80	movl	%eax, 12(%esp)		/* store calling EFLAGS */
81	movl	%ebp, 16(%esp)		/* push %ebp */
82	popl	%eax			/* pop off temp */
83	iret				/* Return from interrupt. */
84invop_pop:
85	/*
86	 * We must emulate a "popl %ebp".  To do this, we do the opposite of
87	 * the above:  we remove the %ebp from the stack, and squeeze up the
88	 * saved state from the trap.
89	 */
90	popal
91	pushl	%eax			/* push temp */
92	movl	16(%esp), %ebp		/* pop %ebp */
93	movl	12(%esp), %eax		/* load calling EFLAGS */
94	movl	%eax, 16(%esp)		/* store calling EFLAGS */
95	movl	8(%esp), %eax		/* load calling CS */
96	movl	%eax, 12(%esp)		/* store calling CS */
97	movl	4(%esp), %eax		/* load calling EIP */
98	incl	%eax			/* increment over LOCK prefix */
99	movl	%eax, 8(%esp)		/* store calling EIP */
100	popl	%eax			/* pop off temp */
101	addl	$4, %esp		/* adjust stack pointer */
102	iret				/* Return from interrupt. */
103invop_leave:
104	/*
105	 * We must emulate a "leave", which is the same as a "movl %ebp, %esp"
106	 * followed by a "popl %ebp".  This looks similar to the above, but
107	 * requires two temporaries:  one for the new base pointer, and one
108	 * for the staging register.
109	 */
110	popa
111	pushl	%eax			/* push temp */
112	pushl	%ebx			/* push temp */
113	movl	%ebp, %ebx		/* set temp to old %ebp */
114	movl	(%ebx), %ebp		/* pop %ebp */
115	movl	16(%esp), %eax		/* load calling EFLAGS */
116	movl	%eax, (%ebx)		/* store calling EFLAGS */
117	movl	12(%esp), %eax		/* load calling CS */
118	movl	%eax, -4(%ebx)		/* store calling CS */
119	movl	8(%esp), %eax		/* load calling EIP */
120	incl	%eax			/* increment over LOCK prefix */
121	movl	%eax, -8(%ebx)		/* store calling EIP */
122	subl	$8, %ebx		/* adjust for three pushes, one pop */
123	movl	%ebx, 8(%esp)		/* temporarily store new %esp */
124	popl	%ebx			/* pop off temp */
125	popl	%eax			/* pop off temp */
126	movl	(%esp), %esp		/* set stack pointer */
127	iret				/* return from interrupt */
128invop_nop:
129	/*
130	 * We must emulate a "nop".  This is obviously not hard:  we need only
131	 * advance the %eip by one.
132	 */
133	popa
134	incl	(%esp)
135	iret				/* return from interrupt */
136
137	END(dtrace_invop_start)
138
139/*
140void dtrace_invop_init(void)
141*/
142	ENTRY(dtrace_invop_init)
143	movl	$dtrace_invop_start, dtrace_invop_jump_addr
144	ret
145	END(dtrace_invop_init)
146
147/*
148void dtrace_invop_uninit(void)
149*/
150	ENTRY(dtrace_invop_uninit)
151	movl	$0, dtrace_invop_jump_addr
152	ret
153	END(dtrace_invop_uninit)
154
155/*
156greg_t dtrace_getfp(void)
157*/
158
159	ENTRY(dtrace_getfp)
160	movl	%ebp, %eax
161	ret
162	END(dtrace_getfp)
163
164/*
165uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
166*/
167
168	ENTRY(dtrace_cas32)
169	ALTENTRY(dtrace_casptr)
170	movl	4(%esp), %edx
171	movl	8(%esp), %eax
172	movl	12(%esp), %ecx
173	lock
174	cmpxchgl %ecx, (%edx)
175	ret
176	END(dtrace_casptr)
177	END(dtrace_cas32)
178
179/*
180uintptr_t dtrace_caller(int aframes)
181*/
182
183	ENTRY(dtrace_caller)
184	movl	$-1, %eax
185	ret
186	END(dtrace_caller)
187
188/*
189void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
190*/
191
192	ENTRY(dtrace_copy)
193	pushl	%ebp
194	movl	%esp, %ebp
195	pushl	%esi
196	pushl	%edi
197
198	movl	8(%ebp), %esi		/* Load source address */
199	movl	12(%ebp), %edi		/* Load destination address */
200	movl	16(%ebp), %ecx		/* Load count */
201	repz				/* Repeat for count... */
202	smovb				/*   move from %ds:si to %es:di */
203
204	popl	%edi
205	popl	%esi
206	movl	%ebp, %esp
207	popl	%ebp
208	ret
209	END(dtrace_copy)
210
211/*
212void dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size)
213*/
214
215	ENTRY(dtrace_copystr)
216
217	pushl	%ebp			/* Setup stack frame */
218	movl	%esp, %ebp
219	pushl	%ebx			/* Save registers */
220
221	movl	8(%ebp), %ebx		/* Load source address */
222	movl	12(%ebp), %edx		/* Load destination address */
223	movl	16(%ebp), %ecx		/* Load count */
224
2250:
226	movb	(%ebx), %al		/* Load from source */
227	movb	%al, (%edx)		/* Store to destination */
228	incl	%ebx			/* Increment source pointer */
229	incl	%edx			/* Increment destination pointer */
230	decl	%ecx			/* Decrement remaining count */
231	cmpb	$0, %al
232	je	1f
233	cmpl	$0, %ecx
234	jne	0b
235
2361:
237	popl	%ebx
238	movl	%ebp, %esp
239	popl	%ebp
240	ret
241
242	END(dtrace_copystr)
243
244/*
245uintptr_t dtrace_fulword(void *addr)
246*/
247
248	ENTRY(dtrace_fulword)
249	movl	4(%esp), %ecx
250	xorl	%eax, %eax
251	movl	(%ecx), %eax
252	ret
253	END(dtrace_fulword)
254
255/*
256uint8_t dtrace_fuword8_nocheck(void *addr)
257*/
258
259	ENTRY(dtrace_fuword8_nocheck)
260	movl	4(%esp), %ecx
261	xorl	%eax, %eax
262	movzbl	(%ecx), %eax
263	ret
264	END(dtrace_fuword8_nocheck)
265
266/*
267uint16_t dtrace_fuword16_nocheck(void *addr)
268*/
269
270	ENTRY(dtrace_fuword16_nocheck)
271	movl	4(%esp), %ecx
272	xorl	%eax, %eax
273	movzwl	(%ecx), %eax
274	ret
275	END(dtrace_fuword16_nocheck)
276
277/*
278uint32_t dtrace_fuword32_nocheck(void *addr)
279*/
280
281	ENTRY(dtrace_fuword32_nocheck)
282	movl	4(%esp), %ecx
283	xorl	%eax, %eax
284	movl	(%ecx), %eax
285	ret
286	END(dtrace_fuword32_nocheck)
287
288/*
289uint64_t dtrace_fuword64_nocheck(void *addr)
290*/
291
292	ENTRY(dtrace_fuword64_nocheck)
293	movl	4(%esp), %ecx
294	xorl	%eax, %eax
295	xorl	%edx, %edx
296	movl	(%ecx), %eax
297	movl	4(%ecx), %edx
298	ret
299	END(dtrace_fuword64_nocheck)
300
301/*
302void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval)
303*/
304
305	ENTRY(dtrace_probe_error)
306	pushl	%ebp
307	movl	%esp, %ebp
308	pushl	0x1c(%ebp)
309	pushl	0x18(%ebp)
310	pushl	0x14(%ebp)
311	pushl	0x10(%ebp)
312	pushl	0xc(%ebp)
313	pushl	0x8(%ebp)
314	pushl	dtrace_probeid_error
315	call	dtrace_probe
316	movl	%ebp, %esp
317	popl	%ebp
318	ret
319	END(dtrace_probe_error)
320
321/*
322void dtrace_membar_producer(void)
323*/
324
325	ENTRY(dtrace_membar_producer)
326	rep;	ret	/* use 2 byte return instruction when branch target */
327			/* AMD Software Optimization Guide - Section 6.2 */
328	END(dtrace_membar_producer)
329
330/*
331void dtrace_membar_consumer(void)
332*/
333
334	ENTRY(dtrace_membar_consumer)
335	rep;	ret	/* use 2 byte return instruction when branch target */
336			/* AMD Software Optimization Guide - Section 6.2 */
337	END(dtrace_membar_consumer)
338
339/*
340dtrace_icookie_t dtrace_interrupt_disable(void)
341*/
342	ENTRY(dtrace_interrupt_disable)
343	pushfl
344	popl	%eax
345	cli
346	ret
347	END(dtrace_interrupt_disable)
348
349/*
350void dtrace_interrupt_enable(dtrace_icookie_t cookie)
351*/
352	ENTRY(dtrace_interrupt_enable)
353	movl	4(%esp), %eax
354	pushl	%eax
355	popfl
356	ret
357	END(dtrace_interrupt_enable)
358