[Devel,RHEL7,COMMIT] ms/kvm: x86: hyperv: avoid livelock in oneshot SynIC timers

Submitted by Konstantin Khorenko on Aug. 7, 2017, 9:33 a.m.


Message ID 201708070933.v779XKih006790@finist_cl7.x64_64.work.ct
State New
Series "kvm: x86: hyperv: avoid livelock in oneshot SynIC timers"
Headers show

Commit Message

Konstantin Khorenko Aug. 7, 2017, 9:33 a.m.
The commit is pushed to "branch-rh7-3.10.0-514.26.1.vz7.35.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.26.1.vz7.33.22
commit d86cb50b159e72f7575ac407d984252395cad053
Author: Roman Kagan <rkagan@virtuozzo.com>
Date:   Mon Aug 7 13:33:20 2017 +0400

    ms/kvm: x86: hyperv: avoid livelock in oneshot SynIC timers
    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>
    (cherry picked from commit f1ff89ec4447c4e39d275a1ca3de43eed2a92745)
 arch/x86/kvm/hyperv.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index c8efdce..ab9501c 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -632,9 +632,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