perf, x86: Add Nehelem PMU programming errata workaround
Implement the workaround for Intel Errata AAK100 and AAP53. Also, remove the Core-i7 name for Nehalem events since there are also Westmere based i7 chips. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <1269608924.12097.147.camel@laptop> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
ea8e61b7bb
commit
11164cd4f6
@ -184,7 +184,7 @@ struct x86_pmu {
|
|||||||
int version;
|
int version;
|
||||||
int (*handle_irq)(struct pt_regs *);
|
int (*handle_irq)(struct pt_regs *);
|
||||||
void (*disable_all)(void);
|
void (*disable_all)(void);
|
||||||
void (*enable_all)(void);
|
void (*enable_all)(int added);
|
||||||
void (*enable)(struct perf_event *);
|
void (*enable)(struct perf_event *);
|
||||||
void (*disable)(struct perf_event *);
|
void (*disable)(struct perf_event *);
|
||||||
int (*hw_config)(struct perf_event_attr *attr, struct hw_perf_event *hwc);
|
int (*hw_config)(struct perf_event_attr *attr, struct hw_perf_event *hwc);
|
||||||
@ -576,7 +576,7 @@ void hw_perf_disable(void)
|
|||||||
x86_pmu.disable_all();
|
x86_pmu.disable_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x86_pmu_enable_all(void)
|
static void x86_pmu_enable_all(int added)
|
||||||
{
|
{
|
||||||
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
int idx;
|
int idx;
|
||||||
@ -784,7 +784,7 @@ void hw_perf_enable(void)
|
|||||||
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
struct perf_event *event;
|
struct perf_event *event;
|
||||||
struct hw_perf_event *hwc;
|
struct hw_perf_event *hwc;
|
||||||
int i;
|
int i, added = cpuc->n_added;
|
||||||
|
|
||||||
if (!x86_pmu_initialized())
|
if (!x86_pmu_initialized())
|
||||||
return;
|
return;
|
||||||
@ -836,7 +836,7 @@ void hw_perf_enable(void)
|
|||||||
cpuc->enabled = 1;
|
cpuc->enabled = 1;
|
||||||
barrier();
|
barrier();
|
||||||
|
|
||||||
x86_pmu.enable_all();
|
x86_pmu.enable_all(added);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc)
|
static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc)
|
||||||
|
@ -483,7 +483,7 @@ static void intel_pmu_disable_all(void)
|
|||||||
intel_pmu_lbr_disable_all();
|
intel_pmu_lbr_disable_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_pmu_enable_all(void)
|
static void intel_pmu_enable_all(int added)
|
||||||
{
|
{
|
||||||
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
|
|
||||||
@ -502,6 +502,40 @@ static void intel_pmu_enable_all(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for:
|
||||||
|
* Intel Errata AAK100 (model 26)
|
||||||
|
* Intel Errata AAP53 (model 30)
|
||||||
|
*
|
||||||
|
* These chips need to be 'reset' when adding counters by programming
|
||||||
|
* the magic three (non counting) events 0x4300D2, 0x4300B1 and 0x4300B5
|
||||||
|
* either in sequence on the same PMC or on different PMCs.
|
||||||
|
*/
|
||||||
|
static void intel_pmu_nhm_enable_all(int added)
|
||||||
|
{
|
||||||
|
if (added) {
|
||||||
|
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 0, 0x4300D2);
|
||||||
|
wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 1, 0x4300B1);
|
||||||
|
wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 2, 0x4300B5);
|
||||||
|
|
||||||
|
wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x3);
|
||||||
|
wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x0);
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
struct perf_event *event = cpuc->events[i];
|
||||||
|
|
||||||
|
if (!event)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
__x86_pmu_enable_event(&event->hw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intel_pmu_enable_all(added);
|
||||||
|
}
|
||||||
|
|
||||||
static inline u64 intel_pmu_get_status(void)
|
static inline u64 intel_pmu_get_status(void)
|
||||||
{
|
{
|
||||||
u64 status;
|
u64 status;
|
||||||
@ -658,7 +692,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
|
|||||||
intel_pmu_drain_bts_buffer();
|
intel_pmu_drain_bts_buffer();
|
||||||
status = intel_pmu_get_status();
|
status = intel_pmu_get_status();
|
||||||
if (!status) {
|
if (!status) {
|
||||||
intel_pmu_enable_all();
|
intel_pmu_enable_all(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,7 +741,7 @@ again:
|
|||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
intel_pmu_enable_all();
|
intel_pmu_enable_all(0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -920,7 +954,8 @@ static __init int intel_pmu_init(void)
|
|||||||
intel_pmu_lbr_init_nhm();
|
intel_pmu_lbr_init_nhm();
|
||||||
|
|
||||||
x86_pmu.event_constraints = intel_nehalem_event_constraints;
|
x86_pmu.event_constraints = intel_nehalem_event_constraints;
|
||||||
pr_cont("Nehalem/Corei7 events, ");
|
x86_pmu.enable_all = intel_pmu_nhm_enable_all;
|
||||||
|
pr_cont("Nehalem events, ");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 28: /* Atom */
|
case 28: /* Atom */
|
||||||
|
@ -535,7 +535,7 @@ static void p4_pmu_enable_event(struct perf_event *event)
|
|||||||
(cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
|
(cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void p4_pmu_enable_all(void)
|
static void p4_pmu_enable_all(int added)
|
||||||
{
|
{
|
||||||
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||||
int idx;
|
int idx;
|
||||||
|
@ -66,7 +66,7 @@ static void p6_pmu_disable_all(void)
|
|||||||
wrmsrl(MSR_P6_EVNTSEL0, val);
|
wrmsrl(MSR_P6_EVNTSEL0, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void p6_pmu_enable_all(void)
|
static void p6_pmu_enable_all(int added)
|
||||||
{
|
{
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user