1*f6aac1c3SLionel Sambuc /* $NetBSD: profile.h,v 1.33 2007/12/20 23:46:13 ad Exp $ */
2*f6aac1c3SLionel Sambuc
3*f6aac1c3SLionel Sambuc /*
4*f6aac1c3SLionel Sambuc * Copyright (c) 1992, 1993
5*f6aac1c3SLionel Sambuc * The Regents of the University of California. All rights reserved.
6*f6aac1c3SLionel Sambuc *
7*f6aac1c3SLionel Sambuc * Redistribution and use in source and binary forms, with or without
8*f6aac1c3SLionel Sambuc * modification, are permitted provided that the following conditions
9*f6aac1c3SLionel Sambuc * are met:
10*f6aac1c3SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
11*f6aac1c3SLionel Sambuc * notice, this list of conditions and the following disclaimer.
12*f6aac1c3SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
13*f6aac1c3SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
14*f6aac1c3SLionel Sambuc * documentation and/or other materials provided with the distribution.
15*f6aac1c3SLionel Sambuc * 3. Neither the name of the University nor the names of its contributors
16*f6aac1c3SLionel Sambuc * may be used to endorse or promote products derived from this software
17*f6aac1c3SLionel Sambuc * without specific prior written permission.
18*f6aac1c3SLionel Sambuc *
19*f6aac1c3SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*f6aac1c3SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*f6aac1c3SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*f6aac1c3SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*f6aac1c3SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*f6aac1c3SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*f6aac1c3SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*f6aac1c3SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*f6aac1c3SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*f6aac1c3SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*f6aac1c3SLionel Sambuc * SUCH DAMAGE.
30*f6aac1c3SLionel Sambuc *
31*f6aac1c3SLionel Sambuc * @(#)profile.h 8.1 (Berkeley) 6/11/93
32*f6aac1c3SLionel Sambuc */
33*f6aac1c3SLionel Sambuc
34*f6aac1c3SLionel Sambuc #ifdef _KERNEL_OPT
35*f6aac1c3SLionel Sambuc #include "opt_multiprocessor.h"
36*f6aac1c3SLionel Sambuc #endif
37*f6aac1c3SLionel Sambuc
38*f6aac1c3SLionel Sambuc #ifdef _KERNEL
39*f6aac1c3SLionel Sambuc #include <machine/cpufunc.h>
40*f6aac1c3SLionel Sambuc #include <machine/lock.h>
41*f6aac1c3SLionel Sambuc #endif
42*f6aac1c3SLionel Sambuc
43*f6aac1c3SLionel Sambuc #define _MCOUNT_DECL static __inline void _mcount
44*f6aac1c3SLionel Sambuc
45*f6aac1c3SLionel Sambuc #ifdef __ELF__
46*f6aac1c3SLionel Sambuc #define MCOUNT_ENTRY "__mcount"
47*f6aac1c3SLionel Sambuc #define MCOUNT_COMPAT __weak_alias(mcount, __mcount)
48*f6aac1c3SLionel Sambuc #else
49*f6aac1c3SLionel Sambuc #define MCOUNT_ENTRY "mcount"
50*f6aac1c3SLionel Sambuc #define MCOUNT_COMPAT /* nothing */
51*f6aac1c3SLionel Sambuc #endif
52*f6aac1c3SLionel Sambuc
53*f6aac1c3SLionel Sambuc #define MCOUNT \
54*f6aac1c3SLionel Sambuc MCOUNT_COMPAT \
55*f6aac1c3SLionel Sambuc extern void mcount(void) __asm(MCOUNT_ENTRY) \
56*f6aac1c3SLionel Sambuc __attribute__((__no_instrument_function__)); \
57*f6aac1c3SLionel Sambuc void \
58*f6aac1c3SLionel Sambuc mcount(void) \
59*f6aac1c3SLionel Sambuc { \
60*f6aac1c3SLionel Sambuc int selfpc, frompcindex; \
61*f6aac1c3SLionel Sambuc int eax, ecx, edx; \
62*f6aac1c3SLionel Sambuc \
63*f6aac1c3SLionel Sambuc __asm volatile("movl %%eax,%0" : "=g" (eax)); \
64*f6aac1c3SLionel Sambuc __asm volatile("movl %%ecx,%0" : "=g" (ecx)); \
65*f6aac1c3SLionel Sambuc __asm volatile("movl %%edx,%0" : "=g" (edx)); \
66*f6aac1c3SLionel Sambuc /* \
67*f6aac1c3SLionel Sambuc * find the return address for mcount, \
68*f6aac1c3SLionel Sambuc * and the return address for mcount's caller. \
69*f6aac1c3SLionel Sambuc * \
70*f6aac1c3SLionel Sambuc * selfpc = pc pushed by mcount call \
71*f6aac1c3SLionel Sambuc */ \
72*f6aac1c3SLionel Sambuc __asm volatile("movl 4(%%ebp),%0" : "=r" (selfpc)); \
73*f6aac1c3SLionel Sambuc /* \
74*f6aac1c3SLionel Sambuc * frompcindex = pc pushed by call into self. \
75*f6aac1c3SLionel Sambuc */ \
76*f6aac1c3SLionel Sambuc __asm volatile("movl (%%ebp),%0;movl 4(%0),%0" \
77*f6aac1c3SLionel Sambuc : "=r" (frompcindex)); \
78*f6aac1c3SLionel Sambuc _mcount((u_long)frompcindex, (u_long)selfpc); \
79*f6aac1c3SLionel Sambuc \
80*f6aac1c3SLionel Sambuc __asm volatile("movl %0,%%edx" : : "g" (edx)); \
81*f6aac1c3SLionel Sambuc __asm volatile("movl %0,%%ecx" : : "g" (ecx)); \
82*f6aac1c3SLionel Sambuc __asm volatile("movl %0,%%eax" : : "g" (eax)); \
83*f6aac1c3SLionel Sambuc }
84*f6aac1c3SLionel Sambuc
85*f6aac1c3SLionel Sambuc #ifdef _KERNEL
86*f6aac1c3SLionel Sambuc #ifdef MULTIPROCESSOR
87*f6aac1c3SLionel Sambuc __cpu_simple_lock_t __mcount_lock;
88*f6aac1c3SLionel Sambuc
89*f6aac1c3SLionel Sambuc static inline void
MCOUNT_ENTER_MP(void)90*f6aac1c3SLionel Sambuc MCOUNT_ENTER_MP(void)
91*f6aac1c3SLionel Sambuc {
92*f6aac1c3SLionel Sambuc __cpu_simple_lock(&__mcount_lock);
93*f6aac1c3SLionel Sambuc __insn_barrier();
94*f6aac1c3SLionel Sambuc }
95*f6aac1c3SLionel Sambuc
96*f6aac1c3SLionel Sambuc static inline void
MCOUNT_EXIT_MP(void)97*f6aac1c3SLionel Sambuc MCOUNT_EXIT_MP(void)
98*f6aac1c3SLionel Sambuc {
99*f6aac1c3SLionel Sambuc __insn_barrier();
100*f6aac1c3SLionel Sambuc __mcount_lock = __SIMPLELOCK_UNLOCKED;
101*f6aac1c3SLionel Sambuc }
102*f6aac1c3SLionel Sambuc #else
103*f6aac1c3SLionel Sambuc #define MCOUNT_ENTER_MP()
104*f6aac1c3SLionel Sambuc #define MCOUNT_EXIT_MP()
105*f6aac1c3SLionel Sambuc #endif
106*f6aac1c3SLionel Sambuc
107*f6aac1c3SLionel Sambuc static inline void
mcount_disable_intr(void)108*f6aac1c3SLionel Sambuc mcount_disable_intr(void)
109*f6aac1c3SLionel Sambuc {
110*f6aac1c3SLionel Sambuc __asm volatile("cli");
111*f6aac1c3SLionel Sambuc }
112*f6aac1c3SLionel Sambuc
113*f6aac1c3SLionel Sambuc static inline u_long
mcount_read_psl(void)114*f6aac1c3SLionel Sambuc mcount_read_psl(void)
115*f6aac1c3SLionel Sambuc {
116*f6aac1c3SLionel Sambuc u_long ef;
117*f6aac1c3SLionel Sambuc
118*f6aac1c3SLionel Sambuc __asm volatile("pushfl; popl %0" : "=r" (ef));
119*f6aac1c3SLionel Sambuc return (ef);
120*f6aac1c3SLionel Sambuc }
121*f6aac1c3SLionel Sambuc
122*f6aac1c3SLionel Sambuc static inline void
mcount_write_psl(u_long ef)123*f6aac1c3SLionel Sambuc mcount_write_psl(u_long ef)
124*f6aac1c3SLionel Sambuc {
125*f6aac1c3SLionel Sambuc __asm volatile("pushl %0; popfl" : : "r" (ef));
126*f6aac1c3SLionel Sambuc }
127*f6aac1c3SLionel Sambuc
128*f6aac1c3SLionel Sambuc #define MCOUNT_ENTER \
129*f6aac1c3SLionel Sambuc s = (int)mcount_read_psl(); \
130*f6aac1c3SLionel Sambuc mcount_disable_intr(); \
131*f6aac1c3SLionel Sambuc MCOUNT_ENTER_MP();
132*f6aac1c3SLionel Sambuc
133*f6aac1c3SLionel Sambuc #define MCOUNT_EXIT \
134*f6aac1c3SLionel Sambuc MCOUNT_EXIT_MP(); \
135*f6aac1c3SLionel Sambuc mcount_write_psl(s);
136*f6aac1c3SLionel Sambuc
137*f6aac1c3SLionel Sambuc #endif /* _KERNEL */
138