@@ -10,5 +10,8 @@ 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;
reset_all_counters();
}
\ No newline at end of file
@@ -37,6 +37,9 @@ struct pmu_caps {
u64 perf_cap;
u32 msr_gp_counter_base;
u32 msr_gp_event_select_base;
+ u32 msr_global_status;
+ u32 msr_global_ctl;
+ u32 msr_global_status_clr;
};
extern struct cpuid cpuid_10;
@@ -194,4 +197,34 @@ static inline void reset_all_counters(void)
reset_all_fixed_counters();
}
+static inline void pmu_clear_global_status(void)
+{
+ wrmsr(pmu.msr_global_status_clr, rdmsr(pmu.msr_global_status));
+}
+
+static inline u64 pmu_get_global_status(void)
+{
+ return rdmsr(pmu.msr_global_status);
+}
+
+static inline u64 pmu_get_global_enable(void)
+{
+ return rdmsr(pmu.msr_global_ctl);
+}
+
+static inline void pmu_set_global_enable(u64 bitmask)
+{
+ wrmsr(pmu.msr_global_ctl, bitmask);
+}
+
+static inline void pmu_reset_global_enable(void)
+{
+ wrmsr(pmu.msr_global_ctl, 0);
+}
+
+static inline void pmu_ack_global_status(u64 value)
+{
+ wrmsr(pmu.msr_global_status_clr, value);
+}
+
#endif /* _X86_PMU_H_ */
@@ -103,15 +103,12 @@ static struct pmu_event* get_counter_event(pmu_counter_t *cnt)
static void global_enable(pmu_counter_t *cnt)
{
cnt->idx = event_to_global_idx(cnt);
-
- wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, rdmsr(MSR_CORE_PERF_GLOBAL_CTRL) |
- (1ull << cnt->idx));
+ pmu_set_global_enable(pmu_get_global_enable() | BIT_ULL(cnt->idx));
}
static void global_disable(pmu_counter_t *cnt)
{
- wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, rdmsr(MSR_CORE_PERF_GLOBAL_CTRL) &
- ~(1ull << cnt->idx));
+ pmu_set_global_enable(pmu_get_global_enable() & ~BIT_ULL(cnt->idx));
}
static void __start_event(pmu_counter_t *evt, uint64_t count)
@@ -289,7 +286,7 @@ static void check_counter_overflow(void)
overflow_preset = measure_for_overflow(&cnt);
/* clear status before test */
- wrmsr(MSR_CORE_PERF_GLOBAL_OVF_CTRL, rdmsr(MSR_CORE_PERF_GLOBAL_STATUS));
+ pmu_clear_global_status();
report_prefix_push("overflow");
@@ -316,10 +313,10 @@ static void check_counter_overflow(void)
idx = event_to_global_idx(&cnt);
__measure(&cnt, cnt.count);
report(cnt.count == 1, "cntr-%d", i);
- status = rdmsr(MSR_CORE_PERF_GLOBAL_STATUS);
+ status = pmu_get_global_status();
report(status & (1ull << idx), "status-%d", i);
- wrmsr(MSR_CORE_PERF_GLOBAL_OVF_CTRL, status);
- status = rdmsr(MSR_CORE_PERF_GLOBAL_STATUS);
+ pmu_ack_global_status(status);
+ status = pmu_get_global_status();
report(!(status & (1ull << idx)), "status clear-%d", i);
report(check_irq() == (i % 2), "irq-%d", i);
}
@@ -428,8 +425,7 @@ static void check_running_counter_wrmsr(void)
report(evt.count < gp_events[1].min, "cntr");
/* clear status before overflow test */
- wrmsr(MSR_CORE_PERF_GLOBAL_OVF_CTRL,
- rdmsr(MSR_CORE_PERF_GLOBAL_STATUS));
+ pmu_clear_global_status();
start_event(&evt);
@@ -441,8 +437,8 @@ static void check_running_counter_wrmsr(void)
loop();
stop_event(&evt);
- status = rdmsr(MSR_CORE_PERF_GLOBAL_STATUS);
- report(status & 1, "status");
+ status = pmu_get_global_status();
+ report(status & 1, "status msr bit");
report_prefix_pop();
}
@@ -462,8 +458,7 @@ static void check_emulated_instr(void)
};
report_prefix_push("emulated instruction");
- wrmsr(MSR_CORE_PERF_GLOBAL_OVF_CTRL,
- rdmsr(MSR_CORE_PERF_GLOBAL_STATUS));
+ pmu_clear_global_status();
start_event(&brnch_cnt);
start_event(&instr_cnt);
@@ -497,7 +492,7 @@ static void check_emulated_instr(void)
:
: "eax", "ebx", "ecx", "edx");
- wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
+ pmu_reset_global_enable();
stop_event(&brnch_cnt);
stop_event(&instr_cnt);
@@ -509,7 +504,7 @@ static void check_emulated_instr(void)
report(brnch_cnt.count - brnch_start >= EXPECTED_BRNCH,
"branch count");
// Additionally check that those counters overflowed properly.
- status = rdmsr(MSR_CORE_PERF_GLOBAL_STATUS);
+ status = pmu_get_global_status();
report(status & 1, "branch counter overflow");
report(status & 2, "instruction counter overflow");
@@ -598,7 +593,7 @@ static void set_ref_cycle_expectations(void)
if (!pmu_nr_gp_counters() || !pmu_gp_counter_is_available(2))
return;
- wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
+ pmu_reset_global_enable();
t0 = fenced_rdtsc();
start_event(&cnt);