[PATCH v10 03/10] mm/vmalloc: use pte_set_huge()/pte_clear_huge() for PTE-level block mappings

Wen Jiang jiangwenxiaomi at gmail.com
Mon Oct 12 00:34:02 PDT 2026


On Sun, 11 Oct 2026 at 22:29, Uladzislau Rezki <urezki at gmail.com> wrote:
>
> On Fri, Oct 02, 2026 at 05:09:40PM +0800, Wen Jiang wrote:
> > vmap installs PTE-level block mappings by reusing set_huge_pte_at() and
> > huge_ptep_get_and_clear() under #ifdef CONFIG_HUGETLB_PAGE. This makes
> > the feature silently unavailable on CONFIG_HUGETLB_PAGE=n kernels and
> > couples mm/vmalloc.c to HugeTLB internals it does not otherwise need.
> >
> > Now that arm64 and powerpc/8xx provide pte_set_huge() and
> > pte_clear_huge(), add the generic fallbacks next to the existing
> > pmd/pud_set_huge() family and convert vmap_pte_range() and
> > vunmap_pte_range() to the new helpers. The CONFIG_HUGETLB_PAGE guards
> > around the block-mapping paths are dropped, so PTE-level block mappings
> > now also work on CONFIG_HUGETLB_PAGE=n kernels, and mm/vmalloc.c no
> > longer includes <linux/hugetlb.h>.
> >
> > The fallbacks exist only to keep the build working on architectures
> > without PTE-level block mapping support. They are unreachable there:
> > the callers only run when arch_vmap_pte_range_map_size() or
> > arch_vmap_pte_range_unmap_size() return a size other than PAGE_SIZE,
> > which requires an arch implementation. BUILD_BUG() makes that
> > explicit rather than silently doing nothing.
> >
> > Signed-off-by: Wen Jiang <jiangwen6 at xiaomi.com>
> > Reviewed-by: Barry Song <baohua at kernel.org>
> > ---
> >  include/linux/pgtable.h | 29 +++++++++++++++++++++++++++++
> >  mm/vmalloc.c            | 19 ++++++-------------
> >  2 files changed, 35 insertions(+), 13 deletions(-)
> >
> > diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
> > index 8c093c119e5a8..a7fd51fec8a17 100644
> > --- a/include/linux/pgtable.h
> > +++ b/include/linux/pgtable.h
> > @@ -2204,6 +2204,35 @@ static inline int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
> >  }
> >  #endif       /* CONFIG_HAVE_ARCH_HUGE_VMAP */
> >
> > +/*
> > + * PTE-level block mappings for vmap.
> > + *
> > + * pte_set_huge() only has to be implemented by architectures whose
> > + * arch_vmap_pte_range_map_size() can return a size other than PAGE_SIZE.
> > + */
> > +#ifndef __HAVE_ARCH_PTE_SET_HUGE
> > +static inline void pte_set_huge(pte_t *ptep, unsigned long addr,
> > +                             phys_addr_t phys, pgprot_t prot,
> > +                             unsigned long size)
> > +{
> > +     BUILD_BUG();
> > +}
> > +#endif
> > +
> > +/*
> > + * Likewise, pte_clear_huge() only has to be implemented by architectures
> > + * whose arch_vmap_pte_range_unmap_size() can return a size other than
> > + * PAGE_SIZE.
> > + */
> > +#ifndef __HAVE_ARCH_PTE_CLEAR_HUGE
> > +static inline pte_t pte_clear_huge(pte_t *ptep, unsigned long addr,
> > +                                unsigned long size)
> > +{
> > +     BUILD_BUG();
> > +     return __pte(0);
> > +}
> > +#endif
> > +
> >  #ifndef __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
> >  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> >  /*
> > diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> > index bea9f76ed7e74..fb757d95bde25 100644
> > --- a/mm/vmalloc.c
> > +++ b/mm/vmalloc.c
> > @@ -38,7 +38,6 @@
> >  #include <linux/rbtree_augmented.h>
> >  #include <linux/overflow.h>
> >  #include <linux/pgtable.h>
> > -#include <linux/hugetlb.h>
> >  #include <linux/sched/mm.h>
> >  #include <asm/tlbflush.h>
> >  #include <asm/shmparam.h>
> > @@ -100,7 +99,7 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
> >       pte_t *pte;
> >       u64 pfn;
> >       struct page *page;
> > -     unsigned long size = PAGE_SIZE;
> > +     unsigned long size;
> >
> >       if (WARN_ON_ONCE(!PAGE_ALIGNED(end - addr)))
> >               return -EINVAL;
> > @@ -121,17 +120,12 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
> >                       BUG();
> >               }
> >
> > -#ifdef CONFIG_HUGETLB_PAGE
> >               size = arch_vmap_pte_range_map_size(addr, end, pfn, max_page_shift);
> >               if (size != PAGE_SIZE) {
> > -                     pte_t entry = pfn_pte(pfn, prot);
> > -
> > -                     entry = arch_make_huge_pte(entry, ilog2(size), 0);
> > -                     set_huge_pte_at(&init_mm, addr, pte, entry, size);
> > +                     pte_set_huge(pte, addr, PFN_PHYS(pfn), prot, size);
> >
> As far as i understand, X86_64 arches do not use this path. This
> specifically is only for ARM64 or powerpc. pte_set_huge() makes me
> thinking about huge-page mappings(PMD/PUD/hugetlb). This helper is
> about mutli page mapping on the PTE level.
>
> Better naming? pte_set_large()?
>
> Any thoughts?
>

Agreed, "huge" is misleading here: on arm64 these are CONT_PTE entries
and the helper writes a range of PTEs rather than a single leaf, so it
is not a PMD/PUD/hugetlb huge mapping. I'll rename them to
pte_set_large()/pte_clear_large() in v11.

Thanks,
Wen



More information about the linux-arm-kernel mailing list