All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] arm64: Add support for PUD THP
@ 2026-09-09  9:00 Jinjiang Tu
  2026-09-09  9:00 ` [PATCH 1/3] mm: define generic pudp_invalidate() implementation Jinjiang Tu
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Jinjiang Tu @ 2026-09-09  9:00 UTC (permalink / raw)
  To: akpm, david, ljs, catalin.marinas, will, mark.rutland,
	ryan.roberts, peterx, dave.jiang, linux-arm-kernel, linux-mm
  Cc: wangkefeng.wang, sunnanyong, tujinjiang

This series adds PUD THP support for arm64, enabling PUD THP for DAX
and pfnmap.

Patch 1 moves the identical pudp_invalidate() implementations from x86
and riscv to a generic location so arm64 can reuse it.

Patch 2 is a minor cleanup that simplifies pmd_special/pmd_mkspecial.

Patch 3 adds the necessary PUD page table helpers and selects
HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD.

Jinjiang Tu (3):
  mm: define generic pudp_invalidate() implementation
  arm64: simplify pmd_special and pmd_mkspecial
  arm64: Add support for PUD THP

 arch/arm64/Kconfig                           |  1 +
 arch/arm64/include/asm/pgtable.h             | 71 +++++++++++++++-----
 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 ++++
 9 files changed, 77 insertions(+), 44 deletions(-)

-- 
2.43.0



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] mm: define generic pudp_invalidate() implementation
  2026-09-09  9:00 [PATCH 0/3] arm64: Add support for PUD THP Jinjiang Tu
@ 2026-09-09  9:00 ` Jinjiang Tu
  2026-09-09 10:24   ` David Hildenbrand (Arm)
  2026-09-09  9:00 ` [PATCH 2/3] arm64: simplify pmd_special and pmd_mkspecial Jinjiang Tu
  2026-09-09  9:00 ` [PATCH 3/3] arm64: Add support for PUD THP Jinjiang Tu
  2 siblings, 1 reply; 6+ messages in thread
From: Jinjiang Tu @ 2026-09-09  9:00 UTC (permalink / raw)
  To: akpm, david, ljs, catalin.marinas, will, mark.rutland,
	ryan.roberts, peterx, dave.jiang, linux-arm-kernel, linux-mm
  Cc: wangkefeng.wang, sunnanyong, tujinjiang

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 <tujinjiang@huawei.com>
---
 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 reserve
diff --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);
+#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_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
+#endif
+
 #ifndef pmdp_collapse_flush
 pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
 			  pmd_t *pmdp)
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] arm64: simplify pmd_special and pmd_mkspecial
  2026-09-09  9:00 [PATCH 0/3] arm64: Add support for PUD THP Jinjiang Tu
  2026-09-09  9:00 ` [PATCH 1/3] mm: define generic pudp_invalidate() implementation Jinjiang Tu
@ 2026-09-09  9:00 ` Jinjiang Tu
  2026-09-09  9:00 ` [PATCH 3/3] arm64: Add support for PUD THP Jinjiang Tu
  2 siblings, 0 replies; 6+ messages in thread
From: Jinjiang Tu @ 2026-09-09  9:00 UTC (permalink / raw)
  To: akpm, david, ljs, catalin.marinas, will, mark.rutland,
	ryan.roberts, peterx, dave.jiang, linux-arm-kernel, linux-mm
  Cc: wangkefeng.wang, sunnanyong, tujinjiang

Use pte_special() and pte_mkspecial() helper to simplify pmd_special()
and pmd_mkspecial(), and kill unused set_pmd_bit() and clear_pmd_bit()
helper.

Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
---
 arch/arm64/include/asm/pgtable.h | 19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 6000905a2e86..427ea3d2bac7 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -243,18 +243,6 @@ static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot)
 	return pte;
 }
 
-static inline pmd_t clear_pmd_bit(pmd_t pmd, pgprot_t prot)
-{
-	pmd_val(pmd) &= ~pgprot_val(prot);
-	return pmd;
-}
-
-static inline pmd_t set_pmd_bit(pmd_t pmd, pgprot_t prot)
-{
-	pmd_val(pmd) |= pgprot_val(prot);
-	return pmd;
-}
-
 static inline pte_t pte_mkwrite_novma(pte_t pte)
 {
 	pte = set_pte_bit(pte, __pgprot(PTE_WRITE));
@@ -619,11 +607,8 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
 }
 
 #ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
-#define pmd_special(pte)	(!!((pmd_val(pte) & PTE_SPECIAL)))
-static inline pmd_t pmd_mkspecial(pmd_t pmd)
-{
-	return set_pmd_bit(pmd, __pgprot(PTE_SPECIAL));
-}
+#define pmd_special(pmd)	pte_special(pmd_pte(pmd))
+#define pmd_mkspecial(pmd)	pte_pmd(pte_mkspecial(pmd_pte(pmd)))
 #endif
 
 #define __pmd_to_phys(pmd)	__pte_to_phys(pmd_pte(pmd))
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] arm64: Add support for PUD THP
  2026-09-09  9:00 [PATCH 0/3] arm64: Add support for PUD THP Jinjiang Tu
  2026-09-09  9:00 ` [PATCH 1/3] mm: define generic pudp_invalidate() implementation Jinjiang Tu
  2026-09-09  9:00 ` [PATCH 2/3] arm64: simplify pmd_special and pmd_mkspecial Jinjiang Tu
@ 2026-09-09  9:00 ` Jinjiang Tu
  2 siblings, 0 replies; 6+ messages in thread
From: Jinjiang Tu @ 2026-09-09  9:00 UTC (permalink / raw)
  To: akpm, david, ljs, catalin.marinas, will, mark.rutland,
	ryan.roberts, peterx, dave.jiang, linux-arm-kernel, linux-mm
  Cc: wangkefeng.wang, sunnanyong, tujinjiang

Add the necessary page table functions to deal with PUD THP, this enables
PUD THP for DAX and pfnmap.

I tested with CONFIG_DEBUG_VM_PGTABLE and CONFIG_PAGE_TABLE_CHECK
enabled.  I wrote a test driver that invokes vmf_insert_pfn_pud() in
the huge_fault callback.  Page table setup works as expected with no
errors, and userspace read/write access to the PUD-sized mapping is
verified correct.

Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
---
 arch/arm64/Kconfig               |  1 +
 arch/arm64/include/asm/pgtable.h | 52 ++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b5a51b0ef944..8a7ca1863595 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -173,6 +173,7 @@ config ARM64
 	select HAVE_ARCH_THREAD_STRUCT_WHITELIST
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+	select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if PAGE_SIZE_4KB
 	select HAVE_ARCH_VMAP_STACK
 	select HAVE_ARM_SMCCC
 	select HAVE_ASM_MODVERSIONS
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 427ea3d2bac7..fdc338970934 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -611,6 +611,11 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
 #define pmd_mkspecial(pmd)	pte_pmd(pte_mkspecial(pmd_pte(pmd)))
 #endif
 
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+#define pud_special(pud)	pte_special(pud_pte(pud))
+#define pud_mkspecial(pud)	pte_pud(pte_mkspecial(pud_pte(pud)))
+#endif
+
 #define __pmd_to_phys(pmd)	__pte_to_phys(pmd_pte(pmd))
 #define __phys_to_pmd_val(phys)	__phys_to_pte_val(phys)
 #define pmd_pfn(pmd)		((__pmd_to_phys(pmd) & PMD_MASK) >> PAGE_SHIFT)
@@ -619,8 +624,15 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
 #define pud_young(pud)		pte_young(pud_pte(pud))
 #define pud_mkyoung(pud)	pte_pud(pte_mkyoung(pud_pte(pud)))
 #define pud_mkwrite_novma(pud)	pte_pud(pte_mkwrite_novma(pud_pte(pud)))
+#define pud_mkwrite(pud)	pud_mkwrite_novma(pud)
 #define pud_mkvalid_k(pud)	pte_pud(pte_mkvalid_k(pud_pte(pud)))
 #define pud_write(pud)		pte_write(pud_pte(pud))
+#define pud_dirty(pud)		pte_dirty(pud_pte(pud))
+#define pud_wrprotect(pud)	pte_pud(pte_wrprotect(pud_pte(pud)))
+#define pud_mkdirty(pud)	pte_pud(pte_mkdirty(pud_pte(pud)))
+#define pud_mkold(pud)		pte_pud(pte_mkold(pud_pte(pud)))
+#define pud_mkinvalid(pud)	pte_pud(pte_mkinvalid(pud_pte(pud)))
+#define pud_mkclean(pud)	pte_pud(pte_mkclean(pud_pte(pud)))
 
 static inline pud_t pud_mkhuge(pud_t pud)
 {
@@ -871,6 +883,13 @@ static inline bool pud_leaf(pud_t pud)
 #define pud_user(pud)		pte_user(pud_pte(pud))
 #define pud_user_exec(pud)	pte_user_exec(pud_pte(pud))
 
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+static inline int pud_trans_huge(pud_t pud)
+{
+	return pud_present(pud) && !pud_table(__pud(pud_val(pud) | PTE_VALID));
+}
+#endif
+
 static inline bool pgtable_l4_enabled(void);
 
 static inline void set_pud(pud_t *pudp, pud_t pud)
@@ -1237,6 +1256,11 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
 	return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
 }
 
+static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)
+{
+	return pte_pud(pte_modify(pud_pte(pud), newprot));
+}
+
 extern int __ptep_set_access_flags_anysz(struct vm_area_struct *vma,
 					 unsigned long address, pte_t *ptep,
 					 pte_t entry, int dirty,
@@ -1261,6 +1285,16 @@ static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
 }
 #endif
 
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+static inline int pudp_set_access_flags(struct vm_area_struct *vma,
+					unsigned long address, pud_t *pudp,
+					pud_t entry, int dirty)
+{
+	return __ptep_set_access_flags_anysz(vma, address, (pte_t *)pudp,
+					     pud_pte(entry), dirty, PUD_SIZE);
+}
+#endif
+
 #ifdef CONFIG_PAGE_TABLE_CHECK
 static inline bool pte_user_accessible_page(struct mm_struct *mm, unsigned long addr, pte_t pte)
 {
@@ -1335,6 +1369,14 @@ static inline bool pmdp_test_and_clear_young(struct vm_area_struct *vma,
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG */
 
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+static inline bool pudp_test_and_clear_young(struct vm_area_struct *vma,
+		unsigned long address, pud_t *pudp)
+{
+	return __ptep_test_and_clear_young(vma, address, (pte_t *)pudp);
+}
+#endif
+
 static inline pte_t __ptep_get_and_clear_anysz(struct mm_struct *mm,
 					       unsigned long address,
 					       pte_t *ptep,
@@ -1497,6 +1539,15 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
 }
 #endif
 
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+static inline pud_t pudp_establish(struct vm_area_struct *vma,
+		unsigned long address, pud_t *pudp, pud_t pud)
+{
+	page_table_check_pud_set(vma->vm_mm, address, pudp, pud);
+	return __pud(xchg_relaxed(&pud_val(*pudp), pud_val(pud)));
+}
+#endif
+
 /*
  * Encode and decode a swap entry:
  *	bits 0-1:	present (must be zero)
@@ -1571,6 +1622,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
 #define update_mmu_cache(vma, addr, ptep) \
 	update_mmu_cache_range(NULL, vma, addr, ptep, 1)
 #define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
+#define update_mmu_cache_pud(vma, address, pud) do { } while (0)
 
 #ifdef CONFIG_ARM64_PA_BITS_52
 #define phys_to_ttbr(addr)	(((addr) | ((addr) >> 46)) & TTBR_BADDR_MASK_52)
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] mm: define generic pudp_invalidate() implementation
  2026-09-09  9:00 ` [PATCH 1/3] mm: define generic pudp_invalidate() implementation Jinjiang Tu
@ 2026-09-09 10:24   ` David Hildenbrand (Arm)
  2026-09-11  2:28     ` Jinjiang Tu
  0 siblings, 1 reply; 6+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 10:24 UTC (permalink / raw)
  To: Jinjiang Tu, akpm, ljs, catalin.marinas, will, mark.rutland,
	ryan.roberts, peterx, dave.jiang, linux-arm-kernel, linux-mm
  Cc: wangkefeng.wang, sunnanyong

On 9/9/26 11:00, Jinjiang Tu wrote:
> 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 <tujinjiang@huawei.com>
> ---
>  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 reserve
> diff --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.

Staring at this file, I do wonder why we are not smarter about combining blocks. E.g., here simply:

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 */

> +#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_PUD

I'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.)

-- 
Cheers,

David


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] mm: define generic pudp_invalidate() implementation
  2026-09-09 10:24   ` David Hildenbrand (Arm)
@ 2026-09-11  2:28     ` Jinjiang Tu
  0 siblings, 0 replies; 6+ messages in thread
From: Jinjiang Tu @ 2026-09-11  2:28 UTC (permalink / raw)
  To: David Hildenbrand (Arm), akpm, ljs, catalin.marinas, will,
	mark.rutland, ryan.roberts, peterx, dave.jiang, linux-arm-kernel,
	linux-mm
  Cc: wangkefeng.wang, sunnanyong


在 2026/9/9 18:24, David Hildenbrand (Arm) 写道:
> On 9/9/26 11:00, Jinjiang Tu wrote:
>> 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 <tujinjiang@huawei.com>
>> ---
>>   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 reserve
>> diff --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.

>
> 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 */
>
>> +#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_PUD
> I'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.)
>


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-09-11  2:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09  9:00 [PATCH 0/3] arm64: Add support for PUD THP Jinjiang Tu
2026-09-09  9:00 ` [PATCH 1/3] mm: define generic pudp_invalidate() implementation Jinjiang Tu
2026-09-09 10:24   ` David Hildenbrand (Arm)
2026-09-11  2:28     ` Jinjiang Tu
2026-09-09  9:00 ` [PATCH 2/3] arm64: simplify pmd_special and pmd_mkspecial Jinjiang Tu
2026-09-09  9:00 ` [PATCH 3/3] arm64: Add support for PUD THP Jinjiang Tu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.