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 64invop_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. */ 82invop_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. */ 101invop_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 */ 126invop_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/* 138greg_t dtrace_getfp(void) 139*/ 140 141 ENTRY(dtrace_getfp) 142 movl %ebp, %eax 143 ret 144 END(dtrace_getfp) 145 146/* 147uint32_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/* 162uintptr_t dtrace_caller(int aframes) 163*/ 164 165 ENTRY(dtrace_caller) 166 movl $-1, %eax 167 ret 168 END(dtrace_caller) 169 170/* 171void 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/* 194void 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 2070: 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 2181: 219 popl %ebx 220 movl %ebp, %esp 221 popl %ebp 222 ret 223 224 END(dtrace_copystr) 225 226/* 227uintptr_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/* 238uint8_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/* 249uint16_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/* 260uint32_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/* 271uint64_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/* 284void 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/* 304void 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/* 313void 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/* 322dtrace_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/* 332void 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) 340