[PATCH 1/4] KVM: arm64: pgtable: Add Stage-2 unmap without TLBI primitive

Mark Rutland mark.rutland at arm.com
Mon Sep 14 02:23:49 PDT 2026


On Mon, Sep 14, 2026 at 09:48:03AM +0100, Mark Rutland wrote:
> On Sat, Sep 12, 2026 at 11:48:31AM +0100, Marc Zyngier wrote:
> > kvm_pgtable_stage2_unmap() iterates over a range, unmapping whatever is
> > within the range, and always guarantees that that the corresponding TLBs
> > are invalidated when the function returns.
> > 
> > While this is safe, it means that iterating over empty range on a system
> > that supports range invalidation results in a TLBI per largest block
> > mapping size (1GB, 32MB or 512MB, depending on the base granule size).
> > 
> > This can be pretty expensive in situation where the whole address space
> > is being torn down, as it happens with NV (where S2 MMUs are recycled
> > regularly), and it would be more efficient to elide the per-subrange
> > TLBIs to solely rely on a VMID-wide TLBI.
> > 
> > For this, provide a kvm_pgtable_stage2_unmap_notlbi() helper that elides
> > all TLBIs, and relies on the caller to do the work.
> > 
> > Note that for  pKVM case, no additional helper is provided, and we
> > fallback on the TLBI-aware version.
> 
> Just to check: I assume that before this is called, we have somehow
> ensured that the S2 being torn down isn't live on any PE, and cannot
> become live on any PE? I asssume that's a natural part of S2 lifetime
> management, but I couldn't figure that out from a quick skim of the hyp
> pgtable code.
>
> Assuming so, it might be worth mentioning that in the commit message,
> since it explains why it's safe to invalidate *after* intermediate
> tables are freed by stage2_unmap_walker() calling mm_ops->put_page(). We
> might also be able to add some test/assertion in
> kvm_pgtable_stage2_unmap_notlbi() to ensure it is not called where the
> tables could be live on a PE.

I see Shuai Xue said something in this area, but just to elaborate:

If it's possible that some PE is performing a translation table walk of
the tables being freed, and if a page for an intermediate table gets
freed and reallocated/reused before the TLBI is executed, then HW might
read a garbage value when trying to read a decriptor from that page.
That could lead to a variety of problems (e.g. permit a guest to access
an arbitrary PA, or cause a HW walk to access an arbitrary PA).

Above I had assumed that the S2 table being unmapped+freed weren't live
(e.g. not programmed into any PE's VTTBR) at the time we performed this
invalidation, and hence kvm_pgtable_stage2_unmap_notlbi() could check
some refcount or something to verify that.

If that is the case, all's good, and you can ignore the rest of this
mail. If that is not the case, read on.

If the tables are potentially live on some PE, then it is not safe to
defer the TLB invalidation. However, we can still reduce the TLBIs with
a slightly more elaborate sequence:

(1) Make a temporary copy of the root table (whatever VTTBR points to)
    for the S2 being invalidated.

(2) Clear the entries from the root table (leaving any child
    intermediate/leaf tables as-is).

(3) Perform TLB invalidation for the entire VMID. This will ensure HW
    can't walk to any of the child tables.

(4) Walk the temporary copy of the root table to free the child tables,
    without any TLB invalidation.

(5) Free the temporary copy of the root table.

Mark.



More information about the linux-arm-kernel mailing list