Adjust the nSVM EFER test to expect a #GP on WRMSR if L2 attempts to clear EFER.SVME to match KVM's new behavior (synthesizing #GP is safer for KVM as it doesn't require yanking the vCPU out of L2, and is fully synchronous). Signed-off-by: Sean Christopherson --- .../selftests/kvm/x86/svm_nested_efer_test.c | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/tools/testing/selftests/kvm/x86/svm_nested_efer_test.c b/tools/testing/selftests/kvm/x86/svm_nested_efer_test.c index fa0d76a9c390..f612146d23ac 100644 --- a/tools/testing/selftests/kvm/x86/svm_nested_efer_test.c +++ b/tools/testing/selftests/kvm/x86/svm_nested_efer_test.c @@ -15,13 +15,18 @@ static bool l2_ran; static void l2_clear_efer_svme(void) { u64 efer = rdmsr(MSR_EFER); + u8 vector; /* generic_svm_setup() initializes EFER_SVME set for L2 */ GUEST_ASSERT(efer & EFER_SVME); - wrmsr(MSR_EFER, efer & ~EFER_SVME); - /* Unreachable, L1 should be shutdown */ - GUEST_ASSERT(0); + vector = wrmsr_safe(MSR_EFER, efer & ~EFER_SVME); + __GUEST_ASSERT(vector == GP_VECTOR, + "Expected #GP when clearing EFER.LME in L2, got %s", + ex_str(vector)); + + l2_ran = true; + vmmcall(); } static void l1_clear_efer_svme(struct svm_test_data *svm) @@ -29,8 +34,7 @@ static void l1_clear_efer_svme(struct svm_test_data *svm) generic_svm_setup(svm, l2_clear_efer_svme); run_guest(svm->vmcb, svm->vmcb_gpa); - /* Unreachable, L1 should be shutdown */ - GUEST_ASSERT(0); + GUEST_DONE(); } static void l2_lmsle(void) @@ -130,31 +134,10 @@ static void test_enumeration(void) ksft_test_result_pass("KVM enumerates EFER_LMSLE_MBZ=%d\n", lmsle_mbz); } -static void test_clear_efer_svme(void) +static void test_efer_in_guest(struct kvm_vcpu *vcpu) { - struct kvm_vcpu *vcpu; - struct kvm_vm *vm; - - vcpu = create_l1_vcpu(&vm, l1_clear_efer_svme); - - vcpu_run(vcpu); - TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); - - kvm_vm_free(vm); - ksft_test_result_pass("L2 clearing EFER.SVME shuts down L1\n"); -} - -static void test_lmsle(bool lmsle_mbz) -{ - struct kvm_vcpu *vcpu; - struct kvm_vm *vm; struct ucall uc; - vcpu = create_l1_vcpu(&vm, l1_lmsle); - - vcpu_set_or_clear_cpuid_feature(vcpu, X86_FEATURE_EFER_LMSLE_MBZ, - lmsle_mbz); - vcpu_run(vcpu); TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); @@ -166,6 +149,32 @@ static void test_lmsle(bool lmsle_mbz) default: TEST_FAIL("Unexpected ucall: %lu", uc.cmd); } +} + +static void test_clear_efer_svme(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vcpu = create_l1_vcpu(&vm, l1_clear_efer_svme); + + test_efer_in_guest(vcpu); + + kvm_vm_free(vm); + ksft_test_result_pass("L2 clearing EFER.SVME gets #GP\n"); +} + +static void test_lmsle(bool lmsle_mbz) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vcpu = create_l1_vcpu(&vm, l1_lmsle); + + vcpu_set_or_clear_cpuid_feature(vcpu, X86_FEATURE_EFER_LMSLE_MBZ, + lmsle_mbz); + + test_efer_in_guest(vcpu); kvm_vm_free(vm); ksft_test_result_pass("Guest EFER_LMSLE_MBZ=%d\n", lmsle_mbz); @@ -248,7 +257,7 @@ int main(int argc, char *argv[]) test_clear_efer_svme(); test_lmsle(true); } else { - ksft_test_result_skip("L2 clearing EFER.SVME shuts down L1\n"); + ksft_test_result_skip("L2 clearing EFER.SVME gets #GP\n"); ksft_test_result_skip("Guest EFER_LMSLE_MBZ=1\n"); } -- 2.56.0.257.gf7497c7d27-goog