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