kvm/x86: Remove Hyper-V SynIC timer stopping
authorAndrey Smetanin <asmetanin@virtuozzo.com>
Mon, 14 Dec 2015 15:33:05 +0000 (18:33 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 16 Dec 2015 17:51:22 +0000 (18:51 +0100)
It's possible that guest send us Hyper-V EOM at the middle
of Hyper-V SynIC timer running, so we start processing of Hyper-V
SynIC timers in vcpu context and stop the Hyper-V SynIC timer
unconditionally:

    host                                       guest
    ------------------------------------------------------------------------------
                                           start periodic stimer
    start periodic timer
    timer expires after 15ms
    send expiration message into guest
    restart periodic timer
    timer expires again after 15 ms
    msg slot is still not cleared so
    setup ->msg_pending
(1) restart periodic timer
                                           process timer msg and clear slot
                                           ->msg_pending was set:
                                               send EOM into host
    received EOM
      kvm_make_request(KVM_REQ_HV_STIMER)

    kvm_hv_process_stimers():
        ...
        stimer_stop()
        if (time_now >= stimer->exp_time)
                stimer_expiration(stimer);

Because the timer was rearmed at (1), time_now < stimer->exp_time
and stimer_expiration is not called.  The timer then never fires.

The patch fixes such situation by not stopping Hyper-V SynIC timer
at all, because it's safe to restart it without stop in vcpu context
and timer callback always returns HRTIMER_NORESTART.

Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
CC: Gleb Natapov <gleb@kernel.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: qemu-devel@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/hyperv.c

index 8ff88293b906a7e90000c40e0840812b571e2710..f34f666778b2651a206cff3dd9384b86178771d9 100644 (file)
@@ -598,7 +598,6 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu)
        for (i = 0; i < ARRAY_SIZE(hv_vcpu->stimer); i++)
                if (test_and_clear_bit(i, hv_vcpu->stimer_pending_bitmap)) {
                        stimer = &hv_vcpu->stimer[i];
-                       stimer_stop(stimer);
                        if (stimer->config & HV_STIMER_ENABLE) {
                                time_now = get_time_ref_counter(vcpu->kvm);
                                if (time_now >= stimer->exp_time)