Re: [PATCH v2 4/8] KVM: arm64: Correctly handle end of VA space TLBI invalidation

Marc Zyngier <[email protected]>
Newsgroups org.kernel.vger.kvm,dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
On Sat, 08 Aug 2026 22:41:31 +0100,
Wei-Lin Chang <[email protected]> wrote:
> 
> Hi Marc,
> 
> On Thu, Aug 06, 2026 at 10:10:22AM +0100, Marc Zyngier wrote:
> > Our TLB invalidation by VA code is based on comparing two ranges,
> > one defined by the TLB, and one defined by the TLBI instruction.
> > 
> > Each range is defined by a start and a size. However, the way the
> > comparison is done doesn't account for address rollover, as it
> > compares an address with (base + size). This works nicely until
> > this expression represent the last page/block in the TTBR1 VA space,
> > as the result is a big fat 0. And a failed TLB invalidation.
> > 
> > Rewrite the comparison in a way that is immune to the address
> > rollover (making the end address inclusive instead of exclusive),
> > and move this into a common helper that is used by both VA and IPA
> > invalidations, as suggested by Hyunwoo Kim (although the IPA version
> > didn't suffer from this particular problem, obviously).
> > 
> > Fixes: 4ffa72ad8f37e ("KVM: arm64: nv: Add S1 TLB invalidation primitive for VNCR_EL2")
> > Reviewed-by: Yuan Yao <[email protected]>
> > Signed-off-by: Marc Zyngier <[email protected]>
> > Cc: [email protected]
> > ---
> >  arch/arm64/kvm/nested.c | 43 ++++++++++++++++++-----------------------
> >  1 file changed, 19 insertions(+), 24 deletions(-)
> > 
> > diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> > index 27bc7ee4b3382..8a602d074dbb4 100644
> > --- a/arch/arm64/kvm/nested.c
> > +++ b/arch/arm64/kvm/nested.c
> > @@ -999,6 +999,20 @@ static void invalidate_vncr(struct vncr_tlb *vt)
> >  		clear_fixmap(vncr_fixmap(vt->cpu));
> >  }
> >  
> > +static bool vncr_tlb_intersects(struct vncr_tlb *vt, u64 addr,
> > +				u64 scope_start, u64 scope_size)
> > +{
> > +	u64 tlb_size, tlb_start, tlb_end, scope_end;
> > +
> > +	tlb_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift, vt->wr.level));
> > +
> > +	tlb_start = addr & ~(tlb_size - 1);
> > +	tlb_end = tlb_start + tlb_size - 1;
> > +	scope_end = scope_start + scope_size - 1;
> 
> I think if scope_end overflows,
> 
> > +
> > +	return !(tlb_end < scope_start || tlb_start > scope_end);
> 
> tlb_start > scope_end can evaluate to true and we return false even when
> there is overlap near the end of the TTBR1 address space.

I assume that you are implicitly talking about TLB Range Invalidation,
right? Because we otherwise align base on size, making overflows
impossible with this patch.

> Therefore I think we need to saturate scope_end to ULONG_MAX when overflow
> happens. This is also what the architecture does when looking at the
> pseudocode J1.2.3.442 TLBIRange (M.c).

That's one possible implementation, because the pseudocode is dealing
with start/end directly, but that's not how our scope works (it deals
with start and size).

For that we need to cap the *size*, similarly to what is done in
handle_ripas2e1is() (see patch #6). Something like the hack below.

	M.

diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/kvm_nested.h
index 21d0f4cbe07f1..5b8edb2e8a87d 100644
--- a/arch/arm64/include/asm/kvm_nested.h
+++ b/arch/arm64/include/asm/kvm_nested.h
@@ -305,6 +305,12 @@ static inline u64 decode_range_tlbi(u64 val, u64 *range, u16 *asid)
 	num	= FIELD_GET(GENMASK(43, 39), val);
 	*range	= __TLBI_RANGE_PAGES(num, scale) << shift;
 
+	/* Cap the range to the correct half of the address space */
+	if (!(base & BIT(48)))
+		*range = min(*range, (BIT(48) - base));
+	else
+		*range = min(*range, ~base + 1);
+
 	return base;
 }
 

-- 
Without deviation from the norm, progress is not possible.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.