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