[PATCH 11/11] KVM: selftests: Extend nested x2APIC test to validate using eVMCS for vmcs12

From: Paolo Bonzini

Date: Sat Sep 26 2026 - 01:34:29 EST


From: Sean Christopherson <seanjc@xxxxxxxxxx>

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
Message-ID: <20260813223610.2043560-7-seanjc@xxxxxxxxxx>
Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
.../selftests/kvm/x86/nested_x2apic_test.c | 53 +++++++++++++++----
1 file changed, 42 insertions(+), 11 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86/nested_x2apic_test.c b/tools/testing/selftests/kvm/x86/nested_x2apic_test.c
index e94d4e77256b..eb89d5bfc0fe 100644
--- a/tools/testing/selftests/kvm/x86/nested_x2apic_test.c
+++ b/tools/testing/selftests/kvm/x86/nested_x2apic_test.c
@@ -50,12 +50,24 @@ static void l1_svm_code(struct svm_test_data *svm)
stgi();
}

-static void l1_vmx_code(struct vmx_pages *vmx)
+static void l1_vmx_code(struct vmx_pages *vmx, struct hyperv_test_pages *hv_pages)
{
u64 control;

+ if (hv_pages) {
+ wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID);
+ enable_vp_assist(hv_pages->vp_assist_gpa, hv_pages->vp_assist);
+ evmcs_enable();
+ }
+
GUEST_ASSERT_EQ(prepare_for_vmx_operation(vmx), true);
- GUEST_ASSERT_EQ(load_vmcs(vmx), true);
+
+ if (hv_pages) {
+ GUEST_ASSERT(load_evmcs(hv_pages));
+ current_evmcs->hv_enlightenments_control.msr_bitmap = 1;
+ } else {
+ GUEST_ASSERT(load_vmcs(vmx));
+ }

prepare_vmcs(vmx, NULL);
GUEST_ASSERT_EQ(vmwrite(GUEST_RIP, (unsigned long)l2_guest_code), 0);
@@ -128,14 +140,14 @@ static void l1_test_x2apic_intercepts(void)
nr_irqs = 0;
}

-static void l1_guest_code(void *test_data)
+static void l1_guest_code(void *test_data, void *hv_pages)
{
x2apic_enable();

if (this_cpu_has(X86_FEATURE_SVM))
l1_svm_code(test_data);
else
- l1_vmx_code(test_data);
+ l1_vmx_code(test_data, hv_pages);

GUEST_ASSERT_EQ(x2apic_read_reg(APIC_TASKPRI), 0);
x2apic_write_reg(APIC_TASKPRI, 0xf0);
@@ -150,9 +162,9 @@ static void l1_guest_code(void *test_data)
GUEST_DONE();
}

-static void __test_x2apic_intercepts(void)
+static void __test_x2apic_intercepts(bool use_evmcs)
{
- gva_t nested_test_data_gva;
+ gva_t nested_test_data_gva, hv_pages_gva = 0;
struct kvm_vcpu *vcpu;
struct kvm_vm *vm;
struct ucall uc;
@@ -169,7 +181,14 @@ static void __test_x2apic_intercepts(void)
else
vcpu_alloc_vmx(vm, &nested_test_data_gva);

- vcpu_args_set(vcpu, 1, nested_test_data_gva);
+ if (use_evmcs) {
+ vcpu_set_hv_cpuid(vcpu);
+ vcpu_enable_evmcs(vcpu);
+
+ vcpu_alloc_hyperv_test_pages(vm, &hv_pages_gva);
+ }
+
+ vcpu_args_set(vcpu, 2, nested_test_data_gva, hv_pages_gva);

vcpu_run(vcpu);

@@ -188,17 +207,29 @@ static void __test_x2apic_intercepts(void)
kvm_vm_free(vm);
}

-#define test_x2apic_intercepts(inhibit_apic_setting) \
+#define _test_x2apic_intercepts(inhibit_apic_setting) \
do { \
+ \
inhibit_apic_setting; \
\
- __test_x2apic_intercepts(); \
+ __test_x2apic_intercepts(use_evmcs); \
} while (0)

+#define test_x2apic_intercepts(use_evmcs_setting) \
+do { \
+ bool use_evmcs_setting; \
+ \
+ _test_x2apic_intercepts(inhibit_apicv = true); \
+ _test_x2apic_intercepts(inhibit_apicv = false); \
+} while (0)
+
+
int main(int argc, char *argv[])
{
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM) || kvm_cpu_has(X86_FEATURE_VMX));

- test_x2apic_intercepts(inhibit_apicv = true);
- test_x2apic_intercepts(inhibit_apicv = false);
+ test_x2apic_intercepts(use_evmcs = false);
+
+ if (kvm_has_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS))
+ test_x2apic_intercepts(use_evmcs = true);
}
--
2.52.0