linux/arch/x86/kvm
Sean Christopherson 45def77ebf KVM: x86: update %rip after emulating IO
Most (all?) x86 platforms provide a port IO based reset mechanism, e.g.
OUT 92h or CF9h.  Userspace may emulate said mechanism, i.e. reset a
vCPU in response to KVM_EXIT_IO, without explicitly announcing to KVM
that it is doing a reset, e.g. Qemu jams vCPU state and resumes running.

To avoid corruping %rip after such a reset, commit 0967b7bf1c ("KVM:
Skip pio instruction when it is emulated, not executed") changed the
behavior of PIO handlers, i.e. today's "fast" PIO handling to skip the
instruction prior to exiting to userspace.  Full emulation doesn't need
such tricks becase re-emulating the instruction will naturally handle
%rip being changed to point at the reset vector.

Updating %rip prior to executing to userspace has several drawbacks:

  - Userspace sees the wrong %rip on the exit, e.g. if PIO emulation
    fails it will likely yell about the wrong address.
  - Single step exits to userspace for are effectively dropped as
    KVM_EXIT_DEBUG is overwritten with KVM_EXIT_IO.
  - Behavior of PIO emulation is different depending on whether it
    goes down the fast path or the slow path.

Rather than skip the PIO instruction before exiting to userspace,
snapshot the linear %rip and cancel PIO completion if the current
value does not match the snapshot.  For a 64-bit vCPU, i.e. the most
common scenario, the snapshot and comparison has negligible overhead
as VMCS.GUEST_RIP will be cached regardless, i.e. there is no extra
VMREAD in this case.

All other alternatives to snapshotting the linear %rip that don't
rely on an explicit reset announcenment suffer from one corner case
or another.  For example, canceling PIO completion on any write to
%rip fails if userspace does a save/restore of %rip, and attempting to
avoid that issue by canceling PIO only if %rip changed then fails if PIO
collides with the reset %rip.  Attempting to zero in on the exact reset
vector won't work for APs, which means adding more hooks such as the
vCPU's MP_STATE, and so on and so forth.

Checking for a linear %rip match technically suffers from corner cases,
e.g. userspace could theoretically rewrite the underlying code page and
expect a different instruction to execute, or the guest hardcodes a PIO
reset at 0xfffffff0, but those are far, far outside of what can be
considered normal operation.

Fixes: 432baf60ee ("KVM: VMX: use kvm_fast_pio_in for handling IN I/O")
Cc: <stable@vger.kernel.org>
Reported-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2019-03-28 17:29:04 +01:00
..
vmx KVM: x86: Emulate MSR_IA32_ARCH_CAPABILITIES on AMD hosts 2019-03-28 17:29:00 +01:00
cpuid.c ARM: some cleanups, direct physical timer assignment, cache sanitization 2019-03-15 15:00:28 -07:00
cpuid.h KVM/x86: Update the reverse_cpuid list to include CPUID_7_EDX 2018-02-03 23:06:51 +01:00
debugfs.c kvm: x86: export TSC information to user-space 2016-09-16 16:57:48 +02:00
emulate.c jump_label: move 'asm goto' support test to Kconfig 2019-01-06 09:46:51 +09:00
hyperv.c x86/kvm/hyper-v: avoid spurious pending stimer on vCPU init 2019-03-28 17:29:03 +01:00
hyperv.h x86/kvm/hyper-v: Introduce KVM_GET_SUPPORTED_HV_CPUID 2018-12-14 17:59:54 +01:00
i8254.c kvm: x86: Add memcg accounting to KVM allocations 2019-02-20 22:48:30 +01:00
i8254.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
i8259.c kvm: x86: Add memcg accounting to KVM allocations 2019-02-20 22:48:30 +01:00
ioapic.c kvm: x86: Add memcg accounting to KVM allocations 2019-02-20 22:48:30 +01:00
ioapic.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
irq_comm.c KVM: x86: don't hold kvm->lock in KVM_SET_GSI_ROUTING 2017-05-02 14:45:45 +02:00
irq.c KVM: x86: Rename interrupt.pending to interrupt.injected 2018-03-28 22:47:06 +02:00
irq.h KVM: x86: don't hold kvm->lock in KVM_SET_GSI_ROUTING 2017-05-02 14:45:45 +02:00
Kconfig treewide: surround Kconfig file paths with double quotes 2018-12-22 00:25:54 +09:00
kvm_cache_regs.h KVM: x86: Add requisite includes to kvm_cache_regs.h 2018-12-14 12:34:22 +01:00
lapic.c kvm: x86: Add memcg accounting to KVM allocations 2019-02-20 22:48:30 +01:00
lapic.h KVM: hyperv: define VP assist page helpers 2018-10-17 00:30:13 +02:00
Makefile KVM: x86: fix TRACE_INCLUDE_PATH and remove -I. header search paths 2019-01-25 19:12:37 +01:00
mmu_audit.c x86/kvm/mmu: make vcpu->mmu a pointer to the current MMU 2018-10-17 00:30:02 +02:00
mmu.c kvm: mmu: Used range based flushing in slot_handle_level_range 2019-03-28 17:28:57 +01:00
mmu.h Revert "KVM: MMU: fast invalidate all pages" 2019-02-20 22:48:47 +01:00
mmutrace.h KVM: x86: fix handling of role.cr4_pae and rename it to 'gpte_size' 2019-03-28 17:27:03 +01:00
mtrr.c KVM: x86: generalize guest_cpuid_has_ helpers 2017-08-07 16:11:50 +02:00
page_track.c kvm: x86: Add memcg accounting to KVM allocations 2019-02-20 22:48:30 +01:00
paging_tmpl.h KVM: Replace old tlb flush function with new one to flush a specified range. 2018-12-21 11:28:41 +01:00
pmu_amd.c KVM: x86: Add support for AMD Core Perf Extension in guest 2018-03-16 22:01:28 +01:00
pmu.c KVM: x86: Add support for VMware backdoor Pseudo-PMCs 2018-03-16 22:02:01 +01:00
pmu.h KVM: x86: Add support for VMware backdoor Pseudo-PMCs 2018-03-16 22:02:01 +01:00
svm.c KVM: SVM: Workaround errata#1096 (insn_len maybe zero on SMAP violation) 2019-03-28 17:27:17 +01:00
trace.h KVM: x86: fix TRACE_INCLUDE_PATH and remove -I. header search paths 2019-01-25 19:12:37 +01:00
tss.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
x86.c KVM: x86: update %rip after emulating IO 2019-03-28 17:29:04 +01:00
x86.h KVM: Explicitly define the "memslot update in-progress" bit 2019-02-20 22:48:34 +01:00