Path: blob/main/sys/cddl/dev/dtrace/i386/dtrace_asm.S
48375 views
/*1* CDDL HEADER START2*3* The contents of this file are subject to the terms of the4* Common Development and Distribution License, Version 1.0 only5* (the "License"). You may not use this file except in compliance6* with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or http://www.opensolaris.org/os/licensing.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/21/*22* Copyright 2004 Sun Microsystems, Inc. All rights reserved.23* Use is subject to license terms.24*/2526#define _ASM2728#include <machine/asmacros.h>29#include <sys/cpuvar_defs.h>30#include <sys/dtrace.h>3132#include "assym.inc"3334ENTRY(dtrace_invop_start)3536pushl %eax /* push %eax -- may be return value */37pushl %esp /* push stack pointer */38subl $8, (%esp) /* skip first arg and segment regs */39pushl 40(%esp) /* push calling EIP */4041/*42* Call dtrace_invop to let it check if the exception was43* a fbt one. The return value in %eax will tell us what44* dtrace_invop wants us to do.45*/46call dtrace_invop47ALTENTRY(dtrace_invop_callsite)48addl $12, %esp49cmpl $DTRACE_INVOP_PUSHL_EBP, %eax50je invop_push51cmpl $DTRACE_INVOP_POPL_EBP, %eax52je invop_pop53cmpl $DTRACE_INVOP_LEAVE, %eax54je invop_leave55cmpl $DTRACE_INVOP_NOP, %eax56je invop_nop5758/* When all else fails handle the trap in the usual way. */59jmpl *dtrace_invop_calltrap_addr6061invop_push:62/*63* We must emulate a "pushl %ebp". To do this, we pull the stack64* down 4 bytes, and then store the base pointer.65*/66popal67subl $4, %esp /* make room for %ebp */68pushl %eax /* push temp */69movl 8(%esp), %eax /* load calling EIP */70incl %eax /* increment over LOCK prefix */71movl %eax, 4(%esp) /* store calling EIP */72movl 12(%esp), %eax /* load calling CS */73movl %eax, 8(%esp) /* store calling CS */74movl 16(%esp), %eax /* load calling EFLAGS */75movl %eax, 12(%esp) /* store calling EFLAGS */76movl %ebp, 16(%esp) /* push %ebp */77popl %eax /* pop off temp */78iret /* Return from interrupt. */79invop_pop:80/*81* We must emulate a "popl %ebp". To do this, we do the opposite of82* the above: we remove the %ebp from the stack, and squeeze up the83* saved state from the trap.84*/85popal86pushl %eax /* push temp */87movl 16(%esp), %ebp /* pop %ebp */88movl 12(%esp), %eax /* load calling EFLAGS */89movl %eax, 16(%esp) /* store calling EFLAGS */90movl 8(%esp), %eax /* load calling CS */91movl %eax, 12(%esp) /* store calling CS */92movl 4(%esp), %eax /* load calling EIP */93incl %eax /* increment over LOCK prefix */94movl %eax, 8(%esp) /* store calling EIP */95popl %eax /* pop off temp */96addl $4, %esp /* adjust stack pointer */97iret /* Return from interrupt. */98invop_leave:99/*100* We must emulate a "leave", which is the same as a "movl %ebp, %esp"101* followed by a "popl %ebp". This looks similar to the above, but102* requires two temporaries: one for the new base pointer, and one103* for the staging register.104*/105popa106pushl %eax /* push temp */107pushl %ebx /* push temp */108movl %ebp, %ebx /* set temp to old %ebp */109movl (%ebx), %ebp /* pop %ebp */110movl 16(%esp), %eax /* load calling EFLAGS */111movl %eax, (%ebx) /* store calling EFLAGS */112movl 12(%esp), %eax /* load calling CS */113movl %eax, -4(%ebx) /* store calling CS */114movl 8(%esp), %eax /* load calling EIP */115incl %eax /* increment over LOCK prefix */116movl %eax, -8(%ebx) /* store calling EIP */117subl $8, %ebx /* adjust for three pushes, one pop */118movl %ebx, 8(%esp) /* temporarily store new %esp */119popl %ebx /* pop off temp */120popl %eax /* pop off temp */121movl (%esp), %esp /* set stack pointer */122iret /* return from interrupt */123invop_nop:124/*125* We must emulate a "nop". This is obviously not hard: we need only126* advance the %eip by one.127*/128popa129incl (%esp)130iret /* return from interrupt */131132END(dtrace_invop_start)133134/*135greg_t dtrace_getfp(void)136*/137138ENTRY(dtrace_getfp)139movl %ebp, %eax140ret141END(dtrace_getfp)142143/*144uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)145*/146147ENTRY(dtrace_cas32)148ALTENTRY(dtrace_casptr)149movl 4(%esp), %edx150movl 8(%esp), %eax151movl 12(%esp), %ecx152lock153cmpxchgl %ecx, (%edx)154ret155END(dtrace_casptr)156END(dtrace_cas32)157158/*159uintptr_t dtrace_caller(int aframes)160*/161162ENTRY(dtrace_caller)163movl $-1, %eax164ret165END(dtrace_caller)166167/*168void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)169*/170171ENTRY(dtrace_copy)172pushl %ebp173movl %esp, %ebp174pushl %esi175pushl %edi176177movl 8(%ebp), %esi /* Load source address */178movl 12(%ebp), %edi /* Load destination address */179movl 16(%ebp), %ecx /* Load count */180repz /* Repeat for count... */181smovb /* move from %ds:si to %es:di */182183popl %edi184popl %esi185movl %ebp, %esp186popl %ebp187ret188END(dtrace_copy)189190/*191void dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size)192*/193194ENTRY(dtrace_copystr)195196pushl %ebp /* Setup stack frame */197movl %esp, %ebp198pushl %ebx /* Save registers */199200movl 8(%ebp), %ebx /* Load source address */201movl 12(%ebp), %edx /* Load destination address */202movl 16(%ebp), %ecx /* Load count */2032040:205movb (%ebx), %al /* Load from source */206movb %al, (%edx) /* Store to destination */207incl %ebx /* Increment source pointer */208incl %edx /* Increment destination pointer */209decl %ecx /* Decrement remaining count */210cmpb $0, %al211je 1f212cmpl $0, %ecx213jne 0b2142151:216popl %ebx217movl %ebp, %esp218popl %ebp219ret220221END(dtrace_copystr)222223/*224uintptr_t dtrace_fulword(void *addr)225*/226227ENTRY(dtrace_fulword)228movl 4(%esp), %ecx229xorl %eax, %eax230movl (%ecx), %eax231ret232END(dtrace_fulword)233234/*235uint8_t dtrace_fuword8_nocheck(void *addr)236*/237238ENTRY(dtrace_fuword8_nocheck)239movl 4(%esp), %ecx240xorl %eax, %eax241movzbl (%ecx), %eax242ret243END(dtrace_fuword8_nocheck)244245/*246uint16_t dtrace_fuword16_nocheck(void *addr)247*/248249ENTRY(dtrace_fuword16_nocheck)250movl 4(%esp), %ecx251xorl %eax, %eax252movzwl (%ecx), %eax253ret254END(dtrace_fuword16_nocheck)255256/*257uint32_t dtrace_fuword32_nocheck(void *addr)258*/259260ENTRY(dtrace_fuword32_nocheck)261movl 4(%esp), %ecx262xorl %eax, %eax263movl (%ecx), %eax264ret265END(dtrace_fuword32_nocheck)266267/*268uint64_t dtrace_fuword64_nocheck(void *addr)269*/270271ENTRY(dtrace_fuword64_nocheck)272movl 4(%esp), %ecx273xorl %eax, %eax274xorl %edx, %edx275movl (%ecx), %eax276movl 4(%ecx), %edx277ret278END(dtrace_fuword64_nocheck)279280/*281void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval)282*/283284ENTRY(dtrace_probe_error)285pushl %ebp286movl %esp, %ebp287pushl 0x1c(%ebp)288pushl 0x18(%ebp)289pushl 0x14(%ebp)290pushl 0x10(%ebp)291pushl 0xc(%ebp)292pushl 0x8(%ebp)293pushl dtrace_probeid_error294call dtrace_probe295movl %ebp, %esp296popl %ebp297ret298END(dtrace_probe_error)299300/*301void dtrace_membar_producer(void)302*/303304ENTRY(dtrace_membar_producer)305rep; ret /* use 2 byte return instruction when branch target */306/* AMD Software Optimization Guide - Section 6.2 */307END(dtrace_membar_producer)308309/*310void dtrace_membar_consumer(void)311*/312313ENTRY(dtrace_membar_consumer)314rep; ret /* use 2 byte return instruction when branch target */315/* AMD Software Optimization Guide - Section 6.2 */316END(dtrace_membar_consumer)317318/*319dtrace_icookie_t dtrace_interrupt_disable(void)320*/321ENTRY(dtrace_interrupt_disable)322pushfl323popl %eax324cli325ret326END(dtrace_interrupt_disable)327328/*329void dtrace_interrupt_enable(dtrace_icookie_t cookie)330*/331ENTRY(dtrace_interrupt_enable)332movl 4(%esp), %eax333pushl %eax334popfl335ret336END(dtrace_interrupt_enable)337338339