From: Mostafa Saleh <smostafa@google.com>
To: linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev,
linux-arm-kernel@lists.infradead.org
Cc: maz@kernel.org, oupton@kernel.org, seiden@linux.ibm.com,
joey.gouly@arm.com, suzuki.poulose@arm.com,
yuzenghui@huawei.com, catalin.marinas@arm.com, will@kernel.org,
vdonnefort@google.com, tabba@google.com,
Mostafa Saleh <smostafa@google.com>
Subject: [RFC PATCH 1/2] KVM: arm64: Add stage2_clean_old_pte()
Date: Fri, 17 Jul 2026 13:08:59 +0000 [thread overview]
Message-ID: <20260717130901.2239134-2-smostafa@google.com> (raw)
In-Reply-To: <20260717130901.2239134-1-smostafa@google.com>
At the moment, the pgtable code rely on BBM in SW which looks like:
Break: stage2_try_break_pte()
1) Break PTE and lock it
2) TLBI
3) Put the ref on the old PTE
Make: stage2_make_pte()
1) Get a ref on the new PTE
2) Install the live PTE
With BBML3, the sequence will look as
1) Get ref on the new PTE
2) Install new PTE
3) TLBI
4) Put the ref on the old PTE
Which requires moving step #2 #3 from the break function to the make
function, although it is possible to do that for SW BBM also, that
means the stage2_try_break_pte() did not fully break the PTE as it
is referenced in TLBs, although that works it seems fragile.
Instead, move this logic to a new function stage2_clean_old_pte()
that can be called from BBML3.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
arch/arm64/kvm/hyp/pgtable.c | 67 ++++++++++++++++++++----------------
1 file changed, 37 insertions(+), 30 deletions(-)
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index 91a7dfad6686..127b7f9541b1 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -810,39 +810,10 @@ static bool stage2_try_set_pte(const struct kvm_pgtable_visit_ctx *ctx, kvm_pte_
return cmpxchg(ctx->ptep, ctx->old, new) == ctx->old;
}
-/**
- * stage2_try_break_pte() - Invalidates a pte according to the
- * 'break-before-make' requirements of the
- * architecture.
- *
- * @ctx: context of the visited pte.
- * @mmu: stage-2 mmu
- *
- * Returns: true if the pte was successfully broken.
- *
- * If the removed pte was valid, performs the necessary serialization and TLB
- * invalidation for the old value. For counted ptes, drops the reference count
- * on the containing table page.
- */
-static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx,
+static void stage2_clean_old_pte(const struct kvm_pgtable_visit_ctx *ctx,
struct kvm_s2_mmu *mmu)
{
struct kvm_pgtable_mm_ops *mm_ops = ctx->mm_ops;
- kvm_pte_t locked_pte;
-
- if (stage2_pte_is_locked(ctx->old)) {
- /*
- * Should never occur if this walker has exclusive access to the
- * page tables.
- */
- WARN_ON(!kvm_pgtable_walk_shared(ctx));
- return false;
- }
-
- locked_pte = FIELD_PREP(KVM_INVALID_PTE_TYPE_MASK,
- KVM_INVALID_PTE_TYPE_LOCKED);
- if (!stage2_try_set_pte(ctx, locked_pte))
- return false;
if (!kvm_pgtable_walk_skip_bbm_tlbi(ctx)) {
/*
@@ -862,6 +833,42 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx,
if (stage2_pte_is_counted(ctx->old))
mm_ops->put_page(ctx->ptep);
+}
+
+/**
+ * stage2_try_break_pte() - Invalidates a pte according to the
+ * 'break-before-make' requirements of the
+ * architecture.
+ *
+ * @ctx: context of the visited pte.
+ * @mmu: stage-2 mmu
+ *
+ * Returns: true if the pte was successfully broken.
+ *
+ * If the removed pte was valid, performs the necessary serialization and TLB
+ * invalidation for the old value. For counted ptes, drops the reference count
+ * on the containing table page.
+ */
+static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx,
+ struct kvm_s2_mmu *mmu)
+{
+ kvm_pte_t locked_pte;
+
+ if (stage2_pte_is_locked(ctx->old)) {
+ /*
+ * Should never occur if this walker has exclusive access to the
+ * page tables.
+ */
+ WARN_ON(!kvm_pgtable_walk_shared(ctx));
+ return false;
+ }
+
+ locked_pte = FIELD_PREP(KVM_INVALID_PTE_TYPE_MASK,
+ KVM_INVALID_PTE_TYPE_LOCKED);
+ if (!stage2_try_set_pte(ctx, locked_pte))
+ return false;
+
+ stage2_clean_old_pte(ctx, mmu);
return true;
}
--
2.55.0.229.g6434b31f56-goog
next prev parent reply other threads:[~2026-07-17 13:09 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-17 13:08 [RFC PATCH 0/2] KVM: arm64: Support BBM level 3 Mostafa Saleh
2026-07-17 13:08 ` Mostafa Saleh [this message]
2026-07-17 13:09 ` [RFC PATCH 2/2] " Mostafa Saleh
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=20260717130901.2239134-2-smostafa@google.com \
--to=smostafa@google.com \
--cc=catalin.marinas@arm.com \
--cc=joey.gouly@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=seiden@linux.ibm.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=vdonnefort@google.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.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