profile.h revision 129446
137535Sdes/* 2135546Sdes * Copyright (c) 1992, 1993 337535Sdes * The Regents of the University of California. All rights reserved. 437535Sdes * 537535Sdes * Redistribution and use in source and binary forms, with or without 637535Sdes * modification, are permitted provided that the following conditions 737535Sdes * are met: 837535Sdes * 1. Redistributions of source code must retain the above copyright 937535Sdes * notice, this list of conditions and the following disclaimer. 1037535Sdes * 2. Redistributions in binary form must reproduce the above copyright 1137535Sdes * notice, this list of conditions and the following disclaimer in the 1237535Sdes * documentation and/or other materials provided with the distribution. 1337535Sdes * 4. Neither the name of the University nor the names of its contributors 1437535Sdes * may be used to endorse or promote products derived from this software 1563012Sdes * without specific prior written permission. 1637535Sdes * 1737535Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1837535Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1937535Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2037535Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2137535Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2237535Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2337535Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2437535Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2537535Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2637535Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2737535Sdes * SUCH DAMAGE. 2837535Sdes * 2984203Sdillon * @(#)profile.h 8.1 (Berkeley) 6/11/93 3084203Sdillon * $FreeBSD: head/sys/amd64/include/profile.h 129446 2004-05-19 16:19:11Z bde $ 3184203Sdillon */ 3263236Sdes 3363236Sdes#ifndef _MACHINE_PROFILE_H_ 3463236Sdes#define _MACHINE_PROFILE_H_ 3563236Sdes 3663236Sdes#ifdef _KERNEL 3763236Sdes 3863236Sdes/* 3963236Sdes * Config generates something to tell the compiler to align functions on 16 4063236Sdes * byte boundaries. A strict alignment is good for keeping the tables small. 4163236Sdes */ 4263236Sdes#define FUNCTION_ALIGNMENT 16 4363236Sdes 4463236Sdes/* 4563236Sdes * The kernel uses assembler stubs instead of unportable inlines. 4663236Sdes * This is mainly to save a little time when profiling is not enabled, 4763236Sdes * which is the usual case for the kernel. 4863236Sdes */ 4990267Sdes#define _MCOUNT_DECL void mcount 5063236Sdes#define MCOUNT 5163236Sdes 5263236Sdes#ifdef GUPROF 5363236Sdes#define MCOUNT_DECL(s) 5463236Sdes#define MCOUNT_ENTER(s) 5563236Sdes#define MCOUNT_EXIT(s) 5663236Sdes#else 5763236Sdes#define MCOUNT_DECL(s) u_long s; 5863236Sdes#ifdef SMP 5963236Sdesextern int mcount_lock; 6063236Sdes#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); \ 6163236Sdes while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \ 6263236Sdes /* nothing */ ; } 6363236Sdes#define MCOUNT_EXIT(s) { atomic_store_rel_int(&mcount_lock, 0); \ 6437535Sdes write_rflags(s); } 6560737Sume#else 66186124Smurray#define MCOUNT_ENTER(s) { s = read_rflags(); disable_intr(); } 6737535Sdes#define MCOUNT_EXIT(s) (write_rflags(s)) 6863012Sdes#endif 6937535Sdes#endif /* GUPROF */ 7063012Sdes 7160376Sdes#else /* !_KERNEL */ 7260189Sdes 7337608Sdes#define FUNCTION_ALIGNMENT 4 7437535Sdes 7537535Sdes#define _MCOUNT_DECL \ 7637535Sdesstatic void _mcount(uintfptr_t frompc, uintfptr_t selfpc) __unused; \ 7760376Sdesstatic void _mcount 7837535Sdes 79202613Sdes#ifdef __GNUC__ 8037535Sdes#define MCOUNT __asm(" \n\ 81141958Skbyanc .globl .mcount \n\ 82141958Skbyanc .type .mcount @function \n\ 83141958Skbyanc.mcount: \n\ 8437535Sdes pushq %rbp \n\ 8540939Sdes movq %rsp,%rbp \n\ 8641862Sdes pushq %rdi \n\ 8737535Sdes pushq %rsi \n\ 8863012Sdes pushq %rdx \n\ 8963012Sdes pushq %rcx \n\ 9037535Sdes pushq %r8 \n\ 9163012Sdes pushq %r9 \n\ 9263012Sdes movq 8(%rbp),%rsi \n\ 9363012Sdes movq (%rbp),%rdi \n\ 9463012Sdes movq 8(%rdi),%rdi \n\ 9563012Sdes call _mcount \n\ 9663012Sdes popq %r9 \n\ 97186124Smurray popq %r8 \n\ 98169386Sdes popq %rcx \n\ 9963012Sdes popq %rdx \n\ 10087317Sdes popq %rsi \n\ 101125696Sdes popq %rdi \n\ 10263012Sdes leave \n\ 10360196Sdes ret \n\ 10463012Sdes .size .mcount, . - .mcount"); 10590267Sdes#if 0 106169386Sdes/* 10790267Sdes * We could use this, except it doesn't preserve the registers that were 10863012Sdes * being passed with arguments to the function that we were inserted 10988771Sdes * into. I've left it here as documentation of what the code above is 11063012Sdes * supposed to do. 11190267Sdes */ 11263012Sdes#define MCOUNT \ 11363012Sdesvoid \ 11463012Sdesmcount() \ 11563012Sdes{ \ 11697859Sdes uintfptr_t selfpc, frompc; \ 11737535Sdes /* \ 11897858Sdes * Find the return address for mcount, \ 11997866Sdes * and the return address for mcount's caller. \ 12097858Sdes * \ 12197866Sdes * selfpc = pc pushed by call to mcount \ 12297866Sdes */ \ 12397866Sdes __asm("movq 8(%%rbp),%0" : "=r" (selfpc)); \ 12497858Sdes /* \ 12597858Sdes * frompc = pc pushed by call to mcount's caller. \ 12697858Sdes * The caller's stack frame has already been built, so %rbp is \ 12763281Sdes * the caller's frame pointer. The caller's raddr is in the \ 12890267Sdes * caller's frame following the caller's caller's frame pointer.\ 12963012Sdes */ \ 13037535Sdes __asm("movq (%%rbp),%0" : "=r" (frompc)); \ 13137535Sdes frompc = ((uintfptr_t *)frompc)[1]; \ 13237608Sdes _mcount(frompc, selfpc); \ 13363012Sdes} 13437608Sdes#endif 13537608Sdes#else /* !__GNUC__ */ 136174588Sdes#define MCOUNT \ 13737608Sdesvoid \ 13890267Sdesmcount() \ 13990267Sdes{ \ 140174588Sdes} 14190267Sdes#endif /* __GNUC__ */ 14290267Sdes 143174761Sdestypedef u_long uintfptr_t; 14490267Sdes 14590267Sdes#endif /* _KERNEL */ 146174761Sdes 14790267Sdes/* 14890267Sdes * An unsigned integral type that can hold non-negative difference between 149174761Sdes * function pointers. 15090267Sdes */ 151174761Sdestypedef u_long fptrdiff_t; 15297859Sdes 15390267Sdes#ifdef _KERNEL 15490267Sdes 15597859Sdesvoid mcount(uintfptr_t frompc, uintfptr_t selfpc); 156176036Sdes 15790267Sdes#else /* !_KERNEL */ 15890267Sdes 15990267Sdes#include <sys/cdefs.h> 16063281Sdes 16190267Sdes__BEGIN_DECLS 16297859Sdes#ifdef __GNUC__ 16397859Sdesvoid mcount(void) __asm(".mcount"); 164106207Sdes#endif 16590267Sdes__END_DECLS 166106207Sdes 167106207Sdes#endif /* _KERNEL */ 168106207Sdes 16990267Sdes#endif /* !_MACHINE_PROFILE_H_ */ 17063012Sdes