Commit 06e05645 authored by Marcelo Tosatti's avatar Marcelo Tosatti Committed by Avi Kivity

KVM: close timer injection race window in __vcpu_run

If a timer fires after kvm_inject_pending_timer_irqs() but before
local_irq_disable() the code will enter guest mode and only inject such
timer interrupt the next time an unrelated event causes an exit.

It would be simpler if the timer->pending irq conversion could be done
with IRQ's disabled, so that the above problem cannot happen.

For now introduce a new vcpu requests bit to cancel guest entry.
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent d4acf7e7
...@@ -200,9 +200,12 @@ int __pit_timer_fn(struct kvm_kpit_state *ps) ...@@ -200,9 +200,12 @@ int __pit_timer_fn(struct kvm_kpit_state *ps)
atomic_inc(&pt->pending); atomic_inc(&pt->pending);
smp_mb__after_atomic_inc(); smp_mb__after_atomic_inc();
if (vcpu0 && waitqueue_active(&vcpu0->wq)) { if (vcpu0) {
vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE; set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
wake_up_interruptible(&vcpu0->wq); if (waitqueue_active(&vcpu0->wq)) {
vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
wake_up_interruptible(&vcpu0->wq);
}
} }
pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period); pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period);
......
...@@ -940,6 +940,7 @@ static int __apic_timer_fn(struct kvm_lapic *apic) ...@@ -940,6 +940,7 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
wait_queue_head_t *q = &apic->vcpu->wq; wait_queue_head_t *q = &apic->vcpu->wq;
atomic_inc(&apic->timer.pending); atomic_inc(&apic->timer.pending);
set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
if (waitqueue_active(q)) { if (waitqueue_active(q)) {
apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
wake_up_interruptible(q); wake_up_interruptible(q);
......
...@@ -2774,6 +2774,7 @@ again: ...@@ -2774,6 +2774,7 @@ again:
} }
} }
clear_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
kvm_inject_pending_timer_irqs(vcpu); kvm_inject_pending_timer_irqs(vcpu);
preempt_disable(); preempt_disable();
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#define KVM_REQ_REPORT_TPR_ACCESS 2 #define KVM_REQ_REPORT_TPR_ACCESS 2
#define KVM_REQ_MMU_RELOAD 3 #define KVM_REQ_MMU_RELOAD 3
#define KVM_REQ_TRIPLE_FAULT 4 #define KVM_REQ_TRIPLE_FAULT 4
#define KVM_REQ_PENDING_TIMER 5
struct kvm_vcpu; struct kvm_vcpu;
extern struct kmem_cache *kvm_vcpu_cache; extern struct kmem_cache *kvm_vcpu_cache;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment