Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e97df763 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

perf/x86/intel/p6: Add userspace RDPMC quirk for PPro

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: default avatarMark 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: default avatarPeter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20140206170815.GW2936@laptop.programming.kicks-ass.net


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 2737fce8
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -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();

@@ -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)
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -409,6 +409,7 @@ struct x86_pmu {
	/*
	 * sysfs attrs
	 */
	int		attr_rdpmc_broken;
	int		attr_rdpmc;
	struct attribute **format_attrs;
	struct attribute **event_attrs;
+33 −15
Original line number Diff line number Diff line
@@ -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;
}