Skip to content

Commit 1dfe571

Browse files
codomaniabonzini
authored andcommitted
KVM: SEV: Add initial SEV-SNP support
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 and set PFERR_PRIVATE_ACCESS for private #NPFs so they are handled appropriately by KVM MMU. Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Co-developed-by: Michael Roth <michael.roth@amd.com> Signed-off-by: Michael Roth <michael.roth@amd.com> Signed-off-by: Ashish Kalra <ashish.kalra@amd.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-ID: <20240501085210.2213060-5-michael.roth@amd.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent a8e3198 commit 1dfe571

5 files changed

Lines changed: 42 additions & 3 deletions

File tree

arch/x86/include/asm/svm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,8 @@ static_assert((X2AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AVIC_
285285

286286
#define AVIC_HPA_MASK ~((0xFFFULL << 52) | 0xFFF)
287287

288-
#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
288+
#define SVM_SEV_FEAT_SNP_ACTIVE BIT(0)
289+
#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
289290

290291
struct vmcb_seg {
291292
u16 selector;

arch/x86/include/uapi/asm/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,5 +874,6 @@ struct kvm_hyperv_eventfd {
874874
#define KVM_X86_SW_PROTECTED_VM 1
875875
#define KVM_X86_SEV_VM 2
876876
#define KVM_X86_SEV_ES_VM 3
877+
#define KVM_X86_SNP_VM 4
877878

878879
#endif /* _ASM_X86_KVM_H */

arch/x86/kvm/svm/sev.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ module_param_named(sev, sev_enabled, bool, 0444);
4747
static bool sev_es_enabled = true;
4848
module_param_named(sev_es, sev_es_enabled, bool, 0444);
4949

50+
/* enable/disable SEV-SNP support */
51+
static bool sev_snp_enabled;
52+
5053
/* enable/disable SEV-ES DebugSwap support */
5154
static bool sev_es_debug_swap_enabled = true;
5255
module_param_named(debug_swap, sev_es_debug_swap_enabled, bool, 0444);
@@ -288,6 +291,9 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
288291
if (sev->es_active && !sev->ghcb_version)
289292
sev->ghcb_version = GHCB_VERSION_DEFAULT;
290293

294+
if (vm_type == KVM_X86_SNP_VM)
295+
sev->vmsa_features |= SVM_SEV_FEAT_SNP_ACTIVE;
296+
291297
ret = sev_asid_new(sev);
292298
if (ret)
293299
goto e_no_asid;
@@ -348,7 +354,8 @@ static int sev_guest_init2(struct kvm *kvm, struct kvm_sev_cmd *argp)
348354
return -EINVAL;
349355

350356
if (kvm->arch.vm_type != KVM_X86_SEV_VM &&
351-
kvm->arch.vm_type != KVM_X86_SEV_ES_VM)
357+
kvm->arch.vm_type != KVM_X86_SEV_ES_VM &&
358+
kvm->arch.vm_type != KVM_X86_SNP_VM)
352359
return -EINVAL;
353360

354361
if (copy_from_user(&data, u64_to_user_ptr(argp->data), sizeof(data)))
@@ -2328,11 +2335,16 @@ void __init sev_set_cpu_caps(void)
23282335
kvm_cpu_cap_set(X86_FEATURE_SEV_ES);
23292336
kvm_caps.supported_vm_types |= BIT(KVM_X86_SEV_ES_VM);
23302337
}
2338+
if (sev_snp_enabled) {
2339+
kvm_cpu_cap_set(X86_FEATURE_SEV_SNP);
2340+
kvm_caps.supported_vm_types |= BIT(KVM_X86_SNP_VM);
2341+
}
23312342
}
23322343

23332344
void __init sev_hardware_setup(void)
23342345
{
23352346
unsigned int eax, ebx, ecx, edx, sev_asid_count, sev_es_asid_count;
2347+
bool sev_snp_supported = false;
23362348
bool sev_es_supported = false;
23372349
bool sev_supported = false;
23382350

@@ -2413,6 +2425,7 @@ void __init sev_hardware_setup(void)
24132425
sev_es_asid_count = min_sev_asid - 1;
24142426
WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count));
24152427
sev_es_supported = true;
2428+
sev_snp_supported = sev_snp_enabled && cc_platform_has(CC_ATTR_HOST_SEV_SNP);
24162429

24172430
out:
24182431
if (boot_cpu_has(X86_FEATURE_SEV))
@@ -2425,9 +2438,15 @@ void __init sev_hardware_setup(void)
24252438
pr_info("SEV-ES %s (ASIDs %u - %u)\n",
24262439
sev_es_supported ? "enabled" : "disabled",
24272440
min_sev_asid > 1 ? 1 : 0, min_sev_asid - 1);
2441+
if (boot_cpu_has(X86_FEATURE_SEV_SNP))
2442+
pr_info("SEV-SNP %s (ASIDs %u - %u)\n",
2443+
sev_snp_supported ? "enabled" : "disabled",
2444+
min_sev_asid > 1 ? 1 : 0, min_sev_asid - 1);
24282445

24292446
sev_enabled = sev_supported;
24302447
sev_es_enabled = sev_es_supported;
2448+
sev_snp_enabled = sev_snp_supported;
2449+
24312450
if (!sev_es_enabled || !cpu_feature_enabled(X86_FEATURE_DEBUG_SWAP) ||
24322451
!cpu_feature_enabled(X86_FEATURE_NO_NESTED_DATA_BP))
24332452
sev_es_debug_swap_enabled = false;

arch/x86/kvm/svm/svm.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2057,6 +2057,9 @@ static int npf_interception(struct kvm_vcpu *vcpu)
20572057
if (WARN_ON_ONCE(error_code & PFERR_SYNTHETIC_MASK))
20582058
error_code &= ~PFERR_SYNTHETIC_MASK;
20592059

2060+
if (sev_snp_guest(vcpu->kvm) && (error_code & PFERR_GUEST_ENC_MASK))
2061+
error_code |= PFERR_PRIVATE_ACCESS;
2062+
20602063
trace_kvm_page_fault(vcpu, fault_address, error_code);
20612064
return kvm_mmu_page_fault(vcpu, fault_address, error_code,
20622065
static_cpu_has(X86_FEATURE_DECODEASSISTS) ?
@@ -4902,8 +4905,11 @@ static int svm_vm_init(struct kvm *kvm)
49024905

49034906
if (type != KVM_X86_DEFAULT_VM &&
49044907
type != KVM_X86_SW_PROTECTED_VM) {
4905-
kvm->arch.has_protected_state = (type == KVM_X86_SEV_ES_VM);
4908+
kvm->arch.has_protected_state =
4909+
(type == KVM_X86_SEV_ES_VM || type == KVM_X86_SNP_VM);
49064910
to_kvm_sev_info(kvm)->need_init = true;
4911+
4912+
kvm->arch.has_private_mem = (type == KVM_X86_SNP_VM);
49074913
}
49084914

49094915
if (!pause_filter_count || !pause_filter_thresh)

arch/x86/kvm/svm/svm.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,18 @@ static __always_inline bool sev_es_guest(struct kvm *kvm)
349349
#endif
350350
}
351351

352+
static __always_inline bool sev_snp_guest(struct kvm *kvm)
353+
{
354+
#ifdef CONFIG_KVM_AMD_SEV
355+
struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
356+
357+
return (sev->vmsa_features & SVM_SEV_FEAT_SNP_ACTIVE) &&
358+
!WARN_ON_ONCE(!sev_es_guest(kvm));
359+
#else
360+
return false;
361+
#endif
362+
}
363+
352364
static inline void vmcb_mark_all_dirty(struct vmcb *vmcb)
353365
{
354366
vmcb->control.clean = 0;

0 commit comments

Comments
 (0)