@@ -438,11 +438,26 @@ static inline int wrmsr_safe(u32 index, u64 val)
return exception_vector();
}
-static inline uint64_t rdpmc(uint32_t index)
+static inline int rdpmc_safe(u32 index, uint64_t *val)
{
uint32_t a, d;
- asm volatile ("rdpmc" : "=a"(a), "=d"(d) : "c"(index));
- return a | ((uint64_t)d << 32);
+
+ asm volatile (ASM_TRY("1f")
+ "rdpmc\n\t"
+ "1:"
+ : "=a"(a), "=d"(d) : "c"(index) : "memory");
+ *val = (uint64_t)a | ((uint64_t)d << 32);
+ return exception_vector();
+}
+
+static inline uint64_t rdpmc(uint32_t index)
+{
+ uint64_t val;
+ int vector = rdpmc_safe(index, &val);
+
+ assert_msg(!vector, "Unexpected %s on RDPMC(%d)",
+ exception_mnemonic(vector), index);
+ return val;
}
static inline int write_cr0_safe(ulong val)
@@ -651,12 +651,22 @@ static void set_ref_cycle_expectations(void)
gp_events[2].max = (gp_events[2].max * cnt.count) / tsc_delta;
}
+static void check_invalid_rdpmc_gp(void)
+{
+ uint64_t val;
+
+ report(rdpmc_safe(64, &val) == GP_VECTOR,
+ "Expected #GP on RDPMC(64)");
+}
+
int main(int ac, char **av)
{
setup_vm();
handle_irq(PC_VECTOR, cnt_overflow);
buf = malloc(N*64);
+ check_invalid_rdpmc_gp();
+
if (!pmu_version()) {
report_skip("No Intel Arch PMU is detected!");
return report_summary();