Re: [PATCH v4] iommu/io-pgtable-arm: Add support for contiguous hint bit
From: Daniel Mentz
Date: Sun Aug 30 2026 - 15:43:45 EST
On Wed, Aug 26, 2026 at 10:55 PM Vijayanand Jitta
<vijayanand.jitta@xxxxxxxxxxxxxxxx> wrote:
> Instead I'll add something like below to arm_lpae_restrict_pgsizes as suggested.
On a related note, I'm debating whether we should change the word
"restrict" to something like "update" or "fixup", since we are no
longer purely restricting page sizes, we are adding new page sizes.
> >>>> +/*
> >>>> + * Install num_entries leaf entries starting at ptep (index map_idx_start
> >>>> + * within the current table), tagging arm_lpae_num_cont()-sized groups with
> >>>> + * the contiguous hint where both idx and paddr are aligned to the group
> >>>> + * size. Entries in a misaligned group are installed without the hint.
> >>>> + *
> >>>> + * idx and paddr both advance by block_size per entry, so their alignment
> >>>> + * relative to the group size is invariant across a run of entries within
> >>>> + * this call: once a group qualifies (or fails to), every later whole group
> >>>> + * does too, up to num_entries. This merges each such run into a single
> >>>> + * arm_lpae_init_pte() call instead of one call per group.
> >>>> + */
> >>>
> >>> Can you provide an example for when this function installs descriptors
> >>> where the contiguous bit is only set on a subset of them. I would
> >>> assume that the contiguous bit is either set for all descriptors or
> >>> none of them.
> >>>
> >>
> >> That assumption doesn't hold in general -- it's only true when the
> >> map request happens to start and end on a cont_size boundary. For an
> >> arbitrary map_pages() call it usually doesn't.
> >
> > I believe you won't see arbitrary map_pages() calls. I understand that
> > these calls are exclusively coming from __iommu_map_domain_pgtbl()
> > which uses iommu_pgsize() to determine optimal page sizes.
> >
> >> Example, 4K granule (num_cont = 16, cont_size = 64K),
> >> iova = paddr = 0x1000, pgcount = 34:
> >>
> >> - idx 1..15 (off != 0, misaligned prefix): installed plain
> >> - idx 16..31 (off == 0, paddr now 64K-aligned): installed w/ CONT
> >> - idx 32..34 (off == 0, remaining < num_cont): installed plain
> >
> > In the example you provided, I expect that you'll receive three
> > separate calls from __iommu_map_domain_pgtbl:
> > * idx 1..15 with pgsize 4KB
> > * one call with pgsize 64KB
> > * idx 32..34 with pgsize 4KB
> >
> > If I took your argument further, I could argue that we'd also have to
> > check if we can put down a block mapping if iova = paddr = 0x0 and
> > pgcount = 512, but we're not doing that either.
> >
> > Could you provide the input parameters to the iommu_map() call that
> > resulted in the parameters you provided i.e. iova = paddr = 0x1000,
> > pgcount = 34:
> >
>
> You're right -- for the iommu_map()/__iommu_map_domain_pgtbl() path, iommu_pgsize()
> already splits the request at the boundaries you describe before install_leaf() ever
> sees it, so install_leaf() doesn't need to handle a mixed prefix/CONT-group/suffix
> chunk for that caller.
>
> That said, install_leaf() is shared by other callers that reach it through
> ops->map_pages() directly, without going through iommu_pgsize(). panthor_vm_map_pages()
> (drivers/gpu/drm/panthor/panthor_mmu.c) is one -- it allocates its io_pgtable_ops via
> alloc_io_pgtable_ops(ARM_64_LPAE_S1, ...), same as any other LPAE consumer, but does its
> own chunking with a local get_pgsize() that only ever returns SZ_4K or SZ_2M, with no
> notion of the 64K/32M CONT boundaries. That can hand install_leaf() exactly the mixed
> iova=paddr=0x1000, pgcount=34 shape in a single call (panfrost's map loop uses the same
> get_pgsize() and hits the same case). So the prefix/aligned-group/suffix handling in
> install_leaf() is still needed for that path.
Maybe other people can chime in here, but I feel, from an API
perspective, we should have only one way to make of use iopgtable. I
think we should just mandate that users honor the updated value for
pgtbl_cfg.pgsize_bitmap (and pgtbl_cfg.ias) after the
alloc_io_pgtable_ops() call and then choose page sizes appropriately.
Otherwise, we end up with two pieces of code in the kernel solving the
same problem. panthor_mmu won't be able to take advantage of the
contiguous bit until it gets updated accordingly, and that's ok.