Commit b6bc164f authored by Kim Phillips's avatar Kim Phillips Committed by Sean Christopherson
Browse files

KVM: SEV: Configure "ALLOWED_SEV_FEATURES" VMCB Field

AMD EPYC 5th generation processors have introduced a feature that allows
the hypervisor to control the SEV_FEATURES that are set for, or by, a
guest [1].  ALLOWED_SEV_FEATURES can be used by the hypervisor to enforce
that SEV-ES and SEV-SNP guests cannot enable features that the
hypervisor does not want to be enabled.

Always enable ALLOWED_SEV_FEATURES.  A VMRUN will fail if any
non-reserved bits are 1 in SEV_FEATURES but are 0 in
ALLOWED_SEV_FEATURES.

Some SEV_FEATURES - currently PmcVirtualization and SecureAvic
(see Appendix B, Table B-4) - require an opt-in via ALLOWED_SEV_FEATURES,
i.e. are off-by-default, whereas all other features are effectively
on-by-default, but still honor ALLOWED_SEV_FEATURES.

[1] Section 15.36.20 "Allowed SEV Features", AMD64 Architecture
    Programmer's Manual, Pub. 24593 Rev. 3.42 - March 2024:
    https://bugzilla.kernel.org/attachment.cgi?id=306250



Co-developed-by: default avatarKishon Vijay Abraham I <kvijayab@amd.com>
Signed-off-by: default avatarKishon Vijay Abraham I <kvijayab@amd.com>
Reviewed-by: default avatarPankaj Gupta <pankaj.gupta@amd.com>
Signed-off-by: default avatarKim Phillips <kim.phillips@amd.com>
Reviewed-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Link: https://lore.kernel.org/r/20250310201603.1217954-3-kim.phillips@amd.com


Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
parent f9f27c4a
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -159,7 +159,10 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
	u64 avic_physical_id;	/* Offset 0xf8 */
	u8 reserved_7[8];
	u64 vmsa_pa;		/* Used for an SEV-ES guest */
	u8 reserved_8[720];
	u8 reserved_8[40];
	u64 allowed_sev_features;	/* Offset 0x138 */
	u64 guest_sev_features;		/* Offset 0x140 */
	u8 reserved_9[664];
	/*
	 * Offset 0x3e0, 32 bytes reserved
	 * for use by hypervisor/software.
@@ -291,6 +294,8 @@ static_assert((X2AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AVIC_
#define SVM_SEV_FEAT_ALTERNATE_INJECTION		BIT(4)
#define SVM_SEV_FEAT_DEBUG_SWAP				BIT(5)

#define VMCB_ALLOWED_SEV_FEATURES_VALID			BIT_ULL(63)

struct vmcb_seg {
	u16 selector;
	u16 attrib;
+5 −0
Original line number Diff line number Diff line
@@ -4451,6 +4451,7 @@ void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm)

static void sev_es_init_vmcb(struct vcpu_svm *svm)
{
	struct kvm_sev_info *sev = to_kvm_sev_info(svm->vcpu.kvm);
	struct vmcb *vmcb = svm->vmcb01.ptr;
	struct kvm_vcpu *vcpu = &svm->vcpu;

@@ -4466,6 +4467,10 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)
	if (svm->sev_es.vmsa && !svm->sev_es.snp_has_guest_vmsa)
		svm->vmcb->control.vmsa_pa = __pa(svm->sev_es.vmsa);

	if (cpu_feature_enabled(X86_FEATURE_ALLOWED_SEV_FEATURES))
		svm->vmcb->control.allowed_sev_features = sev->vmsa_features |
							  VMCB_ALLOWED_SEV_FEATURES_VALID;

	/* Can't intercept CR register access, HV can't modify CR registers */
	svm_clr_intercept(svm, INTERCEPT_CR0_READ);
	svm_clr_intercept(svm, INTERCEPT_CR4_READ);
+2 −0
Original line number Diff line number Diff line
@@ -3452,6 +3452,8 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
	pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id);
	pr_err("%-20s%016llx\n", "avic_physical_id:", control->avic_physical_id);
	pr_err("%-20s%016llx\n", "vmsa_pa:", control->vmsa_pa);
	pr_err("%-20s%016llx\n", "allowed_sev_features:", control->allowed_sev_features);
	pr_err("%-20s%016llx\n", "guest_sev_features:", control->guest_sev_features);

	if (sev_es_guest(vcpu->kvm)) {
		save = sev_decrypt_vmsa(vcpu);