1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)profile.h 8.1 (Berkeley) 6/11/93 32 */ 33 34 #ifndef _MACHINE_PROFILE_H_ 35 #define _MACHINE_PROFILE_H_ 36 37 #ifndef _SYS_CDEFS_H_ 38 #error this file needs sys/cdefs.h as a prerequisite 39 #endif 40 41 #ifdef _KERNEL 42 43 /* 44 * Config generates something to tell the compiler to align functions on 16 45 * byte boundaries. A strict alignment is good for keeping the tables small. 46 */ 47 #define FUNCTION_ALIGNMENT 16 48 49 /* 50 * The kernel uses assembler stubs instead of unportable inlines. 51 * This is mainly to save a little time when profiling is not enabled, 52 * which is the usual case for the kernel. 53 */ 54 #define _MCOUNT_DECL void mcount 55 #define MCOUNT 56 57 #ifdef GUPROF 58 #define MCOUNT_DECL(s) 59 #define MCOUNT_ENTER(s) 60 #define MCOUNT_EXIT(s) 61 #ifdef __GNUCLIKE_ASM 62 #define MCOUNT_OVERHEAD(label) \ 63 __asm __volatile("pushl %0; call __mcount; popl %%ecx" \ 64 : \ 65 : "i" (label) \ 66 : "ax", "dx", "cx", "memory") 67 #define MEXITCOUNT_OVERHEAD() \ 68 __asm __volatile("call .mexitcount; 1:" \ 69 : : \ 70 : "cx", "memory") 71 #define MEXITCOUNT_OVERHEAD_GETLABEL(labelp) \ 72 __asm __volatile("movl $1b,%0" : "=rm" (labelp)) 73 #else 74 #error 75 #endif /* !__GNUCLIKE_ASM */ 76 #else /* !GUPROF */ 77 #define MCOUNT_DECL(s) register_t s; 78 #ifdef SMP 79 extern int mcount_lock; 80 #define MCOUNT_ENTER(s) { s = intr_disable(); \ 81 while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \ 82 /* nothing */ ; } 83 #define MCOUNT_EXIT(s) { atomic_store_rel_int(&mcount_lock, 0); \ 84 intr_restore(s); } 85 #else 86 #define MCOUNT_ENTER(s) { s = intr_disable(); } 87 #define MCOUNT_EXIT(s) (intr_restore(s)) 88 #endif 89 #endif /* GUPROF */ 90 91 void bintr(void); 92 void btrap(void); 93 void eintr(void); 94 #if 0 95 void end_exceptions(void); 96 void start_exceptions(void); 97 #else 98 #include <machine/pmc_mdep.h> /* XXX */ 99 #endif 100 void user(void); 101 102 #include <machine/md_var.h> /* XXX for setidt_disp */ 103 104 #define MCOUNT_DETRAMP(pc) do { \ 105 if ((pc) >= (uintfptr_t)start_exceptions + setidt_disp && \ 106 (pc) < (uintfptr_t)end_exceptions + setidt_disp) \ 107 (pc) -= setidt_disp; \ 108 } while (0) 109 110 #define MCOUNT_FROMPC_INTR(pc) \ 111 ((pc >= (uintfptr_t)btrap && pc < (uintfptr_t)eintr) ? \ 112 ((pc >= (uintfptr_t)bintr) ? (uintfptr_t)bintr : \ 113 (uintfptr_t)btrap) : ~0U) 114 115 #define MCOUNT_USERPC ((uintfptr_t)user) 116 117 #else /* !_KERNEL */ 118 119 #define FUNCTION_ALIGNMENT 4 120 121 #define _MCOUNT_DECL static __inline void _mcount 122 123 #ifdef __GNUCLIKE_ASM 124 #define MCOUNT \ 125 void \ 126 mcount() \ 127 { \ 128 uintfptr_t selfpc, frompc, ecx; \ 129 /* \ 130 * In gcc 4.2, ecx might be used in the caller as the arg \ 131 * pointer if the stack realignment option is set (-mstackrealign) \ 132 * or if the caller has the force_align_arg_pointer attribute \ 133 * (stack realignment is ALWAYS on for main). Preserve ecx \ 134 * here. \ 135 */ \ 136 __asm("" : "=c" (ecx)); \ 137 /* \ 138 * Find the return address for mcount, \ 139 * and the return address for mcount's caller. \ 140 * \ 141 * selfpc = pc pushed by call to mcount \ 142 */ \ 143 __asm("movl 4(%%ebp),%0" : "=r" (selfpc)); \ 144 /* \ 145 * frompc = pc pushed by call to mcount's caller. \ 146 * The caller's stack frame has already been built, so %ebp is \ 147 * the caller's frame pointer. The caller's raddr is in the \ 148 * caller's frame following the caller's caller's frame pointer.\ 149 */ \ 150 __asm("movl (%%ebp),%0" : "=r" (frompc)); \ 151 frompc = ((uintfptr_t *)frompc)[1]; \ 152 _mcount(frompc, selfpc); \ 153 __asm("" : : "c" (ecx)); \ 154 } 155 #else /* !__GNUCLIKE_ASM */ 156 #define MCOUNT 157 #endif /* __GNUCLIKE_ASM */ 158 159 typedef u_int uintfptr_t; 160 161 #endif /* _KERNEL */ 162 163 /* 164 * An unsigned integral type that can hold non-negative difference between 165 * function pointers. 166 */ 167 typedef u_int fptrdiff_t; 168 169 #ifdef _KERNEL 170 171 void mcount(uintfptr_t frompc, uintfptr_t selfpc); 172 173 #else /* !_KERNEL */ 174 175 #include <sys/cdefs.h> 176 177 __BEGIN_DECLS 178 #ifdef __GNUCLIKE_ASM 179 void mcount(void) __asm(".mcount"); 180 #endif 181 __END_DECLS 182 183 #endif /* _KERNEL */ 184 185 #endif /* !_MACHINE_PROFILE_H_ */ 186