1139790Simp/*- 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$ 311543Srgrimes */ 321543Srgrimes 3313107Sbde#ifndef _MACHINE_PROFILE_H_ 3413107Sbde#define _MACHINE_PROFILE_H_ 352166Spaul 36143063Sjoerg#ifndef _SYS_CDEFS_H_ 37143063Sjoerg#error this file needs sys/cdefs.h as a prerequisite 38143063Sjoerg#endif 39143063Sjoerg 4055205Speter#ifdef _KERNEL 4137542Sbde 4213157Sbde/* 4322639Sbde * Config generates something to tell the compiler to align functions on 16 4422639Sbde * byte boundaries. A strict alignment is good for keeping the tables small. 4522639Sbde */ 4622639Sbde#define FUNCTION_ALIGNMENT 16 4722639Sbde 4822639Sbde/* 4913157Sbde * The kernel uses assembler stubs instead of unportable inlines. 5013157Sbde * This is mainly to save a little time when profiling is not enabled, 5113157Sbde * which is the usual case for the kernel. 5213157Sbde */ 5313157Sbde#define _MCOUNT_DECL void mcount 5413157Sbde#define MCOUNT 551543Srgrimes 5617879Sbde#ifdef GUPROF 5717879Sbde#define MCOUNT_DECL(s) 5817879Sbde#define MCOUNT_ENTER(s) 5917879Sbde#define MCOUNT_EXIT(s) 60143063Sjoerg#ifdef __GNUCLIKE_ASM 61129498Sbde#define MCOUNT_OVERHEAD(label) \ 62129498Sbde __asm __volatile("pushl %0; call __mcount; popl %%ecx" \ 63129498Sbde : \ 64163729Sbde : "i" (label) \ 65129498Sbde : "ax", "dx", "cx", "memory") 66129498Sbde#define MEXITCOUNT_OVERHEAD() \ 67129498Sbde __asm __volatile("call .mexitcount; 1:" \ 68129498Sbde : : \ 69129498Sbde : "ax", "dx", "cx", "memory") 70129498Sbde#define MEXITCOUNT_OVERHEAD_GETLABEL(labelp) \ 71129498Sbde __asm __volatile("movl $1b,%0" : "=rm" (labelp)) 72129498Sbde#elif defined(lint) 73129498Sbde#define MCOUNT_OVERHEAD(label) 74129498Sbde#define MEXITCOUNT_OVERHEAD() 75129498Sbde#define MEXITCOUNT_OVERHEAD_GETLABEL() 7617879Sbde#else 77129498Sbde#error 78143063Sjoerg#endif /* !__GNUCLIKE_ASM */ 79129498Sbde#else /* !GUPROF */ 80214346Sjhb#define MCOUNT_DECL(s) register_t s; 8128921Sfsmp#ifdef SMP 8290024Sbdeextern int mcount_lock; 83214346Sjhb#define MCOUNT_ENTER(s) { s = intr_disable(); \ 8479734Sjhb while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \ 8578908Sjhb /* nothing */ ; } 8678908Sjhb#define MCOUNT_EXIT(s) { atomic_store_rel_int(&mcount_lock, 0); \ 87214346Sjhb intr_restore(s); } 8828921Sfsmp#else 89214346Sjhb#define MCOUNT_ENTER(s) { s = intr_disable(); } 90214346Sjhb#define MCOUNT_EXIT(s) (intr_restore(s)) 9128921Sfsmp#endif 9217879Sbde#endif /* GUPROF */ 9317879Sbde 94134398Smarcelvoid bintr(void); 95134398Smarcelvoid btrap(void); 96134398Smarcelvoid eintr(void); 97134398Smarcelvoid user(void); 98134398Smarcel 99134398Smarcel#define MCOUNT_FROMPC_USER(pc) \ 100134398Smarcel ((pc < (uintfptr_t)VM_MAXUSER_ADDRESS) ? (uintfptr_t)user : pc) 101134398Smarcel 102134398Smarcel#define MCOUNT_FROMPC_INTR(pc) \ 103134398Smarcel ((pc >= (uintfptr_t)btrap && pc < (uintfptr_t)eintr) ? \ 104134398Smarcel ((pc >= (uintfptr_t)bintr) ? (uintfptr_t)bintr : \ 105134398Smarcel (uintfptr_t)btrap) : ~0U) 106134398Smarcel 10755205Speter#else /* !_KERNEL */ 10813157Sbde 10922639Sbde#define FUNCTION_ALIGNMENT 4 11022639Sbde 11113157Sbde#define _MCOUNT_DECL static __inline void _mcount 11213157Sbde 113143063Sjoerg#ifdef __GNUCLIKE_ASM 11495195Smarkm#define MCOUNT \ 11595195Smarkmvoid \ 11695195Smarkmmcount() \ 11795195Smarkm{ \ 118180756Sluoqi uintfptr_t selfpc, frompc, ecx; \ 11995195Smarkm /* \ 120180756Sluoqi * In gcc 4.2, ecx might be used in the caller as the arg \ 121180756Sluoqi * pointer if the stack realignment option is set (-mstackrealign) \ 122180756Sluoqi * or if the caller has the force_align_arg_pointer attribute \ 123180756Sluoqi * (stack realignment is ALWAYS on for main). Preserve ecx \ 124180756Sluoqi * here. \ 125180756Sluoqi */ \ 126180756Sluoqi __asm("" : "=c" (ecx)); \ 127180756Sluoqi /* \ 12895195Smarkm * Find the return address for mcount, \ 12995195Smarkm * and the return address for mcount's caller. \ 13095195Smarkm * \ 13195195Smarkm * selfpc = pc pushed by call to mcount \ 13295195Smarkm */ \ 133115659Sobrien __asm("movl 4(%%ebp),%0" : "=r" (selfpc)); \ 13495195Smarkm /* \ 13595195Smarkm * frompc = pc pushed by call to mcount's caller. \ 13695195Smarkm * The caller's stack frame has already been built, so %ebp is \ 13795195Smarkm * the caller's frame pointer. The caller's raddr is in the \ 13895195Smarkm * caller's frame following the caller's caller's frame pointer.\ 13995195Smarkm */ \ 140129445Sbde __asm("movl (%%ebp),%0" : "=r" (frompc)); \ 14195195Smarkm frompc = ((uintfptr_t *)frompc)[1]; \ 14295195Smarkm _mcount(frompc, selfpc); \ 143180756Sluoqi __asm("" : : "c" (ecx)); \ 1441543Srgrimes} 145143063Sjoerg#else /* !__GNUCLIKE_ASM */ 146163735Sbde#define MCOUNT 147143063Sjoerg#endif /* __GNUCLIKE_ASM */ 14837542Sbde 149129445Sbdetypedef u_int uintfptr_t; 15037542Sbde 15155205Speter#endif /* _KERNEL */ 1522166Spaul 15313107Sbde/* 15413107Sbde * An unsigned integral type that can hold non-negative difference between 15513107Sbde * function pointers. 15613107Sbde */ 15731723Steggetypedef u_int fptrdiff_t; 15813107Sbde 15955205Speter#ifdef _KERNEL 16019000Sbde 16192761Salfredvoid mcount(uintfptr_t frompc, uintfptr_t selfpc); 16219000Sbde 16355205Speter#else /* !_KERNEL */ 16419000Sbde 16519000Sbde#include <sys/cdefs.h> 16619000Sbde 16719000Sbde__BEGIN_DECLS 168143063Sjoerg#ifdef __GNUCLIKE_ASM 16992761Salfredvoid mcount(void) __asm(".mcount"); 17033047Sbde#endif 17119000Sbde__END_DECLS 17213157Sbde 17355205Speter#endif /* _KERNEL */ 17419000Sbde 17513157Sbde#endif /* !_MACHINE_PROFILE_H_ */ 176