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
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.
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]
25 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
31 #include <machine/asmacros.h>
32 #include <sys/cpuvar_defs.h>
33 #include <sys/dtrace.h>
38 .type calltrap,@function
39 ENTRY(dtrace_invop_start)
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 */
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.
52 ALTENTRY(dtrace_invop_callsite)
54 cmpl $DTRACE_INVOP_PUSHL_EBP, %eax
56 cmpl $DTRACE_INVOP_POPL_EBP, %eax
58 cmpl $DTRACE_INVOP_LEAVE, %eax
60 cmpl $DTRACE_INVOP_NOP, %eax
63 /* When all else fails handle the trap in the usual way. */
64 jmpl *dtrace_invop_calltrap_addr
68 * We must emulate a "pushl %ebp". To do this, we pull the stack
69 * down 4 bytes, and then store the base pointer.
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. */
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.
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. */
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.
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 */
130 * We must emulate a "nop". This is obviously not hard: we need only
131 * advance the %eip by one.
135 iret /* return from interrupt */
137 END(dtrace_invop_start)
140 void dtrace_invop_init(void)
142 ENTRY(dtrace_invop_init)
143 movl $dtrace_invop_start, dtrace_invop_jump_addr
145 END(dtrace_invop_init)
148 void dtrace_invop_uninit(void)
150 ENTRY(dtrace_invop_uninit)
151 movl $0, dtrace_invop_jump_addr
153 END(dtrace_invop_uninit)
156 greg_t dtrace_getfp(void)
165 uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
169 ALTENTRY(dtrace_casptr)
174 cmpxchgl %ecx, (%edx)
180 uintptr_t dtrace_caller(int aframes)
189 void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
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 */
212 void dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size)
215 ENTRY(dtrace_copystr)
217 pushl %ebp /* Setup stack frame */
219 pushl %ebx /* Save registers */
221 movl 8(%ebp), %ebx /* Load source address */
222 movl 12(%ebp), %edx /* Load destination address */
223 movl 16(%ebp), %ecx /* Load count */
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 */
245 uintptr_t dtrace_fulword(void *addr)
248 ENTRY(dtrace_fulword)
256 uint8_t dtrace_fuword8_nocheck(void *addr)
259 ENTRY(dtrace_fuword8_nocheck)
264 END(dtrace_fuword8_nocheck)
267 uint16_t dtrace_fuword16_nocheck(void *addr)
270 ENTRY(dtrace_fuword16_nocheck)
275 END(dtrace_fuword16_nocheck)
278 uint32_t dtrace_fuword32_nocheck(void *addr)
281 ENTRY(dtrace_fuword32_nocheck)
286 END(dtrace_fuword32_nocheck)
289 uint64_t dtrace_fuword64_nocheck(void *addr)
292 ENTRY(dtrace_fuword64_nocheck)
299 END(dtrace_fuword64_nocheck)
302 void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval)
305 ENTRY(dtrace_probe_error)
314 pushl dtrace_probeid_error
319 END(dtrace_probe_error)
322 void dtrace_membar_producer(void)
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)
331 void dtrace_membar_consumer(void)
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)
340 dtrace_icookie_t dtrace_interrupt_disable(void)
342 ENTRY(dtrace_interrupt_disable)
347 END(dtrace_interrupt_disable)
350 void dtrace_interrupt_enable(dtrace_icookie_t cookie)
352 ENTRY(dtrace_interrupt_enable)
357 END(dtrace_interrupt_enable)