KVM: only abort guest entry if timer count goes from 0->1
authorMarcelo Tosatti <mtosatti@redhat.com>
Wed, 11 Jun 2008 22:52:53 +0000 (19:52 -0300)
committerAvi Kivity <avi@qumranet.com>
Sun, 20 Jul 2008 09:42:32 +0000 (12:42 +0300)
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: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
arch/x86/kvm/i8254.c
arch/x86/kvm/lapic.c

index 9e3391e9a1b7bd45cd6965f8ab9bb03dab317dba..c0f7872a9124873ac9c01937bd4400ca2f3fe47b 100644 (file)
@@ -198,14 +198,11 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps)
        struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0];
        struct kvm_kpit_timer *pt = &ps->pit_timer;
 
-       atomic_inc(&pt->pending);
-       smp_mb__after_atomic_inc();
-       if (vcpu0) {
+       if (!atomic_inc_and_test(&pt->pending))
                set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
-               if (waitqueue_active(&vcpu0->wq)) {
-                       vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
-                       wake_up_interruptible(&vcpu0->wq);
-               }
+       if (vcpu0 && 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);
index 180ba7316da5e57831903ef33893b016b4c63ebd..73f43de69f676b9a784de04b4a7b5dbd43ecc3b1 100644 (file)
@@ -945,8 +945,8 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
        int result = 0;
        wait_queue_head_t *q = &apic->vcpu->wq;
 
-       atomic_inc(&apic->timer.pending);
-       set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
+       if(!atomic_inc_and_test(&apic->timer.pending))
+               set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
        if (waitqueue_active(q)) {
                apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
                wake_up_interruptible(q);