aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/x86.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 3d72fc067059..d51eed239b47 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3930,6 +3930,29 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu)
3930 return EMULATE_FAIL; 3930 return EMULATE_FAIL;
3931} 3931}
3932 3932
3933static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva)
3934{
3935 gpa_t gpa;
3936
3937 /*
3938 * if emulation was due to access to shadowed page table
3939 * and it failed try to unshadow page and re-entetr the
3940 * guest to let CPU execute the instruction.
3941 */
3942 if (kvm_mmu_unprotect_page_virt(vcpu, gva))
3943 return true;
3944
3945 gpa = kvm_mmu_gva_to_gpa_system(vcpu, gva, NULL);
3946
3947 if (gpa == UNMAPPED_GVA)
3948 return true; /* let cpu generate fault */
3949
3950 if (!kvm_is_error_hva(gfn_to_hva(vcpu->kvm, gpa >> PAGE_SHIFT)))
3951 return true;
3952
3953 return false;
3954}
3955
3933int emulate_instruction(struct kvm_vcpu *vcpu, 3956int emulate_instruction(struct kvm_vcpu *vcpu,
3934 unsigned long cr2, 3957 unsigned long cr2,
3935 u16 error_code, 3958 u16 error_code,
@@ -3998,7 +4021,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
3998 4021
3999 ++vcpu->stat.insn_emulation; 4022 ++vcpu->stat.insn_emulation;
4000 if (r) { 4023 if (r) {
4001 if (kvm_mmu_unprotect_page_virt(vcpu, cr2)) 4024 if (reexecute_instruction(vcpu, cr2))
4002 return EMULATE_DONE; 4025 return EMULATE_DONE;
4003 if (emulation_type & EMULTYPE_SKIP) 4026 if (emulation_type & EMULTYPE_SKIP)
4004 return EMULATE_FAIL; 4027 return EMULATE_FAIL;
@@ -4019,12 +4042,7 @@ restart:
4019 r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); 4042 r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
4020 4043
4021 if (r) { /* emulation failed */ 4044 if (r) { /* emulation failed */
4022 /* 4045 if (reexecute_instruction(vcpu, cr2))
4023 * if emulation was due to access to shadowed page table
4024 * and it failed try to unshadow page and re-entetr the
4025 * guest to let CPU execute the instruction.
4026 */
4027 if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
4028 return EMULATE_DONE; 4046 return EMULATE_DONE;
4029 4047
4030 return handle_emulation_failure(vcpu); 4048 return handle_emulation_failure(vcpu);