OSDN Git Service

KVM: Call kvm_arch_memslots_updated() before updating memslots
authorSean Christopherson <sean.j.christopherson@intel.com>
Tue, 5 Feb 2019 20:54:17 +0000 (12:54 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 Mar 2019 19:10:13 +0000 (20:10 +0100)
commit23ad135ae66f7f2b743885b47867c2bd636baf1f
tree308f532d4fd8a18c8141f9adbc7b24a29adf1882
parent585715ef18bf147fb11b1f0731eb6d6f50fbdb45
KVM: Call kvm_arch_memslots_updated() before updating memslots

commit 152482580a1b0accb60676063a1ac57b2d12daf6 upstream.

kvm_arch_memslots_updated() is at this point in time an x86-specific
hook for handling MMIO generation wraparound.  x86 stashes 19 bits of
the memslots generation number in its MMIO sptes in order to avoid
full page fault walks for repeat faults on emulated MMIO addresses.
Because only 19 bits are used, wrapping the MMIO generation number is
possible, if unlikely.  kvm_arch_memslots_updated() alerts x86 that
the generation has changed so that it can invalidate all MMIO sptes in
case the effective MMIO generation has wrapped so as to avoid using a
stale spte, e.g. a (very) old spte that was created with generation==0.

Given that the purpose of kvm_arch_memslots_updated() is to prevent
consuming stale entries, it needs to be called before the new generation
is propagated to memslots.  Invalidating the MMIO sptes after updating
memslots means that there is a window where a vCPU could dereference
the new memslots generation, e.g. 0, and incorrectly reuse an old MMIO
spte that was created with (pre-wrap) generation==0.

Fixes: e59dbe09f8e6 ("KVM: Introduce kvm_arch_memslots_updated()")
Cc: <stable@vger.kernel.org>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/mips/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_host.h
arch/s390/include/asm/kvm_host.h
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/mmu.c
arch/x86/kvm/x86.c
include/linux/kvm_host.h
virt/kvm/arm/mmu.c
virt/kvm/kvm_main.c