@@ -10,6 +10,7 @@
#include "isr.h"
#include "apic.h"
#include "delay.h"
+#include "util.h"
#include "x86/usermode.h"
#define SVM_EXIT_MAX_DR_INTERCEPT 0x3f
@@ -2767,26 +2768,29 @@ static void svm_no_nm_test(void)
"fnop with CR0.TS and CR0.EM unset no #NM excpetion");
}
-static bool check_lbr(u64 *from_excepted, u64 *to_expected)
+static u64 amd_get_lbr_rip(u32 msr)
{
- u64 from = rdmsr(MSR_IA32_LASTBRANCHFROMIP);
- u64 to = rdmsr(MSR_IA32_LASTBRANCHTOIP);
-
- if ((u64)from_excepted != from) {
- report(false, "MSR_IA32_LASTBRANCHFROMIP, expected=0x%lx, actual=0x%lx",
- (u64)from_excepted, from);
- return false;
- }
-
- if ((u64)to_expected != to) {
- report(false, "MSR_IA32_LASTBRANCHFROMIP, expected=0x%lx, actual=0x%lx",
- (u64)from_excepted, from);
- return false;
- }
-
- return true;
+ return rdmsr(msr) & ~AMD_LBR_RECORD_MISPREDICT;
}
+#define HOST_CHECK_LBR(from_expected, to_expected) \
+do { \
+ TEST_EXPECT_EQ((u64)from_expected, amd_get_lbr_rip(MSR_IA32_LASTBRANCHFROMIP)); \
+ TEST_EXPECT_EQ((u64)to_expected, amd_get_lbr_rip(MSR_IA32_LASTBRANCHTOIP)); \
+} while (0)
+
+/*
+ * FIXME: Do something other than generate an exception to communicate failure.
+ * Debugging without expected vs. actual is an absolute nightmare.
+ */
+#define GUEST_CHECK_LBR(from_expected, to_expected) \
+do { \
+ if ((u64)(from_expected) != amd_get_lbr_rip(MSR_IA32_LASTBRANCHFROMIP)) \
+ asm volatile("ud2"); \
+ if ((u64)(to_expected) != amd_get_lbr_rip(MSR_IA32_LASTBRANCHTOIP)) \
+ asm volatile("ud2"); \
+} while (0)
+
static bool check_dbgctl(u64 dbgctl, u64 dbgctl_expected)
{
if (dbgctl != dbgctl_expected) {
@@ -2796,7 +2800,6 @@ static bool check_dbgctl(u64 dbgctl, u64 dbgctl_expected)
return true;
}
-
#define DO_BRANCH(branch_name) \
asm volatile ( \
# branch_name "_from:" \
@@ -2834,11 +2837,8 @@ static void svm_lbrv_test_guest1(void)
asm volatile("ud2\n");
if (rdmsr(MSR_IA32_DEBUGCTLMSR) != 0)
asm volatile("ud2\n");
- if (rdmsr(MSR_IA32_LASTBRANCHFROMIP) != (u64)&guest_branch0_from)
- asm volatile("ud2\n");
- if (rdmsr(MSR_IA32_LASTBRANCHTOIP) != (u64)&guest_branch0_to)
- asm volatile("ud2\n");
+ GUEST_CHECK_LBR(&guest_branch0_from, &guest_branch0_to);
asm volatile ("vmmcall\n");
}
@@ -2855,11 +2855,7 @@ static void svm_lbrv_test_guest2(void)
if (dbgctl != 0)
asm volatile("ud2\n");
- if (rdmsr(MSR_IA32_LASTBRANCHFROMIP) != (u64)&host_branch2_from)
- asm volatile("ud2\n");
- if (rdmsr(MSR_IA32_LASTBRANCHTOIP) != (u64)&host_branch2_to)
- asm volatile("ud2\n");
-
+ GUEST_CHECK_LBR(&host_branch2_from, &host_branch2_to);
wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR);
dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR);
@@ -2868,10 +2864,7 @@ static void svm_lbrv_test_guest2(void)
if (dbgctl != DEBUGCTLMSR_LBR)
asm volatile("ud2\n");
- if (rdmsr(MSR_IA32_LASTBRANCHFROMIP) != (u64)&guest_branch2_from)
- asm volatile("ud2\n");
- if (rdmsr(MSR_IA32_LASTBRANCHTOIP) != (u64)&guest_branch2_to)
- asm volatile("ud2\n");
+ GUEST_CHECK_LBR(&guest_branch2_from, &guest_branch2_to);
asm volatile ("vmmcall\n");
}
@@ -2888,7 +2881,7 @@ static void svm_lbrv_test0(void)
dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR);
check_dbgctl(dbgctl, 0);
- check_lbr(&host_branch0_from, &host_branch0_to);
+ HOST_CHECK_LBR(&host_branch0_from, &host_branch0_to);
}
static void svm_lbrv_test1(void)
@@ -2910,7 +2903,7 @@ static void svm_lbrv_test1(void)
}
check_dbgctl(dbgctl, 0);
- check_lbr(&guest_branch0_from, &guest_branch0_to);
+ HOST_CHECK_LBR(&guest_branch0_from, &guest_branch0_to);
}
static void svm_lbrv_test2(void)
@@ -2934,7 +2927,7 @@ static void svm_lbrv_test2(void)
}
check_dbgctl(dbgctl, 0);
- check_lbr(&guest_branch2_from, &guest_branch2_to);
+ HOST_CHECK_LBR(&guest_branch2_from, &guest_branch2_to);
}
static void svm_lbrv_nested_test1(void)
@@ -2967,7 +2960,7 @@ static void svm_lbrv_nested_test1(void)
}
check_dbgctl(dbgctl, DEBUGCTLMSR_LBR);
- check_lbr(&host_branch3_from, &host_branch3_to);
+ HOST_CHECK_LBR(&host_branch3_from, &host_branch3_to);
}
static void svm_lbrv_nested_test2(void)
@@ -2998,7 +2991,7 @@ static void svm_lbrv_nested_test2(void)
}
check_dbgctl(dbgctl, DEBUGCTLMSR_LBR);
- check_lbr(&host_branch4_from, &host_branch4_to);
+ HOST_CHECK_LBR(&host_branch4_from, &host_branch4_to);
}
Ignore the mispredict bit when comparing the expected versus actual LBR records. Unsurprisingly, relying on the whims of the CPU's branch predictor results in false failures. Fixes: 537d39df ("svm: add tests for LBR virtualization") Signed-off-by: Sean Christopherson <seanjc@google.com> --- x86/svm_tests.c | 65 ++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 36 deletions(-)