[PATCH v4 07/10] KVM: SEV: Disallow setting SNP-only features for non-SNP guests via a single mask

Kim Phillips <[email protected]> Tue, 4 Aug 2026 18:56:08 -0500
Newsgroups org.kernel.vger.kvm,dev.linux.lists.linux-coco,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
As SNP-only features get added, adding them to the valid_vmsa_features mask
in __sev_guest_init() often gets neglected.  Add SVM_SEV_FEAT_SNP_ONLY_MASK
to help group these common features together.

Also establish SNP_ONLY_FEATURES in the sev_init2 selftest as the
corresponding mask for features that must be rejected for non-SNP guests,
populate it with SVM_SEV_FEAT_SECURE_TSC, and exercise the rejection path
by masking those bits out of the features passed for SEV-ES guests.  Define
the selftest's SNP_ONLY_FEATURES as ULL so future bits can use BIT_ULL()
there without truncation against the u64 supported_vmsa_features.

Suggested-by: Sean Christopherson <[email protected]>
Cc: Borislav Petkov (AMD) <[email protected]>
Link: https://lore.kernel.org/kvm/[email protected]/
Signed-off-by: Kim Phillips <[email protected]>
Assisted-by: ClaudeCode:claude-opus-4-7
---
 arch/x86/include/asm/svm.h                        |  2 ++
 arch/x86/kvm/svm/sev.c                            |  2 +-
 tools/testing/selftests/kvm/x86/sev_init2_tests.c | 12 +++++++-----
 3 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 52c900bf7e20..a206a0ed2c58 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -311,6 +311,8 @@ static_assert((X2AVIC_4K_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AV
 #define SVM_SEV_FEAT_DEBUG_SWAP				BIT_ULL(5)
 #define SVM_SEV_FEAT_SECURE_TSC				BIT_ULL(9)
 
+#define SVM_SEV_FEAT_SNP_ONLY_MASK			(SVM_SEV_FEAT_SECURE_TSC)
+
 #define VMCB_ALLOWED_SEV_FEATURES_VALID			BIT_ULL(63)
 
 struct vmcb_seg {
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 944aaea6501f..951f0e6be9e5 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -504,7 +504,7 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
 		return -EINVAL;
 
 	if (!snp_active)
-		valid_vmsa_features &= ~SVM_SEV_FEAT_SECURE_TSC;
+		valid_vmsa_features &= ~SVM_SEV_FEAT_SNP_ONLY_MASK;
 
 	if (data->vmsa_features & ~valid_vmsa_features)
 		return -EINVAL;
diff --git a/tools/testing/selftests/kvm/x86/sev_init2_tests.c b/tools/testing/selftests/kvm/x86/sev_init2_tests.c
index 7b0643bf7ca1..5f4032239f7f 100644
--- a/tools/testing/selftests/kvm/x86/sev_init2_tests.c
+++ b/tools/testing/selftests/kvm/x86/sev_init2_tests.c
@@ -14,16 +14,18 @@
 #include "kselftest.h"
 
 #define SVM_SEV_FEAT_DEBUG_SWAP		BIT_ULL(5)
+#define SVM_SEV_FEAT_SECURE_TSC		BIT_ULL(9)
+
+/* Features valid only for SNP guests, rejected for SEV-ES and below. */
+#define SNP_ONLY_FEATURES		(SVM_SEV_FEAT_SECURE_TSC)
 
 /*
  * Some features may have hidden dependencies, or may only work
  * for certain VM types.  Err on the side of safety and don't
  * expect that all supported features can be passed one by one
  * to KVM_SEV_INIT2.
- *
- * (Well, right now there's only one...)
  */
-#define KNOWN_FEATURES SVM_SEV_FEAT_DEBUG_SWAP
+#define KNOWN_FEATURES		(SVM_SEV_FEAT_DEBUG_SWAP | SNP_ONLY_FEATURES)
 
 int kvm_fd;
 u64 supported_vmsa_features;
@@ -112,7 +114,7 @@ void test_features(u32 vm_type, u64 supported_features)
 		if (!(supported_features & BIT_ULL(i)))
 			test_init2_invalid(vm_type,
 				&(struct kvm_sev_init){ .vmsa_features = BIT_ULL(i) },
-				"unknown feature");
+				"unknown or unsupported feature for VM type");
 		else if (KNOWN_FEATURES & BIT_ULL(i))
 			test_init2(vm_type,
 				&(struct kvm_sev_init){ .vmsa_features = BIT_ULL(i) });
@@ -161,7 +163,7 @@ int main(int argc, char *argv[])
 
 	test_features(KVM_X86_SEV_VM, 0);
 	if (have_sev_es)
-		test_features(KVM_X86_SEV_ES_VM, supported_vmsa_features);
+		test_features(KVM_X86_SEV_ES_VM, supported_vmsa_features & ~SNP_ONLY_FEATURES);
 	if (have_snp)
 		test_features(KVM_X86_SNP_VM, supported_vmsa_features);
 
-- 
2.43.0