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

Wei-Lin Chang weilin.chang at arm.com
Sun Aug 9 14:10:08 PDT 2026


On Sun, Aug 09, 2026 at 07:13:45PM +0100, Marc Zyngier wrote:
> On Sat, 08 Aug 2026 22:41:31 +0100,
> Wei-Lin Chang <weilin.chang at arm.com> 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 <yaoyuan at linux.alibaba.com>
> > > Signed-off-by: Marc Zyngier <maz at kernel.org>
> > > Cc: stable at vger.kernel.org
> > > ---
> > >  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.

Yes, I am talking about TLB range invalidations.

> 
> > 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.

Makes sense.

> 
> 	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;
>  }

This looks correct to me!

Thanks,
Wei-Lin Chang

>  
> 
> -- 
> Without deviation from the norm, progress is not possible.



More information about the linux-arm-kernel mailing list