[PATCH v8 8/9] iommu/arm-smmu-v3: Change how the tlbi describes the invalidation

Jason Gunthorpe jgg at nvidia.com
Sun Oct 4 10:00:12 PDT 2026


On Sun, Oct 04, 2026 at 02:43:33PM +0100, Will Deacon wrote:
> > +	/*
> > +	 * Assumes the page table is formed properly and does not trigger the
> > +	 * 16k TTL=1 condition for leaf-only unless DS is enabled.
> > +	 *
> > +	 * ARM level -1 never has a leaf so something has gone wrong. ARM Level
> > +	 * 0 cannot be hinted because ttl=0 means no-hint.
> > +	 */
> 
> nit: This isn't strictly true for the non-range invalidation operations, so
> I think it would be handy to have a big note saying that this function only
> works for range invalidation or even stick "range" in the function name
> somewhere.

I figured "ttl" was enough since ttl is only used as part of the range
invalidation command. I can change it to range ttl
 
> > @@ -2917,12 +2998,17 @@ static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size,
> >  				  size_t granule, void *cookie)
> >  {
> >  	struct arm_smmu_domain *smmu_domain = cookie;
> > +	u8 tgsz_lg2 = smmu_domain->tgsz_lg2;
> >  	struct arm_smmu_tlbi tlbi = {
> >  		.tgsz_lg2 = smmu_domain->tgsz_lg2,
> > -		.iova = iova,
> > -		.size = size,
> > -		.iopte_size = 1 << smmu_domain->tgsz_lg2,
> > +		.start = iova,
> > +		.last = iova + size - 1,
> >  	};
> > +	u8 table_levels =
> > +		BIT(arm_smmu_pt_lg2sz_to_level(tgsz_lg2, ilog2(size)));
> > +
> > +	tlbi.table_levels_bitmap = table_levels;
> > +	tlbi.leaf_levels_bitmap = table_levels - 1;
> 
> I'm having a tough time understanding this part. Specifically, I'm trying
> to work out what happens if we end up doing a non-leaf invalidation at the
> PGD (1GiB) level with leaves at the PTE (4KiB) level. In that case, don't
> we need to have table_levels describing both PGD and PMD levels so that
> the TTL describes the 4k leaf entries?

The comment you clipped off tried to explain it:

/*
 * Called by io-pgtable-arm.c for each single table level it wants to remove.
 * size is the size of the table level and granule is the tg in bytes. This must
 * clear the walk cache and any leaves within the range.
 */

But, I had AI double check this statement "each single table level"
and it agrees with you and gave the same example. It does look like I
understood it wrong, I thought the segmantion logic in the core code
would save things but it doesn't work quite like that.

This still works right as-is because the leaf_levels_bitmap disables TTL
and forces single to step at 4k, so it isn't a functional bug, but the
comment is wrong and the logic should be more like:

tlbi.table_levels_bitmap = (table_levels | (table_levels - 1)) & ~BIT(0);

Jason



More information about the linux-arm-kernel mailing list