Index: head/sys/cddl/dev/dtrace/amd64/dtrace_asm.S =================================================================== --- head/sys/cddl/dev/dtrace/amd64/dtrace_asm.S (revision 283508) +++ head/sys/cddl/dev/dtrace/amd64/dtrace_asm.S (revision 283509) @@ -1,365 +1,363 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Portions Copyright 2008 John Birrell * * $FreeBSD$ * */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #define _ASM #include #include #include #include "assym.s" #define INTR_POP \ MEXITCOUNT; \ movq TF_RDI(%rsp),%rdi; \ movq TF_RSI(%rsp),%rsi; \ movq TF_RDX(%rsp),%rdx; \ movq TF_RCX(%rsp),%rcx; \ movq TF_R8(%rsp),%r8; \ movq TF_R9(%rsp),%r9; \ movq TF_RAX(%rsp),%rax; \ movq TF_RBX(%rsp),%rbx; \ movq TF_RBP(%rsp),%rbp; \ movq TF_R10(%rsp),%r10; \ movq TF_R11(%rsp),%r11; \ movq TF_R12(%rsp),%r12; \ movq TF_R13(%rsp),%r13; \ movq TF_R14(%rsp),%r14; \ movq TF_R15(%rsp),%r15; \ testb $SEL_RPL_MASK,TF_CS(%rsp); \ jz 1f; \ cli; \ swapgs; \ 1: addq $TF_RIP,%rsp; - .globl calltrap - .type calltrap,@function ENTRY(dtrace_invop_start) /* * #BP traps with %rip set to the next address. We need to decrement * the value to indicate the address of the int3 (0xcc) instruction * that we substituted. */ movq TF_RIP(%rsp), %rdi decq %rdi movq TF_RSP(%rsp), %rsi movq TF_RAX(%rsp), %rdx pushq (%rsi) movq %rsp, %rsi call dtrace_invop ALTENTRY(dtrace_invop_callsite) addq $8, %rsp cmpl $DTRACE_INVOP_PUSHL_EBP, %eax je bp_push cmpl $DTRACE_INVOP_LEAVE, %eax je bp_leave cmpl $DTRACE_INVOP_NOP, %eax je bp_nop cmpl $DTRACE_INVOP_RET, %eax je bp_ret /* When all else fails handle the trap in the usual way. */ jmpq *dtrace_invop_calltrap_addr bp_push: /* * We must emulate a "pushq %rbp". To do this, we pull the stack * down 8 bytes, and then store the base pointer. */ INTR_POP subq $16, %rsp /* make room for %rbp */ pushq %rax /* push temp */ movq 24(%rsp), %rax /* load calling RIP */ movq %rax, 8(%rsp) /* store calling RIP */ movq 32(%rsp), %rax /* load calling CS */ movq %rax, 16(%rsp) /* store calling CS */ movq 40(%rsp), %rax /* load calling RFLAGS */ movq %rax, 24(%rsp) /* store calling RFLAGS */ movq 48(%rsp), %rax /* load calling RSP */ subq $8, %rax /* make room for %rbp */ movq %rax, 32(%rsp) /* store calling RSP */ movq 56(%rsp), %rax /* load calling SS */ movq %rax, 40(%rsp) /* store calling SS */ movq 32(%rsp), %rax /* reload calling RSP */ movq %rbp, (%rax) /* store %rbp there */ popq %rax /* pop off temp */ iretq /* return from interrupt */ /*NOTREACHED*/ bp_leave: /* * We must emulate a "leave", which is the same as a "movq %rbp, %rsp" * followed by a "popq %rbp". This is quite a bit simpler on amd64 * than it is on i386 -- we can exploit the fact that the %rsp is * explicitly saved to effect the pop without having to reshuffle * the other data pushed for the trap. */ INTR_POP pushq %rax /* push temp */ movq 8(%rsp), %rax /* load calling RIP */ movq %rax, 8(%rsp) /* store calling RIP */ movq (%rbp), %rax /* get new %rbp */ addq $8, %rbp /* adjust new %rsp */ movq %rbp, 32(%rsp) /* store new %rsp */ movq %rax, %rbp /* set new %rbp */ popq %rax /* pop off temp */ iretq /* return from interrupt */ /*NOTREACHED*/ bp_nop: /* We must emulate a "nop". */ INTR_POP iretq /*NOTREACHED*/ bp_ret: INTR_POP pushq %rax /* push temp */ movq 32(%rsp), %rax /* load %rsp */ movq (%rax), %rax /* load calling RIP */ movq %rax, 8(%rsp) /* store calling RIP */ addq $8, 32(%rsp) /* adjust new %rsp */ popq %rax /* pop off temp */ iretq /* return from interrupt */ /*NOTREACHED*/ END(dtrace_invop_start) /* void dtrace_invop_init(void) */ ENTRY(dtrace_invop_init) movq $dtrace_invop_start, dtrace_invop_jump_addr(%rip) ret END(dtrace_invop_init) /* void dtrace_invop_uninit(void) */ ENTRY(dtrace_invop_uninit) movq $0, dtrace_invop_jump_addr(%rip) ret END(dtrace_invop_uninit) /* greg_t dtrace_getfp(void) */ ENTRY(dtrace_getfp) movq %rbp, %rax ret END(dtrace_getfp) /* uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) */ ENTRY(dtrace_cas32) movl %esi, %eax lock cmpxchgl %edx, (%rdi) ret END(dtrace_cas32) /* void * dtrace_casptr(void *target, void *cmp, void *new) */ ENTRY(dtrace_casptr) movq %rsi, %rax lock cmpxchgq %rdx, (%rdi) ret END(dtrace_casptr) /* uintptr_t dtrace_caller(int aframes) */ ENTRY(dtrace_caller) movq $-1, %rax ret END(dtrace_caller) /* void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size) */ ENTRY(dtrace_copy) pushq %rbp movq %rsp, %rbp xchgq %rdi, %rsi /* make %rsi source, %rdi dest */ movq %rdx, %rcx /* load count */ repz /* repeat for count ... */ smovb /* move from %ds:rsi to %ed:rdi */ leave ret END(dtrace_copy) /* void dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size, volatile uint16_t *flags) */ ENTRY(dtrace_copystr) pushq %rbp movq %rsp, %rbp 0: movb (%rdi), %al /* load from source */ movb %al, (%rsi) /* store to destination */ addq $1, %rdi /* increment source pointer */ addq $1, %rsi /* increment destination pointer */ subq $1, %rdx /* decrement remaining count */ cmpb $0, %al je 2f testq $0xfff, %rdx /* test if count is 4k-aligned */ jnz 1f /* if not, continue with copying */ testq $CPU_DTRACE_BADADDR, (%rcx) /* load and test dtrace flags */ jnz 2f 1: cmpq $0, %rdx jne 0b 2: leave ret END(dtrace_copystr) /* uintptr_t dtrace_fulword(void *addr) */ ENTRY(dtrace_fulword) movq (%rdi), %rax ret END(dtrace_fulword) /* uint8_t dtrace_fuword8_nocheck(void *addr) */ ENTRY(dtrace_fuword8_nocheck) xorq %rax, %rax movb (%rdi), %al ret END(dtrace_fuword8_nocheck) /* uint16_t dtrace_fuword16_nocheck(void *addr) */ ENTRY(dtrace_fuword16_nocheck) xorq %rax, %rax movw (%rdi), %ax ret END(dtrace_fuword16_nocheck) /* uint32_t dtrace_fuword32_nocheck(void *addr) */ ENTRY(dtrace_fuword32_nocheck) xorq %rax, %rax movl (%rdi), %eax ret END(dtrace_fuword32_nocheck) /* uint64_t dtrace_fuword64_nocheck(void *addr) */ ENTRY(dtrace_fuword64_nocheck) movq (%rdi), %rax ret END(dtrace_fuword64_nocheck) /* void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval) */ ENTRY(dtrace_probe_error) pushq %rbp movq %rsp, %rbp subq $0x8, %rsp movq %r9, (%rsp) movq %r8, %r9 movq %rcx, %r8 movq %rdx, %rcx movq %rsi, %rdx movq %rdi, %rsi movl dtrace_probeid_error(%rip), %edi call dtrace_probe addq $0x8, %rsp leave ret END(dtrace_probe_error) /* void dtrace_membar_producer(void) */ ENTRY(dtrace_membar_producer) rep; ret /* use 2 byte return instruction when branch target */ /* AMD Software Optimization Guide - Section 6.2 */ END(dtrace_membar_producer) /* void dtrace_membar_consumer(void) */ ENTRY(dtrace_membar_consumer) rep; ret /* use 2 byte return instruction when branch target */ /* AMD Software Optimization Guide - Section 6.2 */ END(dtrace_membar_consumer) /* dtrace_icookie_t dtrace_interrupt_disable(void) */ ENTRY(dtrace_interrupt_disable) pushfq popq %rax cli ret END(dtrace_interrupt_disable) /* void dtrace_interrupt_enable(dtrace_icookie_t cookie) */ ENTRY(dtrace_interrupt_enable) pushq %rdi popfq ret END(dtrace_interrupt_enable) Index: head/sys/cddl/dev/dtrace/i386/dtrace_asm.S =================================================================== --- head/sys/cddl/dev/dtrace/i386/dtrace_asm.S (revision 283508) +++ head/sys/cddl/dev/dtrace/i386/dtrace_asm.S (revision 283509) @@ -1,357 +1,355 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * $FreeBSD$ */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #define _ASM #include #include #include #include "assym.s" - .globl calltrap - .type calltrap,@function ENTRY(dtrace_invop_start) pushl %eax /* push %eax -- may be return value */ pushl %esp /* push stack pointer */ addl $48, (%esp) /* adjust to incoming args */ pushl 40(%esp) /* push calling EIP */ /* * Call dtrace_invop to let it check if the exception was * a fbt one. The return value in %eax will tell us what * dtrace_invop wants us to do. */ call dtrace_invop ALTENTRY(dtrace_invop_callsite) addl $12, %esp cmpl $DTRACE_INVOP_PUSHL_EBP, %eax je invop_push cmpl $DTRACE_INVOP_POPL_EBP, %eax je invop_pop cmpl $DTRACE_INVOP_LEAVE, %eax je invop_leave cmpl $DTRACE_INVOP_NOP, %eax je invop_nop /* When all else fails handle the trap in the usual way. */ jmpl *dtrace_invop_calltrap_addr invop_push: /* * We must emulate a "pushl %ebp". To do this, we pull the stack * down 4 bytes, and then store the base pointer. */ popal subl $4, %esp /* make room for %ebp */ pushl %eax /* push temp */ movl 8(%esp), %eax /* load calling EIP */ incl %eax /* increment over LOCK prefix */ movl %eax, 4(%esp) /* store calling EIP */ movl 12(%esp), %eax /* load calling CS */ movl %eax, 8(%esp) /* store calling CS */ movl 16(%esp), %eax /* load calling EFLAGS */ movl %eax, 12(%esp) /* store calling EFLAGS */ movl %ebp, 16(%esp) /* push %ebp */ popl %eax /* pop off temp */ iret /* Return from interrupt. */ invop_pop: /* * We must emulate a "popl %ebp". To do this, we do the opposite of * the above: we remove the %ebp from the stack, and squeeze up the * saved state from the trap. */ popal pushl %eax /* push temp */ movl 16(%esp), %ebp /* pop %ebp */ movl 12(%esp), %eax /* load calling EFLAGS */ movl %eax, 16(%esp) /* store calling EFLAGS */ movl 8(%esp), %eax /* load calling CS */ movl %eax, 12(%esp) /* store calling CS */ movl 4(%esp), %eax /* load calling EIP */ incl %eax /* increment over LOCK prefix */ movl %eax, 8(%esp) /* store calling EIP */ popl %eax /* pop off temp */ addl $4, %esp /* adjust stack pointer */ iret /* Return from interrupt. */ invop_leave: /* * We must emulate a "leave", which is the same as a "movl %ebp, %esp" * followed by a "popl %ebp". This looks similar to the above, but * requires two temporaries: one for the new base pointer, and one * for the staging register. */ popa pushl %eax /* push temp */ pushl %ebx /* push temp */ movl %ebp, %ebx /* set temp to old %ebp */ movl (%ebx), %ebp /* pop %ebp */ movl 16(%esp), %eax /* load calling EFLAGS */ movl %eax, (%ebx) /* store calling EFLAGS */ movl 12(%esp), %eax /* load calling CS */ movl %eax, -4(%ebx) /* store calling CS */ movl 8(%esp), %eax /* load calling EIP */ incl %eax /* increment over LOCK prefix */ movl %eax, -8(%ebx) /* store calling EIP */ subl $8, %ebx /* adjust for three pushes, one pop */ movl %ebx, 8(%esp) /* temporarily store new %esp */ popl %ebx /* pop off temp */ popl %eax /* pop off temp */ movl (%esp), %esp /* set stack pointer */ iret /* return from interrupt */ invop_nop: /* * We must emulate a "nop". This is obviously not hard: we need only * advance the %eip by one. */ popa incl (%esp) iret /* return from interrupt */ END(dtrace_invop_start) /* void dtrace_invop_init(void) */ ENTRY(dtrace_invop_init) movl $dtrace_invop_start, dtrace_invop_jump_addr ret END(dtrace_invop_init) /* void dtrace_invop_uninit(void) */ ENTRY(dtrace_invop_uninit) movl $0, dtrace_invop_jump_addr ret END(dtrace_invop_uninit) /* greg_t dtrace_getfp(void) */ ENTRY(dtrace_getfp) movl %ebp, %eax ret END(dtrace_getfp) /* uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) */ ENTRY(dtrace_cas32) ALTENTRY(dtrace_casptr) movl 4(%esp), %edx movl 8(%esp), %eax movl 12(%esp), %ecx lock cmpxchgl %ecx, (%edx) ret END(dtrace_casptr) END(dtrace_cas32) /* uintptr_t dtrace_caller(int aframes) */ ENTRY(dtrace_caller) movl $-1, %eax ret END(dtrace_caller) /* void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size) */ ENTRY(dtrace_copy) pushl %ebp movl %esp, %ebp pushl %esi pushl %edi movl 8(%ebp), %esi /* Load source address */ movl 12(%ebp), %edi /* Load destination address */ movl 16(%ebp), %ecx /* Load count */ repz /* Repeat for count... */ smovb /* move from %ds:si to %es:di */ popl %edi popl %esi movl %ebp, %esp popl %ebp ret END(dtrace_copy) /* void dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size) */ ENTRY(dtrace_copystr) pushl %ebp /* Setup stack frame */ movl %esp, %ebp pushl %ebx /* Save registers */ movl 8(%ebp), %ebx /* Load source address */ movl 12(%ebp), %edx /* Load destination address */ movl 16(%ebp), %ecx /* Load count */ 0: movb (%ebx), %al /* Load from source */ movb %al, (%edx) /* Store to destination */ incl %ebx /* Increment source pointer */ incl %edx /* Increment destination pointer */ decl %ecx /* Decrement remaining count */ cmpb $0, %al je 1f cmpl $0, %ecx jne 0b 1: popl %ebx movl %ebp, %esp popl %ebp ret END(dtrace_copystr) /* uintptr_t dtrace_fulword(void *addr) */ ENTRY(dtrace_fulword) movl 4(%esp), %ecx xorl %eax, %eax movl (%ecx), %eax ret END(dtrace_fulword) /* uint8_t dtrace_fuword8_nocheck(void *addr) */ ENTRY(dtrace_fuword8_nocheck) movl 4(%esp), %ecx xorl %eax, %eax movzbl (%ecx), %eax ret END(dtrace_fuword8_nocheck) /* uint16_t dtrace_fuword16_nocheck(void *addr) */ ENTRY(dtrace_fuword16_nocheck) movl 4(%esp), %ecx xorl %eax, %eax movzwl (%ecx), %eax ret END(dtrace_fuword16_nocheck) /* uint32_t dtrace_fuword32_nocheck(void *addr) */ ENTRY(dtrace_fuword32_nocheck) movl 4(%esp), %ecx xorl %eax, %eax movl (%ecx), %eax ret END(dtrace_fuword32_nocheck) /* uint64_t dtrace_fuword64_nocheck(void *addr) */ ENTRY(dtrace_fuword64_nocheck) movl 4(%esp), %ecx xorl %eax, %eax xorl %edx, %edx movl (%ecx), %eax movl 4(%ecx), %edx ret END(dtrace_fuword64_nocheck) /* void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval) */ ENTRY(dtrace_probe_error) pushl %ebp movl %esp, %ebp pushl 0x1c(%ebp) pushl 0x18(%ebp) pushl 0x14(%ebp) pushl 0x10(%ebp) pushl 0xc(%ebp) pushl 0x8(%ebp) pushl dtrace_probeid_error call dtrace_probe movl %ebp, %esp popl %ebp ret END(dtrace_probe_error) /* void dtrace_membar_producer(void) */ ENTRY(dtrace_membar_producer) rep; ret /* use 2 byte return instruction when branch target */ /* AMD Software Optimization Guide - Section 6.2 */ END(dtrace_membar_producer) /* void dtrace_membar_consumer(void) */ ENTRY(dtrace_membar_consumer) rep; ret /* use 2 byte return instruction when branch target */ /* AMD Software Optimization Guide - Section 6.2 */ END(dtrace_membar_consumer) /* dtrace_icookie_t dtrace_interrupt_disable(void) */ ENTRY(dtrace_interrupt_disable) pushfl popl %eax cli ret END(dtrace_interrupt_disable) /* void dtrace_interrupt_enable(dtrace_icookie_t cookie) */ ENTRY(dtrace_interrupt_enable) movl 4(%esp), %eax pushl %eax popfl ret END(dtrace_interrupt_enable)