kvm: x86: hyperv: avoid livelock in oneshot SynIC timers
authorRoman Kagan <rkagan@virtuozzo.com>
Thu, 20 Jul 2017 14:26:40 +0000 (17:26 +0300)
committerRadim Krčmář <rkrcmar@redhat.com>
Thu, 20 Jul 2017 15:00:00 +0000 (17:00 +0200)
If the SynIC timer message delivery fails due to SINT message slot being
busy, there's no point to attempt starting the timer again until we're
notified of the slot being released by the guest (via EOM or EOI).

Even worse, when a oneshot timer fails to deliver its message, its
re-arming with an expiration time in the past leads to immediate retry
of the delivery, and so on, without ever letting the guest vcpu to run
and release the slot, which results in a livelock.

To avoid that, only start the timer when there's no timer message
pending delivery.  When there is, meaning the slot is busy, the
processing will be restarted upon notification from the guest that the
slot is released.

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
arch/x86/kvm/hyperv.c

index 2695a34fa1c5190f98b9fdd092e9cc2d3e44b2a0..337b6d2730fa15b14a8c411b9a77662e48f4a190 100644 (file)
@@ -649,9 +649,10 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu)
                                }
 
                                if ((stimer->config & HV_STIMER_ENABLE) &&
-                                   stimer->count)
-                                       stimer_start(stimer);
-                               else
+                                   stimer->count) {
+                                       if (!stimer->msg_pending)
+                                               stimer_start(stimer);
+                               } else
                                        stimer_cleanup(stimer);
                        }
                }