linux-stable/Documentation/virtual/kvm
David Matlack ee3d1570b5 kvm: fix potentially corrupt mmio cache
vcpu exits and memslot mutations can run concurrently as long as the
vcpu does not aquire the slots mutex. Thus it is theoretically possible
for memslots to change underneath a vcpu that is handling an exit.

If we increment the memslot generation number again after
synchronize_srcu_expedited(), vcpus can safely cache memslot generation
without maintaining a single rcu_dereference through an entire vm exit.
And much of the x86/kvm code does not maintain a single rcu_dereference
of the current memslots during each exit.

We can prevent the following case:

   vcpu (CPU 0)                             | thread (CPU 1)
--------------------------------------------+--------------------------
1  vm exit                                  |
2  srcu_read_unlock(&kvm->srcu)             |
3  decide to cache something based on       |
     old memslots                           |
4                                           | change memslots
                                            | (increments generation)
5                                           | synchronize_srcu(&kvm->srcu);
6  retrieve generation # from new memslots  |
7  tag cache with new memslot generation    |
8  srcu_read_unlock(&kvm->srcu)             |
...                                         |
   <action based on cache occurs even       |
    though the caching decision was based   |
    on the old memslots>                    |
...                                         |
   <action *continues* to occur until next  |
    memslot generation change, which may    |
    be never>                               |
                                            |

By incrementing the generation after synchronizing with kvm->srcu readers,
we ensure that the generation retrieved in (6) will become invalid soon
after (8).

Keeping the existing increment is not strictly necessary, but we
do keep it and just move it for consistency from update_memslots to
install_new_memslots.  It invalidates old cached MMIOs immediately,
instead of having to wait for the end of synchronize_srcu_expedited,
which makes the code more clearly correct in case CPU 1 is preempted
right after synchronize_srcu() returns.

To avoid halving the generation space in SPTEs, always presume that the
low bit of the generation is zero when reconstructing a generation number
out of an SPTE.  This effectively disables MMIO caching in SPTEs during
the call to synchronize_srcu_expedited.  Using the low bit this way is
somewhat like a seqcount---where the protected thing is a cache, and
instead of retrying we can simply punt if we observe the low bit to be 1.

Cc: stable@vger.kernel.org
Signed-off-by: David Matlack <dmatlack@google.com>
Reviewed-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Reviewed-by: David Matlack <dmatlack@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-09-03 10:03:41 +02:00
..
devices KVM: s390: Exploiting generic userspace interface for cmma 2014-04-22 13:24:32 +02:00
00-INDEX Documentation/: update 00-INDEX files 2014-02-10 16:01:40 -08:00
api.txt KVM: clarify the idea of kvm_dirty_regs 2014-08-25 14:35:29 +02:00
cpuid.txt Documentation/kvm: Update cpuid documentation for steal time and pv eoi 2013-09-24 19:12:16 +02:00
hypercalls.txt KVM: doc: Fix typo in doc/virtual/kvm 2013-12-31 17:24:54 -02:00
locking.txt KVM: doc: Fix typo in doc/virtual/kvm 2013-12-31 17:24:54 -02:00
mmu.txt kvm: fix potentially corrupt mmio cache 2014-09-03 10:03:41 +02:00
msr.txt KVM: clarify kvmclock documentation 2012-09-17 14:10:23 -03:00
nested-vmx.txt KVM: nVMX: Documentation 2011-07-12 13:15:22 +03:00
ppc-pv.txt KVM: PPC: Disable NX for old magic page using guests 2014-05-30 14:26:24 +02:00
review-checklist.txt
s390-diag.txt KVM: s390: add documentation for diag 501 2014-04-22 13:24:51 +02:00
timekeeping.txt KVM: doc: Fix typo in doc/virtual/kvm 2013-12-31 17:24:54 -02:00