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