kern_pmc.c (122ccdc1cae8922f3845fc4f44b4e0470d342b9b) kern_pmc.c (ebccf1e3a6b11b97cbf5f813dd76636e892a9035)
1/*-
1/*-
2 * Copyright (c) 2003-2008 Joseph Koshy
3 * Copyright (c) 2007 The FreeBSD Foundation
4 * All rights reserved.
2 * Copyright (c) 2003 Joseph Koshy
5 *
3 *
6 * Portions of this software were developed by A. Joseph Koshy under
7 * sponsorship from the FreeBSD Foundation and Google, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.

--- 4 unchanged lines hidden (view full) ---

21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.

--- 4 unchanged lines hidden (view full) ---

16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD$");
33
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
34#include "opt_hwpmc_hooks.h"
30#ifdef HWPMC_HOOKS
35
31
36#include <sys/types.h>
37#include <sys/pmc.h>
38#include <sys/pmckern.h>
39#include <sys/smp.h>
40
32#include <sys/pmckern.h>
33#include <sys/smp.h>
34
41#ifdef HWPMC_HOOKS
42#define PMC_KERNEL_VERSION PMC_VERSION
43#else
44#define PMC_KERNEL_VERSION 0
45#endif
35struct sx pmc_sx;
46
36
47const int pmc_kernel_version = PMC_KERNEL_VERSION;
48
49/* Hook variable. */
50int (*pmc_hook)(struct thread *td, int function, void *arg) = NULL;
51
52/* Interrupt handler */
37/* Hook variable. */
38int (*pmc_hook)(struct thread *td, int function, void *arg) = NULL;
39
40/* Interrupt handler */
53int (*pmc_intr)(int cpu, struct trapframe *tf) = NULL;
41int (*pmc_intr)(int cpu, uintptr_t pc) = NULL;
54
42
55/* Bitmask of CPUs requiring servicing at hardclock time */
56volatile cpumask_t pmc_cpumask;
57
58/*
43/*
59 * A global count of SS mode PMCs. When non-zero, this means that
60 * we have processes that are sampling the system as a whole.
61 */
62volatile int pmc_ss_count;
63
64/*
65 * Since PMC(4) may not be loaded in the current kernel, the
66 * convention followed is that a non-NULL value of 'pmc_hook' implies
67 * the presence of this kernel module.
68 *
69 * This requires us to protect 'pmc_hook' with a
70 * shared (sx) lock -- thus making the process of calling into PMC(4)
71 * somewhat more expensive than a simple 'if' check and indirect call.
72 */
44 * Since PMC(4) may not be loaded in the current kernel, the
45 * convention followed is that a non-NULL value of 'pmc_hook' implies
46 * the presence of this kernel module.
47 *
48 * This requires us to protect 'pmc_hook' with a
49 * shared (sx) lock -- thus making the process of calling into PMC(4)
50 * somewhat more expensive than a simple 'if' check and indirect call.
51 */
73struct sx pmc_sx;
74
52
75static void
76pmc_init_sx(void)
77{
78 sx_init_flags(&pmc_sx, "pmc-sx", SX_NOWITNESS);
79}
80
53
81SYSINIT(pmcsx, SI_SUB_LOCK, SI_ORDER_MIDDLE, pmc_init_sx, NULL);
54SX_SYSINIT(pmc, &pmc_sx, "pmc shared lock");
82
83/*
55
56/*
84 * Helper functions.
85 */
86
87/*
88 * A note on the CPU numbering scheme used by the hwpmc(4) driver.
57 * pmc_cpu_is_disabled
89 *
58 *
90 * CPUs are denoted using numbers in the range 0..[pmc_cpu_max()-1].
91 * CPUs could be numbered "sparsely" in this range; the predicate
92 * `pmc_cpu_is_present()' is used to test whether a given CPU is
93 * physically present.
94 *
95 * Further, a CPU that is physically present may be administratively
96 * disabled or otherwise unavailable for use by hwpmc(4). The
97 * `pmc_cpu_is_active()' predicate tests for CPU usability. An
98 * "active" CPU participates in thread scheduling and can field
99 * interrupts raised by PMC hardware.
100 *
101 * On systems with hyperthreaded CPUs, multiple logical CPUs may share
102 * PMC hardware resources. For such processors one logical CPU is
103 * denoted as the primary owner of the in-CPU PMC resources. The
104 * pmc_cpu_is_primary() predicate is used to distinguish this primary
105 * CPU from the others.
59 * return TRUE if the cpu specified has been disabled.
106 */
107
108int
60 */
61
62int
109pmc_cpu_is_active(int cpu)
110{
111#ifdef SMP
112 return (pmc_cpu_is_present(cpu) &&
113 (hlt_cpus_mask & (1 << cpu)) == 0);
114#else
115 return (1);
116#endif
117}
118
119/* Deprecated. */
120int
121pmc_cpu_is_disabled(int cpu)
122{
63pmc_cpu_is_disabled(int cpu)
64{
123 return (!pmc_cpu_is_active(cpu));
124}
125
126int
127pmc_cpu_is_present(int cpu)
128{
129#ifdef SMP
65#ifdef SMP
130 return (!CPU_ABSENT(cpu));
66 return ((hlt_cpus_mask & (1 << cpu)) != 0);
131#else
67#else
132 return (1);
68 return 0;
133#endif
134}
135
136int
69#endif
70}
71
72int
137pmc_cpu_is_primary(int cpu)
73pmc_cpu_is_logical(int cpu)
138{
139#ifdef SMP
74{
75#ifdef SMP
140 return ((logical_cpus_mask & (1 << cpu)) == 0);
76 return ((logical_cpus_mask & (1 << cpu)) != 0);
141#else
77#else
142 return (1);
78 return 0;
143#endif
144}
145
79#endif
80}
81
146
147/*
148 * Return the maximum CPU number supported by the system. The return
149 * value is used for scaling internal data structures and for runtime
150 * checks.
151 */
152unsigned int
153pmc_cpu_max(void)
154{
155#ifdef SMP
156 return (mp_maxid+1);
157#else
158 return (1);
159#endif
160}
161
162#ifdef INVARIANTS
163
164/*
165 * Return the count of CPUs in the `active' state in the system.
166 */
167int
168pmc_cpu_max_active(void)
169{
170#ifdef SMP
171 /*
172 * When support for CPU hot-plugging is added to the kernel,
173 * this function would change to return the current number
174 * of "active" CPUs.
175 */
176 return (mp_ncpus);
177#else
178 return (1);
179#endif
180}
181
182#endif
82#endif /* HWPMC_HOOKS */