]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/cddl/dev/dtrace/i386/dtrace_asm.S
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / cddl / dev / dtrace / i386 / dtrace_asm.S
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$
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
66 invop_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. */
84 invop_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. */
103 invop_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 */
128 invop_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 /*
140 void 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 /*
148 void 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 /*
156 greg_t dtrace_getfp(void)
157 */
158
159         ENTRY(dtrace_getfp)
160         movl    %ebp, %eax
161         ret
162         END(dtrace_getfp)
163
164 /*
165 uint32_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 /*
180 uintptr_t dtrace_caller(int aframes)
181 */
182
183         ENTRY(dtrace_caller)
184         movl    $-1, %eax
185         ret
186         END(dtrace_caller)
187
188 /*
189 void 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 /*
212 void 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
225 0:
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
236 1:
237         popl    %ebx
238         movl    %ebp, %esp
239         popl    %ebp
240         ret
241
242         END(dtrace_copystr)
243
244 /*
245 uintptr_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 /*
256 uint8_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 /*
267 uint16_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 /*
278 uint32_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 /*
289 uint64_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 /*
302 void 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 /*
322 void 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 /*
331 void 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 /*
340 dtrace_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 /*
350 void 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)