profile.h revision 129445
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 129445 2004-05-19 16:04:26Z 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) 5617879Sbde#else 5717879Sbde#define MCOUNT_DECL(s) u_long s; 5828921Sfsmp#ifdef SMP 5990024Sbdeextern int mcount_lock; 60114349Speter#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); \ 6179734Sjhb while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \ 6278908Sjhb /* nothing */ ; } 6378908Sjhb#define MCOUNT_EXIT(s) { atomic_store_rel_int(&mcount_lock, 0); \ 64114349Speter write_rflags(s); } 6528921Sfsmp#else 66114349Speter#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); } 67114349Speter#define MCOUNT_EXIT(s) (write_rflags(s)) 6828921Sfsmp#endif 6917879Sbde#endif /* GUPROF */ 7017879Sbde 7155205Speter#else /* !_KERNEL */ 7213157Sbde 7322639Sbde#define FUNCTION_ALIGNMENT 4 7422639Sbde 75129408Speter#define _MCOUNT_DECL \ 76129408Speterstatic void _mcount(uintfptr_t frompc, uintfptr_t selfpc) __unused; \ 77129408Speterstatic void _mcount 7813157Sbde 7995195Smarkm#ifdef __GNUC__ 80129445Sbde#define MCOUNT __asm(" \n\ 81129408Speter .globl .mcount \n\ 82129408Speter .type .mcount @function \n\ 83129408Speter.mcount: \n\ 84129408Speter pushq %rbp \n\ 85129445Sbde movq %rsp,%rbp \n\ 86129408Speter pushq %rdi \n\ 87129408Speter pushq %rsi \n\ 88129408Speter pushq %rdx \n\ 89129408Speter pushq %rcx \n\ 90129408Speter pushq %r8 \n\ 91129408Speter pushq %r9 \n\ 92129408Speter movq 8(%rbp),%rsi \n\ 93129408Speter movq (%rbp),%rdi \n\ 94129408Speter movq 8(%rdi),%rdi \n\ 95129408Speter call _mcount \n\ 96129408Speter popq %r9 \n\ 97129408Speter popq %r8 \n\ 98129408Speter popq %rcx \n\ 99129408Speter popq %rdx \n\ 100129408Speter popq %rsi \n\ 101129408Speter popq %rdi \n\ 102129408Speter leave \n\ 103129408Speter ret \n\ 104129408Speter .size .mcount, . - .mcount"); 105129408Speter#if 0 106129408Speter/* 107129408Speter * We could use this, except it doesn't preserve the registers that were 108129408Speter * being passed with arguments to the function that we were inserted 109129408Speter * into. I've left it here as documentation of what the code above is 110129408Speter * supposed to do. 111129408Speter */ 11295195Smarkm#define MCOUNT \ 11395195Smarkmvoid \ 11495195Smarkmmcount() \ 11595195Smarkm{ \ 11695195Smarkm uintfptr_t selfpc, frompc; \ 11795195Smarkm /* \ 11895195Smarkm * Find the return address for mcount, \ 11995195Smarkm * and the return address for mcount's caller. \ 12095195Smarkm * \ 12195195Smarkm * selfpc = pc pushed by call to mcount \ 12295195Smarkm */ \ 123115659Sobrien __asm("movq 8(%%rbp),%0" : "=r" (selfpc)); \ 12495195Smarkm /* \ 12595195Smarkm * frompc = pc pushed by call to mcount's caller. \ 126129445Sbde * The caller's stack frame has already been built, so %rbp is \ 12795195Smarkm * the caller's frame pointer. The caller's raddr is in the \ 12895195Smarkm * caller's frame following the caller's caller's frame pointer.\ 12995195Smarkm */ \ 130129408Speter __asm("movq (%%rbp),%0" : "=r" (frompc)); \ 13195195Smarkm frompc = ((uintfptr_t *)frompc)[1]; \ 13295195Smarkm _mcount(frompc, selfpc); \ 1331543Srgrimes} 134129408Speter#endif 135129445Sbde#else /* !__GNUC__ */ 136129445Sbde#define MCOUNT \ 137129445Sbdevoid \ 138129445Sbdemcount() \ 139129445Sbde{ \ 14095195Smarkm} 141129445Sbde#endif /* __GNUC__ */ 14237542Sbde 143129445Sbdetypedef u_long uintfptr_t; 14437542Sbde 14555205Speter#endif /* _KERNEL */ 1462166Spaul 14713107Sbde/* 14813107Sbde * An unsigned integral type that can hold non-negative difference between 14913107Sbde * function pointers. 15013107Sbde */ 15131723Steggetypedef u_int fptrdiff_t; 15213107Sbde 15355205Speter#ifdef _KERNEL 15419000Sbde 15592761Salfredvoid mcount(uintfptr_t frompc, uintfptr_t selfpc); 15619000Sbde 15755205Speter#else /* !_KERNEL */ 15819000Sbde 15919000Sbde#include <sys/cdefs.h> 16019000Sbde 16119000Sbde__BEGIN_DECLS 16233047Sbde#ifdef __GNUC__ 16392761Salfredvoid mcount(void) __asm(".mcount"); 16433047Sbde#endif 16519000Sbde__END_DECLS 16613157Sbde 16755205Speter#endif /* _KERNEL */ 16819000Sbde 16913157Sbde#endif /* !_MACHINE_PROFILE_H_ */ 170