Skip to content

Commit 515c18a

Browse files
committed
KVM: x86: Drop dedicated logic for direct MMUs in reexecute_instruction()
Now that KVM doesn't pointlessly acquire mmu_lock for direct MMUs, drop the dedicated path entirely and always query indirect_shadow_pages when deciding whether or not to try unprotecting the gfn. For indirect, a.k.a. shadow MMUs, checking indirect_shadow_pages is harmless; unless *every* shadow page was somehow zapped while KVM was attempting to emulate the instruction, indirect_shadow_pages is guaranteed to be non-zero. Well, unless the instruction used a direct hugepage with 2-level paging for its code page, but in that case, there's obviously nothing to unprotect. And in the extremely unlikely case all shadow pages were zapped, there's again obviously nothing to unprotect. Link: https://lore.kernel.org/r/20240203002343.383056-3-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 474b99e commit 515c18a

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

arch/x86/kvm/x86.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8787,27 +8787,27 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
87878787

87888788
kvm_release_pfn_clean(pfn);
87898789

8790-
/* The instructions are well-emulated on direct mmu. */
8791-
if (vcpu->arch.mmu->root_role.direct) {
8792-
if (vcpu->kvm->arch.indirect_shadow_pages)
8793-
kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa));
8794-
8795-
return true;
8796-
}
8797-
87988790
/*
8799-
* if emulation was due to access to shadowed page table
8800-
* and it failed try to unshadow page and re-enter the
8801-
* guest to let CPU execute the instruction.
8791+
* If emulation may have been triggered by a write to a shadowed page
8792+
* table, unprotect the gfn (zap any relevant SPTEs) and re-enter the
8793+
* guest to let the CPU re-execute the instruction in the hope that the
8794+
* CPU can cleanly execute the instruction that KVM failed to emulate.
88028795
*/
8803-
kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa));
8796+
if (vcpu->kvm->arch.indirect_shadow_pages)
8797+
kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa));
88048798

88058799
/*
8806-
* If the access faults on its page table, it can not
8807-
* be fixed by unprotecting shadow page and it should
8808-
* be reported to userspace.
8800+
* If the failed instruction faulted on an access to page tables that
8801+
* are used to translate any part of the instruction, KVM can't resolve
8802+
* the issue by unprotecting the gfn, as zapping the shadow page will
8803+
* result in the instruction taking a !PRESENT page fault and thus put
8804+
* the vCPU into an infinite loop of page faults. E.g. KVM will create
8805+
* a SPTE and write-protect the gfn to resolve the !PRESENT fault, and
8806+
* then zap the SPTE to unprotect the gfn, and then do it all over
8807+
* again. Report the error to userspace.
88098808
*/
8810-
return !(emulation_type & EMULTYPE_WRITE_PF_TO_SP);
8809+
return vcpu->arch.mmu->root_role.direct ||
8810+
!(emulation_type & EMULTYPE_WRITE_PF_TO_SP);
88118811
}
88128812

88138813
static bool retry_instruction(struct x86_emulate_ctxt *ctxt,

0 commit comments

Comments
 (0)