Skip to content

Commit

Permalink
perf/x86/intel/p6: Add userspace RDPMC quirk for PPro
Browse files Browse the repository at this point in the history
PPro machines can die hard when PCE gets enabled due to a CPU erratum.
The safe way it so disable it by default and keep it disabled.

See erratum 26 in:

  http://download.intel.com/design/archives/processors/pro/docs/24268935.pdf

Reported-and-Tested-by: Mark Davies <junk@eslaf.co.uk>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Stephane Eranian <eranian@google.com>
Cc: Vince Weaver <vince@deater.net>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20140206170815.GW2936@laptop.programming.kicks-ass.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Peter Zijlstra authored and Ingo Molnar committed Feb 9, 2014
1 parent 2737fce commit e97df76
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 16 deletions.
6 changes: 5 additions & 1 deletion arch/x86/kernel/cpu/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,8 @@ static int __init init_hw_perf_events(void)

pr_cont("%s PMU driver.\n", x86_pmu.name);

x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */

for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next)
quirk->func();

Expand All @@ -1534,7 +1536,6 @@ static int __init init_hw_perf_events(void)
__EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
0, x86_pmu.num_counters, 0, 0);

x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
x86_pmu_format_group.attrs = x86_pmu.format_attrs;

if (x86_pmu.event_attrs)
Expand Down Expand Up @@ -1820,6 +1821,9 @@ static ssize_t set_attr_rdpmc(struct device *cdev,
if (ret)
return ret;

if (x86_pmu.attr_rdpmc_broken)
return -ENOTSUPP;

if (!!val != !!x86_pmu.attr_rdpmc) {
x86_pmu.attr_rdpmc = !!val;
smp_call_function(change_rdpmc, (void *)val, 1);
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/cpu/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ struct x86_pmu {
/*
* sysfs attrs
*/
int attr_rdpmc_broken;
int attr_rdpmc;
struct attribute **format_attrs;
struct attribute **event_attrs;
Expand Down
48 changes: 33 additions & 15 deletions arch/x86/kernel/cpu/perf_event_p6.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,31 +231,49 @@ static __initconst const struct x86_pmu p6_pmu = {

};

static __init void p6_pmu_rdpmc_quirk(void)
{
if (boot_cpu_data.x86_mask < 9) {
/*
* PPro erratum 26; fixed in stepping 9 and above.
*/
pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n");
x86_pmu.attr_rdpmc_broken = 1;
x86_pmu.attr_rdpmc = 0;
}
}

__init int p6_pmu_init(void)
{
x86_pmu = p6_pmu;

switch (boot_cpu_data.x86_model) {
case 1:
case 3: /* Pentium Pro */
case 5:
case 6: /* Pentium II */
case 7:
case 8:
case 11: /* Pentium III */
case 9:
case 13:
/* Pentium M */
case 1: /* Pentium Pro */
x86_add_quirk(p6_pmu_rdpmc_quirk);
break;

case 3: /* Pentium II - Klamath */
case 5: /* Pentium II - Deschutes */
case 6: /* Pentium II - Mendocino */
break;

case 7: /* Pentium III - Katmai */
case 8: /* Pentium III - Coppermine */
case 10: /* Pentium III Xeon */
case 11: /* Pentium III - Tualatin */
break;

case 9: /* Pentium M - Banias */
case 13: /* Pentium M - Dothan */
break;

default:
pr_cont("unsupported p6 CPU model %d ",
boot_cpu_data.x86_model);
pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model);
return -ENODEV;
}

x86_pmu = p6_pmu;

memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
sizeof(hw_cache_event_ids));


return 0;
}

0 comments on commit e97df76

Please sign in to comment.