dtrace_asm.S revision 1.5
1/* $NetBSD: dtrace_asm.S,v 1.5 2016/06/23 04:35:35 pgoyette Exp $ */ 2 3/* 4 * CDDL HEADER START 5 * 6 * The contents of this file are subject to the terms of the 7 * Common Development and Distribution License, Version 1.0 only 8 * (the "License"). You may not use this file except in compliance 9 * with the License. 10 * 11 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 12 * or http://www.opensolaris.org/os/licensing. 13 * See the License for the specific language governing permissions 14 * and limitations under the License. 15 * 16 * When distributing Covered Code, include this CDDL HEADER in each 17 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 18 * If applicable, add the following below this CDDL HEADER, with the 19 * fields enclosed by brackets "[]" replaced with your own identifying 20 * information: Portions Copyright [yyyy] [name of copyright owner] 21 * 22 * CDDL HEADER END 23 * 24 * $FreeBSD: src/sys/cddl/dev/dtrace/i386/dtrace_asm.S,v 1.1.4.1 2009/08/03 08:13:06 kensmith Exp $ 25 */ 26/* 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31#define _ASM 32 33#include <sys/cpuvar_defs.h> 34#include <sys/dtrace.h> 35#include <machine/asm.h> 36#include <machine/frameasm.h> 37 38 ENTRY(dtrace_invop_start) 39 40 pushl %eax /* push %eax -- may be return value */ 41 pushl %esp /* push stack pointer */ 42 addl $48, (%esp) /* adjust to incoming args */ 43 pushl 40(%esp) /* push calling EIP */ 44 45 /* 46 * Call dtrace_invop to let it check if the exception was 47 * a fbt one. The return value in %eax will tell us what 48 * dtrace_invop wants us to do. 49 */ 50 call dtrace_invop 51 ALTENTRY(dtrace_invop_callsite) 52 addl $12, %esp 53 cmpl $DTRACE_INVOP_PUSHL_EBP, %eax 54 je invop_push 55 cmpl $DTRACE_INVOP_POPL_EBP, %eax 56 je invop_pop 57 cmpl $DTRACE_INVOP_LEAVE, %eax 58 je invop_leave 59 cmpl $DTRACE_INVOP_NOP, %eax 60 je invop_nop 61 62 /* When all else fails handle the trap in the usual way. */ 63 jmpl *dtrace_invop_calltrap_addr 64 65invop_push: 66 /* 67 * We must emulate a "pushl %ebp". To do this, we pull the stack 68 * down 4 bytes, and then store the base pointer. 69 */ 70 popal 71 subl $4, %esp /* make room for %ebp */ 72 pushl %eax /* push temp */ 73 movl 8(%esp), %eax /* load calling EIP */ 74 incl %eax /* increment over LOCK prefix */ 75 movl %eax, 4(%esp) /* store calling EIP */ 76 movl 12(%esp), %eax /* load calling CS */ 77 movl %eax, 8(%esp) /* store calling CS */ 78 movl 16(%esp), %eax /* load calling EFLAGS */ 79 movl %eax, 12(%esp) /* store calling EFLAGS */ 80 movl %ebp, 16(%esp) /* push %ebp */ 81 popl %eax /* pop off temp */ 82 iret /* Return from interrupt. */ 83invop_pop: 84 /* 85 * We must emulate a "popl %ebp". To do this, we do the opposite of 86 * the above: we remove the %ebp from the stack, and squeeze up the 87 * saved state from the trap. 88 */ 89 popal 90 pushl %eax /* push temp */ 91 movl 16(%esp), %ebp /* pop %ebp */ 92 movl 12(%esp), %eax /* load calling EFLAGS */ 93 movl %eax, 16(%esp) /* store calling EFLAGS */ 94 movl 8(%esp), %eax /* load calling CS */ 95 movl %eax, 12(%esp) /* store calling CS */ 96 movl 4(%esp), %eax /* load calling EIP */ 97 incl %eax /* increment over LOCK prefix */ 98 movl %eax, 8(%esp) /* store calling EIP */ 99 popl %eax /* pop off temp */ 100 addl $4, %esp /* adjust stack pointer */ 101 iret /* Return from interrupt. */ 102invop_leave: 103 /* 104 * We must emulate a "leave", which is the same as a "movl %ebp, %esp" 105 * followed by a "popl %ebp". This looks similar to the above, but 106 * requires two temporaries: one for the new base pointer, and one 107 * for the staging register. 108 */ 109 popa 110 pushl %eax /* push temp */ 111 pushl %ebx /* push temp */ 112 movl %ebp, %ebx /* set temp to old %ebp */ 113 movl (%ebx), %ebp /* pop %ebp */ 114 movl 16(%esp), %eax /* load calling EFLAGS */ 115 movl %eax, (%ebx) /* store calling EFLAGS */ 116 movl 12(%esp), %eax /* load calling CS */ 117 movl %eax, -4(%ebx) /* store calling CS */ 118 movl 8(%esp), %eax /* load calling EIP */ 119 incl %eax /* increment over LOCK prefix */ 120 movl %eax, -8(%ebx) /* store calling EIP */ 121 movl %ebx, -4(%esp) /* temporarily store new %esp */ 122 popl %ebx /* pop off temp */ 123 popl %eax /* pop off temp */ 124 movl -12(%esp), %esp /* set stack pointer */ 125 subl $8, %esp /* adjust for three pushes, one pop */ 126 iret /* return from interrupt */ 127invop_nop: 128 /* 129 * We must emulate a "nop". This is obviously not hard: we need only 130 * advance the %eip by one. 131 */ 132 popa 133 incl (%esp) 134 iret /* return from interrupt */ 135 136 END(dtrace_invop_start) 137 138/* 139void dtrace_invop_init(void) 140*/ 141 ENTRY(dtrace_invop_init) 142 movl $dtrace_invop_start, dtrace_invop_jump_addr 143 ret 144 END(dtrace_invop_init) 145 146/* 147void dtrace_invop_uninit(void) 148*/ 149 ENTRY(dtrace_invop_uninit) 150 movl $0, dtrace_invop_jump_addr 151 ret 152 END(dtrace_invop_uninit) 153 154/* 155greg_t dtrace_getfp(void) 156*/ 157 158 ENTRY(dtrace_getfp) 159 movl %ebp, %eax 160 ret 161 END(dtrace_getfp) 162 163/* 164uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) 165*/ 166 167 ENTRY(dtrace_cas32) 168 movl 4(%esp), %edx 169 movl 8(%esp), %eax 170 movl 12(%esp), %ecx 171 lock 172 cmpxchgl %ecx, (%edx) 173 ret 174 END(dtrace_cas32) 175 176/* 177uint32_t dtrace_casptr(uint32_t *target, uint32_t cmp, uint32_t new) 178*/ 179 180 ENTRY(dtrace_casptr) 181 movl 4(%esp), %edx 182 movl 8(%esp), %eax 183 movl 12(%esp), %ecx 184 lock 185 cmpxchgl %ecx, (%edx) 186 ret 187 END(dtrace_casptr) 188 189 190/* 191uintptr_t dtrace_caller(int aframes) 192*/ 193 194 ENTRY(dtrace_caller) 195 movl $-1, %eax 196 ret 197 END(dtrace_caller) 198 199/* 200void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size) 201*/ 202 203 ENTRY(dtrace_copy) 204 pushl %ebp 205 movl %esp, %ebp 206 pushl %esi 207 pushl %edi 208 209 movl 8(%ebp), %esi /* Load source address */ 210 movl 12(%ebp), %edi /* Load destination address */ 211 movl 16(%ebp), %ecx /* Load count */ 212 repz /* Repeat for count... */ 213 smovb /* move from %ds:si to %es:di */ 214 215 popl %edi 216 popl %esi 217 movl %ebp, %esp 218 popl %ebp 219 ret 220 END(dtrace_copy) 221 222/* 223void dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size) 224*/ 225 226 ENTRY(dtrace_copystr) 227 228 pushl %ebp /* Setup stack frame */ 229 movl %esp, %ebp 230 pushl %ebx /* Save registers */ 231 232 movl 8(%ebp), %ebx /* Load source address */ 233 movl 12(%ebp), %edx /* Load destination address */ 234 movl 16(%ebp), %ecx /* Load count */ 235 2360: 237 movb (%ebx), %al /* Load from source */ 238 movb %al, (%edx) /* Store to destination */ 239 incl %ebx /* Increment source pointer */ 240 incl %edx /* Increment destination pointer */ 241 decl %ecx /* Decrement remaining count */ 242 cmpb $0, %al 243 je 1f 244 cmpl $0, %ecx 245 jne 0b 246 2471: 248 popl %ebx 249 movl %ebp, %esp 250 popl %ebp 251 ret 252 253 END(dtrace_copystr) 254 255/* 256uintptr_t dtrace_fulword(void *addr) 257*/ 258 259 ENTRY(dtrace_fulword) 260 movl 4(%esp), %ecx 261 xorl %eax, %eax 262 movl (%ecx), %eax 263 ret 264 END(dtrace_fulword) 265 266/* 267uint8_t dtrace_fuword8_nocheck(void *addr) 268*/ 269 270 ENTRY(dtrace_fuword8_nocheck) 271 movl 4(%esp), %ecx 272 xorl %eax, %eax 273 movzbl (%ecx), %eax 274 ret 275 END(dtrace_fuword8_nocheck) 276 277/* 278uint16_t dtrace_fuword16_nocheck(void *addr) 279*/ 280 281 ENTRY(dtrace_fuword16_nocheck) 282 movl 4(%esp), %ecx 283 xorl %eax, %eax 284 movzwl (%ecx), %eax 285 ret 286 END(dtrace_fuword16_nocheck) 287 288/* 289uint32_t dtrace_fuword32_nocheck(void *addr) 290*/ 291 292 ENTRY(dtrace_fuword32_nocheck) 293 movl 4(%esp), %ecx 294 xorl %eax, %eax 295 movl (%ecx), %eax 296 ret 297 END(dtrace_fuword32_nocheck) 298 299/* 300uint64_t dtrace_fuword64_nocheck(void *addr) 301*/ 302 303 ENTRY(dtrace_fuword64_nocheck) 304 movl 4(%esp), %ecx 305 xorl %eax, %eax 306 xorl %edx, %edx 307 movl (%ecx), %eax 308 movl 4(%ecx), %edx 309 ret 310 END(dtrace_fuword64_nocheck) 311 312/* 313void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval) 314*/ 315 316 ENTRY(dtrace_probe_error) 317 pushl %ebp 318 movl %esp, %ebp 319 pushl 0x1c(%ebp) 320 pushl 0x18(%ebp) 321 pushl 0x14(%ebp) 322 pushl 0x10(%ebp) 323 pushl 0xc(%ebp) 324 pushl 0x8(%ebp) 325 pushl dtrace_probeid_error 326 call dtrace_probe 327 movl %ebp, %esp 328 popl %ebp 329 ret 330 END(dtrace_probe_error) 331 332/* 333void dtrace_membar_producer(void) 334*/ 335 336 ENTRY(dtrace_membar_producer) 337 rep; ret /* use 2 byte return instruction when branch target */ 338 /* AMD Software Optimization Guide - Section 6.2 */ 339 END(dtrace_membar_producer) 340 341/* 342void dtrace_membar_consumer(void) 343*/ 344 345 ENTRY(dtrace_membar_consumer) 346 rep; ret /* use 2 byte return instruction when branch target */ 347 /* AMD Software Optimization Guide - Section 6.2 */ 348 END(dtrace_membar_consumer) 349 350/* 351dtrace_icookie_t dtrace_interrupt_disable(void) 352*/ 353 ENTRY(dtrace_interrupt_disable) 354 pushfl 355 popl %eax 356 cli 357 ret 358 END(dtrace_interrupt_disable) 359 360/* 361void dtrace_interrupt_enable(dtrace_icookie_t cookie) 362*/ 363 ENTRY(dtrace_interrupt_enable) 364 movl 4(%esp), %eax 365 pushl %eax 366 popfl 367 ret 368 END(dtrace_interrupt_enable) 369