191eaf3e1SJohn Birrell/* 291eaf3e1SJohn Birrell * CDDL HEADER START 391eaf3e1SJohn Birrell * 491eaf3e1SJohn Birrell * The contents of this file are subject to the terms of the 591eaf3e1SJohn Birrell * Common Development and Distribution License, Version 1.0 only 691eaf3e1SJohn Birrell * (the "License"). You may not use this file except in compliance 791eaf3e1SJohn Birrell * with the License. 891eaf3e1SJohn Birrell * 991eaf3e1SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1091eaf3e1SJohn Birrell * or http://www.opensolaris.org/os/licensing. 1191eaf3e1SJohn Birrell * See the License for the specific language governing permissions 1291eaf3e1SJohn Birrell * and limitations under the License. 1391eaf3e1SJohn Birrell * 1491eaf3e1SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 1591eaf3e1SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1691eaf3e1SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 1791eaf3e1SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 1891eaf3e1SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 1991eaf3e1SJohn Birrell * 2091eaf3e1SJohn Birrell * CDDL HEADER END 2191eaf3e1SJohn Birrell */ 2291eaf3e1SJohn Birrell/* 2391eaf3e1SJohn Birrell * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 2491eaf3e1SJohn Birrell * Use is subject to license terms. 2591eaf3e1SJohn Birrell */ 2691eaf3e1SJohn Birrell 2791eaf3e1SJohn Birrell#define _ASM 2891eaf3e1SJohn Birrell 2991eaf3e1SJohn Birrell#include <machine/asmacros.h> 3091eaf3e1SJohn Birrell#include <sys/cpuvar_defs.h> 3191eaf3e1SJohn Birrell#include <sys/dtrace.h> 3291eaf3e1SJohn Birrell 33*fc2a8776SEd Maste#include "assym.inc" 3491eaf3e1SJohn Birrell 3591eaf3e1SJohn Birrell ENTRY(dtrace_invop_start) 3691eaf3e1SJohn Birrell 3791eaf3e1SJohn Birrell pushl %eax /* push %eax -- may be return value */ 3891eaf3e1SJohn Birrell pushl %esp /* push stack pointer */ 396c280659SMark Johnston subl $8, (%esp) /* skip first arg and segment regs */ 4091eaf3e1SJohn Birrell pushl 40(%esp) /* push calling EIP */ 4191eaf3e1SJohn Birrell 4291eaf3e1SJohn Birrell /* 4391eaf3e1SJohn Birrell * Call dtrace_invop to let it check if the exception was 4491eaf3e1SJohn Birrell * a fbt one. The return value in %eax will tell us what 4591eaf3e1SJohn Birrell * dtrace_invop wants us to do. 4691eaf3e1SJohn Birrell */ 4791eaf3e1SJohn Birrell call dtrace_invop 4891eaf3e1SJohn Birrell ALTENTRY(dtrace_invop_callsite) 49efa1aff6SMark Johnston addl $12, %esp 5091eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_PUSHL_EBP, %eax 5191eaf3e1SJohn Birrell je invop_push 5291eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_POPL_EBP, %eax 5391eaf3e1SJohn Birrell je invop_pop 5491eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_LEAVE, %eax 5591eaf3e1SJohn Birrell je invop_leave 5691eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_NOP, %eax 5791eaf3e1SJohn Birrell je invop_nop 5891eaf3e1SJohn Birrell 5991eaf3e1SJohn Birrell /* When all else fails handle the trap in the usual way. */ 6091eaf3e1SJohn Birrell jmpl *dtrace_invop_calltrap_addr 6191eaf3e1SJohn Birrell 6291eaf3e1SJohn Birrellinvop_push: 6391eaf3e1SJohn Birrell /* 6491eaf3e1SJohn Birrell * We must emulate a "pushl %ebp". To do this, we pull the stack 6591eaf3e1SJohn Birrell * down 4 bytes, and then store the base pointer. 6691eaf3e1SJohn Birrell */ 6791eaf3e1SJohn Birrell popal 6891eaf3e1SJohn Birrell subl $4, %esp /* make room for %ebp */ 6991eaf3e1SJohn Birrell pushl %eax /* push temp */ 7091eaf3e1SJohn Birrell movl 8(%esp), %eax /* load calling EIP */ 7191eaf3e1SJohn Birrell incl %eax /* increment over LOCK prefix */ 7291eaf3e1SJohn Birrell movl %eax, 4(%esp) /* store calling EIP */ 7391eaf3e1SJohn Birrell movl 12(%esp), %eax /* load calling CS */ 7491eaf3e1SJohn Birrell movl %eax, 8(%esp) /* store calling CS */ 7591eaf3e1SJohn Birrell movl 16(%esp), %eax /* load calling EFLAGS */ 7691eaf3e1SJohn Birrell movl %eax, 12(%esp) /* store calling EFLAGS */ 7791eaf3e1SJohn Birrell movl %ebp, 16(%esp) /* push %ebp */ 7891eaf3e1SJohn Birrell popl %eax /* pop off temp */ 7991eaf3e1SJohn Birrell iret /* Return from interrupt. */ 8091eaf3e1SJohn Birrellinvop_pop: 8191eaf3e1SJohn Birrell /* 8291eaf3e1SJohn Birrell * We must emulate a "popl %ebp". To do this, we do the opposite of 8391eaf3e1SJohn Birrell * the above: we remove the %ebp from the stack, and squeeze up the 8491eaf3e1SJohn Birrell * saved state from the trap. 8591eaf3e1SJohn Birrell */ 8691eaf3e1SJohn Birrell popal 8791eaf3e1SJohn Birrell pushl %eax /* push temp */ 8891eaf3e1SJohn Birrell movl 16(%esp), %ebp /* pop %ebp */ 8991eaf3e1SJohn Birrell movl 12(%esp), %eax /* load calling EFLAGS */ 9091eaf3e1SJohn Birrell movl %eax, 16(%esp) /* store calling EFLAGS */ 9191eaf3e1SJohn Birrell movl 8(%esp), %eax /* load calling CS */ 9291eaf3e1SJohn Birrell movl %eax, 12(%esp) /* store calling CS */ 9391eaf3e1SJohn Birrell movl 4(%esp), %eax /* load calling EIP */ 9491eaf3e1SJohn Birrell incl %eax /* increment over LOCK prefix */ 9591eaf3e1SJohn Birrell movl %eax, 8(%esp) /* store calling EIP */ 9691eaf3e1SJohn Birrell popl %eax /* pop off temp */ 9791eaf3e1SJohn Birrell addl $4, %esp /* adjust stack pointer */ 9891eaf3e1SJohn Birrell iret /* Return from interrupt. */ 9991eaf3e1SJohn Birrellinvop_leave: 10091eaf3e1SJohn Birrell /* 10191eaf3e1SJohn Birrell * We must emulate a "leave", which is the same as a "movl %ebp, %esp" 10291eaf3e1SJohn Birrell * followed by a "popl %ebp". This looks similar to the above, but 10391eaf3e1SJohn Birrell * requires two temporaries: one for the new base pointer, and one 10491eaf3e1SJohn Birrell * for the staging register. 10591eaf3e1SJohn Birrell */ 10691eaf3e1SJohn Birrell popa 10791eaf3e1SJohn Birrell pushl %eax /* push temp */ 10891eaf3e1SJohn Birrell pushl %ebx /* push temp */ 10991eaf3e1SJohn Birrell movl %ebp, %ebx /* set temp to old %ebp */ 11091eaf3e1SJohn Birrell movl (%ebx), %ebp /* pop %ebp */ 11191eaf3e1SJohn Birrell movl 16(%esp), %eax /* load calling EFLAGS */ 11291eaf3e1SJohn Birrell movl %eax, (%ebx) /* store calling EFLAGS */ 11391eaf3e1SJohn Birrell movl 12(%esp), %eax /* load calling CS */ 11491eaf3e1SJohn Birrell movl %eax, -4(%ebx) /* store calling CS */ 11591eaf3e1SJohn Birrell movl 8(%esp), %eax /* load calling EIP */ 11691eaf3e1SJohn Birrell incl %eax /* increment over LOCK prefix */ 11791eaf3e1SJohn Birrell movl %eax, -8(%ebx) /* store calling EIP */ 118cddcb8b4SRyan Stone subl $8, %ebx /* adjust for three pushes, one pop */ 119cddcb8b4SRyan Stone movl %ebx, 8(%esp) /* temporarily store new %esp */ 12091eaf3e1SJohn Birrell popl %ebx /* pop off temp */ 12191eaf3e1SJohn Birrell popl %eax /* pop off temp */ 122cddcb8b4SRyan Stone movl (%esp), %esp /* set stack pointer */ 12391eaf3e1SJohn Birrell iret /* return from interrupt */ 12491eaf3e1SJohn Birrellinvop_nop: 12591eaf3e1SJohn Birrell /* 12691eaf3e1SJohn Birrell * We must emulate a "nop". This is obviously not hard: we need only 12791eaf3e1SJohn Birrell * advance the %eip by one. 12891eaf3e1SJohn Birrell */ 12991eaf3e1SJohn Birrell popa 13091eaf3e1SJohn Birrell incl (%esp) 13191eaf3e1SJohn Birrell iret /* return from interrupt */ 13291eaf3e1SJohn Birrell 13391eaf3e1SJohn Birrell END(dtrace_invop_start) 13491eaf3e1SJohn Birrell 13591eaf3e1SJohn Birrell/* 13691eaf3e1SJohn Birrellgreg_t dtrace_getfp(void) 13791eaf3e1SJohn Birrell*/ 13891eaf3e1SJohn Birrell 13991eaf3e1SJohn Birrell ENTRY(dtrace_getfp) 14091eaf3e1SJohn Birrell movl %ebp, %eax 14191eaf3e1SJohn Birrell ret 14291eaf3e1SJohn Birrell END(dtrace_getfp) 14391eaf3e1SJohn Birrell 14491eaf3e1SJohn Birrell/* 14591eaf3e1SJohn Birrelluint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) 14691eaf3e1SJohn Birrell*/ 14791eaf3e1SJohn Birrell 14891eaf3e1SJohn Birrell ENTRY(dtrace_cas32) 14991eaf3e1SJohn Birrell ALTENTRY(dtrace_casptr) 15091eaf3e1SJohn Birrell movl 4(%esp), %edx 15191eaf3e1SJohn Birrell movl 8(%esp), %eax 15291eaf3e1SJohn Birrell movl 12(%esp), %ecx 15391eaf3e1SJohn Birrell lock 15491eaf3e1SJohn Birrell cmpxchgl %ecx, (%edx) 15591eaf3e1SJohn Birrell ret 15691eaf3e1SJohn Birrell END(dtrace_casptr) 15791eaf3e1SJohn Birrell END(dtrace_cas32) 15891eaf3e1SJohn Birrell 15991eaf3e1SJohn Birrell/* 16091eaf3e1SJohn Birrelluintptr_t dtrace_caller(int aframes) 16191eaf3e1SJohn Birrell*/ 16291eaf3e1SJohn Birrell 16391eaf3e1SJohn Birrell ENTRY(dtrace_caller) 16491eaf3e1SJohn Birrell movl $-1, %eax 16591eaf3e1SJohn Birrell ret 16691eaf3e1SJohn Birrell END(dtrace_caller) 16791eaf3e1SJohn Birrell 16891eaf3e1SJohn Birrell/* 16991eaf3e1SJohn Birrellvoid dtrace_copy(uintptr_t src, uintptr_t dest, size_t size) 17091eaf3e1SJohn Birrell*/ 17191eaf3e1SJohn Birrell 17291eaf3e1SJohn Birrell ENTRY(dtrace_copy) 17391eaf3e1SJohn Birrell pushl %ebp 17491eaf3e1SJohn Birrell movl %esp, %ebp 17591eaf3e1SJohn Birrell pushl %esi 17691eaf3e1SJohn Birrell pushl %edi 17791eaf3e1SJohn Birrell 17891eaf3e1SJohn Birrell movl 8(%ebp), %esi /* Load source address */ 17991eaf3e1SJohn Birrell movl 12(%ebp), %edi /* Load destination address */ 18091eaf3e1SJohn Birrell movl 16(%ebp), %ecx /* Load count */ 18191eaf3e1SJohn Birrell repz /* Repeat for count... */ 18291eaf3e1SJohn Birrell smovb /* move from %ds:si to %es:di */ 18391eaf3e1SJohn Birrell 18491eaf3e1SJohn Birrell popl %edi 18591eaf3e1SJohn Birrell popl %esi 18691eaf3e1SJohn Birrell movl %ebp, %esp 18791eaf3e1SJohn Birrell popl %ebp 18891eaf3e1SJohn Birrell ret 18991eaf3e1SJohn Birrell END(dtrace_copy) 19091eaf3e1SJohn Birrell 19191eaf3e1SJohn Birrell/* 19291eaf3e1SJohn Birrellvoid dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size) 19391eaf3e1SJohn Birrell*/ 19491eaf3e1SJohn Birrell 19591eaf3e1SJohn Birrell ENTRY(dtrace_copystr) 19691eaf3e1SJohn Birrell 19791eaf3e1SJohn Birrell pushl %ebp /* Setup stack frame */ 19891eaf3e1SJohn Birrell movl %esp, %ebp 19991eaf3e1SJohn Birrell pushl %ebx /* Save registers */ 20091eaf3e1SJohn Birrell 20191eaf3e1SJohn Birrell movl 8(%ebp), %ebx /* Load source address */ 20291eaf3e1SJohn Birrell movl 12(%ebp), %edx /* Load destination address */ 20391eaf3e1SJohn Birrell movl 16(%ebp), %ecx /* Load count */ 20491eaf3e1SJohn Birrell 20591eaf3e1SJohn Birrell0: 20691eaf3e1SJohn Birrell movb (%ebx), %al /* Load from source */ 20791eaf3e1SJohn Birrell movb %al, (%edx) /* Store to destination */ 20891eaf3e1SJohn Birrell incl %ebx /* Increment source pointer */ 20991eaf3e1SJohn Birrell incl %edx /* Increment destination pointer */ 21091eaf3e1SJohn Birrell decl %ecx /* Decrement remaining count */ 21191eaf3e1SJohn Birrell cmpb $0, %al 21291eaf3e1SJohn Birrell je 1f 21391eaf3e1SJohn Birrell cmpl $0, %ecx 21491eaf3e1SJohn Birrell jne 0b 21591eaf3e1SJohn Birrell 21691eaf3e1SJohn Birrell1: 21791eaf3e1SJohn Birrell popl %ebx 21891eaf3e1SJohn Birrell movl %ebp, %esp 21991eaf3e1SJohn Birrell popl %ebp 22091eaf3e1SJohn Birrell ret 22191eaf3e1SJohn Birrell 22291eaf3e1SJohn Birrell END(dtrace_copystr) 22391eaf3e1SJohn Birrell 22491eaf3e1SJohn Birrell/* 22591eaf3e1SJohn Birrelluintptr_t dtrace_fulword(void *addr) 22691eaf3e1SJohn Birrell*/ 22791eaf3e1SJohn Birrell 22891eaf3e1SJohn Birrell ENTRY(dtrace_fulword) 22991eaf3e1SJohn Birrell movl 4(%esp), %ecx 23091eaf3e1SJohn Birrell xorl %eax, %eax 23191eaf3e1SJohn Birrell movl (%ecx), %eax 23291eaf3e1SJohn Birrell ret 23391eaf3e1SJohn Birrell END(dtrace_fulword) 23491eaf3e1SJohn Birrell 23591eaf3e1SJohn Birrell/* 23691eaf3e1SJohn Birrelluint8_t dtrace_fuword8_nocheck(void *addr) 23791eaf3e1SJohn Birrell*/ 23891eaf3e1SJohn Birrell 23991eaf3e1SJohn Birrell ENTRY(dtrace_fuword8_nocheck) 24091eaf3e1SJohn Birrell movl 4(%esp), %ecx 24191eaf3e1SJohn Birrell xorl %eax, %eax 24291eaf3e1SJohn Birrell movzbl (%ecx), %eax 24391eaf3e1SJohn Birrell ret 24491eaf3e1SJohn Birrell END(dtrace_fuword8_nocheck) 24591eaf3e1SJohn Birrell 24691eaf3e1SJohn Birrell/* 24791eaf3e1SJohn Birrelluint16_t dtrace_fuword16_nocheck(void *addr) 24891eaf3e1SJohn Birrell*/ 24991eaf3e1SJohn Birrell 25091eaf3e1SJohn Birrell ENTRY(dtrace_fuword16_nocheck) 25191eaf3e1SJohn Birrell movl 4(%esp), %ecx 25291eaf3e1SJohn Birrell xorl %eax, %eax 25391eaf3e1SJohn Birrell movzwl (%ecx), %eax 25491eaf3e1SJohn Birrell ret 25591eaf3e1SJohn Birrell END(dtrace_fuword16_nocheck) 25691eaf3e1SJohn Birrell 25791eaf3e1SJohn Birrell/* 25891eaf3e1SJohn Birrelluint32_t dtrace_fuword32_nocheck(void *addr) 25991eaf3e1SJohn Birrell*/ 26091eaf3e1SJohn Birrell 26191eaf3e1SJohn Birrell ENTRY(dtrace_fuword32_nocheck) 26291eaf3e1SJohn Birrell movl 4(%esp), %ecx 26391eaf3e1SJohn Birrell xorl %eax, %eax 26491eaf3e1SJohn Birrell movl (%ecx), %eax 26591eaf3e1SJohn Birrell ret 26691eaf3e1SJohn Birrell END(dtrace_fuword32_nocheck) 26791eaf3e1SJohn Birrell 26891eaf3e1SJohn Birrell/* 26991eaf3e1SJohn Birrelluint64_t dtrace_fuword64_nocheck(void *addr) 27091eaf3e1SJohn Birrell*/ 27191eaf3e1SJohn Birrell 27291eaf3e1SJohn Birrell ENTRY(dtrace_fuword64_nocheck) 27391eaf3e1SJohn Birrell movl 4(%esp), %ecx 27491eaf3e1SJohn Birrell xorl %eax, %eax 27591eaf3e1SJohn Birrell xorl %edx, %edx 27691eaf3e1SJohn Birrell movl (%ecx), %eax 27791eaf3e1SJohn Birrell movl 4(%ecx), %edx 27891eaf3e1SJohn Birrell ret 27991eaf3e1SJohn Birrell END(dtrace_fuword64_nocheck) 28091eaf3e1SJohn Birrell 28191eaf3e1SJohn Birrell/* 28291eaf3e1SJohn Birrellvoid dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval) 28391eaf3e1SJohn Birrell*/ 28491eaf3e1SJohn Birrell 28591eaf3e1SJohn Birrell ENTRY(dtrace_probe_error) 28691eaf3e1SJohn Birrell pushl %ebp 28791eaf3e1SJohn Birrell movl %esp, %ebp 28891eaf3e1SJohn Birrell pushl 0x1c(%ebp) 28991eaf3e1SJohn Birrell pushl 0x18(%ebp) 29091eaf3e1SJohn Birrell pushl 0x14(%ebp) 29191eaf3e1SJohn Birrell pushl 0x10(%ebp) 29291eaf3e1SJohn Birrell pushl 0xc(%ebp) 29391eaf3e1SJohn Birrell pushl 0x8(%ebp) 29491eaf3e1SJohn Birrell pushl dtrace_probeid_error 29591eaf3e1SJohn Birrell call dtrace_probe 29691eaf3e1SJohn Birrell movl %ebp, %esp 29791eaf3e1SJohn Birrell popl %ebp 29891eaf3e1SJohn Birrell ret 29991eaf3e1SJohn Birrell END(dtrace_probe_error) 30091eaf3e1SJohn Birrell 30191eaf3e1SJohn Birrell/* 30291eaf3e1SJohn Birrellvoid dtrace_membar_producer(void) 30391eaf3e1SJohn Birrell*/ 30491eaf3e1SJohn Birrell 30591eaf3e1SJohn Birrell ENTRY(dtrace_membar_producer) 30691eaf3e1SJohn Birrell rep; ret /* use 2 byte return instruction when branch target */ 30791eaf3e1SJohn Birrell /* AMD Software Optimization Guide - Section 6.2 */ 30891eaf3e1SJohn Birrell END(dtrace_membar_producer) 30991eaf3e1SJohn Birrell 31091eaf3e1SJohn Birrell/* 31191eaf3e1SJohn Birrellvoid dtrace_membar_consumer(void) 31291eaf3e1SJohn Birrell*/ 31391eaf3e1SJohn Birrell 31491eaf3e1SJohn Birrell ENTRY(dtrace_membar_consumer) 31591eaf3e1SJohn Birrell rep; ret /* use 2 byte return instruction when branch target */ 31691eaf3e1SJohn Birrell /* AMD Software Optimization Guide - Section 6.2 */ 31791eaf3e1SJohn Birrell END(dtrace_membar_consumer) 31891eaf3e1SJohn Birrell 31991eaf3e1SJohn Birrell/* 32091eaf3e1SJohn Birrelldtrace_icookie_t dtrace_interrupt_disable(void) 32191eaf3e1SJohn Birrell*/ 32291eaf3e1SJohn Birrell ENTRY(dtrace_interrupt_disable) 32391eaf3e1SJohn Birrell pushfl 32491eaf3e1SJohn Birrell popl %eax 32591eaf3e1SJohn Birrell cli 32691eaf3e1SJohn Birrell ret 32791eaf3e1SJohn Birrell END(dtrace_interrupt_disable) 32891eaf3e1SJohn Birrell 32991eaf3e1SJohn Birrell/* 33091eaf3e1SJohn Birrellvoid dtrace_interrupt_enable(dtrace_icookie_t cookie) 33191eaf3e1SJohn Birrell*/ 33291eaf3e1SJohn Birrell ENTRY(dtrace_interrupt_enable) 33391eaf3e1SJohn Birrell movl 4(%esp), %eax 33491eaf3e1SJohn Birrell pushl %eax 33591eaf3e1SJohn Birrell popfl 33691eaf3e1SJohn Birrell ret 33791eaf3e1SJohn Birrell END(dtrace_interrupt_enable) 338