From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: Sean Christopherson <seanjc@google.com>,
Vitaly Kuznetsov <vkuznets@redhat.com>,
Wanpeng Li <wanpengli@tencent.com>,
Jim Mattson <jmattson@google.com>, Joerg Roedel <joro@8bytes.org>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Ben Gardon <bgardon@google.com>,
David Matlack <dmatlack@google.com>,
Venkatesh Srinivas <venkateshs@google.com>,
Chao Peng <chao.p.peng@linux.intel.com>
Subject: [PATCH 11/12] DO NOT MERGE: KVM: x86/mmu: Use fast_page_fault() to detect spurious shadow MMU faults
Date: Sat, 23 Apr 2022 03:47:51 +0000 [thread overview]
Message-ID: <20220423034752.1161007-12-seanjc@google.com> (raw)
In-Reply-To: <20220423034752.1161007-1-seanjc@google.com>
Sounds good in theory, but in practice it's really, really rare to detect
a spurious fault outside of mmu_lock. The window is teeny tiny, so more
likely than not, spurious faults won't be detected until the slow path,
not too mention spurious faults on !PRESENT pages are rare in and of
themselves.
Not-signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/mmu/mmu.c | 28 ++++++++++++++++++----------
arch/x86/kvm/mmu/paging_tmpl.h | 8 ++++++++
2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 7ba88907d032..850d58793307 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -2994,7 +2994,7 @@ static int handle_abnormal_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fau
return RET_PF_CONTINUE;
}
-static bool page_fault_can_be_fast(struct kvm_page_fault *fault)
+static bool page_fault_can_be_fast(struct kvm_page_fault *fault, bool direct_mmu)
{
/*
* Page faults with reserved bits set, i.e. faults on MMIO SPTEs, only
@@ -3025,8 +3025,12 @@ static bool page_fault_can_be_fast(struct kvm_page_fault *fault)
* either the primary MMU or the guest's page tables, and thus are
* extremely unlikely to be resolved by KVM. Note, instruction fetches
* and writes are mutually exclusive, ignore the "exec" flag.
+ *
+ * KVM doesn't support resolving write-protection violations outside of
+ * mmu_lock for indirect MMUs as the gfn is not stable for indirect
+ * shadow pages. See Documentation/virt/kvm/locking.rst for details.
*/
- return fault->write;
+ return fault->write && direct_mmu;
}
/*
@@ -3097,7 +3101,8 @@ static u64 *fast_pf_get_last_sptep(struct kvm_vcpu *vcpu, gpa_t gpa, u64 *spte)
/*
* Returns one of RET_PF_INVALID, RET_PF_FIXED or RET_PF_SPURIOUS.
*/
-static int fast_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
+static int fast_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault,
+ bool direct_mmu)
{
struct kvm_mmu_page *sp;
int ret = RET_PF_INVALID;
@@ -3105,7 +3110,7 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
u64 *sptep = NULL;
uint retry_count = 0;
- if (!page_fault_can_be_fast(fault))
+ if (!page_fault_can_be_fast(fault, direct_mmu))
return ret;
walk_shadow_page_lockless_begin(vcpu);
@@ -3140,6 +3145,14 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
break;
}
+ /*
+ * KVM doesn't support fixing SPTEs outside of mmu_lock for
+ * indirect MMUs as the gfn isn't stable for indirect shadow
+ * pages. See Documentation/virt/kvm/locking.rst for details.
+ */
+ if (!direct_mmu)
+ break;
+
new_spte = spte;
/*
@@ -3185,11 +3198,6 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
!is_access_allowed(fault, new_spte))
break;
- /*
- * Currently, fast page fault only works for direct mapping
- * since the gfn is not stable for indirect shadow page. See
- * Documentation/virt/kvm/locking.rst to get more detail.
- */
if (fast_pf_fix_direct_spte(vcpu, fault, sptep, spte, new_spte)) {
ret = RET_PF_FIXED;
break;
@@ -4018,7 +4026,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
if (page_fault_handle_page_track(vcpu, fault))
return RET_PF_EMULATE;
- r = fast_page_fault(vcpu, fault);
+ r = fast_page_fault(vcpu, fault, true);
if (r != RET_PF_INVALID)
return r;
diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
index db80f7ccaa4e..d33b01a2714e 100644
--- a/arch/x86/kvm/mmu/paging_tmpl.h
+++ b/arch/x86/kvm/mmu/paging_tmpl.h
@@ -812,6 +812,14 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
return RET_PF_RETRY;
}
+ /* See if the fault has already been resolved by a different vCPU. */
+ r = fast_page_fault(vcpu, fault, false);
+ if (r == RET_PF_SPURIOUS)
+ return r;
+
+ /* Indirect page faults should never be fixed in the fast path. */
+ WARN_ON_ONCE(r != RET_PF_INVALID);
+
fault->gfn = walker.gfn;
fault->slot = kvm_vcpu_gfn_to_memslot(vcpu, fault->gfn);
--
2.36.0.rc2.479.g8af0fa9b8e-goog
next prev parent reply other threads:[~2022-04-23 3:50 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-23 3:47 [PATCH 00/12] KVM: x86/mmu: Bug fixes and cleanups Sean Christopherson
2022-04-23 3:47 ` [PATCH 01/12] KVM: x86/mmu: Don't treat fully writable SPTEs as volatile (modulo A/D) Sean Christopherson
2022-04-23 3:47 ` [PATCH 02/12] KVM: x86/mmu: Move shadow-present check out of spte_has_volatile_bits() Sean Christopherson
2022-04-23 3:47 ` [PATCH 03/12] KVM: x86/mmu: Use atomic XCHG to write TDP MMU SPTEs with volatile bits Sean Christopherson
2022-04-23 3:47 ` [PATCH 04/12] KVM: x86/mmu: Don't attempt fast page fault just because EPT is in use Sean Christopherson
2022-04-23 3:47 ` [PATCH 05/12] KVM: x86/mmu: Drop exec/NX check from "page fault can be fast" Sean Christopherson
2022-04-23 3:47 ` [PATCH 06/12] KVM: x86/mmu: Add RET_PF_CONTINUE to eliminate bool+int* "returns" Sean Christopherson
2022-04-23 3:47 ` [PATCH 07/12] KVM: x86/mmu: Make all page fault handlers internal to the MMU Sean Christopherson
2022-04-23 3:47 ` [PATCH 08/12] KVM: x86/mmu: Use IS_ENABLED() to avoid RETPOLINE for TDP page faults Sean Christopherson
2022-04-23 3:47 ` [PATCH 09/12] KVM: x86/mmu: Expand and clean up page fault stats Sean Christopherson
2022-04-23 3:47 ` [PATCH 10/12] DO NOT MERGE: KVM: x86/mmu: Always send !PRESENT faults down the fast path Sean Christopherson
2022-04-23 3:47 ` Sean Christopherson [this message]
2022-04-23 3:47 ` [PATCH 12/12] DO NOT MERGE: KVM: selftests: Attempt to detect lost dirty bits Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220423034752.1161007-12-seanjc@google.com \
--to=seanjc@google.com \
--cc=bgardon@google.com \
--cc=chao.p.peng@linux.intel.com \
--cc=dmatlack@google.com \
--cc=jmattson@google.com \
--cc=joro@8bytes.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=venkateshs@google.com \
--cc=vkuznets@redhat.com \
--cc=wanpengli@tencent.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®