Re: [PATCH 2/6] KVM: arm64: Handle negative S1 walk levels in VNCR TLB size evaluation

Marc Zyngier <[email protected]> Sat, 01 Aug 2026 14:20:29 +0100
Newsgroups dev.linux.lists.sashiko-reviews,dev.linux.lists.kvmarm,org.kernel.vger.kvm
Message-ID <[email protected]>
On Sat, 01 Aug 2026 14:02:35 +0100,
[email protected] wrote:
> 
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> 
> Pre-existing issues:
> - [High] Stage-1 huge block mappings (e.g., 4TB, 64GB) are incorrectly truncated to 1GB due to a 32-bit return type and a hardcoded fallback, leading to under-invalidation of the VNCR software cache.
> --
> 
> --- Patch [2]: [PATCH 2/6] KVM: arm64: Handle negative S1 walk levels in VNCR TLB size evaluation ---
> commit 55a3817e6985fb11462e68c9b396c2d3ee056461
> Author: Marc Zyngier <[email protected]>
> 
> KVM: arm64: Handle negative S1 walk levels in VNCR TLB size evaluation
> 
> This patch fixes a bug where negative Stage-1 mapping levels (used to indicate
> S1_MMU_DISABLED) were mishandled by pgshift_level_to_ttl(), leading to an
> invalidation size of 0. It introduces __ttl_to_size() and ensures ttl_to_size()
> always falls back to SZ_1G when no valid TTL size is found.
> 
> Link: https://lore.kernel.org/r/ameGoxbn2wzBq2kL@v4bel
> 
> > diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> > index 983ba0adaf4e6..b026d160f253d 100644
> > --- a/arch/arm64/kvm/nested.c
> > +++ b/arch/arm64/kvm/nested.c
> 
> [ ... ]
> 
> > @@ -506,7 +506,7 @@ int kvm_walk_nested_s2(struct kvm_vcpu *vcpu, phys_addr_t gipa,
> >  	return ret;
> >  }
> >  
> > -static unsigned int ttl_to_size(u8 ttl)
> > +static unsigned int __ttl_to_size(u8 ttl)
> 
> [Severity: High]
> This is a pre-existing issue, but does this unsigned int return type cause
> huge block mapping sizes to be incorrectly truncated?
> 
> Since __ttl_to_size() and ttl_to_size() return a 32-bit unsigned int, they
> cannot represent sizes 4GB or larger (like 4TB for 64K granule Level 1, or
> 64GB for 16K granule Level 1).

Which is adequate since we don't support these sizes.

> 
> > @@ -562,10 +562,22 @@ static unsigned int ttl_to_size(u8 ttl)
> >  	return max_size;
> >  }
> >  
> > -static u8 pgshift_level_to_ttl(u16 shift, u8 level)
> > +static unsigned int ttl_to_size(u8 ttl)
> > +{
> > +	return __ttl_to_size(ttl) ?: SZ_1G;
> > +}
> 
> If a nested L1 guest maps its VNCR page in such a huge block using 52-bit
> VAs and later issues a TLBI with a VA far from the VNCR page VA, KVM will
> calculate a severely undersized invalidation window. Because the true size
> overflows unsigned int (or evaluates to 0), the fallback restricts it to 1GB.
> 
> This could leave KVM using a stale IPA, potentially corrupting nested guest
> state by writing into unmapped or reassigned guest physical memory.
> 
> Should these size calculation functions be returning an unsigned long or u64
> instead?

No, we don't support LVA/LVA2 for nested guests.

	M.

-- 
Jazz isn't dead. It just smells funny.