@@ -10,8 +10,10 @@ void pmu_init(void)
pmu.perf_cap = rdmsr(MSR_IA32_PERF_CAPABILITIES);
pmu.msr_gp_counter_base = MSR_IA32_PERFCTR0;
pmu.msr_gp_event_select_base = MSR_P6_EVNTSEL0;
- pmu.msr_global_status = MSR_CORE_PERF_GLOBAL_STATUS;
- pmu.msr_global_ctl = MSR_CORE_PERF_GLOBAL_CTRL;
- pmu.msr_global_status_clr = MSR_CORE_PERF_GLOBAL_OVF_CTRL;
+ if (this_cpu_support_perf_status()) {
+ pmu.msr_global_status = MSR_CORE_PERF_GLOBAL_STATUS;
+ pmu.msr_global_ctl = MSR_CORE_PERF_GLOBAL_CTRL;
+ pmu.msr_global_status_clr = MSR_CORE_PERF_GLOBAL_OVF_CTRL;
+ }
reset_all_counters();
}
\ No newline at end of file
@@ -116,6 +116,11 @@ static inline bool this_cpu_has_perf_global_ctrl(void)
return pmu_version() > 1;
}
+static inline bool this_cpu_support_perf_status(void)
+{
+ return pmu_version() > 1;
+}
+
static inline u8 pmu_nr_gp_counters(void)
{
return (cpuid_10.a >> 8) & 0xff;
@@ -102,12 +102,18 @@ static struct pmu_event* get_counter_event(pmu_counter_t *cnt)
static void global_enable(pmu_counter_t *cnt)
{
+ if (!this_cpu_has_perf_global_ctrl())
+ return;
+
cnt->idx = event_to_global_idx(cnt);
pmu_set_global_enable(pmu_get_global_enable() | BIT_ULL(cnt->idx));
}
static void global_disable(pmu_counter_t *cnt)
{
+ if (!this_cpu_has_perf_global_ctrl())
+ return;
+
pmu_set_global_enable(pmu_get_global_enable() & ~BIT_ULL(cnt->idx));
}
@@ -286,7 +292,8 @@ static void check_counter_overflow(void)
overflow_preset = measure_for_overflow(&cnt);
/* clear status before test */
- pmu_clear_global_status();
+ if (this_cpu_support_perf_status())
+ pmu_clear_global_status();
report_prefix_push("overflow");
@@ -313,6 +320,10 @@ static void check_counter_overflow(void)
idx = event_to_global_idx(&cnt);
__measure(&cnt, cnt.count);
report(cnt.count == 1, "cntr-%d", i);
+
+ if (!this_cpu_support_perf_status())
+ continue;
+
status = pmu_get_global_status();
report(status & (1ull << idx), "status-%d", i);
pmu_ack_global_status(status);
@@ -425,7 +436,8 @@ static void check_running_counter_wrmsr(void)
report(evt.count < gp_events[1].min, "cntr");
/* clear status before overflow test */
- pmu_clear_global_status();
+ if (this_cpu_support_perf_status())
+ pmu_clear_global_status();
start_event(&evt);
@@ -437,8 +449,11 @@ static void check_running_counter_wrmsr(void)
loop();
stop_event(&evt);
- status = pmu_get_global_status();
- report(status & 1, "status msr bit");
+
+ if (this_cpu_support_perf_status()) {
+ status = pmu_get_global_status();
+ report(status & 1, "status msr bit");
+ }
report_prefix_pop();
}
@@ -458,7 +473,8 @@ static void check_emulated_instr(void)
};
report_prefix_push("emulated instruction");
- pmu_clear_global_status();
+ if (this_cpu_support_perf_status())
+ pmu_clear_global_status();
start_event(&brnch_cnt);
start_event(&instr_cnt);
@@ -492,7 +508,8 @@ static void check_emulated_instr(void)
:
: "eax", "ebx", "ecx", "edx");
- pmu_reset_global_enable();
+ if (this_cpu_has_perf_global_ctrl())
+ pmu_reset_global_enable();
stop_event(&brnch_cnt);
stop_event(&instr_cnt);
@@ -503,10 +520,12 @@ static void check_emulated_instr(void)
"instruction count");
report(brnch_cnt.count - brnch_start >= EXPECTED_BRNCH,
"branch count");
- // Additionally check that those counters overflowed properly.
- status = pmu_get_global_status();
- report(status & 1, "branch counter overflow");
- report(status & 2, "instruction counter overflow");
+ if (this_cpu_support_perf_status()) {
+ // Additionally check that those counters overflowed properly.
+ status = pmu_get_global_status();
+ report(status & 1, "branch counter overflow");
+ report(status & 2, "instruction counter overflow");
+ }
report_prefix_pop();
}
@@ -593,7 +612,8 @@ static void set_ref_cycle_expectations(void)
if (!pmu_nr_gp_counters() || !pmu_gp_counter_is_available(2))
return;
- pmu_reset_global_enable();
+ if (this_cpu_has_perf_global_ctrl())
+ pmu_reset_global_enable();
t0 = fenced_rdtsc();
start_event(&cnt);
@@ -644,11 +664,6 @@ int main(int ac, char **av)
return report_summary();
}
- if (pmu_version() == 1) {
- report_skip("PMU version 1 is not supported.");
- return report_summary();
- }
-
set_ref_cycle_expectations();
printf("PMU version: %d\n", pmu_version());