diff options
-rw-r--r-- | arch/x86/kvm/x86.c | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f0288c52d5e4..6f9cab071eca 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4751,25 +4751,25 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu) | |||
4751 | return r; | 4751 | return r; |
4752 | } | 4752 | } |
4753 | 4753 | ||
4754 | static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva) | 4754 | static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t cr2) |
4755 | { | 4755 | { |
4756 | gpa_t gpa; | 4756 | gpa_t gpa = cr2; |
4757 | pfn_t pfn; | 4757 | pfn_t pfn; |
4758 | 4758 | ||
4759 | if (tdp_enabled) | 4759 | if (!vcpu->arch.mmu.direct_map) { |
4760 | return false; | 4760 | /* |
4761 | 4761 | * Write permission should be allowed since only | |
4762 | gpa = kvm_mmu_gva_to_gpa_system(vcpu, gva, NULL); | 4762 | * write access need to be emulated. |
4763 | if (gpa == UNMAPPED_GVA) | 4763 | */ |
4764 | return true; /* let cpu generate fault */ | 4764 | gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2, NULL); |
4765 | 4765 | ||
4766 | /* | 4766 | /* |
4767 | * if emulation was due to access to shadowed page table | 4767 | * If the mapping is invalid in guest, let cpu retry |
4768 | * and it failed try to unshadow page and re-enter the | 4768 | * it to generate fault. |
4769 | * guest to let CPU execute the instruction. | 4769 | */ |
4770 | */ | 4770 | if (gpa == UNMAPPED_GVA) |
4771 | if (kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa))) | 4771 | return true; |
4772 | return true; | 4772 | } |
4773 | 4773 | ||
4774 | /* | 4774 | /* |
4775 | * Do not retry the unhandleable instruction if it faults on the | 4775 | * Do not retry the unhandleable instruction if it faults on the |
@@ -4778,12 +4778,37 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva) | |||
4778 | * instruction -> ... | 4778 | * instruction -> ... |
4779 | */ | 4779 | */ |
4780 | pfn = gfn_to_pfn(vcpu->kvm, gpa_to_gfn(gpa)); | 4780 | pfn = gfn_to_pfn(vcpu->kvm, gpa_to_gfn(gpa)); |
4781 | if (!is_error_noslot_pfn(pfn)) { | 4781 | |
4782 | kvm_release_pfn_clean(pfn); | 4782 | /* |
4783 | * If the instruction failed on the error pfn, it can not be fixed, | ||
4784 | * report the error to userspace. | ||
4785 | */ | ||
4786 | if (is_error_noslot_pfn(pfn)) | ||
4787 | return false; | ||
4788 | |||
4789 | kvm_release_pfn_clean(pfn); | ||
4790 | |||
4791 | /* The instructions are well-emulated on direct mmu. */ | ||
4792 | if (vcpu->arch.mmu.direct_map) { | ||
4793 | unsigned int indirect_shadow_pages; | ||
4794 | |||
4795 | spin_lock(&vcpu->kvm->mmu_lock); | ||
4796 | indirect_shadow_pages = vcpu->kvm->arch.indirect_shadow_pages; | ||
4797 | spin_unlock(&vcpu->kvm->mmu_lock); | ||
4798 | |||
4799 | if (indirect_shadow_pages) | ||
4800 | kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa)); | ||
4801 | |||
4783 | return true; | 4802 | return true; |
4784 | } | 4803 | } |
4785 | 4804 | ||
4786 | return false; | 4805 | /* |
4806 | * if emulation was due to access to shadowed page table | ||
4807 | * and it failed try to unshadow page and re-enter the | ||
4808 | * guest to let CPU execute the instruction. | ||
4809 | */ | ||
4810 | kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa)); | ||
4811 | return true; | ||
4787 | } | 4812 | } |
4788 | 4813 | ||
4789 | static bool retry_instruction(struct x86_emulate_ctxt *ctxt, | 4814 | static bool retry_instruction(struct x86_emulate_ctxt *ctxt, |