From: Mostafa Saleh <smostafa@google.com>
To: Vincent Donnefort <vdonnefort@google.com>
Cc: linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, 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, tabba@google.com,
sebastianene@google.com, keirf@google.com, qperret@google.com,
linu.cherian@arm.com
Subject: Re: [PATCH v3 2/2] KVM: arm64: Support BBM level 3
Date: Tue, 6 Oct 2026 10:47:04 +0000 [thread overview]
Message-ID: <asTRqPfsrnbBWVSF@google.com> (raw)
In-Reply-To: <asO77kvqqwCsJt8I@google.com>
On Mon, Oct 05, 2026 at 04:02:06PM +0100, Vincent Donnefort wrote:
> On Fri, Sep 04, 2026 at 01:28:55PM +0000, Mostafa Saleh wrote:
> > If the system supports hardware Break-Before-Make (BBM) level 3, use it
> > to replace stage-2 PTEs directly. Otherwise, fall back to the software
> > BBM sequence.
> >
> > For BBML3 the sequence is:
> > 1) Get a reference count on the containing table for the new PTE.
> > 2) Atomically update the PTE with the new valid descriptor.
> > 3) Invalidate the TLB for the old PTE.
> > 4) Drop the reference count holding the old PTE.
> >
> > Add 2 helpers:
> > 1) kvm_pgtable_use_bbml3(): Checks for the architecture requirement
> > for BBML3.
> >
> > 2) stage2_use_bbml3(): Extra checks added by SW design (FWB and DIC)
> > - As BBML3 will update the PTE atomically, it can only know it
> > raced with another core at the point of the cmpxchg failing,
> > unlike the SW implementation which locks the PTE first.
> > And as we must issue CMOs to the new mapped page before the
> > update, that means with BBML3 racing cores will issue redundant
> > CMOs.
> >
> > Signed-off-by: Mostafa Saleh <smostafa@google.com>
> > ---
> > arch/arm64/kvm/hyp/pgtable.c | 111 ++++++++++++++++++++++++++++-------
> > 1 file changed, 90 insertions(+), 21 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
> > index d670da8882a5..a9ba761e9a01 100644
> > --- a/arch/arm64/kvm/hyp/pgtable.c
> > +++ b/arch/arm64/kvm/hyp/pgtable.c
> > @@ -82,6 +82,27 @@ static bool kvm_pte_table(kvm_pte_t pte, s8 level)
> > return FIELD_GET(KVM_PTE_TYPE, pte) == KVM_PTE_TYPE_TABLE;
> > }
> >
> > +/*
> > + * Check if BBML3 can be used for this PTE update.
> > + * Fallback to software break-before-make for leaf-to-leaf changes.
> > + */
> > +static bool kvm_pgtable_use_bbml3(const struct kvm_pgtable_visit_ctx *ctx,
> > + kvm_pte_t new)
> > +{
> > + if (!system_supports_bbml3())
> > + return false;
> > +
> > + if (!kvm_pte_valid(ctx->old) || !kvm_pte_valid(new))
> > + return false;
> > +
> > + /* Block <-> Table is ok. */
> > + if (kvm_pte_table(new, ctx->level) ||
> > + kvm_pte_table(ctx->old, ctx->level))
> > + return true;
> > +
> > + return false;
> > +}
> > +
> > static kvm_pte_t *kvm_pte_follow(kvm_pte_t pte, struct kvm_pgtable_mm_ops *mm_ops)
> > {
> > return mm_ops->phys_to_virt(kvm_pte_to_phys(pte));
> > @@ -835,25 +856,46 @@ static void stage2_clean_old_pte(const struct kvm_pgtable_visit_ctx *ctx,
> > mm_ops->put_page(ctx->ptep);
> > }
> >
> > +/*
> > + * Don't use bbml3 for stage-2 if FWB or DIC are not supported
> > + * as that means racing cores will issue duplicate CMOs.
> > + */
> > +static bool stage2_use_bbml3(const struct kvm_pgtable_visit_ctx *ctx,
> > + kvm_pte_t new)
> > +{
> > + if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB) ||
> > + !cpus_have_final_cap(ARM64_HAS_CACHE_DIC))
> > + return false;
> > +
> > + return kvm_pgtable_use_bbml3(ctx, new);
> > +}
> > +
> > /**
> > * stage2_try_break_pte() - Invalidates a pte according to the
> > * 'break-before-make' requirements of the
> > - * architecture.
> > + * architecture, if BBML3 is supported it
> > + * will be used and this function won't
> > + * break the PTE.
> > *
> > * @ctx: context of the visited pte.
> > * @mmu: stage-2 mmu
> > + * @new: New pte installed in make.
> > *
> > - * Returns: true if the pte was successfully broken.
> > + * Returns: true if the pte was successfully broken or BBML3 is used.
> > *
> > * 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)
> > + struct kvm_s2_mmu *mmu, kvm_pte_t new)
> > {
> > kvm_pte_t locked_pte;
> >
> > + /* All handled in stage2_make_pte() */
> > + if (stage2_use_bbml3(ctx, new))
> > + return true;
> > +
>
> Wouldn't it be easier to keep try_break_pte/make_pte to the !bbml3 case and to
> just create a make_pte_bbml3() variant to be called when stage2_use_bbml3()?
>
> if (!stage2_use_bbml3()) {
> if (stage2_try_break_pte())
> return -EAGAIN;
> stage2_make_pte();
> } else {
> if (stage2_make_pte_bbml3())
> return -EAGAIN;
> }
>
> I believe also, the error path would look less weird as we catch an error in
> make_pte() but without reverting the break_pte() (even if it is correct right
> now).
>
> And perhaps you could introduce a function that does both break/make
> (stage2_update_pte()?) called by both stage2_split_walker() and
> stage2_map_walk_leaf(). This would avoid repeating the error path.
I though about that and was not sure about it at the beginning as
mentioned in the cover letter:
Initially, I encapsulated the full logic of BBM in one function,
which was not readable, due to different ordering and dealing with
CMO, TLBI.
I think that can be better if we call the new helper for all sites
except for stage2_map_walker_try_leaf(). Although we would need to
open code the bbml3 check there now. I can try and see how it looks.
Thanks,
Mostafa
>
> Otherwise, everything looks functional to me.
>
> --
> Vincent
>
prev parent reply other threads:[~2026-10-06 10:47 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-04 13:28 [PATCH v3 0/2] KVM: arm64: Add support for BBM level 3 Mostafa Saleh
2026-09-04 13:28 ` [PATCH v3 1/2] KVM: arm64: Add stage2_clean_old_pte() Mostafa Saleh
2026-09-04 13:28 ` [PATCH v3 2/2] KVM: arm64: Support BBM level 3 Mostafa Saleh
2026-10-05 15:02 ` Vincent Donnefort
2026-10-06 10:47 ` Mostafa Saleh [this message]
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=asTRqPfsrnbBWVSF@google.com \
--to=smostafa@google.com \
--cc=catalin.marinas@arm.com \
--cc=joey.gouly@arm.com \
--cc=keirf@google.com \
--cc=kvmarm@lists.linux.dev \
--cc=linu.cherian@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=qperret@google.com \
--cc=sebastianene@google.com \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.