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.inc"
36
37 ENTRY(dtrace_invop_start)
38
39 pushl %eax /* push %eax -- may be return value */
40 pushl %esp /* push stack pointer */
41 subl $8, (%esp) /* skip first arg and segment regs */
42 pushl 40(%esp) /* push calling EIP */
43
44 /*
45 * Call dtrace_invop to let it check if the exception was
46 * a fbt one. The return value in %eax will tell us what
47 * dtrace_invop wants us to do.
48 */
49 call dtrace_invop
50 ALTENTRY(dtrace_invop_callsite)
51 addl $12, %esp
52 cmpl $DTRACE_INVOP_PUSHL_EBP, %eax
53 je invop_push
54 cmpl $DTRACE_INVOP_POPL_EBP, %eax
55 je invop_pop
56 cmpl $DTRACE_INVOP_LEAVE, %eax
57 je invop_leave
58 cmpl $DTRACE_INVOP_NOP, %eax
59 je invop_nop
60
61 /* When all else fails handle the trap in the usual way. */
62 jmpl *dtrace_invop_calltrap_addr
63
64 invop_push:
65 /*
66 * We must emulate a "pushl %ebp". To do this, we pull the stack
67 * down 4 bytes, and then store the base pointer.
68 */
69 popal
70 subl $4, %esp /* make room for %ebp */
71 pushl %eax /* push temp */
72 movl 8(%esp), %eax /* load calling EIP */
73 incl %eax /* increment over LOCK prefix */
74 movl %eax, 4(%esp) /* store calling EIP */
75 movl 12(%esp), %eax /* load calling CS */
76 movl %eax, 8(%esp) /* store calling CS */
77 movl 16(%esp), %eax /* load calling EFLAGS */
78 movl %eax, 12(%esp) /* store calling EFLAGS */
79 movl %ebp, 16(%esp) /* push %ebp */
80 popl %eax /* pop off temp */
81 iret /* Return from interrupt. */
82 invop_pop:
83 /*
84 * We must emulate a "popl %ebp". To do this, we do the opposite of
85 * the above: we remove the %ebp from the stack, and squeeze up the
86 * saved state from the trap.
87 */
88 popal
89 pushl %eax /* push temp */
90 movl 16(%esp), %ebp /* pop %ebp */
91 movl 12(%esp), %eax /* load calling EFLAGS */
92 movl %eax, 16(%esp) /* store calling EFLAGS */
93 movl 8(%esp), %eax /* load calling CS */
94 movl %eax, 12(%esp) /* store calling CS */
95 movl 4(%esp), %eax /* load calling EIP */
96 incl %eax /* increment over LOCK prefix */
97 movl %eax, 8(%esp) /* store calling EIP */
98 popl %eax /* pop off temp */
99 addl $4, %esp /* adjust stack pointer */
100 iret /* Return from interrupt. */
101 invop_leave:
102 /*
103 * We must emulate a "leave", which is the same as a "movl %ebp, %esp"
104 * followed by a "popl %ebp". This looks similar to the above, but
105 * requires two temporaries: one for the new base pointer, and one
106 * for the staging register.
107 */
108 popa
109 pushl %eax /* push temp */
110 pushl %ebx /* push temp */
111 movl %ebp, %ebx /* set temp to old %ebp */
112 movl (%ebx), %ebp /* pop %ebp */
113 movl 16(%esp), %eax /* load calling EFLAGS */
114 movl %eax, (%ebx) /* store calling EFLAGS */
115 movl 12(%esp), %eax /* load calling CS */
116 movl %eax, -4(%ebx) /* store calling CS */
117 movl 8(%esp), %eax /* load calling EIP */
118 incl %eax /* increment over LOCK prefix */
119 movl %eax, -8(%ebx) /* store calling EIP */
120 subl $8, %ebx /* adjust for three pushes, one pop */
121 movl %ebx, 8(%esp) /* temporarily store new %esp */
122 popl %ebx /* pop off temp */
123 popl %eax /* pop off temp */
124 movl (%esp), %esp /* set stack pointer */
125 iret /* return from interrupt */
126 invop_nop:
127 /*
128 * We must emulate a "nop". This is obviously not hard: we need only
129 * advance the %eip by one.
130 */
131 popa
132 incl (%esp)
133 iret /* return from interrupt */
134
135 END(dtrace_invop_start)
136
137 /*
138 greg_t dtrace_getfp(void)
139 */
140
141 ENTRY(dtrace_getfp)
142 movl %ebp, %eax
143 ret
144 END(dtrace_getfp)
145
146 /*
147 uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
148 */
149
150 ENTRY(dtrace_cas32)
151 ALTENTRY(dtrace_casptr)
152 movl 4(%esp), %edx
153 movl 8(%esp), %eax
154 movl 12(%esp), %ecx
155 lock
156 cmpxchgl %ecx, (%edx)
157 ret
158 END(dtrace_casptr)
159 END(dtrace_cas32)
160
161 /*
162 uintptr_t dtrace_caller(int aframes)
163 */
164
165 ENTRY(dtrace_caller)
166 movl $-1, %eax
167 ret
168 END(dtrace_caller)
169
170 /*
171 void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
172 */
173
174 ENTRY(dtrace_copy)
175 pushl %ebp
176 movl %esp, %ebp
177 pushl %esi
178 pushl %edi
179
180 movl 8(%ebp), %esi /* Load source address */
181 movl 12(%ebp), %edi /* Load destination address */
182 movl 16(%ebp), %ecx /* Load count */
183 repz /* Repeat for count... */
184 smovb /* move from %ds:si to %es:di */
185
186 popl %edi
187 popl %esi
188 movl %ebp, %esp
189 popl %ebp
190 ret
191 END(dtrace_copy)
192
193 /*
194 void dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size)
195 */
196
197 ENTRY(dtrace_copystr)
198
199 pushl %ebp /* Setup stack frame */
200 movl %esp, %ebp
201 pushl %ebx /* Save registers */
202
203 movl 8(%ebp), %ebx /* Load source address */
204 movl 12(%ebp), %edx /* Load destination address */
205 movl 16(%ebp), %ecx /* Load count */
206
207 0:
208 movb (%ebx), %al /* Load from source */
209 movb %al, (%edx) /* Store to destination */
210 incl %ebx /* Increment source pointer */
211 incl %edx /* Increment destination pointer */
212 decl %ecx /* Decrement remaining count */
213 cmpb $0, %al
214 je 1f
215 cmpl $0, %ecx
216 jne 0b
217
218 1:
219 popl %ebx
220 movl %ebp, %esp
221 popl %ebp
222 ret
223
224 END(dtrace_copystr)
225
226 /*
227 uintptr_t dtrace_fulword(void *addr)
228 */
229
230 ENTRY(dtrace_fulword)
231 movl 4(%esp), %ecx
232 xorl %eax, %eax
233 movl (%ecx), %eax
234 ret
235 END(dtrace_fulword)
236
237 /*
238 uint8_t dtrace_fuword8_nocheck(void *addr)
239 */
240
241 ENTRY(dtrace_fuword8_nocheck)
242 movl 4(%esp), %ecx
243 xorl %eax, %eax
244 movzbl (%ecx), %eax
245 ret
246 END(dtrace_fuword8_nocheck)
247
248 /*
249 uint16_t dtrace_fuword16_nocheck(void *addr)
250 */
251
252 ENTRY(dtrace_fuword16_nocheck)
253 movl 4(%esp), %ecx
254 xorl %eax, %eax
255 movzwl (%ecx), %eax
256 ret
257 END(dtrace_fuword16_nocheck)
258
259 /*
260 uint32_t dtrace_fuword32_nocheck(void *addr)
261 */
262
263 ENTRY(dtrace_fuword32_nocheck)
264 movl 4(%esp), %ecx
265 xorl %eax, %eax
266 movl (%ecx), %eax
267 ret
268 END(dtrace_fuword32_nocheck)
269
270 /*
271 uint64_t dtrace_fuword64_nocheck(void *addr)
272 */
273
274 ENTRY(dtrace_fuword64_nocheck)
275 movl 4(%esp), %ecx
276 xorl %eax, %eax
277 xorl %edx, %edx
278 movl (%ecx), %eax
279 movl 4(%ecx), %edx
280 ret
281 END(dtrace_fuword64_nocheck)
282
283 /*
284 void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval)
285 */
286
287 ENTRY(dtrace_probe_error)
288 pushl %ebp
289 movl %esp, %ebp
290 pushl 0x1c(%ebp)
291 pushl 0x18(%ebp)
292 pushl 0x14(%ebp)
293 pushl 0x10(%ebp)
294 pushl 0xc(%ebp)
295 pushl 0x8(%ebp)
296 pushl dtrace_probeid_error
297 call dtrace_probe
298 movl %ebp, %esp
299 popl %ebp
300 ret
301 END(dtrace_probe_error)
302
303 /*
304 void dtrace_membar_producer(void)
305 */
306
307 ENTRY(dtrace_membar_producer)
308 rep; ret /* use 2 byte return instruction when branch target */
309 /* AMD Software Optimization Guide - Section 6.2 */
310 END(dtrace_membar_producer)
311
312 /*
313 void dtrace_membar_consumer(void)
314 */
315
316 ENTRY(dtrace_membar_consumer)
317 rep; ret /* use 2 byte return instruction when branch target */
318 /* AMD Software Optimization Guide - Section 6.2 */
319 END(dtrace_membar_consumer)
320
321 /*
322 dtrace_icookie_t dtrace_interrupt_disable(void)
323 */
324 ENTRY(dtrace_interrupt_disable)
325 pushfl
326 popl %eax
327 cli
328 ret
329 END(dtrace_interrupt_disable)
330
331 /*
332 void dtrace_interrupt_enable(dtrace_icookie_t cookie)
333 */
334 ENTRY(dtrace_interrupt_enable)
335 movl 4(%esp), %eax
336 pushl %eax
337 popfl
338 ret
339 END(dtrace_interrupt_enable)
Cache object: 6ce6cdada1e16821c9733c12a6954f50
|