xref: /freebsd/sys/i386/include/profile.h (revision e8f00dec4beb7ce9e672cffab4c9ad5c1d770e8a)
186cb007fSWarner Losh /*-
26cda32c0SRodney W. Grimes  * Copyright (c) 1992, 1993
36cda32c0SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
46cda32c0SRodney W. Grimes  *
56cda32c0SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
66cda32c0SRodney W. Grimes  * modification, are permitted provided that the following conditions
76cda32c0SRodney W. Grimes  * are met:
86cda32c0SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
96cda32c0SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
106cda32c0SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
116cda32c0SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
126cda32c0SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
136cda32c0SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
146cda32c0SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
156cda32c0SRodney W. Grimes  *    without specific prior written permission.
166cda32c0SRodney W. Grimes  *
176cda32c0SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
186cda32c0SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
196cda32c0SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
206cda32c0SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
216cda32c0SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
226cda32c0SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
236cda32c0SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
246cda32c0SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
256cda32c0SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
266cda32c0SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
276cda32c0SRodney W. Grimes  * SUCH DAMAGE.
286cda32c0SRodney W. Grimes  *
296cda32c0SRodney W. Grimes  *	@(#)profile.h	8.1 (Berkeley) 6/11/93
30c3aac50fSPeter Wemm  * $FreeBSD$
316cda32c0SRodney W. Grimes  */
326cda32c0SRodney W. Grimes 
33912e6037SBruce Evans #ifndef _MACHINE_PROFILE_H_
34912e6037SBruce Evans #define	_MACHINE_PROFILE_H_
35836dc83bSPaul Richards 
36a5f50ef9SJoerg Wunsch #ifndef _SYS_CDEFS_H_
37a5f50ef9SJoerg Wunsch #error this file needs sys/cdefs.h as a prerequisite
38a5f50ef9SJoerg Wunsch #endif
39a5f50ef9SJoerg Wunsch 
40664a31e4SPeter Wemm #ifdef _KERNEL
41930a6423SBruce Evans 
42e5171bbeSBruce Evans /*
43a7d00b5bSBruce Evans  * Config generates something to tell the compiler to align functions on 16
44a7d00b5bSBruce Evans  * byte boundaries.  A strict alignment is good for keeping the tables small.
45a7d00b5bSBruce Evans  */
46a7d00b5bSBruce Evans #define	FUNCTION_ALIGNMENT	16
47a7d00b5bSBruce Evans 
48a7d00b5bSBruce Evans /*
49e5171bbeSBruce Evans  * The kernel uses assembler stubs instead of unportable inlines.
50e5171bbeSBruce Evans  * This is mainly to save a little time when profiling is not enabled,
51e5171bbeSBruce Evans  * which is the usual case for the kernel.
52e5171bbeSBruce Evans  */
53e5171bbeSBruce Evans #define	_MCOUNT_DECL void mcount
54e5171bbeSBruce Evans #define	MCOUNT
55e5171bbeSBruce Evans 
561f403fcfSBruce Evans #ifdef GUPROF
571f403fcfSBruce Evans #define	MCOUNT_DECL(s)
581f403fcfSBruce Evans #define	MCOUNT_ENTER(s)
591f403fcfSBruce Evans #define	MCOUNT_EXIT(s)
60a5f50ef9SJoerg Wunsch #ifdef __GNUCLIKE_ASM
61e77c22bfSBruce Evans #define	MCOUNT_OVERHEAD(label)						\
62e77c22bfSBruce Evans 	__asm __volatile("pushl %0; call __mcount; popl %%ecx"		\
63e77c22bfSBruce Evans 			 :						\
64853b92daSBruce Evans 			 : "i" (label)					\
65e77c22bfSBruce Evans 			 : "ax", "dx", "cx", "memory")
66e77c22bfSBruce Evans #define	MEXITCOUNT_OVERHEAD()						\
67e77c22bfSBruce Evans 	__asm __volatile("call .mexitcount; 1:"				\
68e77c22bfSBruce Evans 			 : :						\
69e77c22bfSBruce Evans 			 : "ax", "dx", "cx", "memory")
70e77c22bfSBruce Evans #define	MEXITCOUNT_OVERHEAD_GETLABEL(labelp)				\
71e77c22bfSBruce Evans 	__asm __volatile("movl $1b,%0" : "=rm" (labelp))
72e77c22bfSBruce Evans #elif defined(lint)
73e77c22bfSBruce Evans #define	MCOUNT_OVERHEAD(label)
74e77c22bfSBruce Evans #define	MEXITCOUNT_OVERHEAD()
75e77c22bfSBruce Evans #define	MEXITCOUNT_OVERHEAD_GETLABEL()
761f403fcfSBruce Evans #else
77e77c22bfSBruce Evans #error
78a5f50ef9SJoerg Wunsch #endif /* !__GNUCLIKE_ASM */
79e77c22bfSBruce Evans #else /* !GUPROF */
801f403fcfSBruce Evans #define	MCOUNT_DECL(s)	u_long s;
8178292efeSSteve Passe #ifdef SMP
8292fd4795SBruce Evans extern int	mcount_lock;
8325142c5eSJohn Baldwin #define	MCOUNT_ENTER(s)	{ s = read_eflags(); disable_intr(); \
84ce11a18fSJohn Baldwin  			  while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \
8525142c5eSJohn Baldwin 			  	/* nothing */ ; }
8625142c5eSJohn Baldwin #define	MCOUNT_EXIT(s)	{ atomic_store_rel_int(&mcount_lock, 0); \
8725142c5eSJohn Baldwin 			  write_eflags(s); }
8878292efeSSteve Passe #else
895c623cb6STor Egge #define	MCOUNT_ENTER(s)	{ s = read_eflags(); disable_intr(); }
901f403fcfSBruce Evans #define	MCOUNT_EXIT(s)	(write_eflags(s))
9178292efeSSteve Passe #endif
921f403fcfSBruce Evans #endif /* GUPROF */
931f403fcfSBruce Evans 
940f2fe153SMarcel Moolenaar void bintr(void);
950f2fe153SMarcel Moolenaar void btrap(void);
960f2fe153SMarcel Moolenaar void eintr(void);
970f2fe153SMarcel Moolenaar void user(void);
980f2fe153SMarcel Moolenaar 
990f2fe153SMarcel Moolenaar #define	MCOUNT_FROMPC_USER(pc)					\
1000f2fe153SMarcel Moolenaar 	((pc < (uintfptr_t)VM_MAXUSER_ADDRESS) ? (uintfptr_t)user : pc)
1010f2fe153SMarcel Moolenaar 
1020f2fe153SMarcel Moolenaar #define	MCOUNT_FROMPC_INTR(pc)					\
1030f2fe153SMarcel Moolenaar 	((pc >= (uintfptr_t)btrap && pc < (uintfptr_t)eintr) ?	\
1040f2fe153SMarcel Moolenaar 	    ((pc >= (uintfptr_t)bintr) ? (uintfptr_t)bintr :	\
1050f2fe153SMarcel Moolenaar 		(uintfptr_t)btrap) : ~0U)
1060f2fe153SMarcel Moolenaar 
107664a31e4SPeter Wemm #else /* !_KERNEL */
108e5171bbeSBruce Evans 
109a7d00b5bSBruce Evans #define	FUNCTION_ALIGNMENT	4
110a7d00b5bSBruce Evans 
111e5171bbeSBruce Evans #define	_MCOUNT_DECL static __inline void _mcount
1126cda32c0SRodney W. Grimes 
113a5f50ef9SJoerg Wunsch #ifdef __GNUCLIKE_ASM
1146cda32c0SRodney W. Grimes #define	MCOUNT								\
115e5171bbeSBruce Evans void									\
116e5171bbeSBruce Evans mcount()								\
117e5171bbeSBruce Evans {									\
118e8f00decSLuoqi Chen 	uintfptr_t selfpc, frompc, ecx;					\
119e8f00decSLuoqi Chen 	/*								\
120e8f00decSLuoqi Chen 	 * In gcc 4.2, ecx might be used in the caller as the arg	\
121e8f00decSLuoqi Chen 	 * pointer if the stack realignment option is set (-mstackrealign) \
122e8f00decSLuoqi Chen 	 * or if the caller has the force_align_arg_pointer attribute	\
123e8f00decSLuoqi Chen 	 * (stack realignment is ALWAYS on for main).  Preserve ecx	\
124e8f00decSLuoqi Chen 	 * here.							\
125e8f00decSLuoqi Chen 	 */								\
126e8f00decSLuoqi Chen 	__asm("" : "=c" (ecx));						\
1276cda32c0SRodney W. Grimes 	/*								\
128912e6037SBruce Evans 	 * Find the return address for mcount,				\
1296cda32c0SRodney W. Grimes 	 * and the return address for mcount's caller.			\
1306cda32c0SRodney W. Grimes 	 *								\
131912e6037SBruce Evans 	 * selfpc = pc pushed by call to mcount				\
1326cda32c0SRodney W. Grimes 	 */								\
13369bb4041SDavid E. O'Brien 	__asm("movl 4(%%ebp),%0" : "=r" (selfpc));			\
1346cda32c0SRodney W. Grimes 	/*								\
135912e6037SBruce Evans 	 * frompc = pc pushed by call to mcount's caller.		\
136912e6037SBruce Evans 	 * The caller's stack frame has already been built, so %ebp is	\
137912e6037SBruce Evans 	 * the caller's frame pointer.  The caller's raddr is in the	\
138912e6037SBruce Evans 	 * caller's frame following the caller's caller's frame pointer.\
1396cda32c0SRodney W. Grimes 	 */								\
14069bb4041SDavid E. O'Brien 	__asm("movl (%%ebp),%0" : "=r" (frompc));			\
14137889b39SBruce Evans 	frompc = ((uintfptr_t *)frompc)[1];				\
142912e6037SBruce Evans 	_mcount(frompc, selfpc);					\
143e8f00decSLuoqi Chen 	__asm("" : : "c" (ecx));					\
1446cda32c0SRodney W. Grimes }
145a5f50ef9SJoerg Wunsch #else /* !__GNUCLIKE_ASM */
14643f0ea0aSBruce Evans #define	MCOUNT
147a5f50ef9SJoerg Wunsch #endif /* __GNUCLIKE_ASM */
148930a6423SBruce Evans 
14919b5915aSBruce Evans typedef	u_int	uintfptr_t;
150930a6423SBruce Evans 
151664a31e4SPeter Wemm #endif /* _KERNEL */
152912e6037SBruce Evans 
153912e6037SBruce Evans /*
154912e6037SBruce Evans  * An unsigned integral type that can hold non-negative difference between
155912e6037SBruce Evans  * function pointers.
156912e6037SBruce Evans  */
1575c623cb6STor Egge typedef	u_int	fptrdiff_t;
158912e6037SBruce Evans 
159664a31e4SPeter Wemm #ifdef _KERNEL
160d6b9e17eSBruce Evans 
161b63dc6adSAlfred Perlstein void	mcount(uintfptr_t frompc, uintfptr_t selfpc);
162d6b9e17eSBruce Evans 
163664a31e4SPeter Wemm #else /* !_KERNEL */
164d6b9e17eSBruce Evans 
165d6b9e17eSBruce Evans #include <sys/cdefs.h>
166d6b9e17eSBruce Evans 
167d6b9e17eSBruce Evans __BEGIN_DECLS
168a5f50ef9SJoerg Wunsch #ifdef __GNUCLIKE_ASM
169b63dc6adSAlfred Perlstein void	mcount(void) __asm(".mcount");
1705584f22bSJohn Polstra #endif
171e5171bbeSBruce Evans __END_DECLS
172e5171bbeSBruce Evans 
173664a31e4SPeter Wemm #endif /* _KERNEL */
174d6b9e17eSBruce Evans 
175e5171bbeSBruce Evans #endif /* !_MACHINE_PROFILE_H_ */
176