[Devel] [PATCH] kvm: x86: hyperv: avoid livelock in oneshot SynIC timers

Roman Kagan rkagan at virtuozzo.com
Thu Jul 20 13:01:38 MSK 2017


On Thu, Jul 20, 2017 at 11:38:19AM +0300, Konstantin Khorenko wrote:
> Need it in update 5?

That's up to Den to decide.  The livelock is only triggerable with
one-shot SynIC timers; none of our regular guests uses them (Windows
uses periodic timers, Linux does use one-shot timers but needs to be
started with hyperv on and kvm off which doesn't happen in normal use).

> Any bug id?

The problem was noticed in a special scenario on my dev machine with the
mainstream kernel so I didn't bother to file a bug.

I'm about to post the patch to the KVM list so you'll have the master
commit id once (if) it's merged.

Roman.

> 
> --
> Best regards,
> 
> Konstantin Khorenko,
> Virtuozzo Linux Kernel Team
> 
> On 07/19/2017 08:31 PM, Roman Kagan wrote:
> > 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, 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 the guest releases the slot, the processing is
> > resumed so the timer will be started then.
> > 
> > Signed-off-by: Roman Kagan <rkagan at virtuozzo.com>
> > ---
> >  arch/x86/kvm/hyperv.c | 7 ++++---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> > 
> > diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
> > index c8efdce3e702..ab9501c2f32c 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
> >  					stimer_cleanup(stimer);
> >  			}
> >  		}
> > 


More information about the Devel mailing list