|
@@ -1519,7 +1519,7 @@ static __initconst const struct x86_pmu intel_pmu = {
|
|
|
.guest_get_msrs = intel_guest_get_msrs,
|
|
|
};
|
|
|
|
|
|
-static void intel_clovertown_quirks(void)
|
|
|
+static __init void intel_clovertown_quirk(void)
|
|
|
{
|
|
|
/*
|
|
|
* PEBS is unreliable due to:
|
|
@@ -1545,30 +1545,61 @@ static void intel_clovertown_quirks(void)
|
|
|
x86_pmu.pebs_constraints = NULL;
|
|
|
}
|
|
|
|
|
|
-static void intel_sandybridge_quirks(void)
|
|
|
+static __init void intel_sandybridge_quirk(void)
|
|
|
{
|
|
|
printk(KERN_WARNING "PEBS disabled due to CPU errata.\n");
|
|
|
x86_pmu.pebs = 0;
|
|
|
x86_pmu.pebs_constraints = NULL;
|
|
|
}
|
|
|
|
|
|
-static const int intel_event_id_to_hw_id[] __initconst = {
|
|
|
- PERF_COUNT_HW_CPU_CYCLES,
|
|
|
- PERF_COUNT_HW_INSTRUCTIONS,
|
|
|
- PERF_COUNT_HW_BUS_CYCLES,
|
|
|
- PERF_COUNT_HW_CACHE_REFERENCES,
|
|
|
- PERF_COUNT_HW_CACHE_MISSES,
|
|
|
- PERF_COUNT_HW_BRANCH_INSTRUCTIONS,
|
|
|
- PERF_COUNT_HW_BRANCH_MISSES,
|
|
|
+static const struct { int id; char *name; } intel_arch_events_map[] __initconst = {
|
|
|
+ { PERF_COUNT_HW_CPU_CYCLES, "cpu cycles" },
|
|
|
+ { PERF_COUNT_HW_INSTRUCTIONS, "instructions" },
|
|
|
+ { PERF_COUNT_HW_BUS_CYCLES, "bus cycles" },
|
|
|
+ { PERF_COUNT_HW_CACHE_REFERENCES, "cache references" },
|
|
|
+ { PERF_COUNT_HW_CACHE_MISSES, "cache misses" },
|
|
|
+ { PERF_COUNT_HW_BRANCH_INSTRUCTIONS, "branch instructions" },
|
|
|
+ { PERF_COUNT_HW_BRANCH_MISSES, "branch misses" },
|
|
|
};
|
|
|
|
|
|
+static __init void intel_arch_events_quirk(void)
|
|
|
+{
|
|
|
+ int bit;
|
|
|
+
|
|
|
+ /* disable event that reported as not presend by cpuid */
|
|
|
+ for_each_set_bit(bit, x86_pmu.events_mask, ARRAY_SIZE(intel_arch_events_map)) {
|
|
|
+ intel_perfmon_event_map[intel_arch_events_map[bit].id] = 0;
|
|
|
+ printk(KERN_WARNING "CPUID marked event: \'%s\' unavailable\n",
|
|
|
+ intel_arch_events_map[bit].name);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static __init void intel_nehalem_quirk(void)
|
|
|
+{
|
|
|
+ union cpuid10_ebx ebx;
|
|
|
+
|
|
|
+ ebx.full = x86_pmu.events_maskl;
|
|
|
+ if (ebx.split.no_branch_misses_retired) {
|
|
|
+ /*
|
|
|
+ * Erratum AAJ80 detected, we work it around by using
|
|
|
+ * the BR_MISP_EXEC.ANY event. This will over-count
|
|
|
+ * branch-misses, but it's still much better than the
|
|
|
+ * architectural event which is often completely bogus:
|
|
|
+ */
|
|
|
+ intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
|
|
|
+ ebx.split.no_branch_misses_retired = 0;
|
|
|
+ x86_pmu.events_maskl = ebx.full;
|
|
|
+ printk(KERN_INFO "CPU erratum AAJ80 worked around\n");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
__init int intel_pmu_init(void)
|
|
|
{
|
|
|
union cpuid10_edx edx;
|
|
|
union cpuid10_eax eax;
|
|
|
union cpuid10_ebx ebx;
|
|
|
unsigned int unused;
|
|
|
- int version, bit;
|
|
|
+ int version;
|
|
|
|
|
|
if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
|
|
|
switch (boot_cpu_data.x86) {
|
|
@@ -1599,6 +1630,9 @@ __init int intel_pmu_init(void)
|
|
|
x86_pmu.cntval_bits = eax.split.bit_width;
|
|
|
x86_pmu.cntval_mask = (1ULL << eax.split.bit_width) - 1;
|
|
|
|
|
|
+ x86_pmu.events_maskl = ebx.full;
|
|
|
+ x86_pmu.events_mask_len = eax.split.mask_length;
|
|
|
+
|
|
|
/*
|
|
|
* Quirk: v2 perfmon does not report fixed-purpose events, so
|
|
|
* assume at least 3 events:
|
|
@@ -1618,6 +1652,8 @@ __init int intel_pmu_init(void)
|
|
|
|
|
|
intel_ds_init();
|
|
|
|
|
|
+ x86_add_quirk(intel_arch_events_quirk); /* Install first, so it runs last */
|
|
|
+
|
|
|
/*
|
|
|
* Install the hw-cache-events table:
|
|
|
*/
|
|
@@ -1627,7 +1663,7 @@ __init int intel_pmu_init(void)
|
|
|
break;
|
|
|
|
|
|
case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */
|
|
|
- x86_pmu.quirks = intel_clovertown_quirks;
|
|
|
+ x86_add_quirk(intel_clovertown_quirk);
|
|
|
case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */
|
|
|
case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */
|
|
|
case 29: /* six-core 45 nm xeon "Dunnington" */
|
|
@@ -1661,18 +1697,8 @@ __init int intel_pmu_init(void)
|
|
|
/* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
|
|
|
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x1803fb1;
|
|
|
|
|
|
- if (ebx.split.no_branch_misses_retired) {
|
|
|
- /*
|
|
|
- * Erratum AAJ80 detected, we work it around by using
|
|
|
- * the BR_MISP_EXEC.ANY event. This will over-count
|
|
|
- * branch-misses, but it's still much better than the
|
|
|
- * architectural event which is often completely bogus:
|
|
|
- */
|
|
|
- intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
|
|
|
- ebx.split.no_branch_misses_retired = 0;
|
|
|
+ x86_add_quirk(intel_nehalem_quirk);
|
|
|
|
|
|
- pr_cont("erratum AAJ80 worked around, ");
|
|
|
- }
|
|
|
pr_cont("Nehalem events, ");
|
|
|
break;
|
|
|
|
|
@@ -1712,7 +1738,7 @@ __init int intel_pmu_init(void)
|
|
|
break;
|
|
|
|
|
|
case 42: /* SandyBridge */
|
|
|
- x86_pmu.quirks = intel_sandybridge_quirks;
|
|
|
+ x86_add_quirk(intel_sandybridge_quirk);
|
|
|
case 45: /* SandyBridge, "Romely-EP" */
|
|
|
memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
|
|
|
sizeof(hw_cache_event_ids));
|
|
@@ -1749,12 +1775,6 @@ __init int intel_pmu_init(void)
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- x86_pmu.events_maskl = ebx.full;
|
|
|
- x86_pmu.events_mask_len = eax.split.mask_length;
|
|
|
-
|
|
|
- /* disable event that reported as not presend by cpuid */
|
|
|
- for_each_set_bit(bit, x86_pmu.events_mask, ARRAY_SIZE(intel_event_id_to_hw_id))
|
|
|
- intel_perfmon_event_map[intel_event_id_to_hw_id[bit]] = 0;
|
|
|
|
|
|
return 0;
|
|
|
}
|