[PATCH v7 2/7] arm64/vmalloc: Allow arch_vmap_pte_range_map_size to batch multiple CONT_PTE
Barry Song
baohua at kernel.org
Tue Jul 28 20:57:45 PDT 2026
On Wed, Jul 29, 2026 at 11:45 AM Barry Song <baohua at kernel.org> wrote:
>
> On Wed, Jul 22, 2026 at 2:17 AM David Carlier <devnexen at gmail.com> wrote:
> >
> > Barry, Wen - the returned span is capped at PMD_SIZE >> 1 but only
> > checked for CONT_PTE_SIZE alignment. In the batched vmap() path pages
> > are only contiguous within a naturally aligned block, so when a PMD
> > boundary splits a batch the next region starts mid block and the span
> > runs past the contiguous run - set_huge_pte_at() maps the wrong pages,
> > tail of the array left unmapped, no warning.
> >
> > What do you think of clamping the span to the pfn physical alignment,
> > like 8xx does:
> >
> > while (!IS_ALIGNED(PFN_PHYS(pfn), size))
> > size >>= 1;
>
> Thanks, David.
>
> I noticed that 8xx has simplified this to a simple
>
> if (!IS_ALIGNED(PFN_PHYS(pfn), size))
>
> Could we do the same here?
>
> diff --git a/arch/arm64/include/asm/vmalloc.h b/arch/arm64/include/asm/vmalloc.h
> index d665f9d68742..a27101e24f76 100644
> --- a/arch/arm64/include/asm/vmalloc.h
> +++ b/arch/arm64/include/asm/vmalloc.h
> @@ -46,6 +46,8 @@ static inline unsigned long
> arch_vmap_pte_range_map_size(unsigned long addr,
>
> size = min3(end - addr, 1UL << max_page_shift, PMD_SIZE >> 1);
> size = rounddown_pow_of_two(size);
> + if (!IS_ALIGNED(PFN_PHYS(pfn), size) || size < CONT_PTE_SIZE)
> + return PAGE_SIZE;
> return size;
> }
On second thought, the caller is walking the PUD, PMD, and PTE
page tables, so it won't pass anything that crosses a PMD
boundary here.
otherwise, the caller has been wrong. for example:
static int vmap_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
phys_addr_t phys_addr, pgprot_t prot,
unsigned int max_page_shift, pgtbl_mod_mask *mask)
{
pmd_t *pmd;
unsigned long next;
int err = 0;
...
do {
next = pmd_addr_end(addr, end);
if (vmap_try_huge_pmd(pmd, addr, next, phys_addr, prot,
max_page_shift)) {
*mask |= PGTBL_PMD_MODIFIED;
continue;
}
err = vmap_pte_range(pmd, addr, next, phys_addr, prot,
max_page_shift, mask);
if (err)
break;
} while (pmd++, phys_addr += (next - addr), addr = next, addr != end);
return err;
}
I guess we don't need to do anything here, David?
Barry
More information about the linux-arm-kernel
mailing list