]> 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)
commit62928b13e0644c1f6d26051fad2f667a8a8eaf65
tree2fd5017a8aea7c525cdc3592935b5b452a93e116
parentc04b9fd59ce79877e94a386417611301abb2f263
KVM: x86/mmu: Reintroduce fast invalidate/zap for flushing memslot

James Harvey reported a livelock that was introduced by commit
7da482ec2d2fc ("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 (b16daaf306a2f, "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 7da482ec2d2fc) 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 a911c034a669d ("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 973175a98bda0
("Revert "KVM: MMU: fast invalidate all pages"") and a partial revert of
commit 7550b7a731d48 ("Revert "KVM: x86: use the fast way to invalidate
all pages""), i.e. restores the behavior of commit 06f4d94ef525c ("KVM:
MMU: fast invalidate all pages") and commit a911c034a669d ("KVM: x86:
use the fast way to invalidate all pages") respectively.

Fixes: 7da482ec2d2fc ("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