diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2008-06-11 18:52:53 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-07-20 05:42:32 -0400 |
commit | 622395a9e63bf87a16faecf555ed02375cbae5b7 (patch) | |
tree | c4a8082660a4e4bf8f687a33921d292ae35f6394 /arch/x86/kvm | |
parent | 7f39f8ac177db258200053074aa7a3d98656b1cf (diff) |
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: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/i8254.c | 11 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.c | 4 |
2 files changed, 6 insertions, 9 deletions
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 9e3391e9a1b7..c0f7872a9124 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c | |||
@@ -198,14 +198,11 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps) | |||
198 | struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0]; | 198 | struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0]; |
199 | struct kvm_kpit_timer *pt = &ps->pit_timer; | 199 | struct kvm_kpit_timer *pt = &ps->pit_timer; |
200 | 200 | ||
201 | atomic_inc(&pt->pending); | 201 | if (!atomic_inc_and_test(&pt->pending)) |
202 | smp_mb__after_atomic_inc(); | ||
203 | if (vcpu0) { | ||
204 | set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests); | 202 | set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests); |
205 | if (waitqueue_active(&vcpu0->wq)) { | 203 | if (vcpu0 && waitqueue_active(&vcpu0->wq)) { |
206 | vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE; | 204 | vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE; |
207 | wake_up_interruptible(&vcpu0->wq); | 205 | wake_up_interruptible(&vcpu0->wq); |
208 | } | ||
209 | } | 206 | } |
210 | 207 | ||
211 | pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period); | 208 | pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period); |
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 180ba7316da5..73f43de69f67 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -945,8 +945,8 @@ static int __apic_timer_fn(struct kvm_lapic *apic) | |||
945 | int result = 0; | 945 | int result = 0; |
946 | wait_queue_head_t *q = &apic->vcpu->wq; | 946 | wait_queue_head_t *q = &apic->vcpu->wq; |
947 | 947 | ||
948 | atomic_inc(&apic->timer.pending); | 948 | if(!atomic_inc_and_test(&apic->timer.pending)) |
949 | set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests); | 949 | set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests); |
950 | if (waitqueue_active(q)) { | 950 | if (waitqueue_active(q)) { |
951 | apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; | 951 | apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; |
952 | wake_up_interruptible(q); | 952 | wake_up_interruptible(q); |