KVM: nVMX: Re-evaluate L1 pending events when running L2 and L1 got posted-interrupt

"Linux Kernel Mailing List" <[email protected]>
Newsgroups gmane.linux.kernel.commits.head
Message-ID <[email protected]>
Web:        https://git.kernel.org/torvalds/c/f27a85c4988d408a2918a3bcbc3d7fe4fb2dc2b3
Commit:     f27a85c4988d408a2918a3bcbc3d7fe4fb2dc2b3
Parent:     e7387b0e27ec3a203bda4910dc4a107f6c5f912f
Refname:    refs/heads/master
Author:     Liran Alon <[email protected]>
AuthorDate: Sun Dec 24 18:12:55 2017 +0200
Committer:  Radim Krčmář <[email protected]>
CommitDate: Tue Jan 16 16:40:09 2018 +0100

    KVM: nVMX: Re-evaluate L1 pending events when running L2 and L1 got posted-interrupt
    
    In case posted-interrupt was delivered to CPU while it is in host
    (outside guest), then posted-interrupt delivery will be done by
    calling sync_pir_to_irr() at vmentry after interrupts are disabled.
    
    sync_pir_to_irr() will check vmx->pi_desc.control ON bit and if
    set, it will sync vmx->pi_desc.pir to IRR and afterwards update RVI to
    ensure virtual-interrupt-delivery will dispatch interrupt to guest.
    
    However, it is possible that L1 will receive a posted-interrupt while
    CPU runs at host and is about to enter L2. In this case, the call to
    sync_pir_to_irr() will indeed update the L1's APIC IRR but
    vcpu_enter_guest() will then just resume into L2 guest without
    re-evaluating if it should exit from L2 to L1 as a result of this
    new pending L1 event.
    
    To address this case, if sync_pir_to_irr() has a new L1 injectable
    interrupt and CPU is running L2, we force exit GUEST_MODE which will
    result in another iteration of vcpu_run() run loop which will call
    kvm_vcpu_running() which will call check_nested_events() which will
    handle the pending L1 event properly.
    
    Signed-off-by: Liran Alon <[email protected]>
    Reviewed-by: Nikita Leshenko <[email protected]>
    Reviewed-by: Krish Sadhukhan <[email protected]>
    Reviewed-by: Liam Merwick <[email protected]>
    Signed-off-by: Liam Merwick <[email protected]>
    Signed-off-by: Konrad Rzeszutek Wilk <[email protected]>
    Signed-off-by: Paolo Bonzini <[email protected]>
    Signed-off-by: Radim Krčmář <[email protected]>
---
 arch/x86/kvm/vmx.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 5ea482bb1b9c..5fe94e375d2d 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -8978,6 +8978,7 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	int max_irr;
+	bool max_irr_updated;
 
 	WARN_ON(!vcpu->arch.apicv_active);
 	if (pi_test_on(&vmx->pi_desc)) {
@@ -8987,7 +8988,16 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
 		 * But on x86 this is just a compiler barrier anyway.
 		 */
 		smp_mb__after_atomic();
-		kvm_apic_update_irr(vcpu, vmx->pi_desc.pir, &max_irr);
+		max_irr_updated =
+			kvm_apic_update_irr(vcpu, vmx->pi_desc.pir, &max_irr);
+
+		/*
+		 * If we are running L2 and L1 has a new pending interrupt
+		 * which can be injected, we should re-evaluate
+		 * what should be done with this new L1 interrupt.
+		 */
+		if (is_guest_mode(vcpu) && max_irr_updated)
+			kvm_vcpu_exiting_guest_mode(vcpu);
 	} else {
 		max_irr = kvm_lapic_find_highest_irr(vcpu);
 	}
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.