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@xxxxxxxxxx> --- x86/svm_tests.c | 65 ++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/x86/svm_tests.c b/x86/svm_tests.c index e20f6697..9a89155a 100644 --- a/x86/svm_tests.c +++ b/x86/svm_tests.c @@ -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); } -- 2.41.0.162.gfafddb0af9-goog