]> git.baikalelectronics.ru Git - kernel.git/commit
KVM: x86/mmu: Reintroduce fast invalidate/zap for flushing memslot
authorSean Christopherson <sean.j.christopherson@intel.com>
Fri, 13 Sep 2019 02:46:02 +0000 (19:46 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Sat, 14 Sep 2019 07:25:11 +0000 (09:25 +0200)
commit0a0156770a69172d8e0397ce77781ca97c69be63
tree2fd5017a8aea7c525cdc3592935b5b452a93e116
parent018652d1277083e3213026a882bb4117385a42db
KVM: x86/mmu: Reintroduce fast invalidate/zap for flushing memslot

James Harvey reported a livelock that was introduced by commit
ad98e1e0effee ("Revert "KVM: x86/mmu: Zap only the relevant pages when
removing a memslot"").

The livelock occurs because kvm_mmu_zap_all() as it exists today will
voluntarily reschedule and drop KVM's mmu_lock, which allows other vCPUs
to add shadow pages.  With enough vCPUs, kvm_mmu_zap_all() can get stuck
in an infinite loop as it can never zap all pages before observing lock
contention or the need to reschedule.  The equivalent of kvm_mmu_zap_all()
that was in use at the time of the reverted commit (2955cb206c319, "KVM:
x86/mmu: Zap only the relevant pages when removing a memslot") employed
a fast invalidate mechanism and was not susceptible to the above livelock.

There are three ways to fix the livelock:

- Reverting the revert (commit ad98e1e0effee) is not a viable option as
  the revert is needed to fix a regression that occurs when the guest has
  one or more assigned devices.  It's unlikely we'll root cause the device
  assignment regression soon enough to fix the regression timely.

- Remove the conditional reschedule from kvm_mmu_zap_all().  However, although
  removing the reschedule would be a smaller code change, it's less safe
  in the sense that the resulting kvm_mmu_zap_all() hasn't been used in
  the wild for flushing memslots since the fast invalidate mechanism was
  introduced by commit f085ba33c57e3 ("KVM: x86: use the fast way to
  invalidate all pages"), back in 2013.

- Reintroduce the fast invalidate mechanism and use it when zapping shadow
  pages in response to a memslot being deleted/moved, which is what this
  patch does.

For all intents and purposes, this is a revert of commit 8f936b1d515f8
("Revert "KVM: MMU: fast invalidate all pages"") and a partial revert of
commit 38a7665f5fc82 ("Revert "KVM: x86: use the fast way to invalidate
all pages""), i.e. restores the behavior of commit dbf2723c68bc2 ("KVM:
MMU: fast invalidate all pages") and commit f085ba33c57e3 ("KVM: x86:
use the fast way to invalidate all pages") respectively.

Fixes: ad98e1e0effee ("Revert "KVM: x86/mmu: Zap only the relevant pages when removing a memslot"")
Reported-by: James Harvey <jamespharvey20@gmail.com>
Cc: Alex Willamson <alex.williamson@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/mmu.c