vmap installs PTE-level block mappings (PTE_CONT on arm64) by reusing set_huge_pte_at() and huge_ptep_get_and_clear(), which are HugeTLB helpers gated by 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.
Add pte_set_huge()/pte_clear_huge() to arm64, joining the existing pmd_set_huge()/pud_set_huge() family in mm/mmu.c. They build on __set_ptes() and __get_and_clear_full_ptes() directly, so they do not depend on CONFIG_HUGETLB_PAGE. There is no caller yet: mm/vmalloc.c is converted later in this series, once the generic fallbacks are in place. Signed-off-by: Wen Jiang <[email protected]> --- arch/arm64/include/asm/pgtable.h | 6 ++++++ arch/arm64/mm/mmu.c | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 6000905a2e865..9b762eb68cff0 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -1978,6 +1978,12 @@ static inline void clear_young_dirty_ptes(struct vm_area_struct *vma, #endif /* CONFIG_ARM64_CONTPTE */ +#define __HAVE_ARCH_PTE_SET_HUGE +void pte_set_huge(pte_t *ptep, unsigned long addr, phys_addr_t phys, + pgprot_t prot, unsigned long size); +#define __HAVE_ARCH_PTE_CLEAR_HUGE +pte_t pte_clear_huge(pte_t *ptep, unsigned long addr, unsigned long size); + #endif /* !__ASSEMBLER__ */ #endif /* __ASM_PGTABLE_H */ diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 79d90226fd5dc..4a3d084bb7556 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1912,6 +1912,26 @@ int pmd_clear_huge(pmd_t *pmdp) return 1; } +void pte_set_huge(pte_t *ptep, unsigned long addr, phys_addr_t phys, + pgprot_t prot, unsigned long size) +{ + unsigned long pfn = __phys_to_pfn(phys); + pte_t pte = pte_mkcont(pfn_pte(pfn, prot)); + unsigned int nr = size >> PAGE_SHIFT; + + VM_WARN_ON(!IS_ALIGNED(size, CONT_PTE_SIZE)); + VM_WARN_ON(!IS_ALIGNED(addr, CONT_PTE_SIZE)); + VM_WARN_ON(!IS_ALIGNED(pfn, CONT_PTES)); + + __set_ptes(&init_mm, addr, ptep, pte, nr); +} + +pte_t pte_clear_huge(pte_t *ptep, unsigned long addr, unsigned long size) +{ + return __get_and_clear_full_ptes(&init_mm, addr, ptep, + size >> PAGE_SHIFT, 0); +} + int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr) { pte_t *table; -- 2.34.1
