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>
37 ENTRY(dtrace_invop_start)
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 */
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.
50 ALTENTRY(dtrace_invop_callsite)
52 cmpl $DTRACE_INVOP_PUSHL_EBP, %eax
54 cmpl $DTRACE_INVOP_POPL_EBP, %eax
56 cmpl $DTRACE_INVOP_LEAVE, %eax
58 cmpl $DTRACE_INVOP_NOP, %eax
61 /* When all else fails handle the trap in the usual way. */
62 jmpl *dtrace_invop_calltrap_addr
66 * We must emulate a "pushl %ebp". To do this, we pull the stack
67 * down 4 bytes, and then store the base pointer.
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. */
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.
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. */
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.
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 */
128 * We must emulate a "nop". This is obviously not hard: we need only
129 * advance the %eip by one.
133 iret /* return from interrupt */
135 END(dtrace_invop_start)
138 void dtrace_invop_init(void)
140 ENTRY(dtrace_invop_init)
141 movl $dtrace_invop_start, dtrace_invop_jump_addr
143 END(dtrace_invop_init)
146 void dtrace_invop_uninit(void)
148 ENTRY(dtrace_invop_uninit)
149 movl $0, dtrace_invop_jump_addr
151 END(dtrace_invop_uninit)
154 greg_t dtrace_getfp(void)
163 uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
167 ALTENTRY(dtrace_casptr)
172 cmpxchgl %ecx, (%edx)
178 uintptr_t dtrace_caller(int aframes)
187 void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
196 movl 8(%ebp), %esi /* Load source address */
197 movl 12(%ebp), %edi /* Load destination address */
198 movl 16(%ebp), %ecx /* Load count */
199 repz /* Repeat for count... */
200 smovb /* move from %ds:si to %es:di */
210 void dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size)
213 ENTRY(dtrace_copystr)
215 pushl %ebp /* Setup stack frame */
217 pushl %ebx /* Save registers */
219 movl 8(%ebp), %ebx /* Load source address */
220 movl 12(%ebp), %edx /* Load destination address */
221 movl 16(%ebp), %ecx /* Load count */
224 movb (%ebx), %al /* Load from source */
225 movb %al, (%edx) /* Store to destination */
226 incl %ebx /* Increment source pointer */
227 incl %edx /* Increment destination pointer */
228 decl %ecx /* Decrement remaining count */
243 uintptr_t dtrace_fulword(void *addr)
246 ENTRY(dtrace_fulword)
254 uint8_t dtrace_fuword8_nocheck(void *addr)
257 ENTRY(dtrace_fuword8_nocheck)
262 END(dtrace_fuword8_nocheck)
265 uint16_t dtrace_fuword16_nocheck(void *addr)
268 ENTRY(dtrace_fuword16_nocheck)
273 END(dtrace_fuword16_nocheck)
276 uint32_t dtrace_fuword32_nocheck(void *addr)
279 ENTRY(dtrace_fuword32_nocheck)
284 END(dtrace_fuword32_nocheck)
287 uint64_t dtrace_fuword64_nocheck(void *addr)
290 ENTRY(dtrace_fuword64_nocheck)
297 END(dtrace_fuword64_nocheck)
300 void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval)
303 ENTRY(dtrace_probe_error)
312 pushl dtrace_probeid_error
317 END(dtrace_probe_error)
320 void dtrace_membar_producer(void)
323 ENTRY(dtrace_membar_producer)
324 rep; ret /* use 2 byte return instruction when branch target */
325 /* AMD Software Optimization Guide - Section 6.2 */
326 END(dtrace_membar_producer)
329 void dtrace_membar_consumer(void)
332 ENTRY(dtrace_membar_consumer)
333 rep; ret /* use 2 byte return instruction when branch target */
334 /* AMD Software Optimization Guide - Section 6.2 */
335 END(dtrace_membar_consumer)
338 dtrace_icookie_t dtrace_interrupt_disable(void)
340 ENTRY(dtrace_interrupt_disable)
345 END(dtrace_interrupt_disable)
348 void dtrace_interrupt_enable(dtrace_icookie_t cookie)
350 ENTRY(dtrace_interrupt_enable)
355 END(dtrace_interrupt_enable)