FAILED: patch "[PATCH] KVM: nVMX: Morph notification vector IRQ on nested VM-Enter" failed to apply to 4.19-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 25bb2cf97139f81e3bb8910d26016a529019528e Mon Sep 17 00:00:00 2001
From: Sean Christopherson <[email protected]>
Date: Wed, 12 Aug 2020 10:51:29 -0700
Subject: [PATCH] KVM: nVMX: Morph notification vector IRQ on nested VM-Enter
to pending PI
On successful nested VM-Enter, check for pending interrupts and convert the highest priority interrupt to a pending posted interrupt if it matches L2's notification vector. If the vCPU receives a notification interrupt before nested VM-Enter (assuming L1 disables IRQs before doing VM-Enter), the pending interrupt (for L1) should be recognized and processed as a posted interrupt when interrupts become unblocked after VM-Enter to L2.
This fixes a bug where L1/L2 will get stuck in an infinite loop if L1 is trying to inject an interrupt into L2 by setting the appropriate bit in L2's PIR and sending a self-IPI prior to VM-Enter (as opposed to KVM's method of manually moving the vector from PIR->vIRR/RVI). KVM will observe the IPI while the vCPU is in L1 context and so won't immediately morph it to a posted interrupt for L2. The pending interrupt will be seen by vmx_check_nested_events(), cause KVM to force an immediate exit after nested VM-Enter, and eventually be reflected to L1 as a VM-Exit. After handling the VM-Exit, L1 will see that L2 has a pending interrupt in PIR, send another IPI, and repeat until L2 is killed.
Note, posted interrupts require virtual interrupt deliveriy, and virtual interrupt delivery requires exit-on-interrupt, ergo interrupts will be unconditionally unmasked on VM-Enter if posted interrupts are enabled.
Message-Id: <[email protected]>
arch/x86/kvm/lapic.c +7 -0
@@ -494,6 +494,12 @@ static inline void apic_clear_irr(int vec, struct kvm_lapic *apic) } } +void kvm_apic_clear_irr (struct kvm_vcpu *vcpu,int vec) +{ +apic_clear_irr (vec, vcpu->arch.apic); +} +EXPORT_SYMBOL_GPL (kvm_apic_clear_irr); +static inline void apic_set_isr (int vec,struct kvm_lapic *apic) {struct kvm_vcpu *vcpu;
@@ -2465,6 +2471,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)__apic_update_ppr (apic, &ppr);return apic_has_interrupt_for_ppr (apic, ppr); } +EXPORT_SYMBOL_GPL (kvm_apic_has_interrupt);int kvm_apic_accept_pic_intr (struct kvm_vcpu *vcpu) {
arch/x86/kvm/lapic.h +1 -0
@@ -89,6 +89,7 @@ int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,bool kvm_apic_match_dest (struct kvm_vcpu *vcpu,struct kvm_lapic *source,int shorthand,unsigned int dest,int dest_mode);int kvm_apic_compare_prio (struct kvm_vcpu *vcpu1,struct kvm_vcpu *vcpu2); +void kvm_apic_clear_irr (struct kvm_vcpu *vcpu,int vec);bool __kvm_apic_update_irr (u32 *pir,void *regs,int *max_irr);bool kvm_apic_update_irr (struct kvm_vcpu *vcpu,u32 *pir,int *max_irr);void kvm_apic_update_ppr (struct kvm_vcpu *vcpu);
arch/x86/kvm/vmx/nested.c +8 -0
@@ -3531,6 +3531,14 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)if (unlikely (status !=NVMX_VMENTRY_SUCCESS )) goto vmentry_failed; +/* Emulate processing of posted interrupts on VM-Enter. */ +if (nested_cpu_has_posted_intr (vmcs12) && +kvm_apic_has_interrupt (vcpu) == vmx->nested.posted_intr_nv) { + vmx->nested.pi_pending = true; +kvm_make_request (KVM_REQ_EVENT , vcpu); +kvm_apic_clear_irr (vcpu, vmx->nested.posted_intr_nv); + } +/* Hide L1D cache contents from the nested guest. */ vmx->vcpu.arch.l1tf_flush_l1d = true;