profile.h revision 129499
11543Srgrimes/* 21543Srgrimes * Copyright (c) 1992, 1993 31543Srgrimes * The Regents of the University of California. All rights reserved. 41543Srgrimes * 51543Srgrimes * Redistribution and use in source and binary forms, with or without 61543Srgrimes * modification, are permitted provided that the following conditions 71543Srgrimes * are met: 81543Srgrimes * 1. Redistributions of source code must retain the above copyright 91543Srgrimes * notice, this list of conditions and the following disclaimer. 101543Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111543Srgrimes * notice, this list of conditions and the following disclaimer in the 121543Srgrimes * documentation and/or other materials provided with the distribution. 131543Srgrimes * 4. Neither the name of the University nor the names of its contributors 141543Srgrimes * may be used to endorse or promote products derived from this software 151543Srgrimes * without specific prior written permission. 161543Srgrimes * 171543Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181543Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191543Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201543Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211543Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221543Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231543Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241543Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251543Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261543Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271543Srgrimes * SUCH DAMAGE. 281543Srgrimes * 291543Srgrimes * @(#)profile.h 8.1 (Berkeley) 6/11/93 3050477Speter * $FreeBSD: head/sys/amd64/include/profile.h 129499 2004-05-20 16:22:57Z bde $ 311543Srgrimes */ 321543Srgrimes 3313107Sbde#ifndef _MACHINE_PROFILE_H_ 3413107Sbde#define _MACHINE_PROFILE_H_ 352166Spaul 3655205Speter#ifdef _KERNEL 3737542Sbde 3813157Sbde/* 3922639Sbde * Config generates something to tell the compiler to align functions on 16 4022639Sbde * byte boundaries. A strict alignment is good for keeping the tables small. 4122639Sbde */ 4222639Sbde#define FUNCTION_ALIGNMENT 16 4322639Sbde 4422639Sbde/* 4513157Sbde * The kernel uses assembler stubs instead of unportable inlines. 4613157Sbde * This is mainly to save a little time when profiling is not enabled, 4713157Sbde * which is the usual case for the kernel. 4813157Sbde */ 4913157Sbde#define _MCOUNT_DECL void mcount 5013157Sbde#define MCOUNT 511543Srgrimes 5217879Sbde#ifdef GUPROF 5317879Sbde#define MCOUNT_DECL(s) 5417879Sbde#define MCOUNT_ENTER(s) 5517879Sbde#define MCOUNT_EXIT(s) 56129499Sbde#ifdef __GNUC__ 57129499Sbde#define MCOUNT_OVERHEAD(label) \ 58129499Sbde __asm __volatile("pushq %0; call __mcount; popq %%rcx" \ 59129499Sbde : \ 60129499Sbde : "i" (profil) \ 61129499Sbde : "ax", "dx", "cx", "di", "si", "r8", "r9", "memory") 62129499Sbde#define MEXITCOUNT_OVERHEAD() \ 63129499Sbde __asm __volatile("call .mexitcount; 1:" \ 64129499Sbde : : \ 65129499Sbde : "ax", "dx", "cx", "di", "si", "r8", "r9", "memory") 66129499Sbde#define MEXITCOUNT_OVERHEAD_GETLABEL(labelp) \ 67129499Sbde __asm __volatile("movq $1b,%0" : "=rm" (labelp)) 68129499Sbde#elif defined(lint) 69129499Sbde#define MCOUNT_OVERHEAD(label) 70129499Sbde#define MEXITCOUNT_OVERHEAD() 71129499Sbde#define MEXITCOUNT_OVERHEAD_GETLABEL() 7217879Sbde#else 73129499Sbde#error 74129499Sbde#endif /* __GNUC */ 75129499Sbde#else /* !GUPROF */ 7617879Sbde#define MCOUNT_DECL(s) u_long s; 7728921Sfsmp#ifdef SMP 7890024Sbdeextern int mcount_lock; 79114349Speter#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); \ 8079734Sjhb while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \ 8178908Sjhb /* nothing */ ; } 8278908Sjhb#define MCOUNT_EXIT(s) { atomic_store_rel_int(&mcount_lock, 0); \ 83114349Speter write_rflags(s); } 8428921Sfsmp#else 85114349Speter#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); } 86114349Speter#define MCOUNT_EXIT(s) (write_rflags(s)) 8728921Sfsmp#endif 8817879Sbde#endif /* GUPROF */ 8917879Sbde 9055205Speter#else /* !_KERNEL */ 9113157Sbde 9222639Sbde#define FUNCTION_ALIGNMENT 4 9322639Sbde 94129408Speter#define _MCOUNT_DECL \ 95129408Speterstatic void _mcount(uintfptr_t frompc, uintfptr_t selfpc) __unused; \ 96129408Speterstatic void _mcount 9713157Sbde 9895195Smarkm#ifdef __GNUC__ 99129445Sbde#define MCOUNT __asm(" \n\ 100129408Speter .globl .mcount \n\ 101129408Speter .type .mcount @function \n\ 102129408Speter.mcount: \n\ 103129408Speter pushq %rbp \n\ 104129445Sbde movq %rsp,%rbp \n\ 105129408Speter pushq %rdi \n\ 106129408Speter pushq %rsi \n\ 107129408Speter pushq %rdx \n\ 108129408Speter pushq %rcx \n\ 109129408Speter pushq %r8 \n\ 110129408Speter pushq %r9 \n\ 111129408Speter movq 8(%rbp),%rsi \n\ 112129408Speter movq (%rbp),%rdi \n\ 113129408Speter movq 8(%rdi),%rdi \n\ 114129408Speter call _mcount \n\ 115129408Speter popq %r9 \n\ 116129408Speter popq %r8 \n\ 117129408Speter popq %rcx \n\ 118129408Speter popq %rdx \n\ 119129408Speter popq %rsi \n\ 120129408Speter popq %rdi \n\ 121129408Speter leave \n\ 122129408Speter ret \n\ 123129408Speter .size .mcount, . - .mcount"); 124129408Speter#if 0 125129408Speter/* 126129408Speter * We could use this, except it doesn't preserve the registers that were 127129408Speter * being passed with arguments to the function that we were inserted 128129408Speter * into. I've left it here as documentation of what the code above is 129129408Speter * supposed to do. 130129408Speter */ 13195195Smarkm#define MCOUNT \ 13295195Smarkmvoid \ 13395195Smarkmmcount() \ 13495195Smarkm{ \ 13595195Smarkm uintfptr_t selfpc, frompc; \ 13695195Smarkm /* \ 13795195Smarkm * Find the return address for mcount, \ 13895195Smarkm * and the return address for mcount's caller. \ 13995195Smarkm * \ 14095195Smarkm * selfpc = pc pushed by call to mcount \ 14195195Smarkm */ \ 142115659Sobrien __asm("movq 8(%%rbp),%0" : "=r" (selfpc)); \ 14395195Smarkm /* \ 14495195Smarkm * frompc = pc pushed by call to mcount's caller. \ 145129445Sbde * The caller's stack frame has already been built, so %rbp is \ 14695195Smarkm * the caller's frame pointer. The caller's raddr is in the \ 14795195Smarkm * caller's frame following the caller's caller's frame pointer.\ 14895195Smarkm */ \ 149129408Speter __asm("movq (%%rbp),%0" : "=r" (frompc)); \ 15095195Smarkm frompc = ((uintfptr_t *)frompc)[1]; \ 15195195Smarkm _mcount(frompc, selfpc); \ 1521543Srgrimes} 153129408Speter#endif 154129445Sbde#else /* !__GNUC__ */ 155129445Sbde#define MCOUNT \ 156129445Sbdevoid \ 157129445Sbdemcount() \ 158129445Sbde{ \ 15995195Smarkm} 160129445Sbde#endif /* __GNUC__ */ 16137542Sbde 162129445Sbdetypedef u_long uintfptr_t; 16337542Sbde 16455205Speter#endif /* _KERNEL */ 1652166Spaul 16613107Sbde/* 16713107Sbde * An unsigned integral type that can hold non-negative difference between 16813107Sbde * function pointers. 16913107Sbde */ 170129446Sbdetypedef u_long fptrdiff_t; 17113107Sbde 17255205Speter#ifdef _KERNEL 17319000Sbde 17492761Salfredvoid mcount(uintfptr_t frompc, uintfptr_t selfpc); 17519000Sbde 17655205Speter#else /* !_KERNEL */ 17719000Sbde 17819000Sbde#include <sys/cdefs.h> 17919000Sbde 18019000Sbde__BEGIN_DECLS 18133047Sbde#ifdef __GNUC__ 18292761Salfredvoid mcount(void) __asm(".mcount"); 18333047Sbde#endif 18419000Sbde__END_DECLS 18513157Sbde 18655205Speter#endif /* _KERNEL */ 18719000Sbde 18813157Sbde#endif /* !_MACHINE_PROFILE_H_ */ 189