diff options
author | Paul Mackerras <paulus@samba.org> | 2009-02-10 22:35:35 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2009-02-10 23:06:59 -0500 |
commit | 0475f9ea8e2cc030298908949e0d5da9f2fc2cfe (patch) | |
tree | eb2585d92e00ae4c7fc7e0654ffacde7e8a57e1c /arch/x86 | |
parent | d278c48435625cb6b7edcf6a547620768b175709 (diff) |
perf_counters: allow users to count user, kernel and/or hypervisor events
Impact: new perf_counter feature
This extends the perf_counter_hw_event struct with bits that specify
that events in user, kernel and/or hypervisor mode should not be
counted (i.e. should be excluded), and adds code to program the PMU
mode selection bits accordingly on x86 and powerpc.
For software counters, we don't currently have the infrastructure to
distinguish which mode an event occurs in, so we currently fail the
counter initialization if the setting of the hw_event.exclude_* bits
would require us to distinguish. Context switches and CPU migrations
are currently considered to occur in kernel mode.
On x86, this changes the previous policy that only root can count
kernel events. Now non-root users can count kernel events or exclude
them. Non-root users still can't use NMI events, though. On x86 we
don't appear to have any way to control whether hypervisor events are
counted or not, so hw_event.exclude_hv is ignored.
On powerpc, the selection of whether to count events in user, kernel
and/or hypervisor mode is PMU-wide, not per-counter, so this adds a
check that the hw_event.exclude_* settings are the same as other events
on the PMU. Counters being added to a group have to have the same
settings as the other hardware counters in the group. Counters and
groups can only be enabled in hw_perf_group_sched_in or power_perf_enable
if they have the same settings as any other counters already on the
PMU. If we are not running on a hypervisor, the exclude_hv setting
is ignored (by forcing it to 0) since we can't ever get any
hypervisor events.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/cpu/perf_counter.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index 9901e46998d1..383d4c6423a1 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c | |||
@@ -107,21 +107,25 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
107 | return -EINVAL; | 107 | return -EINVAL; |
108 | 108 | ||
109 | /* | 109 | /* |
110 | * Count user events, and generate PMC IRQs: | 110 | * Generate PMC IRQs: |
111 | * (keep 'enabled' bit clear for now) | 111 | * (keep 'enabled' bit clear for now) |
112 | */ | 112 | */ |
113 | hwc->config = ARCH_PERFMON_EVENTSEL_USR | ARCH_PERFMON_EVENTSEL_INT; | 113 | hwc->config = ARCH_PERFMON_EVENTSEL_INT; |
114 | 114 | ||
115 | /* | 115 | /* |
116 | * If privileged enough, count OS events too, and allow | 116 | * Count user and OS events unless requested not to. |
117 | * NMI events as well: | ||
118 | */ | 117 | */ |
119 | hwc->nmi = 0; | 118 | if (!hw_event->exclude_user) |
120 | if (capable(CAP_SYS_ADMIN)) { | 119 | hwc->config |= ARCH_PERFMON_EVENTSEL_USR; |
120 | if (!hw_event->exclude_kernel) | ||
121 | hwc->config |= ARCH_PERFMON_EVENTSEL_OS; | 121 | hwc->config |= ARCH_PERFMON_EVENTSEL_OS; |
122 | if (hw_event->nmi) | 122 | |
123 | hwc->nmi = 1; | 123 | /* |
124 | } | 124 | * If privileged enough, allow NMI events: |
125 | */ | ||
126 | hwc->nmi = 0; | ||
127 | if (capable(CAP_SYS_ADMIN) && hw_event->nmi) | ||
128 | hwc->nmi = 1; | ||
125 | 129 | ||
126 | hwc->irq_period = hw_event->irq_period; | 130 | hwc->irq_period = hw_event->irq_period; |
127 | /* | 131 | /* |
@@ -248,10 +252,13 @@ __pmc_fixed_enable(struct perf_counter *counter, | |||
248 | int err; | 252 | int err; |
249 | 253 | ||
250 | /* | 254 | /* |
251 | * Enable IRQ generation (0x8) and ring-3 counting (0x2), | 255 | * Enable IRQ generation (0x8), |
252 | * and enable ring-0 counting if allowed: | 256 | * and enable ring-3 counting (0x2) and ring-0 counting (0x1) |
257 | * if requested: | ||
253 | */ | 258 | */ |
254 | bits = 0x8ULL | 0x2ULL; | 259 | bits = 0x8ULL; |
260 | if (hwc->config & ARCH_PERFMON_EVENTSEL_USR) | ||
261 | bits |= 0x2; | ||
255 | if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) | 262 | if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) |
256 | bits |= 0x1; | 263 | bits |= 0x1; |
257 | bits <<= (idx * 4); | 264 | bits <<= (idx * 4); |