Secure AVIC does not support accelerating device interrupts, so have kvm_arch_has_irq_bypass() return false for a Secure AVIC enabled SEV-SNP guest. Since we now have to consult kvm_arch, move the function to x86.c and export it for use by KVM submodules. Due to this, avic_pi_update_irte() should never be called for a Secure AVIC guest. Add a WARN_ON() so that it is clear something is broken. Signed-off-by: Naveen N Rao (AMD) --- arch/x86/include/asm/kvm_host.h | 8 ++------ arch/x86/kvm/svm/avic.c | 7 +++++++ arch/x86/kvm/svm/sev.c | 3 +++ arch/x86/kvm/x86.c | 7 +++++++ 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index d81179b43199..cabb368b7908 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1380,6 +1380,8 @@ struct kvm_arch { bool apic_access_memslot_enabled; bool apic_access_memslot_inhibited; + bool apicv_has_irq_bypass; + /* * Force apicv_update_lock and apicv_nr_irq_window_req to reside in a * dedicated cacheline. They are write-mostly, whereas most everything @@ -2063,10 +2065,4 @@ static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) { kvm_x86_call(vcpu_unblocking)(vcpu); } - -static inline bool kvm_arch_has_irq_bypass(struct kvm *kvm) -{ - return enable_device_posted_irqs; -} - #endif /* _ASM_X86_KVM_HOST_H */ diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 7340c9e251e0..9b4d3a10198b 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -919,6 +919,13 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm, unsigned int host_irq, uint32_t guest_irq, struct kvm_vcpu *vcpu, u32 vector) { + /* + * Complain loudly as we should never reach here for Secure AVIC. + * See kvm_arch_has_irq_bypass() + */ + if (WARN_ON_ONCE(snp_is_secure_avic_enabled(kvm))) + return -EINVAL; + /* * If the IRQ was affined to a different vCPU, remove the IRTE metadata * from the *previous* vCPU's list. diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 686227a15328..a47bb417bd98 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -566,6 +566,9 @@ 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)) + kvm->arch.apicv_has_irq_bypass = false; + kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_SEV); return 0; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8dbc0fa302a8..ed94aa8ebc0d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7233,6 +7233,7 @@ static void kvm_apicv_init(struct kvm *kvm) APICV_INHIBIT_REASON_DISABLED; set_or_clear_apicv_inhibit(&kvm->arch.apicv_inhibit_reasons, reason, true); + kvm->arch.apicv_has_irq_bypass = true; init_rwsem(&kvm->arch.apicv_update_lock); } @@ -10572,6 +10573,12 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu) return (vcpu->arch.msr_kvm_poll_control & 1) == 0; } +bool kvm_arch_has_irq_bypass(struct kvm *kvm) +{ + return enable_device_posted_irqs && kvm->arch.apicv_has_irq_bypass; +} +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_arch_has_irq_bypass); + #ifdef CONFIG_KVM_GUEST_MEMFD /* * KVM doesn't yet support initializing guest_memfd memory as shared for VMs -- 2.54.0