linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] KVM: nVMX: Fix IRQs inject to L2 which belong to L1 since race
@ 2014-07-02  6:54 Wanpeng Li
  2014-07-02  7:20 ` Hu, Robert
                   ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Wanpeng Li @ 2014-07-02  6:54 UTC (permalink / raw)
  To: Paolo Bonzini, Jan Kiszka, Gleb Natapov
  Cc: Hu Robert, kvm, linux-kernel, Wanpeng Li

This patch fix bug https://bugzilla.kernel.org/show_bug.cgi?id=72381 

If we didn't inject a still-pending event to L1 since nested_run_pending,
KVM_REQ_EVENT should be requested after the vmexit in order to inject the 
event to L1. However, current log blindly request a KVM_REQ_EVENT even if 
there is no still-pending event to L1 which blocked by nested_run_pending. 
There is a race which lead to an interrupt will be injected to L2 which 
belong to L1 if L0 send an interrupt to L1 during this window. 

               VCPU0                               another thread 

L1 intr not blocked on L2 first entry
vmx_vcpu_run req event 
kvm check request req event 
check_nested_events don't have any intr 
not nested exit 
                                            intr occur (8254, lapic timer etc)
inject_pending_event now have intr 
inject interrupt 

This patch fix this race by introduced a l1_events_blocked field in nested_vmx 
which indicates there is still-pending event which blocked by nested_run_pending, 
and smart request a KVM_REQ_EVENT if there is a still-pending event which blocked 
by nested_run_pending.

Signed-off-by: Wanpeng Li <wanpeng.li@linux.intel.com>
---
 arch/x86/kvm/vmx.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index f4e5aed..fe69c49 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -372,6 +372,7 @@ struct nested_vmx {
 	u64 vmcs01_tsc_offset;
 	/* L2 must run next, and mustn't decide to exit to L1. */
 	bool nested_run_pending;
+	bool l1_events_blocked;
 	/*
 	 * Guest pages referred to in vmcs02 with host-physical pointers, so
 	 * we must keep them pinned while L2 runs.
@@ -7380,8 +7381,10 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 	 * we did not inject a still-pending event to L1 now because of
 	 * nested_run_pending, we need to re-enable this bit.
 	 */
-	if (vmx->nested.nested_run_pending)
+	if (to_vmx(vcpu)->nested.l1_events_blocked) {
+		to_vmx(vcpu)->nested.l1_events_blocked = false;
 		kvm_make_request(KVM_REQ_EVENT, vcpu);
+	}
 
 	vmx->nested.nested_run_pending = 0;
 
@@ -8197,15 +8200,20 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
 
 	if (nested_cpu_has_preemption_timer(get_vmcs12(vcpu)) &&
 	    vmx->nested.preemption_timer_expired) {
-		if (vmx->nested.nested_run_pending)
+		if (vmx->nested.nested_run_pending) {
+			vmx->nested.l1_events_blocked = true;
 			return -EBUSY;
+		}
 		nested_vmx_vmexit(vcpu, EXIT_REASON_PREEMPTION_TIMER, 0, 0);
 		return 0;
 	}
 
 	if (vcpu->arch.nmi_pending && nested_exit_on_nmi(vcpu)) {
-		if (vmx->nested.nested_run_pending ||
-		    vcpu->arch.interrupt.pending)
+		if (vmx->nested.nested_run_pending) {
+			vmx->nested.l1_events_blocked = true;
+			return -EBUSY;
+		}
+		if (vcpu->arch.interrupt.pending)
 			return -EBUSY;
 		nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
 				  NMI_VECTOR | INTR_TYPE_NMI_INTR |
@@ -8221,8 +8229,10 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
 
 	if ((kvm_cpu_has_interrupt(vcpu) || external_intr) &&
 	    nested_exit_on_intr(vcpu)) {
-		if (vmx->nested.nested_run_pending)
+		if (vmx->nested.nested_run_pending) {
+			vmx->nested.l1_events_blocked = true;
 			return -EBUSY;
+		}
 		nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0);
 	}
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2014-07-08  5:49 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-02  6:54 [PATCH] KVM: nVMX: Fix IRQs inject to L2 which belong to L1 since race Wanpeng Li
2014-07-02  7:20 ` Hu, Robert
2014-07-02  9:03   ` Jan Kiszka
2014-07-02  9:13     ` Hu, Robert
2014-07-02  9:16       ` Jan Kiszka
2014-07-02  9:01 ` Jan Kiszka
2014-07-03  2:59   ` Wanpeng Li
2014-07-03  5:15   ` Bandan Das
2014-07-03  6:59     ` Wanpeng Li
2014-07-03 17:27       ` Bandan Das
2014-07-04  2:52         ` Wanpeng Li
2014-07-04  5:43           ` Jan Kiszka
2014-07-04  6:08             ` Wanpeng Li
2014-07-04  7:19               ` Jan Kiszka
2014-07-04  7:39                 ` Wanpeng Li
2014-07-04  7:46                   ` Paolo Bonzini
2014-07-04  7:59                     ` Wanpeng Li
2014-07-04  8:14                       ` Paolo Bonzini
2014-07-04  7:42             ` Paolo Bonzini
2014-07-04  9:33             ` Jan Kiszka
2014-07-04  9:38               ` Paolo Bonzini
2014-07-04 10:52                 ` Jan Kiszka
2014-07-04 11:07                   ` Jan Kiszka
2014-07-04 11:28                     ` Paolo Bonzini
2014-07-04  6:17     ` Wanpeng Li
2014-07-04  7:21       ` Jan Kiszka
2014-07-07  0:56       ` Bandan Das
2014-07-07  8:46         ` Wanpeng Li
2014-07-07 13:03           ` Paolo Bonzini
2014-07-07 17:31             ` Bandan Das
2014-07-07 17:34               ` Paolo Bonzini
2014-07-07 17:38                 ` Bandan Das
2014-07-07 23:14                   ` Wanpeng Li
2014-07-08  4:35                     ` Bandan Das
2014-07-07 23:38             ` Wanpeng Li
2014-07-08  5:49               ` Paolo Bonzini
2014-07-02 16:27 ` Bandan Das
2014-07-03  5:11   ` Wanpeng Li
2014-07-03  5:29     ` Bandan Das
2014-07-03  7:33       ` Jan Kiszka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).