Re: [PATCH 1/3] mm: define generic pudp_invalidate() implementation
From: Jinjiang Tu <hidden>
Date: 2026-09-11 02:29:10
Also in:
linux-mm
在 2026/9/9 18:24, David Hildenbrand (Arm) 写道:
On 9/9/26 11:00, Jinjiang Tu wrote:quoted
x86 and riscv have identical pudp_invalidate() implementations. Move it to mm/pgtable-generic.c with the __HAVE_ARCH_PUDP_INVALIDATE override guard. PowerPC keeps its own implementation. In the later patch, arm64 will use the generic implementation too. No functional change intended. Signed-off-by: Jinjiang Tu <redacted> --- arch/powerpc/include/asm/book3s/64/pgtable.h | 1 + arch/riscv/include/asm/pgtable.h | 3 --- arch/riscv/mm/pgtable.c | 9 --------- arch/x86/include/asm/pgtable.h | 3 --- arch/x86/mm/pgtable.c | 12 ------------ include/linux/pgtable.h | 7 +++++++ mm/pgtable-generic.c | 14 ++++++++++++++ 7 files changed, 22 insertions(+), 27 deletions(-)diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index f4db7d7fbd5c..55d33c5537f1 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h@@ -1419,6 +1419,7 @@ static inline pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, #define __HAVE_ARCH_PMDP_INVALIDATE extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp); +#define __HAVE_ARCH_PUDP_INVALIDATE extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, pud_t *pudp);diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 40b1ed4f3ea8..327fa378032b 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h@@ -1159,9 +1159,6 @@ static inline pud_t pud_mkinvalid(pud_t pud) return __pud(pud_val(pud) & ~(_PAGE_PRESENT | _PAGE_PROT_NONE)); } -extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, - pud_t *pudp); - static inline pud_t pud_modify(pud_t pud, pgprot_t newprot) { return pte_pud(pte_modify(pud_pte(pud), newprot));diff --git a/arch/riscv/mm/pgtable.c b/arch/riscv/mm/pgtable.c index 9c4427d0b187..156e385e7db4 100644 --- a/arch/riscv/mm/pgtable.c +++ b/arch/riscv/mm/pgtable.c@@ -154,15 +154,6 @@ pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, return pmd; } -pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, - pud_t *pudp) -{ - VM_WARN_ON_ONCE(!pud_present(*pudp)); - pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp)); - - flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE); - return old; -} #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index d5f4917c1edc..97051c02385e 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h@@ -1387,9 +1387,6 @@ static inline pud_t pudp_establish(struct vm_area_struct *vma, extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp); -pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, - pud_t *pudp); - /* * Page table pages are page-aligned. The lower half of the top * level is used for userspace and the top half for the kernel.diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index cb03f5a2b243..0945908631dc 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c@@ -519,18 +519,6 @@ pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address, } #endif -#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \ - defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) -pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, - pud_t *pudp) -{ - VM_WARN_ON_ONCE(!pud_present(*pudp)); - pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp)); - flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE); - return old; -} -#endif - /** * reserve_top_address - Reserve a hole in the top of the kernel address space * @reserve: Size of hole to reservediff --git a/include/linux/pgtable.h b/include/linux/pgtable.h index 8c093c119e5a..32173005b087 100644 --- a/include/linux/pgtable.h +++ b/include/linux/pgtable.h@@ -1318,6 +1318,13 @@ extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp); #endif +#ifndef __HAVE_ARCH_PUDP_INVALIDATE +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD +extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, + pud_t *pudp);No "extern" please.
Will update it.
Staring at this file, I do wonder why we are not smarter about combining blocks. E.g., here simply:'
Do you mean merging all #ifdef CONFIG_TRANSPARENT_HUGEPAGE blocks? There are many of them scattered across include/linux/pgtable.h and arch/arm64/include/asm/pgtable.h. They are intentionally kept separate to group the PTE, PMD, and PUD level variants of the same operation together. For example, ptep_set_access_flags, pmdp_set_access_flags, and pudp_set_access_flags are placed adjacently.
quoted hunk ↗ jump to hunk
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h index e3c8ab96941c5..8c9fe3bf580d4 100644 --- a/include/linux/pgtable.h +++ b/include/linux/pgtable.h@@ -1229,9 +1229,9 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, } #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif -#ifndef __HAVE_ARCH_PUDP_SET_WRPROTECT -#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD #ifdef CONFIG_TRANSPARENT_HUGEPAGE +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD +#ifndef __HAVE_ARCH_PUDP_SET_WRPROTECT static inline void pudp_set_wrprotect(struct mm_struct *mm, unsigned long address, pud_t *pudp) {@@ -1245,9 +1245,13 @@ static inline void pudp_set_wrprotect(struct mm_struct *mm, { BUILD_BUG(); } -#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ -#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */ #endif +#ifndef __HAVE_ARCH_PUDP_INVALIDATE +pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, + pud_t *pudp); +#endif +#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */ +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */quoted
+#endif +#endif + #ifndef __HAVE_ARCH_PTE_SAME static inline int pte_same(pte_t pte_a, pte_t pte_b) {diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c index b91b1a98029c..ac1175d9a59a 100644 --- a/mm/pgtable-generic.c +++ b/mm/pgtable-generic.c@@ -217,6 +217,20 @@ pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address, } #endif +#ifndef __HAVE_ARCH_PUDP_INVALIDATE +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUDI'd revert these and similarly see if they can be combined somehow (likely combining with pudp_huge_clear_flush is harder as we are quite inconsistent with it, gluing it to __HAVE_ARCH_PMDP_HUGE_CLEAR_FLUSH). Which raises the question whether we could also piggy-back on __HAVE_ARCH_PMDP_SET_WRPROTECT (I suspect no without a closer look.)