[RFC Part2 PATCH 13/30] KVM: SVM: add initial SEV-SNP support
From: Brijesh Singh <hidden>
Date: 2021-03-24 17:06:27
Also in:
linux-crypto, lkml
Subsystem:
kernel virtual machine for x86 (kvm/x86), the rest, x86 architecture (32-bit and 64-bit) · Maintainers:
Sean Christopherson, Paolo Bonzini, Linus Torvalds, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen
The next generation of SEV is called SEV-SNP (Secure Nested Paging). SEV-SNP builds upon existing SEV and SEV-ES functionality while adding new hardware based security protection. SEV-SNP adds strong memory encryption integrity protection to help prevent malicious hypervisor-based attacks such as data replay, memory re-mapping, and more, to create an isolated execution environment. The SNP feature can be enabled in the KVM by passing the sev-snp module parameter. Cc: Thomas Gleixner <redacted> Cc: Ingo Molnar <mingo@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Joerg Roedel <redacted> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Dave Hansen <redacted> Cc: "Peter Zijlstra (Intel)" <peterz@infradead.org> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: David Rientjes <rientjes@google.com> Cc: Sean Christopherson <seanjc@google.com> Cc: x86@kernel.org Cc: kvm@vger.kernel.org Signed-off-by: Brijesh Singh <redacted> --- arch/x86/kvm/svm/sev.c | 17 +++++++++++++++++ arch/x86/kvm/svm/svm.c | 5 +++++ arch/x86/kvm/svm/svm.h | 13 +++++++++++++ 3 files changed, 35 insertions(+)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 48017fef1cd9..b720837faf5a 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c@@ -19,6 +19,7 @@ #include <asm/fpu/internal.h> #include <asm/trapnr.h> +#include <asm/sev-snp.h> #include "x86.h" #include "svm.h"
@@ -1249,6 +1250,7 @@ void sev_vm_destroy(struct kvm *kvm) void __init sev_hardware_setup(void) { unsigned int eax, ebx, ecx, edx; + bool sev_snp_supported = false; bool sev_es_supported = false; bool sev_supported = false;
@@ -1298,9 +1300,24 @@ void __init sev_hardware_setup(void) pr_info("SEV-ES supported: %u ASIDs\n", min_sev_asid - 1); sev_es_supported = true; + /* SEV-SNP support requested? */ + if (!sev_snp) + goto out; + + /* Does the CPU support SEV-SNP? */ + if (!boot_cpu_has(X86_FEATURE_SEV_SNP)) + goto out; + + if (!snp_key_active()) + goto out; + + pr_info("SEV-SNP supported: %u ASIDs\n", min_sev_asid - 1); + sev_snp_supported = true; + out: sev = sev_supported; sev_es = sev_es_supported; + sev_snp = sev_snp_supported; } void sev_hardware_teardown(void)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 3442d44ca53b..aa7ff4685c87 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c@@ -197,6 +197,10 @@ module_param(sev, int, 0444); int sev_es = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT); module_param(sev_es, int, 0444); +/* enable/disable SEV-SNP support */ +int sev_snp = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT); +module_param(sev_snp, int, 0444); + bool __read_mostly dump_invalid_vmcb; module_param(dump_invalid_vmcb, bool, 0644);
@@ -986,6 +990,7 @@ static __init int svm_hardware_setup(void) } else { sev = false; sev_es = false; + sev_snp = false; } svm_adjust_mmio_mask();
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 6e7d070f8b86..3dd60d2a567a 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h@@ -73,6 +73,7 @@ enum { struct kvm_sev_info { bool active; /* SEV enabled guest */ bool es_active; /* SEV-ES enabled guest */ + bool snp_active; /* SEV-SNP enabled guest */ unsigned int asid; /* ASID used for this guest */ unsigned int handle; /* SEV firmware handle */ int fd; /* SEV device fd */
@@ -241,6 +242,17 @@ static inline bool sev_es_guest(struct kvm *kvm) #endif } +static 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_es_guest(kvm) && sev->snp_active; +#else + return false; +#endif +} + static inline void vmcb_mark_all_dirty(struct vmcb *vmcb) { vmcb->control.clean = 0;
@@ -407,6 +419,7 @@ static inline bool gif_set(struct vcpu_svm *svm) extern int sev; extern int sev_es; +extern int sev_snp; extern bool dump_invalid_vmcb; u32 svm_msrpm_offset(u32 msr);
--
2.17.1