Re: [PATCH v12 09/29] KVM: SEV: Add initial SEV-SNP support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 3/29/24 23:58, Michael Roth wrote:
SEV-SNP builds upon existing SEV and SEV-ES functionality while adding
new hardware-based security protection. SEV-SNP adds strong memory
encryption and integrity protection to help prevent malicious
hypervisor-based attacks such as data replay, memory re-mapping, and
more, to create an isolated execution environment.

Define a new KVM_X86_SNP_VM type which makes use of these capabilities
and extend the KVM_SEV_INIT2 ioctl to support it. Also add a basic
helper to check whether SNP is enabled.

Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx>
Signed-off-by: Ashish Kalra <ashish.kalra@xxxxxxx>
[mdr: commit fixups, use similar ASID reporting as with SEV/SEV-ES]
Signed-off-by: Michael Roth <michael.roth@xxxxxxx>
---
  arch/x86/include/asm/svm.h      |  3 ++-
  arch/x86/include/uapi/asm/kvm.h |  1 +
  arch/x86/kvm/svm/sev.c          | 21 ++++++++++++++++++++-
  arch/x86/kvm/svm/svm.c          |  3 ++-
  arch/x86/kvm/svm/svm.h          | 12 ++++++++++++
  arch/x86/kvm/x86.c              |  2 +-
  6 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 728c98175b9c..544a43c1cf11 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -285,7 +285,8 @@ static_assert((X2AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AVIC_
#define AVIC_HPA_MASK ~((0xFFFULL << 52) | 0xFFF) -#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
+#define SVM_SEV_FEAT_SNP_ACTIVE				BIT(0)
+#define SVM_SEV_FEAT_DEBUG_SWAP				BIT(5)
struct vmcb_seg {
  	u16 selector;
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index 51b13080ed4b..725b75cfe9ff 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -868,5 +868,6 @@ struct kvm_hyperv_eventfd {
  #define KVM_X86_SW_PROTECTED_VM	1
  #define KVM_X86_SEV_VM		2
  #define KVM_X86_SEV_ES_VM	3
+#define KVM_X86_SNP_VM		4
#endif /* _ASM_X86_KVM_H */
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 1e65f5634ad3..3d9771163562 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -46,6 +46,9 @@ module_param_named(sev, sev_enabled, bool, 0444);
  static bool sev_es_enabled = true;
  module_param_named(sev_es, sev_es_enabled, bool, 0444);
+/* enable/disable SEV-SNP support */
+static bool sev_snp_enabled;
+
  /* enable/disable SEV-ES DebugSwap support */
  static bool sev_es_debug_swap_enabled = true;
  module_param_named(debug_swap, sev_es_debug_swap_enabled, bool, 0444);
@@ -275,6 +278,9 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
  	sev->es_active = es_active;
  	sev->vmsa_features = data->vmsa_features;
+ if (vm_type == KVM_X86_SNP_VM)
+		sev->vmsa_features |= SVM_SEV_FEAT_SNP_ACTIVE;
+
  	ret = sev_asid_new(sev);
  	if (ret)
  		goto e_no_asid;
@@ -326,7 +332,8 @@ static int sev_guest_init2(struct kvm *kvm, struct kvm_sev_cmd *argp)
  		return -EINVAL;
if (kvm->arch.vm_type != KVM_X86_SEV_VM &&
-	    kvm->arch.vm_type != KVM_X86_SEV_ES_VM)
+	    kvm->arch.vm_type != KVM_X86_SEV_ES_VM &&
+	    kvm->arch.vm_type != KVM_X86_SNP_VM)
  		return -EINVAL;
if (copy_from_user(&data, u64_to_user_ptr(argp->data), sizeof(data)))
@@ -2297,11 +2304,16 @@ void __init sev_set_cpu_caps(void)
  		kvm_cpu_cap_set(X86_FEATURE_SEV_ES);
  		kvm_caps.supported_vm_types |= BIT(KVM_X86_SEV_ES_VM);
  	}
+	if (sev_snp_enabled) {
+		kvm_cpu_cap_set(X86_FEATURE_SEV_SNP);
+		kvm_caps.supported_vm_types |= BIT(KVM_X86_SNP_VM);
+	}
  }
void __init sev_hardware_setup(void)
  {
  	unsigned int eax, ebx, ecx, edx, sev_asid_count, sev_es_asid_count;
+	bool sev_snp_supported = false;
  	bool sev_es_supported = false;
  	bool sev_supported = false;
@@ -2382,6 +2394,7 @@ void __init sev_hardware_setup(void)
  	sev_es_asid_count = min_sev_asid - 1;
  	WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count));
  	sev_es_supported = true;
+	sev_snp_supported = sev_snp_enabled && cc_platform_has(CC_ATTR_HOST_SEV_SNP);
out:
  	if (boot_cpu_has(X86_FEATURE_SEV))
@@ -2394,9 +2407,15 @@ void __init sev_hardware_setup(void)
  		pr_info("SEV-ES %s (ASIDs %u - %u)\n",
  			sev_es_supported ? "enabled" : "disabled",
  			min_sev_asid > 1 ? 1 : 0, min_sev_asid - 1);
+	if (boot_cpu_has(X86_FEATURE_SEV_SNP))
+		pr_info("SEV-SNP %s (ASIDs %u - %u)\n",
+			sev_snp_supported ? "enabled" : "disabled",
+			min_sev_asid > 1 ? 1 : 0, min_sev_asid - 1);
sev_enabled = sev_supported;
  	sev_es_enabled = sev_es_supported;
+	sev_snp_enabled = sev_snp_supported;
+
  	if (!sev_es_enabled || !cpu_feature_enabled(X86_FEATURE_DEBUG_SWAP) ||
  	    !cpu_feature_enabled(X86_FEATURE_NO_NESTED_DATA_BP))
  		sev_es_debug_swap_enabled = false;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 0f3b59da0d4a..2c162f6a1d78 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -4890,7 +4890,8 @@ static int svm_vm_init(struct kvm *kvm)
if (type != KVM_X86_DEFAULT_VM &&
  	    type != KVM_X86_SW_PROTECTED_VM) {
-		kvm->arch.has_protected_state = (type == KVM_X86_SEV_ES_VM);
+		kvm->arch.has_protected_state =
+			(type == KVM_X86_SEV_ES_VM || type == KVM_X86_SNP_VM);
  		to_kvm_sev_info(kvm)->need_init = true;
  	}
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 157eb3f65269..4a01a81dd9b9 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -348,6 +348,18 @@ static __always_inline bool sev_es_guest(struct kvm *kvm)
  #endif
  }
+static __always_inline bool sev_snp_guest(struct kvm *kvm)
+{
+#ifdef CONFIG_KVM_AMD_SEV
+	struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
+
+	return (sev->vmsa_features & SVM_SEV_FEAT_SNP_ACTIVE) &&
+	       !WARN_ON_ONCE(!sev_es_guest(kvm));
+#else
+	return false;
+#endif
+}
+
  static inline void vmcb_mark_all_dirty(struct vmcb *vmcb)
  {
  	vmcb->control.clean = 0;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 64eda7949f09..f85735b6235d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -12603,7 +12603,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
kvm->arch.vm_type = type;
  	kvm->arch.has_private_mem =
-		(type == KVM_X86_SW_PROTECTED_VM);
+		(type == KVM_X86_SW_PROTECTED_VM || type == KVM_X86_SNP_VM);
ret = kvm_page_track_init(kvm);
  	if (ret)

Reviewed-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>

Paolo





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux