Commit 9c74fb50 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar

perf_counter: Fix up P6 PMU details

The P6 doesn't seem to support cache ref/hit/miss counts, so
we extend the generic hardware event codes to have 0 and -1
mean the same thing as for the generic cache events.

Furthermore, it turns out the 0 event does not count
(that is, its reported that on PPro it actually does count
something), therefore use a event configuration that's
specified not to count to disable the counters.
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <new-submission>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 11d1578f
...@@ -84,6 +84,14 @@ static u64 p6_pmu_event_map(int event) ...@@ -84,6 +84,14 @@ static u64 p6_pmu_event_map(int event)
return p6_perfmon_event_map[event]; return p6_perfmon_event_map[event];
} }
/*
* Counter setting that is specified not to count anything.
* We use this to effectively disable a counter.
*
* L2_RQSTS with 0 MESI unit mask.
*/
#define P6_NOP_COUNTER 0x0000002EULL
static u64 p6_pmu_raw_event(u64 event) static u64 p6_pmu_raw_event(u64 event)
{ {
#define P6_EVNTSEL_EVENT_MASK 0x000000FFULL #define P6_EVNTSEL_EVENT_MASK 0x000000FFULL
...@@ -704,6 +712,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter) ...@@ -704,6 +712,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
{ {
struct perf_counter_attr *attr = &counter->attr; struct perf_counter_attr *attr = &counter->attr;
struct hw_perf_counter *hwc = &counter->hw; struct hw_perf_counter *hwc = &counter->hw;
u64 config;
int err; int err;
if (!x86_pmu_initialized()) if (!x86_pmu_initialized())
...@@ -756,10 +765,19 @@ static int __hw_perf_counter_init(struct perf_counter *counter) ...@@ -756,10 +765,19 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
if (attr->config >= x86_pmu.max_events) if (attr->config >= x86_pmu.max_events)
return -EINVAL; return -EINVAL;
/* /*
* The generic map: * The generic map:
*/ */
hwc->config |= x86_pmu.event_map(attr->config); config = x86_pmu.event_map(attr->config);
if (config == 0)
return -ENOENT;
if (config == -1LL)
return -EINVAL;
hwc->config |= config;
return 0; return 0;
} }
...@@ -767,7 +785,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter) ...@@ -767,7 +785,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
static void p6_pmu_disable_all(void) static void p6_pmu_disable_all(void)
{ {
struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
unsigned long val; u64 val;
if (!cpuc->enabled) if (!cpuc->enabled)
return; return;
...@@ -917,10 +935,10 @@ static inline void ...@@ -917,10 +935,10 @@ static inline void
p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
{ {
struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
unsigned long val = ARCH_PERFMON_EVENTSEL0_ENABLE; u64 val = P6_NOP_COUNTER;
if (!cpuc->enabled) if (cpuc->enabled)
val = 0; val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
(void)checking_wrmsrl(hwc->config_base + idx, val); (void)checking_wrmsrl(hwc->config_base + idx, val);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment