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