From: Yosry Ahmed Date: Mon, 16 Mar 2026 20:27:32 +0000 (+0000) Subject: KVM: selftests: Drop 'invalid' from svm_nested_invalid_vmcb12_gpa's name X-Git-Tag: ceph-for-7.1-rc4~208^2~4^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=052ca584bd7c51de0de96e684631570459d46cda;p=ceph-client.git KVM: selftests: Drop 'invalid' from svm_nested_invalid_vmcb12_gpa's name The test checks both invalid GPAs as well as unmappable GPAs, so drop 'invalid' from its name. Signed-off-by: Yosry Ahmed Link: https://patch.msgid.link/20260316202732.3164936-10-yosry@kernel.org Signed-off-by: Sean Christopherson --- diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm index ba87cd31872b..83792d136ac3 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -111,9 +111,9 @@ TEST_GEN_PROGS_x86 += x86/vmx_preemption_timer_test TEST_GEN_PROGS_x86 += x86/svm_vmcall_test TEST_GEN_PROGS_x86 += x86/svm_int_ctl_test TEST_GEN_PROGS_x86 += x86/svm_nested_clear_efer_svme -TEST_GEN_PROGS_x86 += x86/svm_nested_invalid_vmcb12_gpa TEST_GEN_PROGS_x86 += x86/svm_nested_shutdown_test TEST_GEN_PROGS_x86 += x86/svm_nested_soft_inject_test +TEST_GEN_PROGS_x86 += x86/svm_nested_vmcb12_gpa TEST_GEN_PROGS_x86 += x86/svm_lbr_nested_state TEST_GEN_PROGS_x86 += x86/tsc_scaling_sync TEST_GEN_PROGS_x86 += x86/sync_regs_test diff --git a/tools/testing/selftests/kvm/x86/svm_nested_invalid_vmcb12_gpa.c b/tools/testing/selftests/kvm/x86/svm_nested_invalid_vmcb12_gpa.c deleted file mode 100644 index 569869bed20b..000000000000 --- a/tools/testing/selftests/kvm/x86/svm_nested_invalid_vmcb12_gpa.c +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2026, Google LLC. - */ -#include "kvm_util.h" -#include "vmx.h" -#include "svm_util.h" -#include "kselftest.h" -#include "kvm_test_harness.h" -#include "test_util.h" - - -#define L2_GUEST_STACK_SIZE 64 - -#define SYNC_GP 101 -#define SYNC_L2_STARTED 102 - -static unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - -static void guest_gp_handler(struct ex_regs *regs) -{ - GUEST_SYNC(SYNC_GP); -} - -static void l2_code(void) -{ - GUEST_SYNC(SYNC_L2_STARTED); - vmcall(); -} - -static void l1_vmrun(struct svm_test_data *svm, u64 gpa) -{ - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); - - asm volatile ("vmrun %[gpa]" : : [gpa] "a" (gpa) : "memory"); -} - -static void l1_vmload(struct svm_test_data *svm, u64 gpa) -{ - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); - - asm volatile ("vmload %[gpa]" : : [gpa] "a" (gpa) : "memory"); -} - -static void l1_vmsave(struct svm_test_data *svm, u64 gpa) -{ - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); - - asm volatile ("vmsave %[gpa]" : : [gpa] "a" (gpa) : "memory"); -} - -static void l1_vmexit(struct svm_test_data *svm, u64 gpa) -{ - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); - - run_guest(svm->vmcb, svm->vmcb_gpa); - GUEST_ASSERT(svm->vmcb->control.exit_code == SVM_EXIT_VMMCALL); - GUEST_DONE(); -} - -static u64 unmappable_gpa(struct kvm_vcpu *vcpu) -{ - struct userspace_mem_region *region; - u64 region_gpa_end, vm_gpa_end = 0; - int i; - - hash_for_each(vcpu->vm->regions.slot_hash, i, region, slot_node) { - region_gpa_end = region->region.guest_phys_addr + region->region.memory_size; - vm_gpa_end = max(vm_gpa_end, region_gpa_end); - } - - return vm_gpa_end; -} - -static void test_invalid_vmcb12(struct kvm_vcpu *vcpu) -{ - vm_vaddr_t nested_gva = 0; - struct ucall uc; - - - vm_install_exception_handler(vcpu->vm, GP_VECTOR, guest_gp_handler); - vcpu_alloc_svm(vcpu->vm, &nested_gva); - vcpu_args_set(vcpu, 2, nested_gva, -1ULL); - vcpu_run(vcpu); - - TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); - TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); - TEST_ASSERT_EQ(uc.args[1], SYNC_GP); -} - -static void test_unmappable_vmcb12(struct kvm_vcpu *vcpu) -{ - vm_vaddr_t nested_gva = 0; - - vcpu_alloc_svm(vcpu->vm, &nested_gva); - vcpu_args_set(vcpu, 2, nested_gva, unmappable_gpa(vcpu)); - vcpu_run(vcpu); - - TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR); - TEST_ASSERT_EQ(vcpu->run->emulation_failure.suberror, KVM_INTERNAL_ERROR_EMULATION); -} - -static void test_unmappable_vmcb12_vmexit(struct kvm_vcpu *vcpu) -{ - struct kvm_x86_state *state; - vm_vaddr_t nested_gva = 0; - struct ucall uc; - - /* - * Enter L2 (with a legit vmcb12 GPA), then overwrite vmcb12 GPA with an - * unmappable GPA. KVM will fail to map vmcb12 on nested VM-Exit and - * cause a shutdown. - */ - vcpu_alloc_svm(vcpu->vm, &nested_gva); - vcpu_args_set(vcpu, 2, nested_gva, unmappable_gpa(vcpu)); - vcpu_run(vcpu); - TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); - TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); - TEST_ASSERT_EQ(uc.args[1], SYNC_L2_STARTED); - - state = vcpu_save_state(vcpu); - state->nested.hdr.svm.vmcb_pa = unmappable_gpa(vcpu); - vcpu_load_state(vcpu, state); - vcpu_run(vcpu); - TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); - - kvm_x86_state_cleanup(state); -} - -KVM_ONE_VCPU_TEST_SUITE(vmcb12_gpa); - -KVM_ONE_VCPU_TEST(vmcb12_gpa, vmrun_invalid, l1_vmrun) -{ - test_invalid_vmcb12(vcpu); -} - -KVM_ONE_VCPU_TEST(vmcb12_gpa, vmload_invalid, l1_vmload) -{ - test_invalid_vmcb12(vcpu); -} - -KVM_ONE_VCPU_TEST(vmcb12_gpa, vmsave_invalid, l1_vmsave) -{ - test_invalid_vmcb12(vcpu); -} - -KVM_ONE_VCPU_TEST(vmcb12_gpa, vmrun_unmappable, l1_vmrun) -{ - test_unmappable_vmcb12(vcpu); -} - -KVM_ONE_VCPU_TEST(vmcb12_gpa, vmload_unmappable, l1_vmload) -{ - test_unmappable_vmcb12(vcpu); -} - -KVM_ONE_VCPU_TEST(vmcb12_gpa, vmsave_unmappable, l1_vmsave) -{ - test_unmappable_vmcb12(vcpu); -} - -/* - * Invalid vmcb12_gpa cannot be test for #VMEXIT as KVM_SET_NESTED_STATE will - * reject it. - */ -KVM_ONE_VCPU_TEST(vmcb12_gpa, vmexit_unmappable, l1_vmexit) -{ - test_unmappable_vmcb12_vmexit(vcpu); -} - -int main(int argc, char *argv[]) -{ - TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); - - return test_harness_run(argc, argv); -} diff --git a/tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c b/tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c new file mode 100644 index 000000000000..569869bed20b --- /dev/null +++ b/tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026, Google LLC. + */ +#include "kvm_util.h" +#include "vmx.h" +#include "svm_util.h" +#include "kselftest.h" +#include "kvm_test_harness.h" +#include "test_util.h" + + +#define L2_GUEST_STACK_SIZE 64 + +#define SYNC_GP 101 +#define SYNC_L2_STARTED 102 + +static unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + +static void guest_gp_handler(struct ex_regs *regs) +{ + GUEST_SYNC(SYNC_GP); +} + +static void l2_code(void) +{ + GUEST_SYNC(SYNC_L2_STARTED); + vmcall(); +} + +static void l1_vmrun(struct svm_test_data *svm, u64 gpa) +{ + generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + asm volatile ("vmrun %[gpa]" : : [gpa] "a" (gpa) : "memory"); +} + +static void l1_vmload(struct svm_test_data *svm, u64 gpa) +{ + generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + asm volatile ("vmload %[gpa]" : : [gpa] "a" (gpa) : "memory"); +} + +static void l1_vmsave(struct svm_test_data *svm, u64 gpa) +{ + generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + asm volatile ("vmsave %[gpa]" : : [gpa] "a" (gpa) : "memory"); +} + +static void l1_vmexit(struct svm_test_data *svm, u64 gpa) +{ + generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + run_guest(svm->vmcb, svm->vmcb_gpa); + GUEST_ASSERT(svm->vmcb->control.exit_code == SVM_EXIT_VMMCALL); + GUEST_DONE(); +} + +static u64 unmappable_gpa(struct kvm_vcpu *vcpu) +{ + struct userspace_mem_region *region; + u64 region_gpa_end, vm_gpa_end = 0; + int i; + + hash_for_each(vcpu->vm->regions.slot_hash, i, region, slot_node) { + region_gpa_end = region->region.guest_phys_addr + region->region.memory_size; + vm_gpa_end = max(vm_gpa_end, region_gpa_end); + } + + return vm_gpa_end; +} + +static void test_invalid_vmcb12(struct kvm_vcpu *vcpu) +{ + vm_vaddr_t nested_gva = 0; + struct ucall uc; + + + vm_install_exception_handler(vcpu->vm, GP_VECTOR, guest_gp_handler); + vcpu_alloc_svm(vcpu->vm, &nested_gva); + vcpu_args_set(vcpu, 2, nested_gva, -1ULL); + vcpu_run(vcpu); + + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); + TEST_ASSERT_EQ(uc.args[1], SYNC_GP); +} + +static void test_unmappable_vmcb12(struct kvm_vcpu *vcpu) +{ + vm_vaddr_t nested_gva = 0; + + vcpu_alloc_svm(vcpu->vm, &nested_gva); + vcpu_args_set(vcpu, 2, nested_gva, unmappable_gpa(vcpu)); + vcpu_run(vcpu); + + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR); + TEST_ASSERT_EQ(vcpu->run->emulation_failure.suberror, KVM_INTERNAL_ERROR_EMULATION); +} + +static void test_unmappable_vmcb12_vmexit(struct kvm_vcpu *vcpu) +{ + struct kvm_x86_state *state; + vm_vaddr_t nested_gva = 0; + struct ucall uc; + + /* + * Enter L2 (with a legit vmcb12 GPA), then overwrite vmcb12 GPA with an + * unmappable GPA. KVM will fail to map vmcb12 on nested VM-Exit and + * cause a shutdown. + */ + vcpu_alloc_svm(vcpu->vm, &nested_gva); + vcpu_args_set(vcpu, 2, nested_gva, unmappable_gpa(vcpu)); + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); + TEST_ASSERT_EQ(uc.args[1], SYNC_L2_STARTED); + + state = vcpu_save_state(vcpu); + state->nested.hdr.svm.vmcb_pa = unmappable_gpa(vcpu); + vcpu_load_state(vcpu, state); + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); + + kvm_x86_state_cleanup(state); +} + +KVM_ONE_VCPU_TEST_SUITE(vmcb12_gpa); + +KVM_ONE_VCPU_TEST(vmcb12_gpa, vmrun_invalid, l1_vmrun) +{ + test_invalid_vmcb12(vcpu); +} + +KVM_ONE_VCPU_TEST(vmcb12_gpa, vmload_invalid, l1_vmload) +{ + test_invalid_vmcb12(vcpu); +} + +KVM_ONE_VCPU_TEST(vmcb12_gpa, vmsave_invalid, l1_vmsave) +{ + test_invalid_vmcb12(vcpu); +} + +KVM_ONE_VCPU_TEST(vmcb12_gpa, vmrun_unmappable, l1_vmrun) +{ + test_unmappable_vmcb12(vcpu); +} + +KVM_ONE_VCPU_TEST(vmcb12_gpa, vmload_unmappable, l1_vmload) +{ + test_unmappable_vmcb12(vcpu); +} + +KVM_ONE_VCPU_TEST(vmcb12_gpa, vmsave_unmappable, l1_vmsave) +{ + test_unmappable_vmcb12(vcpu); +} + +/* + * Invalid vmcb12_gpa cannot be test for #VMEXIT as KVM_SET_NESTED_STATE will + * reject it. + */ +KVM_ONE_VCPU_TEST(vmcb12_gpa, vmexit_unmappable, l1_vmexit) +{ + test_unmappable_vmcb12_vmexit(vcpu); +} + +int main(int argc, char *argv[]) +{ + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); + + return test_harness_run(argc, argv); +}