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: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
11d1578f94
commit
9c74fb5086
1 changed files with 23 additions and 5 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue