aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/perf_counter.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2009-02-10 22:35:35 -0500
committerPaul Mackerras <paulus@samba.org>2009-02-10 23:06:59 -0500
commit0475f9ea8e2cc030298908949e0d5da9f2fc2cfe (patch)
treeeb2585d92e00ae4c7fc7e0654ffacde7e8a57e1c /arch/x86/kernel/cpu/perf_counter.c
parentd278c48435625cb6b7edcf6a547620768b175709 (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/kernel/cpu/perf_counter.c')
-rw-r--r--arch/x86/kernel/cpu/perf_counter.c31
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);