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