]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
KVM: Avoid instruction emulation when event delivery is pending
authorAvi Kivity <avi@qumranet.com>
Wed, 13 Aug 2008 15:00:28 +0000 (18:00 +0300)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 20 Aug 2008 18:05:06 +0000 (11:05 -0700)
(cherry-picked from commit 577bdc496614ced56d999bbb425e85adf2386490)

When an event (such as an interrupt) is injected, and the stack is
shadowed (and therefore write protected), the guest will exit.  The
current code will see that the stack is shadowed and emulate a few
instructions, each time postponing the injection.  Eventually the
injection may succeed, but at that time the guest may be unwilling
to accept the interrupt (for example, the TPR may have changed).

This occurs every once in a while during a Windows 2008 boot.

Fix by unshadowing the fault address if the fault was due to an event
injection.

Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c

index c26d811d9191aa232df87d7b6bee3da49d609492..67d00bc7f88bdcdb07ba0717c85bd65da484b16b 100644 (file)
@@ -1792,6 +1792,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
        spin_unlock(&vcpu->kvm->mmu_lock);
        return r;
 }
+EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt);
 
 void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
 {
index 06992d6833bb2131d88e976d950067c6ceb34d55..7d6071d11eb89c8ee310024d907711e4c2038a38 100644 (file)
@@ -1007,13 +1007,18 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
        struct kvm *kvm = svm->vcpu.kvm;
        u64 fault_address;
        u32 error_code;
+       bool event_injection = false;
 
        if (!irqchip_in_kernel(kvm) &&
-               is_external_interrupt(exit_int_info))
+           is_external_interrupt(exit_int_info)) {
+               event_injection = true;
                push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
+       }
 
        fault_address  = svm->vmcb->control.exit_info_2;
        error_code = svm->vmcb->control.exit_info_1;
+       if (event_injection)
+               kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
        return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
 }
 
index 2ce9063038cd87ad2dfd69774c848309a961a350..3ff39c1f9b034453c7330e4fbf2f39a097d3c9d4 100644 (file)
@@ -2258,6 +2258,8 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                cr2 = vmcs_readl(EXIT_QUALIFICATION);
                KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
                            (u32)((u64)cr2 >> 32), handler);
+               if (vect_info & VECTORING_INFO_VALID_MASK)
+                       kvm_mmu_unprotect_page_virt(vcpu, cr2);
                return kvm_mmu_page_fault(vcpu, cr2, error_code);
        }