Commit 622395a9 authored by Marcelo Tosatti's avatar Marcelo Tosatti Committed by Avi Kivity

KVM: only abort guest entry if timer count goes from 0->1

Only abort guest entry if the timer count went from 0->1, since for 1->2
or larger the bit will either be set already or a timer irq will have
been injected.

Using atomic_inc_and_test() for it also introduces an SMP barrier
to the LAPIC version (thought it was unecessary because of timer
migration, but guest can be scheduled to a different pCPU between exit
and kvm_vcpu_block(), so there is the possibility for a race).

Noticed by Avi.
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent 7f39f8ac
...@@ -198,15 +198,12 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps) ...@@ -198,15 +198,12 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps)
struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0]; struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0];
struct kvm_kpit_timer *pt = &ps->pit_timer; struct kvm_kpit_timer *pt = &ps->pit_timer;
atomic_inc(&pt->pending); if (!atomic_inc_and_test(&pt->pending))
smp_mb__after_atomic_inc();
if (vcpu0) {
set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests); set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
if (waitqueue_active(&vcpu0->wq)) { if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE; vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
wake_up_interruptible(&vcpu0->wq); 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);
pt->scheduled = ktime_to_ns(pt->timer.expires); pt->scheduled = ktime_to_ns(pt->timer.expires);
......
...@@ -945,7 +945,7 @@ static int __apic_timer_fn(struct kvm_lapic *apic) ...@@ -945,7 +945,7 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
int result = 0; int result = 0;
wait_queue_head_t *q = &apic->vcpu->wq; wait_queue_head_t *q = &apic->vcpu->wq;
atomic_inc(&apic->timer.pending); if(!atomic_inc_and_test(&apic->timer.pending))
set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests); 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;
......
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