diff options
-rw-r--r-- | arch/x86/kvm/x86.c | 32 |
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 | ||
3933 | static 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 | |||
3933 | int emulate_instruction(struct kvm_vcpu *vcpu, | 3956 | int 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); |