Secure AVIC does not have IPI virtualization (except for Self-IPIs which is not relevant for KVM), i.e., guest ICR writes are not accelerated by the hardware but results in a #VC that the guest is expected to handle with the help of the hypervisor. This also means there are no AVIC Physical/Logical ID tables to be setup. Add a helper avic_ipiv_is_supported() to query support for IPIv and use the same to short-circuit various AVIC flows related to AVIC data structures such as the Physical and Logical ID tables for Secure AVIC. Signed-off-by: Naveen N Rao (AMD) --- arch/x86/kvm/svm/svm.h | 1 + arch/x86/kvm/svm/avic.c | 23 ++++++++++++++++++++++- arch/x86/kvm/svm/sev.c | 4 +++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 1157d022bac1..e48744f6d756 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -131,6 +131,7 @@ struct kvm_svm { u32 *avic_logical_id_table; u64 *avic_physical_id_table; struct hlist_node hnode; + bool avic_ipiv_is_not_supported; #ifdef CONFIG_KVM_AMD_SEV struct kvm_sev_info sev_info; diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index c9e375c5a9c1..0a4e91e15e74 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -76,6 +76,12 @@ static bool avic_ipiv_is_soft_disabled(void) return !enable_ipiv; } +/* IPIv is not supported in Secure AVIC mode, no AVIC tables necessary */ +static bool avic_ipiv_is_supported(struct kvm *kvm) +{ + return !to_kvm_svm(kvm)->avic_ipiv_is_not_supported; +} + static int avic_param_set(const char *val, const struct kernel_param *kp) { if (val && sysfs_streq(val, "auto")) { @@ -364,7 +370,7 @@ int avic_vcpu_precreate(struct kvm *kvm) { int r; - if (!irqchip_in_kernel(kvm) || WARN_ON_ONCE(!enable_apicv)) + if (!irqchip_in_kernel(kvm) || WARN_ON_ONCE(!enable_apicv) || !avic_ipiv_is_supported(kvm)) return 0; /* @@ -435,6 +441,9 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu) u32 id = vcpu->vcpu_id; u64 new_entry; + if (!avic_ipiv_is_supported(vcpu->kvm)) + return 0; + /* * Inhibit AVIC if the vCPU ID is bigger than what is supported by AVIC * hardware. Immediately clear apicv_active, i.e. don't wait until the @@ -1069,6 +1078,9 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu, lockdep_assert_preemption_disabled(); + if (!avic_ipiv_is_supported(vcpu->kvm)) + return; + if (WARN_ON(h_physical_id & ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK)) return; @@ -1113,6 +1125,9 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu, void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { + if (!avic_ipiv_is_supported(vcpu->kvm)) + return; + /* * No need to update anything if the vCPU is blocking, i.e. if the vCPU * is being scheduled in after being preempted. The CPU entries in the @@ -1135,6 +1150,9 @@ static void __avic_vcpu_put(struct kvm_vcpu *vcpu, enum avic_vcpu_action action) lockdep_assert_preemption_disabled(); + if (!avic_ipiv_is_supported(vcpu->kvm)) + return; + if (WARN_ON_ONCE(vcpu->vcpu_id * sizeof(entry) >= PAGE_SIZE << avic_get_physical_id_table_order(vcpu->kvm))) return; @@ -1185,6 +1203,9 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu) */ u64 entry = to_svm(vcpu)->avic_physical_id_entry; + if (!avic_ipiv_is_supported(vcpu->kvm)) + return; + /* * Nothing to do if IsRunning == '0' due to vCPU blocking, i.e. if the * vCPU is preempted while its in the process of blocking. WARN if the diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index a47bb417bd98..a12e7e9f9fa1 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -566,8 +566,10 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp, INIT_LIST_HEAD(&sev->mirror_vms); sev->need_init = false; - if (snp_is_secure_avic_enabled(kvm)) + if (snp_is_secure_avic_enabled(kvm)) { kvm->arch.apicv_has_irq_bypass = false; + to_kvm_svm(kvm)->avic_ipiv_is_not_supported = true; + } kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_SEV); -- 2.54.0