[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250923050942.206116-22-Neeraj.Upadhyay@amd.com>
Date: Tue, 23 Sep 2025 10:39:28 +0530
From: Neeraj Upadhyay <Neeraj.Upadhyay@....com>
To: <kvm@...r.kernel.org>, <seanjc@...gle.com>, <pbonzini@...hat.com>
CC: <linux-kernel@...r.kernel.org>, <Thomas.Lendacky@....com>,
<nikunj@....com>, <Santosh.Shukla@....com>, <Vasant.Hegde@....com>,
<Suravee.Suthikulpanit@....com>, <bp@...en8.de>, <David.Kaplan@....com>,
<huibo.wang@....com>, <naveen.rao@....com>, <pgonda@...gle.com>,
<linux-kselftest@...r.kernel.org>, <shuah@...nel.org>, <tiala@...rosoft.com>
Subject: [RFC PATCH v2 21/35] KVM: selftests: Add SEV guest support in xapic_state_test
The xapic_state_test validates the behavior of the local APIC across
different states and modes (xAPIC vs. x2APIC). Previously, this test
only ran on standard, unencrypted VMs.
With the recent addition of a #VC handler to emulate MMIO accesses for
SEV-ES guests, the necessary infrastructure is in place to test APIC
functionality within encrypted environments.
Extend xapic_state_test to support SEV, SEV-ES, and SNP guests. This
provides crucial regression testing for APIC functionality in these
confidential computing environments.
The test functions are refactored to handle the new VM setup flow,
enabling existing APIC tests to run transparently on encrypted guests.
Signed-off-by: Neeraj Upadhyay <Neeraj.Upadhyay@....com>
---
.../selftests/kvm/x86/xapic_state_test.c | 117 ++++++++++++++++--
1 file changed, 109 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86/xapic_state_test.c b/tools/testing/selftests/kvm/x86/xapic_state_test.c
index fdebff1165c7..91f593ef22dc 100644
--- a/tools/testing/selftests/kvm/x86/xapic_state_test.c
+++ b/tools/testing/selftests/kvm/x86/xapic_state_test.c
@@ -9,6 +9,7 @@
#include "kvm_util.h"
#include "processor.h"
#include "test_util.h"
+#include "sev.h"
struct xapic_vcpu {
struct kvm_vcpu *vcpu;
@@ -160,6 +161,27 @@ static void __test_apic_id(struct kvm_vcpu *vcpu, uint64_t apic_base)
expected, apic_id);
}
+static inline bool is_sev_vm_type(int type)
+{
+ return type == KVM_X86_SEV_VM ||
+ type == KVM_X86_SEV_ES_VM ||
+ type == KVM_X86_SNP_VM;
+}
+
+static inline uint64_t get_sev_policy(int vm_type)
+{
+ switch (vm_type) {
+ case KVM_X86_SEV_VM:
+ return SEV_POLICY_NO_DBG;
+ case KVM_X86_SEV_ES_VM:
+ return SEV_POLICY_ES;
+ case KVM_X86_SNP_VM:
+ return snp_default_policy();
+ default:
+ return 0;
+ }
+}
+
/*
* Verify that KVM switches the APIC_ID between xAPIC and x2APIC when userspace
* stuffs MSR_IA32_APICBASE. Setting the APIC_ID when x2APIC is enabled and
@@ -168,16 +190,22 @@ static void __test_apic_id(struct kvm_vcpu *vcpu, uint64_t apic_base)
* attempted to transition from x2APIC to xAPIC without disabling the APIC is
* architecturally disallowed.
*/
-static void test_apic_id(void)
+static void test_apic_id(int vm_type)
{
const uint32_t NR_VCPUS = 3;
struct kvm_vcpu *vcpus[NR_VCPUS];
uint64_t apic_base;
struct kvm_vm *vm;
int i;
+ struct vm_shape shape = {
+ .mode = VM_MODE_DEFAULT,
+ .type = vm_type,
+ };
- vm = vm_create_with_vcpus(NR_VCPUS, NULL, vcpus);
+ vm = __vm_create_with_vcpus(shape, NR_VCPUS, 0, NULL, vcpus);
vm_enable_cap(vm, KVM_CAP_X2APIC_API, KVM_X2APIC_API_USE_32BIT_IDS);
+ if (is_sev_vm(vm))
+ vm_sev_launch(vm, get_sev_policy(vm_type), NULL);
for (i = 0; i < NR_VCPUS; i++) {
apic_base = vcpu_get_msr(vcpus[i], MSR_IA32_APICBASE);
@@ -195,15 +223,21 @@ static void test_apic_id(void)
kvm_vm_free(vm);
}
-static void test_x2apic_id(void)
+static void test_x2apic_id(int vm_type)
{
struct kvm_lapic_state lapic = {};
struct kvm_vcpu *vcpu;
struct kvm_vm *vm;
int i;
+ bool is_sev = is_sev_vm_type(vm_type);
- vm = vm_create_with_one_vcpu(&vcpu, NULL);
+ if (is_sev)
+ vm = vm_sev_create_with_one_vcpu(vm_type, NULL, &vcpu);
+ else
+ vm = vm_create_with_one_vcpu(&vcpu, NULL);
vcpu_set_msr(vcpu, MSR_IA32_APICBASE, MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
+ if (is_sev)
+ vm_sev_launch(vm, get_sev_policy(vm_type), NULL);
/*
* Try stuffing a modified x2APIC ID, KVM should ignore the value and
@@ -222,6 +256,46 @@ static void test_x2apic_id(void)
kvm_vm_free(vm);
}
+void get_cmdline_args(int argc, char *argv[], int *vm_type)
+{
+ for (;;) {
+ int opt = getopt(argc, argv, "t:");
+
+ if (opt == -1)
+ break;
+ switch (opt) {
+ case 't':
+ *vm_type = parse_size(optarg);
+ switch (*vm_type) {
+ case KVM_X86_DEFAULT_VM:
+ break;
+ case KVM_X86_SEV_VM:
+ TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV));
+ break;
+ case KVM_X86_SEV_ES_VM:
+ TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV_ES));
+ break;
+ case KVM_X86_SNP_VM:
+ TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV_SNP));
+ break;
+ default:
+ TEST_ASSERT(false, "Unsupported VM type :%d",
+ *vm_type);
+ }
+ break;
+ default:
+ TEST_ASSERT(false,
+ "Usage: -t <vm type>. Default is %d.\n"
+ "Supported values:\n"
+ "0 - default\n"
+ "2 - SEV\n"
+ "3 - SEV-ES\n"
+ "4 - SNP",
+ KVM_X86_DEFAULT_VM);
+ }
+ }
+}
+
int main(int argc, char *argv[])
{
struct xapic_vcpu x = {
@@ -229,8 +303,24 @@ int main(int argc, char *argv[])
.is_x2apic = true,
};
struct kvm_vm *vm;
+ int vm_type = KVM_X86_DEFAULT_VM;
+ bool is_sev;
+
+ get_cmdline_args(argc, argv, &vm_type);
+ is_sev = is_sev_vm_type(vm_type);
+
+ if (is_sev)
+ vm = vm_sev_create_with_one_vcpu(vm_type, x2apic_guest_code,
+ &x.vcpu);
+ else
+ vm = vm_create_with_one_vcpu(&x.vcpu, x2apic_guest_code);
+
+ if (is_sev_es_vm(vm))
+ vm_install_exception_handler(vm, 29, sev_es_vc_handler);
+
+ if (is_sev)
+ vm_sev_launch(vm, get_sev_policy(vm_type), NULL);
- vm = vm_create_with_one_vcpu(&x.vcpu, x2apic_guest_code);
test_icr(&x);
kvm_vm_free(vm);
@@ -239,7 +329,15 @@ int main(int argc, char *argv[])
* the guest in order to test AVIC. KVM disallows changing CPUID after
* KVM_RUN and AVIC is disabled if _any_ vCPU is allowed to use x2APIC.
*/
- vm = vm_create_with_one_vcpu(&x.vcpu, xapic_guest_code);
+ if (is_sev)
+ vm = vm_sev_create_with_one_vcpu(vm_type, xapic_guest_code,
+ &x.vcpu);
+ else
+ vm = vm_create_with_one_vcpu(&x.vcpu, xapic_guest_code);
+
+ if (is_sev_es_vm(vm))
+ vm_install_exception_handler(vm, 29, sev_es_vc_handler);
+
x.is_x2apic = false;
/*
@@ -254,9 +352,12 @@ int main(int argc, char *argv[])
vcpu_clear_cpuid_feature(x.vcpu, X86_FEATURE_X2APIC);
virt_pg_map(vm, APIC_DEFAULT_GPA, APIC_DEFAULT_GPA);
+ if (is_sev)
+ vm_sev_launch(vm, get_sev_policy(vm_type), NULL);
+
test_icr(&x);
kvm_vm_free(vm);
- test_apic_id();
- test_x2apic_id();
+ test_apic_id(vm_type);
+ test_x2apic_id(vm_type);
}
--
2.34.1
Powered by blists - more mailing lists