Add Secure AVIC to sev_supported_vmsa_features allowing VMM to enable Secure AVIC for SEV-SNP guests. Gate the same on all dependencies for Secure AVIC being satisfied: - X86_FEATURE_SNP_SECURE_AVIC itself signaling platform support - X86_FEATURE_IDLE_HLT, more on this below - 'enable_apicv' for dependency on AVIC being enabled - 'vnmi' so that NMIs can be injected. And the implied dependency of vnmi on vgif so that VGIF is enabled for a Secure AVIC guest to unmask interrupts. Secure AVIC has a hard dependency on idle hlt intercept since KVM has no visibility into pending interrupts within the guest. If the guest took a '#VMEXIT' just before 'sti; hlt' with interrupts disabled, and KVM injected into the guest IRR (Requested_IRR --> guest vIRR), those won't be deliverable before 'hlt' due to the interrupt shadow. On hlt intercept, KVM won't be able to observe interrupts pending in the guest APIC_IRR, KVM's APIC shadow backing page has nothing pending and so will block the vCPU. Idle hlt intercept addresses this by preventing the intercept from firing so that the vCPU proceeds to take those interrupts. Because 'enable_apicv' and 'vnmi' are new dependencies, move the call to sev_hardware_setup() after they have been setup in svm_hardware_setup(). Co-developed-by: Neeraj Upadhyay Signed-off-by: Neeraj Upadhyay Signed-off-by: Naveen N Rao (AMD) --- arch/x86/kvm/svm/sev.c | 13 ++++++++++--- arch/x86/kvm/svm/svm.c | 17 +++++++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 7c9c25135df8..b67cf1399cbf 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -512,7 +512,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_SECURE_TSC | SVM_SEV_FEAT_SECURE_AVIC); if (data->vmsa_features & ~valid_vmsa_features) return -EINVAL; @@ -3234,8 +3234,15 @@ void __init sev_hardware_setup(void) cpu_feature_enabled(X86_FEATURE_NO_NESTED_DATA_BP)) sev_supported_vmsa_features |= SVM_SEV_FEAT_DEBUG_SWAP; - if (sev_snp_enabled && tsc_khz && cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC)) - sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC; + if (sev_snp_enabled) { + if (tsc_khz && cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC)) + sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC; + + if (cpu_feature_enabled(X86_FEATURE_SNP_SECURE_AVIC) && + cpu_feature_enabled(X86_FEATURE_IDLE_HLT) && + enable_apicv && vnmi) + sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_AVIC; + } } void sev_hardware_unsetup(void) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 2e32670ff957..a20f0abe138b 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5731,14 +5731,6 @@ static __init int svm_hardware_setup(void) iopm_base = __sme_set(__pa(iopm_va)); - /* - * Note, SEV setup consumes npt_enabled and enable_mmio_caching (which - * may be modified by svm_adjust_mmio_mask()), as well as nrips. - */ - sev_hardware_setup(); - - svm_hv_hardware_setup(); - enable_apicv = avic_hardware_setup(); if (!enable_apicv) { enable_ipiv = false; @@ -5781,6 +5773,15 @@ static __init int svm_hardware_setup(void) if (!enable_pmu) pr_info("PMU virtualization is disabled\n"); + /* + * Note, SEV setup consumes npt_enabled and enable_mmio_caching (which + * may be modified by svm_adjust_mmio_mask()), as well as nrips, vnmi + * and enable_apicv. + */ + sev_hardware_setup(); + + svm_hv_hardware_setup(); + svm_set_cpu_caps(); kvm_caps.inapplicable_quirks &= ~KVM_X86_QUIRK_CD_NW_CLEARED; -- 2.54.0