Re: Avoid unneccessary %dr6 accesses in nested VM setups

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Tue, Oct 16, 2018 at 02:25:42PM +0800, Wanpeng Li wrote:
> On Tue, 16 Oct 2018 at 04:45, Christian Ehrhardt <lk@xxxxxxx> wrote:
> >
> >
> > Hi,
> >
> > while debugging a nested VM setup where Linux runs as an L1
> > guest, I found lots of VM exits due to %dr6 writes. However,
> > neither L0 nor L1 or L2 where using debug registers.
> >
> > The behaviour was introdued with change efdab992 and the
> > original author suggested the patch below.
> >
> > BTW: I'm not related to the other guy with the same name.
> >
> >      regards    Christian
> >
> >
> > From e18794eaa15a6bd8829a86a806bc8acb964eefb9 Mon Sep 17 00:00:00 2001
> > From: Christian Ehrhardt <lk@xxxxxx>
> > Date: Mon, 15 Oct 2018 20:05:48 +0200
> > Subject: [PATCH 1/2] KVM: x86: Only clear %dr6 if really neccessary
> >
> > Change efdab992: "KVM: x86: fix escape of guest dr6 to the host"
> > has negative effects if Linux runs as the L1 guest in a nested
> > VM setup:
> >
> > Each call to kvm_arch_vcpu_put causes an additional L1->L0 exit due
> > to the %dr6 write even if neither L1 nor L2 uses debug registers.
> > As the current hardware value of %dr6 is already in vcpu->arch.dr6
> > we can avoid the debug register write if the value is already zero.
> >
> > Update the comment and reformat it while there.
> >
> > Signed-off-by: Christian Ehrhardt <lk@xxxxxxx>
> > ---
> >  arch/x86/kvm/x86.c | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index ca717737347e..37d046c5c9c1 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -3185,11 +3185,13 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
> >         kvm_x86_ops->vcpu_put(vcpu);
> >         vcpu->arch.last_host_tsc = rdtsc();
> >         /*
> > -        * If userspace has set any breakpoints or watchpoints, dr6 is restored
> > -        * on every vmexit, but if not, we might have a stale dr6 from the
> > -        * guest. do_debug expects dr6 to be cleared after it runs, do the same.
> > +        * If userspace has set any breakpoints or watchpoints, dr6 is
> > +        * restored on every vmexit, but if not, we might have a stale
> > +        * dr6 from the guest. do_debug expects dr6 to be cleared after
> > +        * it runs, do the same if dr6 has a non-zero value.
> >          */
> > -       set_debugreg(0, 6);
> > +       if (vcpu->arch.dr6)
> > +               set_debugreg(0, 6);
> 
> I tried this immediately after the offline discussion between Paolo
> and you several months ago, however, I can observe the issue was still
> present.

True. After re-reading the intel manual  that's because man bits
in %dr6 are reserved and set to 1. The check above must be

	if (vcpu->arch.dr6 & DR6_RESERVED)
		set_debugreg(0, 6);

instead of

	if (vcpu->arch.dr6)
		set_debugreg(0, 6);

I'll prepare an updated patch tonight. However, I still cannot test
this easily as this would require recompiling the distribution
kernel used for L1...

     regards    Christian




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux