Skip to content

Commit

Permalink
KVM: x86/mmu: Drop exec/NX check from "page fault can be fast"
Browse files Browse the repository at this point in the history
Tweak the "page fault can be fast" logic to explicitly check for !PRESENT
faults in the access tracking case, and drop the exec/NX check that
becomes redundant as a result.  No sane hardware will generate an access
that is both an instruct fetch and a write, i.e. it's a waste of cycles.
If hardware goes off the rails, or KVM runs under a misguided hypervisor,
spuriously running throught fast path is benign (KVM has been uknowingly
being doing exactly that for years).

Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20220423034752.1161007-6-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
Sean Christopherson authored and Paolo Bonzini committed May 12, 2022
1 parent 54275f7 commit 5c64aba
Showing 1 changed file with 12 additions and 7 deletions.
19 changes: 12 additions & 7 deletions arch/x86/kvm/mmu/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3044,16 +3044,14 @@ static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fa
static bool page_fault_can_be_fast(struct kvm_page_fault *fault)
{
/*
* Do not fix the mmio spte with invalid generation number which
* need to be updated by slow page fault path.
* Page faults with reserved bits set, i.e. faults on MMIO SPTEs, only
* reach the common page fault handler if the SPTE has an invalid MMIO
* generation number. Refreshing the MMIO generation needs to go down
* the slow path. Note, EPT Misconfigs do NOT set the PRESENT flag!
*/
if (fault->rsvd)
return false;

/* See if the page fault is due to an NX violation */
if (unlikely(fault->exec && fault->present))
return false;

/*
* #PF can be fast if:
*
Expand All @@ -3069,7 +3067,14 @@ static bool page_fault_can_be_fast(struct kvm_page_fault *fault)
* SPTE is MMU-writable (determined later), the fault can be fixed
* by setting the Writable bit, which can be done out of mmu_lock.
*/
return !kvm_ad_enabled() || (fault->write && fault->present);
if (!fault->present)
return !kvm_ad_enabled();

/*
* Note, instruction fetches and writes are mutually exclusive, ignore
* the "exec" flag.
*/
return fault->write;
}

/*
Expand Down

0 comments on commit 5c64aba

Please sign in to comment.