@@ -2,6 +2,20 @@
struct pmu_caps pmu;
+/*
+ * All AMD CPUs that support vPMU have MSR_K7_PERFCTRx, but the
+ * values written to it are discarded when vPMU is globally disabled.
+ */
+static inline bool amd_k7_counter_is_durable(void)
+{
+ u64 after, before = (1ull << PMC_DEFAULT_WIDTH) - 1;
+
+ wrmsr_safe(MSR_K7_PERFCTR0, before);
+ rdmsr_safe(MSR_K7_PERFCTR0, &after);
+
+ return before == after;
+}
+
void pmu_init(void)
{
pmu.is_intel = is_intel();
@@ -38,7 +52,7 @@ void pmu_init(void)
pmu.msr_global_ctl = MSR_CORE_PERF_GLOBAL_CTRL;
pmu.msr_global_status_clr = MSR_CORE_PERF_GLOBAL_OVF_CTRL;
}
- } else {
+ } else if (amd_k7_counter_is_durable()){
if (this_cpu_has(X86_FEATURE_PERFCTR_CORE)) {
/* Performance Monitoring Version 2 Supported */
if (this_cpu_has(X86_FEATURE_AMD_PMU_V2)) {
@@ -684,6 +684,9 @@ int main(int ac, char **av)
gp_events_size = sizeof(intel_gp_events)/sizeof(intel_gp_events[0]);
report_prefix_push("Intel");
set_ref_cycle_expectations();
+ } else if (!pmu.nr_gp_counters) {
+ report_skip("No AMD PMU is detected!");
+ return report_summary();
} else {
gp_events_size = sizeof(amd_gp_events)/sizeof(amd_gp_events[0]);
gp_events = (struct pmu_event *)amd_gp_events;