1179237Sjb/* 2179237Sjb * CDDL HEADER START 3179237Sjb * 4179237Sjb * The contents of this file are subject to the terms of the 5179237Sjb * Common Development and Distribution License, Version 1.0 only 6179237Sjb * (the "License"). You may not use this file except in compliance 7179237Sjb * with the License. 8179237Sjb * 9179237Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10179237Sjb * or http://www.opensolaris.org/os/licensing. 11179237Sjb * See the License for the specific language governing permissions 12179237Sjb * and limitations under the License. 13179237Sjb * 14179237Sjb * When distributing Covered Code, include this CDDL HEADER in each 15179237Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16179237Sjb * If applicable, add the following below this CDDL HEADER, with the 17179237Sjb * fields enclosed by brackets "[]" replaced with your own identifying 18179237Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 19179237Sjb * 20179237Sjb * CDDL HEADER END 21179237Sjb * 22179237Sjb * $FreeBSD$ 23179237Sjb */ 24179237Sjb/* 25179237Sjb * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 26179237Sjb * Use is subject to license terms. 27179237Sjb */ 28179237Sjb 29179237Sjb#define _ASM 30179237Sjb 31179237Sjb#include <machine/asmacros.h> 32179237Sjb#include <sys/cpuvar_defs.h> 33179237Sjb#include <sys/dtrace.h> 34179237Sjb 35179237Sjb#include "assym.s" 36179237Sjb 37179237Sjb .globl calltrap 38179237Sjb .type calltrap,@function 39179237Sjb ENTRY(dtrace_invop_start) 40179237Sjb 41179237Sjb pushl %eax /* push %eax -- may be return value */ 42179237Sjb pushl %esp /* push stack pointer */ 43179237Sjb addl $48, (%esp) /* adjust to incoming args */ 44179237Sjb pushl 40(%esp) /* push calling EIP */ 45179237Sjb 46179237Sjb /* 47179237Sjb * Call dtrace_invop to let it check if the exception was 48179237Sjb * a fbt one. The return value in %eax will tell us what 49179237Sjb * dtrace_invop wants us to do. 50179237Sjb */ 51179237Sjb call dtrace_invop 52269557Smarkj ALTENTRY(dtrace_invop_callsite) 53179237Sjb addl $12, %esp 54179237Sjb cmpl $DTRACE_INVOP_PUSHL_EBP, %eax 55179237Sjb je invop_push 56179237Sjb cmpl $DTRACE_INVOP_POPL_EBP, %eax 57179237Sjb je invop_pop 58179237Sjb cmpl $DTRACE_INVOP_LEAVE, %eax 59179237Sjb je invop_leave 60179237Sjb cmpl $DTRACE_INVOP_NOP, %eax 61179237Sjb je invop_nop 62179237Sjb 63179237Sjb /* When all else fails handle the trap in the usual way. */ 64179237Sjb jmpl *dtrace_invop_calltrap_addr 65179237Sjb 66179237Sjbinvop_push: 67179237Sjb /* 68179237Sjb * We must emulate a "pushl %ebp". To do this, we pull the stack 69179237Sjb * down 4 bytes, and then store the base pointer. 70179237Sjb */ 71179237Sjb popal 72179237Sjb subl $4, %esp /* make room for %ebp */ 73179237Sjb pushl %eax /* push temp */ 74179237Sjb movl 8(%esp), %eax /* load calling EIP */ 75179237Sjb incl %eax /* increment over LOCK prefix */ 76179237Sjb movl %eax, 4(%esp) /* store calling EIP */ 77179237Sjb movl 12(%esp), %eax /* load calling CS */ 78179237Sjb movl %eax, 8(%esp) /* store calling CS */ 79179237Sjb movl 16(%esp), %eax /* load calling EFLAGS */ 80179237Sjb movl %eax, 12(%esp) /* store calling EFLAGS */ 81179237Sjb movl %ebp, 16(%esp) /* push %ebp */ 82179237Sjb popl %eax /* pop off temp */ 83179237Sjb iret /* Return from interrupt. */ 84179237Sjbinvop_pop: 85179237Sjb /* 86179237Sjb * We must emulate a "popl %ebp". To do this, we do the opposite of 87179237Sjb * the above: we remove the %ebp from the stack, and squeeze up the 88179237Sjb * saved state from the trap. 89179237Sjb */ 90179237Sjb popal 91179237Sjb pushl %eax /* push temp */ 92179237Sjb movl 16(%esp), %ebp /* pop %ebp */ 93179237Sjb movl 12(%esp), %eax /* load calling EFLAGS */ 94179237Sjb movl %eax, 16(%esp) /* store calling EFLAGS */ 95179237Sjb movl 8(%esp), %eax /* load calling CS */ 96179237Sjb movl %eax, 12(%esp) /* store calling CS */ 97179237Sjb movl 4(%esp), %eax /* load calling EIP */ 98179237Sjb incl %eax /* increment over LOCK prefix */ 99179237Sjb movl %eax, 8(%esp) /* store calling EIP */ 100179237Sjb popl %eax /* pop off temp */ 101179237Sjb addl $4, %esp /* adjust stack pointer */ 102179237Sjb iret /* Return from interrupt. */ 103179237Sjbinvop_leave: 104179237Sjb /* 105179237Sjb * We must emulate a "leave", which is the same as a "movl %ebp, %esp" 106179237Sjb * followed by a "popl %ebp". This looks similar to the above, but 107179237Sjb * requires two temporaries: one for the new base pointer, and one 108179237Sjb * for the staging register. 109179237Sjb */ 110179237Sjb popa 111179237Sjb pushl %eax /* push temp */ 112179237Sjb pushl %ebx /* push temp */ 113179237Sjb movl %ebp, %ebx /* set temp to old %ebp */ 114179237Sjb movl (%ebx), %ebp /* pop %ebp */ 115179237Sjb movl 16(%esp), %eax /* load calling EFLAGS */ 116179237Sjb movl %eax, (%ebx) /* store calling EFLAGS */ 117179237Sjb movl 12(%esp), %eax /* load calling CS */ 118179237Sjb movl %eax, -4(%ebx) /* store calling CS */ 119179237Sjb movl 8(%esp), %eax /* load calling EIP */ 120179237Sjb incl %eax /* increment over LOCK prefix */ 121179237Sjb movl %eax, -8(%ebx) /* store calling EIP */ 122227430Srstone subl $8, %ebx /* adjust for three pushes, one pop */ 123227430Srstone movl %ebx, 8(%esp) /* temporarily store new %esp */ 124179237Sjb popl %ebx /* pop off temp */ 125179237Sjb popl %eax /* pop off temp */ 126227430Srstone movl (%esp), %esp /* set stack pointer */ 127179237Sjb iret /* return from interrupt */ 128179237Sjbinvop_nop: 129179237Sjb /* 130179237Sjb * We must emulate a "nop". This is obviously not hard: we need only 131179237Sjb * advance the %eip by one. 132179237Sjb */ 133179237Sjb popa 134179237Sjb incl (%esp) 135179237Sjb iret /* return from interrupt */ 136179237Sjb 137179237Sjb END(dtrace_invop_start) 138179237Sjb 139179237Sjb/* 140179237Sjbvoid dtrace_invop_init(void) 141179237Sjb*/ 142179237Sjb ENTRY(dtrace_invop_init) 143179237Sjb movl $dtrace_invop_start, dtrace_invop_jump_addr 144179237Sjb ret 145179237Sjb END(dtrace_invop_init) 146179237Sjb 147179237Sjb/* 148179237Sjbvoid dtrace_invop_uninit(void) 149179237Sjb*/ 150179237Sjb ENTRY(dtrace_invop_uninit) 151179237Sjb movl $0, dtrace_invop_jump_addr 152179237Sjb ret 153179237Sjb END(dtrace_invop_uninit) 154179237Sjb 155179237Sjb/* 156179237Sjbgreg_t dtrace_getfp(void) 157179237Sjb*/ 158179237Sjb 159179237Sjb ENTRY(dtrace_getfp) 160179237Sjb movl %ebp, %eax 161179237Sjb ret 162179237Sjb END(dtrace_getfp) 163179237Sjb 164179237Sjb/* 165179237Sjbuint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) 166179237Sjb*/ 167179237Sjb 168179237Sjb ENTRY(dtrace_cas32) 169179237Sjb ALTENTRY(dtrace_casptr) 170179237Sjb movl 4(%esp), %edx 171179237Sjb movl 8(%esp), %eax 172179237Sjb movl 12(%esp), %ecx 173179237Sjb lock 174179237Sjb cmpxchgl %ecx, (%edx) 175179237Sjb ret 176179237Sjb END(dtrace_casptr) 177179237Sjb END(dtrace_cas32) 178179237Sjb 179179237Sjb/* 180179237Sjbuintptr_t dtrace_caller(int aframes) 181179237Sjb*/ 182179237Sjb 183179237Sjb ENTRY(dtrace_caller) 184179237Sjb movl $-1, %eax 185179237Sjb ret 186179237Sjb END(dtrace_caller) 187179237Sjb 188179237Sjb/* 189179237Sjbvoid dtrace_copy(uintptr_t src, uintptr_t dest, size_t size) 190179237Sjb*/ 191179237Sjb 192179237Sjb ENTRY(dtrace_copy) 193179237Sjb pushl %ebp 194179237Sjb movl %esp, %ebp 195179237Sjb pushl %esi 196179237Sjb pushl %edi 197179237Sjb 198179237Sjb movl 8(%ebp), %esi /* Load source address */ 199179237Sjb movl 12(%ebp), %edi /* Load destination address */ 200179237Sjb movl 16(%ebp), %ecx /* Load count */ 201179237Sjb repz /* Repeat for count... */ 202179237Sjb smovb /* move from %ds:si to %es:di */ 203179237Sjb 204179237Sjb popl %edi 205179237Sjb popl %esi 206179237Sjb movl %ebp, %esp 207179237Sjb popl %ebp 208179237Sjb ret 209179237Sjb END(dtrace_copy) 210179237Sjb 211179237Sjb/* 212179237Sjbvoid dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size) 213179237Sjb*/ 214179237Sjb 215179237Sjb ENTRY(dtrace_copystr) 216179237Sjb 217179237Sjb pushl %ebp /* Setup stack frame */ 218179237Sjb movl %esp, %ebp 219179237Sjb pushl %ebx /* Save registers */ 220179237Sjb 221179237Sjb movl 8(%ebp), %ebx /* Load source address */ 222179237Sjb movl 12(%ebp), %edx /* Load destination address */ 223179237Sjb movl 16(%ebp), %ecx /* Load count */ 224179237Sjb 225179237Sjb0: 226179237Sjb movb (%ebx), %al /* Load from source */ 227179237Sjb movb %al, (%edx) /* Store to destination */ 228179237Sjb incl %ebx /* Increment source pointer */ 229179237Sjb incl %edx /* Increment destination pointer */ 230179237Sjb decl %ecx /* Decrement remaining count */ 231179237Sjb cmpb $0, %al 232179237Sjb je 1f 233179237Sjb cmpl $0, %ecx 234179237Sjb jne 0b 235179237Sjb 236179237Sjb1: 237179237Sjb popl %ebx 238179237Sjb movl %ebp, %esp 239179237Sjb popl %ebp 240179237Sjb ret 241179237Sjb 242179237Sjb END(dtrace_copystr) 243179237Sjb 244179237Sjb/* 245179237Sjbuintptr_t dtrace_fulword(void *addr) 246179237Sjb*/ 247179237Sjb 248179237Sjb ENTRY(dtrace_fulword) 249179237Sjb movl 4(%esp), %ecx 250179237Sjb xorl %eax, %eax 251179237Sjb movl (%ecx), %eax 252179237Sjb ret 253179237Sjb END(dtrace_fulword) 254179237Sjb 255179237Sjb/* 256179237Sjbuint8_t dtrace_fuword8_nocheck(void *addr) 257179237Sjb*/ 258179237Sjb 259179237Sjb ENTRY(dtrace_fuword8_nocheck) 260179237Sjb movl 4(%esp), %ecx 261179237Sjb xorl %eax, %eax 262179237Sjb movzbl (%ecx), %eax 263179237Sjb ret 264179237Sjb END(dtrace_fuword8_nocheck) 265179237Sjb 266179237Sjb/* 267179237Sjbuint16_t dtrace_fuword16_nocheck(void *addr) 268179237Sjb*/ 269179237Sjb 270179237Sjb ENTRY(dtrace_fuword16_nocheck) 271179237Sjb movl 4(%esp), %ecx 272179237Sjb xorl %eax, %eax 273179237Sjb movzwl (%ecx), %eax 274179237Sjb ret 275179237Sjb END(dtrace_fuword16_nocheck) 276179237Sjb 277179237Sjb/* 278179237Sjbuint32_t dtrace_fuword32_nocheck(void *addr) 279179237Sjb*/ 280179237Sjb 281179237Sjb ENTRY(dtrace_fuword32_nocheck) 282179237Sjb movl 4(%esp), %ecx 283179237Sjb xorl %eax, %eax 284179237Sjb movl (%ecx), %eax 285179237Sjb ret 286179237Sjb END(dtrace_fuword32_nocheck) 287179237Sjb 288179237Sjb/* 289179237Sjbuint64_t dtrace_fuword64_nocheck(void *addr) 290179237Sjb*/ 291179237Sjb 292179237Sjb ENTRY(dtrace_fuword64_nocheck) 293179237Sjb movl 4(%esp), %ecx 294179237Sjb xorl %eax, %eax 295179237Sjb xorl %edx, %edx 296179237Sjb movl (%ecx), %eax 297179237Sjb movl 4(%ecx), %edx 298179237Sjb ret 299179237Sjb END(dtrace_fuword64_nocheck) 300179237Sjb 301179237Sjb/* 302179237Sjbvoid dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval) 303179237Sjb*/ 304179237Sjb 305179237Sjb ENTRY(dtrace_probe_error) 306179237Sjb pushl %ebp 307179237Sjb movl %esp, %ebp 308179237Sjb pushl 0x1c(%ebp) 309179237Sjb pushl 0x18(%ebp) 310179237Sjb pushl 0x14(%ebp) 311179237Sjb pushl 0x10(%ebp) 312179237Sjb pushl 0xc(%ebp) 313179237Sjb pushl 0x8(%ebp) 314179237Sjb pushl dtrace_probeid_error 315179237Sjb call dtrace_probe 316179237Sjb movl %ebp, %esp 317179237Sjb popl %ebp 318179237Sjb ret 319179237Sjb END(dtrace_probe_error) 320179237Sjb 321179237Sjb/* 322179237Sjbvoid dtrace_membar_producer(void) 323179237Sjb*/ 324179237Sjb 325179237Sjb ENTRY(dtrace_membar_producer) 326179237Sjb rep; ret /* use 2 byte return instruction when branch target */ 327179237Sjb /* AMD Software Optimization Guide - Section 6.2 */ 328179237Sjb END(dtrace_membar_producer) 329179237Sjb 330179237Sjb/* 331179237Sjbvoid dtrace_membar_consumer(void) 332179237Sjb*/ 333179237Sjb 334179237Sjb ENTRY(dtrace_membar_consumer) 335179237Sjb rep; ret /* use 2 byte return instruction when branch target */ 336179237Sjb /* AMD Software Optimization Guide - Section 6.2 */ 337179237Sjb END(dtrace_membar_consumer) 338179237Sjb 339179237Sjb/* 340179237Sjbdtrace_icookie_t dtrace_interrupt_disable(void) 341179237Sjb*/ 342179237Sjb ENTRY(dtrace_interrupt_disable) 343179237Sjb pushfl 344179237Sjb popl %eax 345179237Sjb cli 346179237Sjb ret 347179237Sjb END(dtrace_interrupt_disable) 348179237Sjb 349179237Sjb/* 350179237Sjbvoid dtrace_interrupt_enable(dtrace_icookie_t cookie) 351179237Sjb*/ 352179237Sjb ENTRY(dtrace_interrupt_enable) 353179237Sjb movl 4(%esp), %eax 354179237Sjb pushl %eax 355179237Sjb popfl 356179237Sjb ret 357179237Sjb END(dtrace_interrupt_enable) 358