The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v1 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests
@ 2026-07-09 16:47 Hemanth Selam
  2026-07-09 16:47 ` [PATCH v1 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Hemanth Selam @ 2026-07-09 16:47 UTC (permalink / raw)
  To: seanjc, pbonzini, shuah; +Cc: kvm, linux-kselftest, linux-kernel, Hemanth Selam

This small series fills in two pre-existing TODOs in the x86 SEV
selftests. Both are test-only changes; there is no functional change to
the kernel.

Patch 1 adds negative coverage to sev_init2_tests: when the platform
does not support a given SEV VM type (SEV-ES or SEV-SNP), it verifies
that KVM_CREATE_VM rejects that type with -EINVAL. Previously the test
only exercised the VM types that were supported, so a mismatch between
KVM_CAP_VM_TYPES and the actual KVM_CREATE_VM enforcement would have
gone unnoticed.

Patch 2 makes sev_smoke_test capture the launch measurement returned by
KVM_SEV_LAUNCH_MEASURE for SEV and SEV-ES guests and asserts that it is
not all zeros, instead of discarding it. A full attestation-style
validation is not possible from the selftest (userspace does not hold
the transport keys used to derive the measurement), but a non-zero
check catches a PSP/plumbing failure that silently leaves the buffer
untouched. SEV-SNP uses a different launch flow and is skipped.

Testing: built and run on an AMD EPYC 9755 (Turin) host running this
tree, across two boot configurations:
 - SEV + SEV-ES enabled, SEV-SNP disabled
 - SEV + SEV-SNP enabled (SEV-ES unusable)
Together these exercised both new rejection branches (SEV-ES and
SEV-SNP) and the launch-measurement check for SEV/SEV-ES, plus SEV-SNP
guest creation and launch. Both tests pass in every configuration, and
checkpatch is clean on both patches.

Hemanth Selam (2):
  KVM: selftests: SEV: Verify unsupported VM types are rejected at
    creation
  KVM: selftests: SEV: Sanity check the launch measurement

 .../selftests/kvm/x86/sev_init2_tests.c       | 23 +++++++++++++--
 .../selftests/kvm/x86/sev_smoke_test.c        | 29 +++++++++++++++++--
 2 files changed, 47 insertions(+), 5 deletions(-)

base-commit: 0e35b9b6ec0ffcc5e23cbdec09f5c622ad532b53
-- 
2.43.7


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v1 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation
  2026-07-09 16:47 [PATCH v1 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
@ 2026-07-09 16:47 ` Hemanth Selam
  2026-07-09 16:47 ` [PATCH v1 2/2] KVM: selftests: SEV: Sanity check the launch measurement Hemanth Selam
  2026-07-09 17:49 ` [PATCH v2 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
  2 siblings, 0 replies; 9+ messages in thread
From: Hemanth Selam @ 2026-07-09 16:47 UTC (permalink / raw)
  To: seanjc, pbonzini, shuah; +Cc: kvm, linux-kselftest, linux-kernel, Hemanth Selam

test_vm_types() only exercised creation of the SEV/SEV-ES/SEV-SNP VM
types that the platform actually supports, leaving the previously noted
TODO ("check that unsupported types cannot be created") unaddressed.

Add test_create_invalid_type() which issues a raw KVM_CREATE_VM for a
given type and asserts it fails with -EINVAL, and invoke it for
KVM_X86_SEV_ES_VM / KVM_X86_SNP_VM whenever the corresponding capability
is not advertised. Because vm_create_barebones_type() asserts that
KVM_CREATE_VM succeeds, the check is issued directly against the KVM fd
so the negative path can be observed.

While here, stop shadowing the file-scope kvm_fd with a local in main()
so the new helper can use it.

Signed-off-by: Hemanth Selam <hemanth.selam@gmail.com>
---
 .../selftests/kvm/x86/sev_init2_tests.c       | 23 ++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86/sev_init2_tests.c b/tools/testing/selftests/kvm/x86/sev_init2_tests.c
index 8db88c355f16..724ff11f16c9 100644
--- a/tools/testing/selftests/kvm/x86/sev_init2_tests.c
+++ b/tools/testing/selftests/kvm/x86/sev_init2_tests.c
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <pthread.h>
+#include <unistd.h>
 
 #include "test_util.h"
 #include "kvm_util.h"
@@ -73,19 +74,34 @@ static void test_init2_invalid(unsigned long vm_type, struct kvm_sev_init *init,
 	kvm_vm_free(vm);
 }
 
+static void test_create_invalid_type(unsigned long vm_type, const char *msg)
+{
+	int fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, (void *)vm_type);
+
+	TEST_ASSERT(fd < 0 && errno == EINVAL,
+		    "KVM_CREATE_VM should reject unsupported type (%s), got fd=%d errno=%d",
+		    msg, fd, errno);
+	if (fd >= 0)
+		close(fd);
+}
+
 void test_vm_types(void)
 {
 	test_init2(KVM_X86_SEV_VM, &(struct kvm_sev_init){});
 
 	/*
-	 * TODO: check that unsupported types cannot be created.  Probably
-	 * a separate selftest.
+	 * Types that aren't supported by the platform must be rejected by
+	 * KVM_CREATE_VM itself, before any KVM_SEV_INIT2 can be attempted.
 	 */
 	if (have_sev_es)
 		test_init2(KVM_X86_SEV_ES_VM, &(struct kvm_sev_init){});
+	else
+		test_create_invalid_type(KVM_X86_SEV_ES_VM, "SEV-ES is unsupported");
 
 	if (have_snp)
 		test_init2(KVM_X86_SNP_VM, &(struct kvm_sev_init){});
+	else
+		test_create_invalid_type(KVM_X86_SNP_VM, "SEV-SNP is unsupported");
 
 	test_init2_invalid(0, &(struct kvm_sev_init){},
 			   "VM type is KVM_X86_DEFAULT_VM");
@@ -121,9 +137,10 @@ void test_features(u32 vm_type, u64 supported_features)
 
 int main(int argc, char *argv[])
 {
-	int kvm_fd = open_kvm_dev_path_or_exit();
 	bool have_sev;
 
+	kvm_fd = open_kvm_dev_path_or_exit();
+
 	TEST_REQUIRE(__kvm_has_device_attr(kvm_fd, KVM_X86_GRP_SEV,
 					   KVM_X86_SEV_VMSA_FEATURES) == 0);
 	kvm_device_attr_get(kvm_fd, KVM_X86_GRP_SEV,
-- 
2.43.7


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 2/2] KVM: selftests: SEV: Sanity check the launch measurement
  2026-07-09 16:47 [PATCH v1 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
  2026-07-09 16:47 ` [PATCH v1 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
@ 2026-07-09 16:47 ` Hemanth Selam
  2026-07-09 17:49 ` [PATCH v2 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
  2 siblings, 0 replies; 9+ messages in thread
From: Hemanth Selam @ 2026-07-09 16:47 UTC (permalink / raw)
  To: seanjc, pbonzini, shuah; +Cc: kvm, linux-kselftest, linux-kernel, Hemanth Selam

test_sev() launched the guest while discarding the launch measurement
and left a TODO to validate it. A full attestation-style validation is
not possible from the selftest because userspace does not possess the
transport keys the PSP uses to derive the measurement, so recomputing
the expected value cannot be done here.

Capture the measurement returned by KVM_SEV_LAUNCH_MEASURE for SEV and
SEV-ES guests and assert that it is not all zeros, which catches a PSP
or plumbing failure that silently leaves the buffer untouched. SNP does
not return a measurement through this path, so it is skipped.

Signed-off-by: Hemanth Selam <hemanth.selam@gmail.com>
---
 .../selftests/kvm/x86/sev_smoke_test.c        | 29 +++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86/sev_smoke_test.c b/tools/testing/selftests/kvm/x86/sev_smoke_test.c
index 6b2cbe2a90b7..795b03a6b7f3 100644
--- a/tools/testing/selftests/kvm/x86/sev_smoke_test.c
+++ b/tools/testing/selftests/kvm/x86/sev_smoke_test.c
@@ -150,16 +150,41 @@ static void test_sync_vmsa(u32 type, u64 policy)
 	kvm_vm_free(vm);
 }
 
+static bool is_measurement_nonzero(const u8 *measurement, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++)
+		if (measurement[i])
+			return true;
+
+	return false;
+}
+
 static void test_sev(void *guest_code, u32 type, u64 policy)
 {
+	u8 measurement[256];
 	struct kvm_vcpu *vcpu;
 	struct kvm_vm *vm;
 	struct ucall uc;
 
 	vm = vm_sev_create_with_one_vcpu(type, guest_code, &vcpu);
 
-	/* TODO: Validate the measurement is as expected. */
-	vm_sev_launch(vm, policy, NULL);
+	/*
+	 * Capture the launch measurement and sanity check it.  A full
+	 * attestation-style validation (recomputing the expected value) isn't
+	 * possible here as userspace does not possess the transport keys the
+	 * PSP uses to derive the measurement; at minimum it must be non-zero.
+	 * SNP does not return a measurement through this path, so skip it.
+	 */
+	if (is_sev_snp_vm(vm)) {
+		vm_sev_launch(vm, policy, NULL);
+	} else {
+		memset(measurement, 0, sizeof(measurement));
+		vm_sev_launch(vm, policy, measurement);
+		TEST_ASSERT(is_measurement_nonzero(measurement, sizeof(measurement)),
+			    "SEV launch measurement is unexpectedly all zeros");
+	}
 
 	for (;;) {
 		vcpu_run(vcpu);
-- 
2.43.7


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests
  2026-07-09 16:47 [PATCH v1 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
  2026-07-09 16:47 ` [PATCH v1 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
  2026-07-09 16:47 ` [PATCH v1 2/2] KVM: selftests: SEV: Sanity check the launch measurement Hemanth Selam
@ 2026-07-09 17:49 ` Hemanth Selam
  2026-07-09 17:49   ` [PATCH v2 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
                     ` (2 more replies)
  2 siblings, 3 replies; 9+ messages in thread
From: Hemanth Selam @ 2026-07-09 17:49 UTC (permalink / raw)
  To: seanjc, pbonzini, shuah; +Cc: kvm, linux-kselftest, linux-kernel, Hemanth Selam

This small series fills in two pre-existing TODOs in the x86 SEV
selftests. Both are test-only changes; there is no functional change to
the kernel.

Patch 1 adds negative coverage to sev_init2_tests: when the platform
does not support a given SEV VM type (SEV-ES or SEV-SNP), it verifies
that KVM_CREATE_VM rejects that type with -EINVAL. Previously the test
only exercised the VM types that were supported, so a mismatch between
KVM_CAP_VM_TYPES and the actual KVM_CREATE_VM enforcement would have
gone unnoticed.

Patch 2 makes sev_smoke_test capture the launch measurement returned by
KVM_SEV_LAUNCH_MEASURE for SEV and SEV-ES guests and asserts that it is
not all zeros, instead of discarding it. A full attestation-style
validation is not possible from the selftest (userspace does not hold
the transport keys used to derive the measurement), but a non-zero
check catches a PSP/plumbing failure that silently leaves the buffer
untouched. SEV-SNP uses a different launch flow and is skipped.

Testing: built and run on an AMD EPYC 9755 (Turin) host running this
tree (7.2.0-rc2), with sev/sev_es/sev_snp all enabled. Both tests pass.
The new rejection path was additionally exercised by reloading kvm_amd
with sev_snp=0 so the unsupported types are rejected: under strace,
KVM_CREATE_VM for the SEV-ES and SNP types both return -EINVAL and the
test passes. checkpatch --strict is clean on both patches.

Changes in v2:
 - Patch 1: fix unreachable fd cleanup in test_create_invalid_type().
   TEST_ASSERT() aborts on failure, so the trailing "if (fd >= 0)
   close(fd)" could never run; close the fd (and latch errno) before
   the assert instead, so an unexpectedly-created VM is not leaked.
   Reported-by: Sashiko AI review.
 - Trimmed the added in-code comments to short high-level notes and
   moved the detailed rationale into the commit messages.
 - No functional change to patch 2.

v1: https://lore.kernel.org/all/20260709164751.621326-1-hemanth.selam@gmail.com/

Hemanth Selam (2):
  KVM: selftests: SEV: Verify unsupported VM types are rejected at
    creation
  KVM: selftests: SEV: Sanity check the launch measurement

 .../selftests/kvm/x86/sev_init2_tests.c       | 27 +++++++++++++++++--
 .../selftests/kvm/x86/sev_smoke_test.c        | 23 +++++++++++++++--
 2 files changed, 46 insertions(+), 4 deletions(-)

-- 
2.43.7


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation
  2026-07-09 17:49 ` [PATCH v2 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
@ 2026-07-09 17:49   ` Hemanth Selam
  2026-07-09 20:21     ` Sean Christopherson
  2026-07-10  5:06     ` Hemanth Selam
  2026-07-09 17:49   ` [PATCH v2 2/2] KVM: selftests: SEV: Sanity check the launch measurement Hemanth Selam
  2026-07-10  5:04   ` [PATCH v3] KVM: selftests: Add a test for KVM_CREATE_VM VM type enforcement Hemanth Selam
  2 siblings, 2 replies; 9+ messages in thread
From: Hemanth Selam @ 2026-07-09 17:49 UTC (permalink / raw)
  To: seanjc, pbonzini, shuah; +Cc: kvm, linux-kselftest, linux-kernel, Hemanth Selam

test_vm_types() only exercised creation of the SEV/SEV-ES/SEV-SNP VM
types that the platform actually supports, leaving the previously noted
TODO ("check that unsupported types cannot be created") unaddressed.

Add test_create_invalid_type() which issues a raw KVM_CREATE_VM for a
given type and asserts it fails with -EINVAL, and invoke it for
KVM_X86_SEV_ES_VM / KVM_X86_SNP_VM whenever the corresponding capability
is not advertised. Because vm_create_barebones_type() asserts that
KVM_CREATE_VM succeeds, the check is issued directly against the KVM fd
so the negative path can be observed.

TEST_ASSERT() aborts the program when its condition fails, so the helper
releases the fd and latches errno before asserting: if KVM_CREATE_VM
ever wrongly succeeds, the VM fd is closed rather than leaked, and errno
is captured before close() can clobber it.

While here, stop shadowing the file-scope kvm_fd with a local in main()
so the new helper can use it.

Signed-off-by: Hemanth Selam <hemanth.selam@gmail.com>
---
 .../selftests/kvm/x86/sev_init2_tests.c       | 27 +++++++++++++++----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86/sev_init2_tests.c b/tools/testing/selftests/kvm/x86/sev_init2_tests.c
index 8db88c355f16..7663418b3fa8 100644
--- a/tools/testing/selftests/kvm/x86/sev_init2_tests.c
+++ b/tools/testing/selftests/kvm/x86/sev_init2_tests.c
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <pthread.h>
+#include <unistd.h>
 
 #include "test_util.h"
 #include "kvm_util.h"
@@ -73,19 +74,34 @@ static void test_init2_invalid(unsigned long vm_type, struct kvm_sev_init *init,
 	kvm_vm_free(vm);
 }
 
+static void test_create_invalid_type(unsigned long vm_type, const char *msg)
+{
+	int fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, (void *)vm_type);
+	int err = errno;
+
+	/* Clean up before asserting; TEST_ASSERT() aborts on failure. */
+	if (fd >= 0)
+		close(fd);
+
+	TEST_ASSERT(fd < 0 && err == EINVAL,
+		    "KVM_CREATE_VM should reject unsupported type (%s), got fd=%d errno=%d",
+		    msg, fd, err);
+}
+
 void test_vm_types(void)
 {
 	test_init2(KVM_X86_SEV_VM, &(struct kvm_sev_init){});
 
-	/*
-	 * TODO: check that unsupported types cannot be created.  Probably
-	 * a separate selftest.
-	 */
+	/* Unsupported types must be rejected by KVM_CREATE_VM itself. */
 	if (have_sev_es)
 		test_init2(KVM_X86_SEV_ES_VM, &(struct kvm_sev_init){});
+	else
+		test_create_invalid_type(KVM_X86_SEV_ES_VM, "SEV-ES is unsupported");
 
 	if (have_snp)
 		test_init2(KVM_X86_SNP_VM, &(struct kvm_sev_init){});
+	else
+		test_create_invalid_type(KVM_X86_SNP_VM, "SEV-SNP is unsupported");
 
 	test_init2_invalid(0, &(struct kvm_sev_init){},
 			   "VM type is KVM_X86_DEFAULT_VM");
@@ -121,9 +137,10 @@ void test_features(u32 vm_type, u64 supported_features)
 
 int main(int argc, char *argv[])
 {
-	int kvm_fd = open_kvm_dev_path_or_exit();
 	bool have_sev;
 
+	kvm_fd = open_kvm_dev_path_or_exit();
+
 	TEST_REQUIRE(__kvm_has_device_attr(kvm_fd, KVM_X86_GRP_SEV,
 					   KVM_X86_SEV_VMSA_FEATURES) == 0);
 	kvm_device_attr_get(kvm_fd, KVM_X86_GRP_SEV,
-- 
2.43.7


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/2] KVM: selftests: SEV: Sanity check the launch measurement
  2026-07-09 17:49 ` [PATCH v2 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
  2026-07-09 17:49   ` [PATCH v2 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
@ 2026-07-09 17:49   ` Hemanth Selam
  2026-07-10  5:04   ` [PATCH v3] KVM: selftests: Add a test for KVM_CREATE_VM VM type enforcement Hemanth Selam
  2 siblings, 0 replies; 9+ messages in thread
From: Hemanth Selam @ 2026-07-09 17:49 UTC (permalink / raw)
  To: seanjc, pbonzini, shuah; +Cc: kvm, linux-kselftest, linux-kernel, Hemanth Selam

test_sev() launched the guest while discarding the launch measurement
and left a TODO to validate it. A full attestation-style validation is
not possible from the selftest because userspace does not possess the
transport keys the PSP uses to derive the measurement, so recomputing
the expected value cannot be done here.

Capture the measurement returned by KVM_SEV_LAUNCH_MEASURE for SEV and
SEV-ES guests and assert that it is not all zeros, which catches a PSP
or plumbing failure that silently leaves the buffer untouched. SNP does
not return a measurement through this path, so it is skipped.

Signed-off-by: Hemanth Selam <hemanth.selam@gmail.com>
---
 .../selftests/kvm/x86/sev_smoke_test.c        | 23 +++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86/sev_smoke_test.c b/tools/testing/selftests/kvm/x86/sev_smoke_test.c
index 6b2cbe2a90b7..9ce465b4a770 100644
--- a/tools/testing/selftests/kvm/x86/sev_smoke_test.c
+++ b/tools/testing/selftests/kvm/x86/sev_smoke_test.c
@@ -150,16 +150,35 @@ static void test_sync_vmsa(u32 type, u64 policy)
 	kvm_vm_free(vm);
 }
 
+static bool is_measurement_nonzero(const u8 *measurement, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++)
+		if (measurement[i])
+			return true;
+
+	return false;
+}
+
 static void test_sev(void *guest_code, u32 type, u64 policy)
 {
+	u8 measurement[256];
 	struct kvm_vcpu *vcpu;
 	struct kvm_vm *vm;
 	struct ucall uc;
 
 	vm = vm_sev_create_with_one_vcpu(type, guest_code, &vcpu);
 
-	/* TODO: Validate the measurement is as expected. */
-	vm_sev_launch(vm, policy, NULL);
+	/* Sanity check the measurement; SNP has no measurement here. */
+	if (is_sev_snp_vm(vm)) {
+		vm_sev_launch(vm, policy, NULL);
+	} else {
+		memset(measurement, 0, sizeof(measurement));
+		vm_sev_launch(vm, policy, measurement);
+		TEST_ASSERT(is_measurement_nonzero(measurement, sizeof(measurement)),
+			    "SEV launch measurement is unexpectedly all zeros");
+	}
 
 	for (;;) {
 		vcpu_run(vcpu);
-- 
2.43.7


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation
  2026-07-09 17:49   ` [PATCH v2 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
@ 2026-07-09 20:21     ` Sean Christopherson
  2026-07-10  5:06     ` Hemanth Selam
  1 sibling, 0 replies; 9+ messages in thread
From: Sean Christopherson @ 2026-07-09 20:21 UTC (permalink / raw)
  To: Hemanth Selam; +Cc: pbonzini, shuah, kvm, linux-kselftest, linux-kernel

On Thu, Jul 09, 2026, Hemanth Selam wrote:
> @@ -73,19 +74,34 @@ static void test_init2_invalid(unsigned long vm_type, struct kvm_sev_init *init,
>  	kvm_vm_free(vm);
>  }
>  
> +static void test_create_invalid_type(unsigned long vm_type, const char *msg)
> +{
> +	int fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, (void *)vm_type);
> +	int err = errno;
> +
> +	/* Clean up before asserting; TEST_ASSERT() aborts on failure. */

Literally every test relies on the kernel to clean up fds on an early exit.  I
see no reason for this to behave differently.

Also, Sashiko was wrong.  If KVM_CREATE_VM fails with something other than EINVAL,
the assert will NOT fire, but fd will be < 0.

> +	if (fd >= 0)
> +		close(fd);
> +
> +	TEST_ASSERT(fd < 0 && err == EINVAL,
> +		    "KVM_CREATE_VM should reject unsupported type (%s), got fd=%d errno=%d",
> +		    msg, fd, err);

test_assert logs the errno, no need to spit it out here as well.

> +}
> +
>  void test_vm_types(void)
>  {
>  	test_init2(KVM_X86_SEV_VM, &(struct kvm_sev_init){});
>  
> -	/*
> -	 * TODO: check that unsupported types cannot be created.  Probably
> -	 * a separate selftest.

Heh, I agree with the comment: put this in a separate selftest.  This doesn't
have anything to do with KVM_SEV_INIT2, and in fact doesn't even have anyting to
do with SEV+ or even x86.  E.g. add a kvm_vm_types_test that attempts to create
all possible VM types, and asserts success/failure based on the output from
kvm_check_cap(KVM_CAP_VM_TYPES).

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3] KVM: selftests: Add a test for KVM_CREATE_VM VM type enforcement
  2026-07-09 17:49 ` [PATCH v2 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
  2026-07-09 17:49   ` [PATCH v2 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
  2026-07-09 17:49   ` [PATCH v2 2/2] KVM: selftests: SEV: Sanity check the launch measurement Hemanth Selam
@ 2026-07-10  5:04   ` Hemanth Selam
  2 siblings, 0 replies; 9+ messages in thread
From: Hemanth Selam @ 2026-07-10  5:04 UTC (permalink / raw)
  To: seanjc, pbonzini, shuah; +Cc: kvm, linux-kselftest, linux-kernel, Hemanth Selam

KVM_CAP_VM_TYPES advertises the bitmap of VM types that KVM_CREATE_VM
accepts, but nothing verified that the ioctl actually enforces it: that
every advertised type can be created and every non-advertised type is
rejected. sev_init2_tests carried a TODO for this ("check that
unsupported types cannot be created. Probably a separate selftest"),
but the check is not specific to SEV or KVM_SEV_INIT2, and not even to
x86.

Add a standalone test that walks the type space and, for each value,
asserts that KVM_CREATE_VM succeeds iff the corresponding bit is set in
KVM_CAP_VM_TYPES, and otherwise fails with -EINVAL. The walk extends
past bit 31 so that out-of-range type values, which can never be
advertised in the u32 bitmap, are also confirmed to be rejected. The
test only depends on KVM_CAP_VM_TYPES, so it lives in the common set and
is skipped on architectures that don't advertise the capability.

Drop the now-addressed TODO from sev_init2_tests.c.

Tested on an AMD SEV-SNP capable host. With KVM_CAP_VM_TYPES=0x15
(DEFAULT/SEV/SNP), only the advertised types are created and everything
else is rejected:

  $ strace -e trace=ioctl ./vm_types_test 2>&1 | grep KVM_CREATE_VM
  ioctl(3, KVM_CREATE_VM, 0)    = 4              # DEFAULT
  ioctl(3, KVM_CREATE_VM, 0x1)  = -1 EINVAL      # SW_PROTECTED
  ioctl(3, KVM_CREATE_VM, 0x2)  = 4              # SEV
  ioctl(3, KVM_CREATE_VM, 0x3)  = -1 EINVAL      # SEV-ES
  ioctl(3, KVM_CREATE_VM, 0x4)  = 4              # SNP
  ioctl(3, KVM_CREATE_VM, 0x5)  = -1 EINVAL      # TDX
  ... 0x6..0x3f all -1 EINVAL ...

Reloading kvm_amd with sev_snp=0 drops the bitmap to 0x5 and only types
0 and 2 are then created, confirming the test tracks the advertised set
rather than hard-coded types.

Signed-off-by: Hemanth Selam <hemanth.selam@gmail.com>
---
Changes in v3:
 - Reworked into a separate, generic test that checks all VM types
   against KVM_CAP_VM_TYPES (per review), instead of adding negative
   checks to sev_init2_tests; also cover out-of-range types. Dropped the
   manual fd cleanup and the redundant errno in the assert message, and
   removed the addressed TODO from sev_init2_tests.c.
 - Dropped the separate "SEV: Sanity check the launch measurement" patch
   that accompanied v1/v2; this revision is a single patch.

v2: https://lore.kernel.org/all/20260709174955.628913-1-hemanth.selam@gmail.com/
v1: https://lore.kernel.org/all/20260709164751.621326-1-hemanth.selam@gmail.com/

 tools/testing/selftests/kvm/Makefile.kvm      |  1 +
 tools/testing/selftests/kvm/vm_types_test.c   | 50 +++++++++++++++++++
 .../selftests/kvm/x86/sev_init2_tests.c       |  4 --
 3 files changed, 51 insertions(+), 4 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/vm_types_test.c

diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index d28a057fa6c2..ad74d0b98694 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -66,6 +66,7 @@ TEST_GEN_PROGS_COMMON += kvm_page_table_test
 TEST_GEN_PROGS_COMMON += set_memory_region_test
 TEST_GEN_PROGS_COMMON += memslot_modification_stress_test
 TEST_GEN_PROGS_COMMON += memslot_perf_test
+TEST_GEN_PROGS_COMMON += vm_types_test
 
 # Compiled test targets
 TEST_GEN_PROGS_x86 = $(TEST_GEN_PROGS_COMMON)
diff --git a/tools/testing/selftests/kvm/vm_types_test.c b/tools/testing/selftests/kvm/vm_types_test.c
new file mode 100644
index 000000000000..e8ef3b018f6c
--- /dev/null
+++ b/tools/testing/selftests/kvm/vm_types_test.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Verify that KVM_CREATE_VM accepts exactly the VM types enumerated by
+ * KVM_CAP_VM_TYPES, and rejects every other type with -EINVAL.
+ */
+#include <errno.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <linux/kvm.h>
+
+#include "kvm_util.h"
+#include "test_util.h"
+
+int main(void)
+{
+	unsigned int supported_types;
+	unsigned long type;
+	int kvm_fd, fd;
+
+	TEST_REQUIRE(kvm_has_cap(KVM_CAP_VM_TYPES));
+
+	kvm_fd = open_kvm_dev_path_or_exit();
+	supported_types = kvm_check_cap(KVM_CAP_VM_TYPES);
+	pr_info("KVM_CAP_VM_TYPES: 0x%x\n", supported_types);
+
+	/*
+	 * KVM_CAP_VM_TYPES is a u32 bitmap, so only types 0..31 can ever be
+	 * advertised.  Walk past that range as well to confirm that any
+	 * out-of-range type is rejected rather than silently accepted.
+	 */
+	for (type = 0; type < 64; type++) {
+		bool supported = type < 32 && (supported_types & (1U << type));
+
+		fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, (void *)type);
+
+		if (supported) {
+			TEST_ASSERT(fd >= 0,
+				    "KVM_CREATE_VM(%lu) should succeed, KVM_CAP_VM_TYPES=0x%x",
+				    type, supported_types);
+			close(fd);
+		} else {
+			TEST_ASSERT(fd < 0 && errno == EINVAL,
+				    "KVM_CREATE_VM(%lu) should fail with EINVAL, KVM_CAP_VM_TYPES=0x%x",
+				    type, supported_types);
+		}
+	}
+
+	return 0;
+}
diff --git a/tools/testing/selftests/kvm/x86/sev_init2_tests.c b/tools/testing/selftests/kvm/x86/sev_init2_tests.c
index 8db88c355f16..d4227dc922ab 100644
--- a/tools/testing/selftests/kvm/x86/sev_init2_tests.c
+++ b/tools/testing/selftests/kvm/x86/sev_init2_tests.c
@@ -77,10 +77,6 @@ void test_vm_types(void)
 {
 	test_init2(KVM_X86_SEV_VM, &(struct kvm_sev_init){});
 
-	/*
-	 * TODO: check that unsupported types cannot be created.  Probably
-	 * a separate selftest.
-	 */
 	if (have_sev_es)
 		test_init2(KVM_X86_SEV_ES_VM, &(struct kvm_sev_init){});
 
-- 
2.43.7


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation
  2026-07-09 17:49   ` [PATCH v2 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
  2026-07-09 20:21     ` Sean Christopherson
@ 2026-07-10  5:06     ` Hemanth Selam
  1 sibling, 0 replies; 9+ messages in thread
From: Hemanth Selam @ 2026-07-10  5:06 UTC (permalink / raw)
  To: seanjc; +Cc: pbonzini, shuah, kvm, linux-kselftest, linux-kernel,
	Hemanth Selam

On Thu, Jul 09, 2026, Sean Christopherson wrote:
> Literally every test relies on the kernel to clean up fds on an early
> exit.  I see no reason for this to behave differently.
>
> Also, Sashiko was wrong.  If KVM_CREATE_VM fails with something other
> than EINVAL, the assert will NOT fire, but fd will be < 0.

Agreed on both; dropped the manual close() and the errno latching.

> test_assert logs the errno, no need to spit it out here as well.

Removed.

> Heh, I agree with the comment: put this in a separate selftest.  This
> doesn't have anything to do with KVM_SEV_INIT2, and in fact doesn't
> even have anyting to do with SEV+ or even x86.  E.g. add a
> kvm_vm_types_test that attempts to create all possible VM types, and
> asserts success/failure based on the output from
> kvm_check_cap(KVM_CAP_VM_TYPES).

Done.  v3 drops the sev_init2_tests changes and adds a standalone,
arch-generic test that walks all type values (including out-of-range
ones) and asserts KVM_CREATE_VM success/failure against
KVM_CAP_VM_TYPES:

  https://lore.kernel.org/all/20260710050442.826777-1-hemanth.selam@gmail.com/

I also dropped the "SEV: Sanity check the launch measurement" patch for
now; v3 is just the VM-types test.

Thanks for the review!

Hemanth

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-07-10  5:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-09 16:47 [PATCH v1 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
2026-07-09 16:47 ` [PATCH v1 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
2026-07-09 16:47 ` [PATCH v1 2/2] KVM: selftests: SEV: Sanity check the launch measurement Hemanth Selam
2026-07-09 17:49 ` [PATCH v2 0/2] KVM: selftests: SEV: address two TODOs in the SEV tests Hemanth Selam
2026-07-09 17:49   ` [PATCH v2 1/2] KVM: selftests: SEV: Verify unsupported VM types are rejected at creation Hemanth Selam
2026-07-09 20:21     ` Sean Christopherson
2026-07-10  5:06     ` Hemanth Selam
2026-07-09 17:49   ` [PATCH v2 2/2] KVM: selftests: SEV: Sanity check the launch measurement Hemanth Selam
2026-07-10  5:04   ` [PATCH v3] KVM: selftests: Add a test for KVM_CREATE_VM VM type enforcement Hemanth Selam

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox