[Devel] [PATCH RHEL7 COMMIT] ms/KVM: x86: inject exceptions produced by x86_decode_insn

Konstantin Khorenko khorenko at virtuozzo.com
Thu Oct 3 15:03:48 MSK 2019


The commit is pushed to "branch-rh7-3.10.0-957.27.2.vz7.107.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.27.2.vz7.107.13
------>
commit 6f2e003e7b28ca1c3d8d0c2fd390a78b65142838
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Oct 3 15:03:46 2019 +0300

    ms/KVM: x86: inject exceptions produced by x86_decode_insn
    
    Sometimes, a processor might execute an instruction while another
    processor is updating the page tables for that instruction's code page,
    but before the TLB shootdown completes.  The interesting case happens
    if the page is in the TLB.
    
    In general, the processor will succeed in executing the instruction and
    nothing bad happens.  However, what if the instruction is an MMIO access?
    If *that* happens, KVM invokes the emulator, and the emulator gets the
    updated page tables.  If the update side had marked the code page as non
    present, the page table walk then will fail and so will x86_decode_insn.
    
    Unfortunately, even though kvm_fetch_guest_virt is correctly returning
    X86EMUL_PROPAGATE_FAULT, x86_decode_insn's caller treats the failure as
    a fatal error if the instruction cannot simply be reexecuted (as is the
    case for MMIO).  And this in fact happened sometimes when rebooting
    Windows 2012r2 guests.  Just checking ctxt->have_exception and injecting
    the exception if true is enough to fix the case.
    
    Thanks to Eduardo Habkost for helping in the debugging of this issue.
    
    Reported-by: Yanan Fu <yfu at redhat.com>
    Cc: Eduardo Habkost <ehabkost at redhat.com>
    Cc: stable at vger.kernel.org
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Radim Krčmář <rkrcmar at redhat.com>
    
    https://jira.sw.ru/browse/PSBM-68018
    (cherry-picked from 6ea6e84309ca7e0e850b3083e6b09344ee15c290)
    Signed-off-by: Jan Dakinevich <jan.dakinevich at virtuozzo.com>
    
    =====================
    Patchset description:
    
    fix emulation error on Windows bootup
    
    This series intended to fix (again) a bug that was a subject of the
    following change:
    
      6ea6e84 ("KVM: x86: inject exceptions produced by x86_decode_insn")
    
    Suddenly, that fix had a couple mistakes. First, ctxt->have_exception was
    not set if fault happened during instruction decoding. Second, returning
    value of inject_emulated_instruction was used to make the decision to
    reenter guest, but this could happen iff on nested page fault, that is not
    the scope where this bug could occur.
    
    https://lkml.org/lkml/2019/8/29/152
    
    Jan Dakinevich (2):
      KVM: x86: always stop emulation on page fault
      KVM: x86: set ctxt->have_exception in x86_decode_insn()
    
    Paolo Bonzini (1):
      KVM: x86: inject exceptions produced by x86_decode_insn
---
 arch/x86/kvm/x86.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 13a9dd5087d3..94cfe99bc4c9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5759,6 +5759,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 			if (reexecute_instruction(vcpu, cr2, write_fault_to_spt,
 						emulation_type))
 				return EMULATE_DONE;
+			if (ctxt->have_exception && inject_emulated_exception(vcpu))
+				return EMULATE_DONE;
 			if (emulation_type & EMULTYPE_SKIP)
 				return EMULATE_FAIL;
 			return handle_emulation_failure(vcpu, emulation_type);



More information about the Devel mailing list