1139731Simp/*- 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 61129499Sbde#define MCOUNT_OVERHEAD(label) \ 62129499Sbde __asm __volatile("pushq %0; call __mcount; popq %%rcx" \ 63129499Sbde : \ 64163729Sbde : "i" (label) \ 65129499Sbde : "ax", "dx", "cx", "di", "si", "r8", "r9", "memory") 66129499Sbde#define MEXITCOUNT_OVERHEAD() \ 67129499Sbde __asm __volatile("call .mexitcount; 1:" \ 68129499Sbde : : \ 69129499Sbde : "ax", "dx", "cx", "di", "si", "r8", "r9", "memory") 70129499Sbde#define MEXITCOUNT_OVERHEAD_GETLABEL(labelp) \ 71129499Sbde __asm __volatile("movq $1b,%0" : "=rm" (labelp)) 72129499Sbde#elif defined(lint) 73129499Sbde#define MCOUNT_OVERHEAD(label) 74129499Sbde#define MEXITCOUNT_OVERHEAD() 75129499Sbde#define MEXITCOUNT_OVERHEAD_GETLABEL() 7617879Sbde#else 77143063Sjoerg#error this file needs to be ported to your compiler 78143434Speter#endif /* !__GNUCLIKE_ASM */ 79129499Sbde#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) : ~0UL) 106134398Smarcel 10755205Speter#else /* !_KERNEL */ 10813157Sbde 10922639Sbde#define FUNCTION_ALIGNMENT 4 11022639Sbde 111129408Speter#define _MCOUNT_DECL \ 112132846Skanstatic void _mcount(uintfptr_t frompc, uintfptr_t selfpc) __used; \ 113129408Speterstatic void _mcount 11413157Sbde 115143434Speter#ifdef __GNUCLIKE_ASM 116129445Sbde#define MCOUNT __asm(" \n\ 117163738Sbde .text \n\ 118163738Sbde .p2align 4,0x90 \n\ 119129408Speter .globl .mcount \n\ 120163738Sbde .type .mcount,@function \n\ 121129408Speter.mcount: \n\ 122129408Speter pushq %rdi \n\ 123129408Speter pushq %rsi \n\ 124129408Speter pushq %rdx \n\ 125129408Speter pushq %rcx \n\ 126129408Speter pushq %r8 \n\ 127129408Speter pushq %r9 \n\ 128130321Speter pushq %rax \n\ 129163738Sbde movq 8(%rbp),%rdi \n\ 130163738Sbde movq 7*8(%rsp),%rsi \n\ 131129408Speter call _mcount \n\ 132130321Speter popq %rax \n\ 133129408Speter popq %r9 \n\ 134129408Speter popq %r8 \n\ 135129408Speter popq %rcx \n\ 136129408Speter popq %rdx \n\ 137129408Speter popq %rsi \n\ 138129408Speter popq %rdi \n\ 139129408Speter ret \n\ 140129408Speter .size .mcount, . - .mcount"); 141129408Speter#if 0 142129408Speter/* 143129408Speter * We could use this, except it doesn't preserve the registers that were 144129408Speter * being passed with arguments to the function that we were inserted 145129408Speter * into. I've left it here as documentation of what the code above is 146129408Speter * supposed to do. 147129408Speter */ 14895195Smarkm#define MCOUNT \ 14995195Smarkmvoid \ 15095195Smarkmmcount() \ 15195195Smarkm{ \ 15295195Smarkm uintfptr_t selfpc, frompc; \ 15395195Smarkm /* \ 15495195Smarkm * Find the return address for mcount, \ 15595195Smarkm * and the return address for mcount's caller. \ 15695195Smarkm * \ 15795195Smarkm * selfpc = pc pushed by call to mcount \ 15895195Smarkm */ \ 159115659Sobrien __asm("movq 8(%%rbp),%0" : "=r" (selfpc)); \ 16095195Smarkm /* \ 16195195Smarkm * frompc = pc pushed by call to mcount's caller. \ 162129445Sbde * The caller's stack frame has already been built, so %rbp is \ 16395195Smarkm * the caller's frame pointer. The caller's raddr is in the \ 16495195Smarkm * caller's frame following the caller's caller's frame pointer.\ 16595195Smarkm */ \ 166129408Speter __asm("movq (%%rbp),%0" : "=r" (frompc)); \ 16795195Smarkm frompc = ((uintfptr_t *)frompc)[1]; \ 16895195Smarkm _mcount(frompc, selfpc); \ 1691543Srgrimes} 170129408Speter#endif 171143063Sjoerg#else /* !__GNUCLIKE_ASM */ 172163735Sbde#define MCOUNT 173143063Sjoerg#endif /* __GNUCLIKE_ASM */ 17437542Sbde 175129445Sbdetypedef u_long uintfptr_t; 17637542Sbde 17755205Speter#endif /* _KERNEL */ 1782166Spaul 17913107Sbde/* 18013107Sbde * An unsigned integral type that can hold non-negative difference between 18113107Sbde * function pointers. 18213107Sbde */ 183129446Sbdetypedef u_long fptrdiff_t; 18413107Sbde 18555205Speter#ifdef _KERNEL 18619000Sbde 18792761Salfredvoid mcount(uintfptr_t frompc, uintfptr_t selfpc); 18819000Sbde 18955205Speter#else /* !_KERNEL */ 19019000Sbde 19119000Sbde#include <sys/cdefs.h> 19219000Sbde 19319000Sbde__BEGIN_DECLS 194143063Sjoerg#ifdef __GNUCLIKE_ASM 19592761Salfredvoid mcount(void) __asm(".mcount"); 19633047Sbde#endif 19719000Sbde__END_DECLS 19813157Sbde 19955205Speter#endif /* _KERNEL */ 20019000Sbde 20113157Sbde#endif /* !_MACHINE_PROFILE_H_ */ 202