* [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table()
@ 2024-12-30 9:07 Qi Zheng
2024-12-30 9:07 ` [PATCH v4 01/15] Revert "mm: pgtable: make ptlock be freed by RCU" Qi Zheng
` (16 more replies)
0 siblings, 17 replies; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
Changes in v4:
- remove [PATCH v3 15/17] and [PATCH v3 16/17] (Mike Rapoport)
(the tlb_remove_page_ptdesc() and tlb_remove_ptdesc() are intermediate
products of the project: https://kernelnewbies.org/MatthewWilcox/Memdescs,
so keep them)
- collect Acked-by
Changes in v3:
- take patch #5 and #6 from Kevin Brodsky's patch series below.
Link: https://lore.kernel.org/lkml/20241219164425.2277022-1-kevin.brodsky@arm.com/
- separate the statistics part from [PATCH v2 02/15] as [PATCH v3 04/17], and
replace the rest part with Kevin Brodsky's patch #6
(Alexander Gordeev and Kevin Brodsky)
- change the commit message of [PATCH v2 10/15] and [PATCH v2 11/15]
(Alexander Gordeev)
- fix the bug introduced by [PATCH v2 11/15]
(Peter Zijlstra)
- rebase onto the next-20241220
Changes in v2:
- add [PATCH v2 13|14|15/15] (suggested by Peter Zijlstra)
- add Originally-bys and Suggested-bys
- rebase onto the next-20241218
Hi all,
As proposed [1] by Peter Zijlstra below, this patch series aims to move
pagetable_*_dtor() into __tlb_remove_table(). This will cleanup pagetable_*_dtor()
a bit and more gracefully fix the UAF issue [2] reported by syzbot.
```
Notably:
- s390 pud isn't calling the existing pagetable_pud_[cd]tor()
- none of the p4d things have pagetable_p4d_[cd]tor() (x86,arm64,s390,riscv)
and they have inconsistent accounting
- while much of the _ctor calls are in generic code, many of the _dtor
calls are in arch code for hysterial raisins, this could easily be
fixed
- if we fix ptlock_free() to handle NULL, then all the _dtor()
functions can use it, and we can observe they're all identical
and can be folded
after all that cleanup, you can move the _dtor from *_free_tlb() into
tlb_remove_table() -- which for the above case, would then have it
called from __tlb_remove_table_free().
```
And hi Andrew, I developed the code based on the latest linux-next, so I reverted
the "mm: pgtable: make ptlock be freed by RCU" first. Once the review of this
patch series is completed, the "mm: pgtable: make ptlock be freed by RCU" can be
dropped directly from mm tree, and this revert patch will not be needed.
This series is based on next-20241220. And I tested this patch series on x86 and
only cross-compiled it on arm, arm64, powerpc, riscv, s390 and sparc.
Comments and suggestions are welcome!
Thanks,
Qi
[1]. https://lore.kernel.org/all/20241211133433.GC12500@noisy.programming.kicks-ass.net/
[2]. https://lore.kernel.org/all/67548279.050a0220.a30f1.015b.GAE@google.com/
Kevin Brodsky (2):
riscv: mm: Skip pgtable level check in {pud,p4d}_alloc_one
asm-generic: pgalloc: Provide generic p4d_{alloc_one,free}
Qi Zheng (13):
Revert "mm: pgtable: make ptlock be freed by RCU"
mm: pgtable: add statistics for P4D level page table
arm64: pgtable: use mmu gather to free p4d level page table
s390: pgtable: add statistics for PUD and P4D level page table
mm: pgtable: introduce pagetable_dtor()
arm: pgtable: move pagetable_dtor() to __tlb_remove_table()
arm64: pgtable: move pagetable_dtor() to __tlb_remove_table()
riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
x86: pgtable: move pagetable_dtor() to __tlb_remove_table()
s390: pgtable: also move pagetable_dtor() of PxD to
__tlb_remove_table()
mm: pgtable: introduce generic __tlb_remove_table()
mm: pgtable: move __tlb_remove_table_one() in x86 to generic file
mm: pgtable: introduce generic pagetable_dtor_free()
Documentation/mm/split_page_table_lock.rst | 4 +-
arch/arm/include/asm/tlb.h | 10 ----
arch/arm64/include/asm/pgalloc.h | 18 ------
arch/arm64/include/asm/tlb.h | 21 ++++---
arch/csky/include/asm/pgalloc.h | 2 +-
arch/hexagon/include/asm/pgalloc.h | 2 +-
arch/loongarch/include/asm/pgalloc.h | 2 +-
arch/m68k/include/asm/mcf_pgalloc.h | 4 +-
arch/m68k/include/asm/sun3_pgalloc.h | 2 +-
arch/m68k/mm/motorola.c | 2 +-
arch/mips/include/asm/pgalloc.h | 2 +-
arch/nios2/include/asm/pgalloc.h | 2 +-
arch/openrisc/include/asm/pgalloc.h | 2 +-
arch/powerpc/include/asm/tlb.h | 1 +
arch/powerpc/mm/book3s64/mmu_context.c | 2 +-
arch/powerpc/mm/book3s64/pgtable.c | 2 +-
arch/powerpc/mm/pgtable-frag.c | 4 +-
arch/riscv/include/asm/pgalloc.h | 69 +++++-----------------
arch/riscv/include/asm/tlb.h | 18 ------
arch/riscv/mm/init.c | 4 +-
arch/s390/include/asm/pgalloc.h | 31 +++++++---
arch/s390/include/asm/tlb.h | 43 +++++++-------
arch/s390/mm/pgalloc.c | 23 +-------
arch/sh/include/asm/pgalloc.h | 2 +-
arch/sparc/include/asm/tlb_32.h | 1 +
arch/sparc/include/asm/tlb_64.h | 1 +
arch/sparc/mm/init_64.c | 2 +-
arch/sparc/mm/srmmu.c | 2 +-
arch/um/include/asm/pgalloc.h | 6 +-
arch/x86/include/asm/pgalloc.h | 18 ------
arch/x86/include/asm/tlb.h | 33 -----------
arch/x86/kernel/paravirt.c | 1 +
arch/x86/mm/pgtable.c | 13 ++--
include/asm-generic/pgalloc.h | 55 +++++++++++++++--
include/asm-generic/tlb.h | 14 ++++-
include/linux/mm.h | 50 ++++++----------
include/linux/mm_types.h | 9 +--
mm/memory.c | 23 +++-----
mm/mmu_gather.c | 20 ++++++-
39 files changed, 211 insertions(+), 309 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH v4 01/15] Revert "mm: pgtable: make ptlock be freed by RCU"
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2024-12-30 9:07 ` [PATCH v4 02/15] riscv: mm: Skip pgtable level check in {pud,p4d}_alloc_one Qi Zheng
` (15 subsequent siblings)
16 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
This reverts commit 2f3443770437e49abc39af26962d293851cbab6d.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
---
include/linux/mm.h | 2 +-
include/linux/mm_types.h | 9 +--------
mm/memory.c | 22 ++++++----------------
3 files changed, 8 insertions(+), 25 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d61b9c7a3a7b0..c49bc7b764535 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2925,7 +2925,7 @@ void ptlock_free(struct ptdesc *ptdesc);
static inline spinlock_t *ptlock_ptr(struct ptdesc *ptdesc)
{
- return &(ptdesc->ptl->ptl);
+ return ptdesc->ptl;
}
#else /* ALLOC_SPLIT_PTLOCKS */
static inline void ptlock_cache_init(void)
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 90ab8293d714a..6b27db7f94963 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -434,13 +434,6 @@ FOLIO_MATCH(flags, _flags_2a);
FOLIO_MATCH(compound_head, _head_2a);
#undef FOLIO_MATCH
-#if ALLOC_SPLIT_PTLOCKS
-struct pt_lock {
- spinlock_t ptl;
- struct rcu_head rcu;
-};
-#endif
-
/**
* struct ptdesc - Memory descriptor for page tables.
* @__page_flags: Same as page flags. Powerpc only.
@@ -489,7 +482,7 @@ struct ptdesc {
union {
unsigned long _pt_pad_2;
#if ALLOC_SPLIT_PTLOCKS
- struct pt_lock *ptl;
+ spinlock_t *ptl;
#else
spinlock_t ptl;
#endif
diff --git a/mm/memory.c b/mm/memory.c
index b9b05c3f93f11..9423967b24180 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -7034,34 +7034,24 @@ static struct kmem_cache *page_ptl_cachep;
void __init ptlock_cache_init(void)
{
- page_ptl_cachep = kmem_cache_create("page->ptl", sizeof(struct pt_lock), 0,
+ page_ptl_cachep = kmem_cache_create("page->ptl", sizeof(spinlock_t), 0,
SLAB_PANIC, NULL);
}
bool ptlock_alloc(struct ptdesc *ptdesc)
{
- struct pt_lock *pt_lock;
+ spinlock_t *ptl;
- pt_lock = kmem_cache_alloc(page_ptl_cachep, GFP_KERNEL);
- if (!pt_lock)
+ ptl = kmem_cache_alloc(page_ptl_cachep, GFP_KERNEL);
+ if (!ptl)
return false;
- ptdesc->ptl = pt_lock;
+ ptdesc->ptl = ptl;
return true;
}
-static void ptlock_free_rcu(struct rcu_head *head)
-{
- struct pt_lock *pt_lock;
-
- pt_lock = container_of(head, struct pt_lock, rcu);
- kmem_cache_free(page_ptl_cachep, pt_lock);
-}
-
void ptlock_free(struct ptdesc *ptdesc)
{
- struct pt_lock *pt_lock = ptdesc->ptl;
-
- call_rcu(&pt_lock->rcu, ptlock_free_rcu);
+ kmem_cache_free(page_ptl_cachep, ptdesc->ptl);
}
#endif
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 02/15] riscv: mm: Skip pgtable level check in {pud,p4d}_alloc_one
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
2024-12-30 9:07 ` [PATCH v4 01/15] Revert "mm: pgtable: make ptlock be freed by RCU" Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2025-01-06 11:20 ` Alexandre Ghiti
2024-12-30 9:07 ` [PATCH v4 03/15] asm-generic: pgalloc: Provide generic p4d_{alloc_one,free} Qi Zheng
` (14 subsequent siblings)
16 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng, Palmer Dabbelt
From: Kevin Brodsky <kevin.brodsky@arm.com>
{pmd,pud,p4d}_alloc_one() is never called if the corresponding page
table level is folded, as {pmd,pud,p4d}_alloc() already does the
required check. We can therefore remove the runtime page table level
checks in {pud,p4d}_alloc_one. The PUD helper becomes equivalent to
the generic version, so we remove it altogether.
This is consistent with the way arm64 and x86 handle this situation
(runtime check in p4d_free() only).
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
---
arch/riscv/include/asm/pgalloc.h | 22 ++++------------------
1 file changed, 4 insertions(+), 18 deletions(-)
diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h
index f52264304f772..8ad0bbe838a24 100644
--- a/arch/riscv/include/asm/pgalloc.h
+++ b/arch/riscv/include/asm/pgalloc.h
@@ -12,7 +12,6 @@
#include <asm/tlb.h>
#ifdef CONFIG_MMU
-#define __HAVE_ARCH_PUD_ALLOC_ONE
#define __HAVE_ARCH_PUD_FREE
#include <asm-generic/pgalloc.h>
@@ -88,15 +87,6 @@ static inline void pgd_populate_safe(struct mm_struct *mm, pgd_t *pgd,
}
}
-#define pud_alloc_one pud_alloc_one
-static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
- if (pgtable_l4_enabled)
- return __pud_alloc_one(mm, addr);
-
- return NULL;
-}
-
#define pud_free pud_free
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
{
@@ -118,15 +108,11 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
#define p4d_alloc_one p4d_alloc_one
static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- if (pgtable_l5_enabled) {
- gfp_t gfp = GFP_PGTABLE_USER;
-
- if (mm == &init_mm)
- gfp = GFP_PGTABLE_KERNEL;
- return (p4d_t *)get_zeroed_page(gfp);
- }
+ gfp_t gfp = GFP_PGTABLE_USER;
- return NULL;
+ if (mm == &init_mm)
+ gfp = GFP_PGTABLE_KERNEL;
+ return (p4d_t *)get_zeroed_page(gfp);
}
static inline void __p4d_free(struct mm_struct *mm, p4d_t *p4d)
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 03/15] asm-generic: pgalloc: Provide generic p4d_{alloc_one,free}
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
2024-12-30 9:07 ` [PATCH v4 01/15] Revert "mm: pgtable: make ptlock be freed by RCU" Qi Zheng
2024-12-30 9:07 ` [PATCH v4 02/15] riscv: mm: Skip pgtable level check in {pud,p4d}_alloc_one Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2024-12-30 9:07 ` [PATCH v4 04/15] mm: pgtable: add statistics for P4D level page table Qi Zheng
` (13 subsequent siblings)
16 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
From: Kevin Brodsky <kevin.brodsky@arm.com>
Four architectures currently implement 5-level pgtables: arm64,
riscv, x86 and s390. The first three have essentially the same
implementation for p4d_alloc_one() and p4d_free(), so we've got an
opportunity to reduce duplication like at the lower levels.
Provide a generic version of p4d_alloc_one() and p4d_free(), and
make use of it on those architectures.
Their implementation is the same as at PUD level, except that
p4d_free() performs a runtime check by calling mm_p4d_folded().
5-level pgtables depend on a runtime-detected hardware feature on
all supported architectures, so we might as well include this check
in the generic implementation. No runtime check is required in
p4d_alloc_one() as the top-level p4d_alloc() already does the
required check.
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
---
arch/arm64/include/asm/pgalloc.h | 17 ------------
arch/riscv/include/asm/pgalloc.h | 23 ----------------
arch/x86/include/asm/pgalloc.h | 18 -------------
include/asm-generic/pgalloc.h | 45 ++++++++++++++++++++++++++++++++
4 files changed, 45 insertions(+), 58 deletions(-)
diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h
index e75422864d1bd..2965f5a7e39e3 100644
--- a/arch/arm64/include/asm/pgalloc.h
+++ b/arch/arm64/include/asm/pgalloc.h
@@ -85,23 +85,6 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgdp, p4d_t *p4dp)
__pgd_populate(pgdp, __pa(p4dp), pgdval);
}
-static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
- gfp_t gfp = GFP_PGTABLE_USER;
-
- if (mm == &init_mm)
- gfp = GFP_PGTABLE_KERNEL;
- return (p4d_t *)get_zeroed_page(gfp);
-}
-
-static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
-{
- if (!pgtable_l5_enabled())
- return;
- BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
- free_page((unsigned long)p4d);
-}
-
#define __p4d_free_tlb(tlb, p4d, addr) p4d_free((tlb)->mm, p4d)
#else
static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t p4dp, pgdval_t prot)
diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h
index 8ad0bbe838a24..551d614d3369c 100644
--- a/arch/riscv/include/asm/pgalloc.h
+++ b/arch/riscv/include/asm/pgalloc.h
@@ -105,29 +105,6 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
}
}
-#define p4d_alloc_one p4d_alloc_one
-static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
- gfp_t gfp = GFP_PGTABLE_USER;
-
- if (mm == &init_mm)
- gfp = GFP_PGTABLE_KERNEL;
- return (p4d_t *)get_zeroed_page(gfp);
-}
-
-static inline void __p4d_free(struct mm_struct *mm, p4d_t *p4d)
-{
- BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
- free_page((unsigned long)p4d);
-}
-
-#define p4d_free p4d_free
-static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
-{
- if (pgtable_l5_enabled)
- __p4d_free(mm, p4d);
-}
-
static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
unsigned long addr)
{
diff --git a/arch/x86/include/asm/pgalloc.h b/arch/x86/include/asm/pgalloc.h
index dcd836b59bebd..dd4841231bb9f 100644
--- a/arch/x86/include/asm/pgalloc.h
+++ b/arch/x86/include/asm/pgalloc.h
@@ -147,24 +147,6 @@ static inline void pgd_populate_safe(struct mm_struct *mm, pgd_t *pgd, p4d_t *p4
set_pgd_safe(pgd, __pgd(_PAGE_TABLE | __pa(p4d)));
}
-static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
- gfp_t gfp = GFP_KERNEL_ACCOUNT;
-
- if (mm == &init_mm)
- gfp &= ~__GFP_ACCOUNT;
- return (p4d_t *)get_zeroed_page(gfp);
-}
-
-static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
-{
- if (!pgtable_l5_enabled())
- return;
-
- BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
- free_page((unsigned long)p4d);
-}
-
extern void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d);
static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h
index 7c48f5fbf8aa7..59131629ac9cc 100644
--- a/include/asm-generic/pgalloc.h
+++ b/include/asm-generic/pgalloc.h
@@ -215,6 +215,51 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
#endif /* CONFIG_PGTABLE_LEVELS > 3 */
+#if CONFIG_PGTABLE_LEVELS > 4
+
+static inline p4d_t *__p4d_alloc_one_noprof(struct mm_struct *mm, unsigned long addr)
+{
+ gfp_t gfp = GFP_PGTABLE_USER;
+ struct ptdesc *ptdesc;
+
+ if (mm == &init_mm)
+ gfp = GFP_PGTABLE_KERNEL;
+ gfp &= ~__GFP_HIGHMEM;
+
+ ptdesc = pagetable_alloc_noprof(gfp, 0);
+ if (!ptdesc)
+ return NULL;
+
+ return ptdesc_address(ptdesc);
+}
+#define __p4d_alloc_one(...) alloc_hooks(__p4d_alloc_one_noprof(__VA_ARGS__))
+
+#ifndef __HAVE_ARCH_P4D_ALLOC_ONE
+static inline p4d_t *p4d_alloc_one_noprof(struct mm_struct *mm, unsigned long addr)
+{
+ return __p4d_alloc_one_noprof(mm, addr);
+}
+#define p4d_alloc_one(...) alloc_hooks(p4d_alloc_one_noprof(__VA_ARGS__))
+#endif
+
+static inline void __p4d_free(struct mm_struct *mm, p4d_t *p4d)
+{
+ struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
+
+ BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
+ pagetable_free(ptdesc);
+}
+
+#ifndef __HAVE_ARCH_P4D_FREE
+static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
+{
+ if (!mm_p4d_folded(mm))
+ __p4d_free(mm, p4d);
+}
+#endif
+
+#endif /* CONFIG_PGTABLE_LEVELS > 4 */
+
#ifndef __HAVE_ARCH_PGD_FREE
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 04/15] mm: pgtable: add statistics for P4D level page table
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (2 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 03/15] asm-generic: pgalloc: Provide generic p4d_{alloc_one,free} Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2025-01-02 16:53 ` Kevin Brodsky
2024-12-30 9:07 ` [PATCH v4 05/15] arm64: pgtable: use mmu gather to free p4d " Qi Zheng
` (12 subsequent siblings)
16 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
Like other levels of page tables, add statistics for P4D level page table.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Originally-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
arch/riscv/include/asm/pgalloc.h | 6 +++++-
arch/x86/mm/pgtable.c | 3 +++
include/asm-generic/pgalloc.h | 2 ++
include/linux/mm.h | 16 ++++++++++++++++
4 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h
index 551d614d3369c..3466fbe2e508d 100644
--- a/arch/riscv/include/asm/pgalloc.h
+++ b/arch/riscv/include/asm/pgalloc.h
@@ -108,8 +108,12 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
unsigned long addr)
{
- if (pgtable_l5_enabled)
+ if (pgtable_l5_enabled) {
+ struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
+
+ pagetable_p4d_dtor(ptdesc);
riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
+ }
}
#endif /* __PAGETABLE_PMD_FOLDED */
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 69a357b15974a..3d6e84da45b24 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -94,6 +94,9 @@ void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
#if CONFIG_PGTABLE_LEVELS > 4
void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d)
{
+ struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
+
+ pagetable_p4d_dtor(ptdesc);
paravirt_release_p4d(__pa(p4d) >> PAGE_SHIFT);
paravirt_tlb_remove_table(tlb, virt_to_page(p4d));
}
diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h
index 59131629ac9cc..bb482eeca0c3e 100644
--- a/include/asm-generic/pgalloc.h
+++ b/include/asm-generic/pgalloc.h
@@ -230,6 +230,7 @@ static inline p4d_t *__p4d_alloc_one_noprof(struct mm_struct *mm, unsigned long
if (!ptdesc)
return NULL;
+ pagetable_p4d_ctor(ptdesc);
return ptdesc_address(ptdesc);
}
#define __p4d_alloc_one(...) alloc_hooks(__p4d_alloc_one_noprof(__VA_ARGS__))
@@ -247,6 +248,7 @@ static inline void __p4d_free(struct mm_struct *mm, p4d_t *p4d)
struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
+ pagetable_p4d_dtor(ptdesc);
pagetable_free(ptdesc);
}
diff --git a/include/linux/mm.h b/include/linux/mm.h
index c49bc7b764535..5d82f42ddd5cc 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3175,6 +3175,22 @@ static inline void pagetable_pud_dtor(struct ptdesc *ptdesc)
lruvec_stat_sub_folio(folio, NR_PAGETABLE);
}
+static inline void pagetable_p4d_ctor(struct ptdesc *ptdesc)
+{
+ struct folio *folio = ptdesc_folio(ptdesc);
+
+ __folio_set_pgtable(folio);
+ lruvec_stat_add_folio(folio, NR_PAGETABLE);
+}
+
+static inline void pagetable_p4d_dtor(struct ptdesc *ptdesc)
+{
+ struct folio *folio = ptdesc_folio(ptdesc);
+
+ __folio_clear_pgtable(folio);
+ lruvec_stat_sub_folio(folio, NR_PAGETABLE);
+}
+
extern void __init pagecache_init(void);
extern void free_initmem(void);
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 05/15] arm64: pgtable: use mmu gather to free p4d level page table
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (3 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 04/15] mm: pgtable: add statistics for P4D level page table Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2024-12-30 9:07 ` [PATCH v4 06/15] s390: pgtable: add statistics for PUD and P4D " Qi Zheng
` (11 subsequent siblings)
16 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
Like other levels of page tables, also use mmu gather mechanism to free
p4d level page table.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Originally-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: linux-arm-kernel@lists.infradead.org
---
arch/arm64/include/asm/pgalloc.h | 1 -
arch/arm64/include/asm/tlb.h | 14 ++++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h
index 2965f5a7e39e3..1b4509d3382c6 100644
--- a/arch/arm64/include/asm/pgalloc.h
+++ b/arch/arm64/include/asm/pgalloc.h
@@ -85,7 +85,6 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgdp, p4d_t *p4dp)
__pgd_populate(pgdp, __pa(p4dp), pgdval);
}
-#define __p4d_free_tlb(tlb, p4d, addr) p4d_free((tlb)->mm, p4d)
#else
static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t p4dp, pgdval_t prot)
{
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index a947c6e784ed2..445282cde9afb 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -111,4 +111,18 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pudp,
}
#endif
+#if CONFIG_PGTABLE_LEVELS > 4
+static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4dp,
+ unsigned long addr)
+{
+ struct ptdesc *ptdesc = virt_to_ptdesc(p4dp);
+
+ if (!pgtable_l5_enabled())
+ return;
+
+ pagetable_p4d_dtor(ptdesc);
+ tlb_remove_ptdesc(tlb, ptdesc);
+}
+#endif
+
#endif
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 06/15] s390: pgtable: add statistics for PUD and P4D level page table
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (4 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 05/15] arm64: pgtable: use mmu gather to free p4d " Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2025-01-06 10:32 ` Alexander Gordeev
2024-12-30 9:07 ` [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor() Qi Zheng
` (10 subsequent siblings)
16 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
Like PMD and PTE level page table, also add statistics for PUD and P4D
page table.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: linux-s390@vger.kernel.org
---
arch/s390/include/asm/pgalloc.h | 29 +++++++++++++++++++-------
arch/s390/include/asm/tlb.h | 37 +++++++++++++++++----------------
2 files changed, 40 insertions(+), 26 deletions(-)
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index 7b84ef6dc4b6d..a0c1ca5d8423c 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -53,29 +53,42 @@ static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long address)
{
unsigned long *table = crst_table_alloc(mm);
- if (table)
- crst_table_init(table, _REGION2_ENTRY_EMPTY);
+ if (!table)
+ return NULL;
+ crst_table_init(table, _REGION2_ENTRY_EMPTY);
+ pagetable_p4d_ctor(virt_to_ptdesc(table));
+
return (p4d_t *) table;
}
static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
{
- if (!mm_p4d_folded(mm))
- crst_table_free(mm, (unsigned long *) p4d);
+ if (mm_p4d_folded(mm))
+ return;
+
+ pagetable_p4d_dtor(virt_to_ptdesc(p4d));
+ crst_table_free(mm, (unsigned long *) p4d);
}
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
{
unsigned long *table = crst_table_alloc(mm);
- if (table)
- crst_table_init(table, _REGION3_ENTRY_EMPTY);
+
+ if (!table)
+ return NULL;
+ crst_table_init(table, _REGION3_ENTRY_EMPTY);
+ pagetable_pud_ctor(virt_to_ptdesc(table));
+
return (pud_t *) table;
}
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
{
- if (!mm_pud_folded(mm))
- crst_table_free(mm, (unsigned long *) pud);
+ if (mm_pud_folded(mm))
+ return;
+
+ pagetable_pud_dtor(virt_to_ptdesc(pud));
+ crst_table_free(mm, (unsigned long *) pud);
}
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index e95b2c8081eb8..b946964afce8e 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -110,24 +110,6 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
tlb_remove_ptdesc(tlb, pmd);
}
-/*
- * p4d_free_tlb frees a pud table and clears the CRSTE for the
- * region second table entry from the tlb.
- * If the mm uses a four level page table the single p4d is freed
- * as the pgd. p4d_free_tlb checks the asce_limit against 8PB
- * to avoid the double free of the p4d in this case.
- */
-static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
- unsigned long address)
-{
- if (mm_p4d_folded(tlb->mm))
- return;
- __tlb_adjust_range(tlb, address, PAGE_SIZE);
- tlb->mm->context.flush_mm = 1;
- tlb->freed_tables = 1;
- tlb_remove_ptdesc(tlb, p4d);
-}
-
/*
* pud_free_tlb frees a pud table and clears the CRSTE for the
* region third table entry from the tlb.
@@ -140,11 +122,30 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
{
if (mm_pud_folded(tlb->mm))
return;
+ pagetable_pud_dtor(virt_to_ptdesc(pud));
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
tlb->cleared_p4ds = 1;
tlb_remove_ptdesc(tlb, pud);
}
+/*
+ * p4d_free_tlb frees a p4d table and clears the CRSTE for the
+ * region second table entry from the tlb.
+ * If the mm uses a four level page table the single p4d is freed
+ * as the pgd. p4d_free_tlb checks the asce_limit against 8PB
+ * to avoid the double free of the p4d in this case.
+ */
+static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
+ unsigned long address)
+{
+ if (mm_p4d_folded(tlb->mm))
+ return;
+ pagetable_p4d_dtor(virt_to_ptdesc(p4d));
+ __tlb_adjust_range(tlb, address, PAGE_SIZE);
+ tlb->mm->context.flush_mm = 1;
+ tlb->freed_tables = 1;
+ tlb_remove_ptdesc(tlb, p4d);
+}
#endif /* _S390_TLB_H */
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (5 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 06/15] s390: pgtable: add statistics for PUD and P4D " Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2025-01-06 10:34 ` Alexander Gordeev
2024-12-30 9:07 ` [PATCH v4 08/15] arm: pgtable: move pagetable_dtor() to __tlb_remove_table() Qi Zheng
` (9 subsequent siblings)
16 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
The pagetable_p*_dtor() are exactly the same except for the handling of
ptlock. If we make ptlock_free() handle the case where ptdesc->ptl is
NULL and remove VM_BUG_ON_PAGE() from pmd_ptlock_free(), we can unify
pagetable_p*_dtor() into one function. Let's introduce pagetable_dtor()
to do this.
Later, pagetable_dtor() will be moved to tlb_remove_ptdesc(), so that
ptlock and page table pages can be freed together (regardless of whether
RCU is used). This prevents the use-after-free problem where the ptlock
is freed immediately but the page table pages is freed later via RCU.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Originally-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
Documentation/mm/split_page_table_lock.rst | 4 +-
arch/arm/include/asm/tlb.h | 4 +-
arch/arm64/include/asm/tlb.h | 8 ++--
arch/csky/include/asm/pgalloc.h | 2 +-
arch/hexagon/include/asm/pgalloc.h | 2 +-
arch/loongarch/include/asm/pgalloc.h | 2 +-
arch/m68k/include/asm/mcf_pgalloc.h | 4 +-
arch/m68k/include/asm/sun3_pgalloc.h | 2 +-
arch/m68k/mm/motorola.c | 2 +-
arch/mips/include/asm/pgalloc.h | 2 +-
arch/nios2/include/asm/pgalloc.h | 2 +-
arch/openrisc/include/asm/pgalloc.h | 2 +-
arch/powerpc/mm/book3s64/mmu_context.c | 2 +-
arch/powerpc/mm/book3s64/pgtable.c | 2 +-
arch/powerpc/mm/pgtable-frag.c | 4 +-
arch/riscv/include/asm/pgalloc.h | 8 ++--
arch/riscv/mm/init.c | 4 +-
arch/s390/include/asm/pgalloc.h | 6 +--
arch/s390/include/asm/tlb.h | 6 +--
arch/s390/mm/pgalloc.c | 2 +-
arch/sh/include/asm/pgalloc.h | 2 +-
arch/sparc/mm/init_64.c | 2 +-
arch/sparc/mm/srmmu.c | 2 +-
arch/um/include/asm/pgalloc.h | 6 +--
arch/x86/mm/pgtable.c | 12 ++---
include/asm-generic/pgalloc.h | 8 ++--
include/linux/mm.h | 52 ++++------------------
mm/memory.c | 3 +-
28 files changed, 62 insertions(+), 95 deletions(-)
diff --git a/Documentation/mm/split_page_table_lock.rst b/Documentation/mm/split_page_table_lock.rst
index 581446d4a4eba..8e1ceb0a6619a 100644
--- a/Documentation/mm/split_page_table_lock.rst
+++ b/Documentation/mm/split_page_table_lock.rst
@@ -62,7 +62,7 @@ Support of split page table lock by an architecture
===================================================
There's no need in special enabling of PTE split page table lock: everything
-required is done by pagetable_pte_ctor() and pagetable_pte_dtor(), which
+required is done by pagetable_pte_ctor() and pagetable_dtor(), which
must be called on PTE table allocation / freeing.
Make sure the architecture doesn't use slab allocator for page table
@@ -73,7 +73,7 @@ PMD split lock only makes sense if you have more than two page table
levels.
PMD split lock enabling requires pagetable_pmd_ctor() call on PMD table
-allocation and pagetable_pmd_dtor() on freeing.
+allocation and pagetable_dtor() on freeing.
Allocation usually happens in pmd_alloc_one(), freeing in pmd_free() and
pmd_free_tlb(), but make sure you cover all PMD table allocation / freeing
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index f40d06ad5d2a3..ef79bf1e8563f 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -41,7 +41,7 @@ __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr)
{
struct ptdesc *ptdesc = page_ptdesc(pte);
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
#ifndef CONFIG_ARM_LPAE
/*
@@ -61,7 +61,7 @@ __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)
#ifdef CONFIG_ARM_LPAE
struct ptdesc *ptdesc = virt_to_ptdesc(pmdp);
- pagetable_pmd_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
#endif
}
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index 445282cde9afb..408d0f36a8a8f 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -82,7 +82,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
{
struct ptdesc *ptdesc = page_ptdesc(pte);
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
}
@@ -92,7 +92,7 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
{
struct ptdesc *ptdesc = virt_to_ptdesc(pmdp);
- pagetable_pmd_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
}
#endif
@@ -106,7 +106,7 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pudp,
if (!pgtable_l4_enabled())
return;
- pagetable_pud_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
}
#endif
@@ -120,7 +120,7 @@ static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4dp,
if (!pgtable_l5_enabled())
return;
- pagetable_p4d_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
}
#endif
diff --git a/arch/csky/include/asm/pgalloc.h b/arch/csky/include/asm/pgalloc.h
index 9c84c9012e534..f1ce5b7b28f22 100644
--- a/arch/csky/include/asm/pgalloc.h
+++ b/arch/csky/include/asm/pgalloc.h
@@ -63,7 +63,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
#define __pte_free_tlb(tlb, pte, address) \
do { \
- pagetable_pte_dtor(page_ptdesc(pte)); \
+ pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc(tlb, page_ptdesc(pte)); \
} while (0)
diff --git a/arch/hexagon/include/asm/pgalloc.h b/arch/hexagon/include/asm/pgalloc.h
index 55988625e6fbc..40e42a0e71673 100644
--- a/arch/hexagon/include/asm/pgalloc.h
+++ b/arch/hexagon/include/asm/pgalloc.h
@@ -89,7 +89,7 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_pte_dtor((page_ptdesc(pte))); \
+ pagetable_dtor((page_ptdesc(pte))); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
diff --git a/arch/loongarch/include/asm/pgalloc.h b/arch/loongarch/include/asm/pgalloc.h
index a7b9c9e73593d..7211dff8c969e 100644
--- a/arch/loongarch/include/asm/pgalloc.h
+++ b/arch/loongarch/include/asm/pgalloc.h
@@ -57,7 +57,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
#define __pte_free_tlb(tlb, pte, address) \
do { \
- pagetable_pte_dtor(page_ptdesc(pte)); \
+ pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), page_ptdesc(pte)); \
} while (0)
diff --git a/arch/m68k/include/asm/mcf_pgalloc.h b/arch/m68k/include/asm/mcf_pgalloc.h
index 302c5bf67179e..22d6c1fcabfb4 100644
--- a/arch/m68k/include/asm/mcf_pgalloc.h
+++ b/arch/m68k/include/asm/mcf_pgalloc.h
@@ -37,7 +37,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pgtable,
{
struct ptdesc *ptdesc = virt_to_ptdesc(pgtable);
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
@@ -61,7 +61,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pgtable)
{
struct ptdesc *ptdesc = virt_to_ptdesc(pgtable);
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
diff --git a/arch/m68k/include/asm/sun3_pgalloc.h b/arch/m68k/include/asm/sun3_pgalloc.h
index 4a137eecb6fe4..2b626cb3ad0ae 100644
--- a/arch/m68k/include/asm/sun3_pgalloc.h
+++ b/arch/m68k/include/asm/sun3_pgalloc.h
@@ -19,7 +19,7 @@ extern const char bad_pmd_string[];
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_pte_dtor(page_ptdesc(pte)); \
+ pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), page_ptdesc(pte)); \
} while (0)
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index c1761d309fc61..81715cece70c6 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -201,7 +201,7 @@ int free_pointer_table(void *table, int type)
list_del(dp);
mmu_page_dtor((void *)page);
if (type == TABLE_PTE)
- pagetable_pte_dtor(virt_to_ptdesc((void *)page));
+ pagetable_dtor(virt_to_ptdesc((void *)page));
free_page (page);
return 1;
} else if (ptable_list[type].next != dp) {
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h
index f4440edcd8fe2..36d9805033c4b 100644
--- a/arch/mips/include/asm/pgalloc.h
+++ b/arch/mips/include/asm/pgalloc.h
@@ -56,7 +56,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
#define __pte_free_tlb(tlb, pte, address) \
do { \
- pagetable_pte_dtor(page_ptdesc(pte)); \
+ pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), page_ptdesc(pte)); \
} while (0)
diff --git a/arch/nios2/include/asm/pgalloc.h b/arch/nios2/include/asm/pgalloc.h
index ce6bb8e74271f..12a536b7bfbd4 100644
--- a/arch/nios2/include/asm/pgalloc.h
+++ b/arch/nios2/include/asm/pgalloc.h
@@ -30,7 +30,7 @@ extern pgd_t *pgd_alloc(struct mm_struct *mm);
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_pte_dtor(page_ptdesc(pte)); \
+ pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
diff --git a/arch/openrisc/include/asm/pgalloc.h b/arch/openrisc/include/asm/pgalloc.h
index c6a73772a5466..596e2355824e3 100644
--- a/arch/openrisc/include/asm/pgalloc.h
+++ b/arch/openrisc/include/asm/pgalloc.h
@@ -68,7 +68,7 @@ extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm);
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_pte_dtor(page_ptdesc(pte)); \
+ pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
diff --git a/arch/powerpc/mm/book3s64/mmu_context.c b/arch/powerpc/mm/book3s64/mmu_context.c
index 1715b07c630c9..4e1e45420bd49 100644
--- a/arch/powerpc/mm/book3s64/mmu_context.c
+++ b/arch/powerpc/mm/book3s64/mmu_context.c
@@ -253,7 +253,7 @@ static void pmd_frag_destroy(void *pmd_frag)
count = ((unsigned long)pmd_frag & ~PAGE_MASK) >> PMD_FRAG_SIZE_SHIFT;
/* We allow PTE_FRAG_NR fragments from a PTE page */
if (atomic_sub_and_test(PMD_FRAG_NR - count, &ptdesc->pt_frag_refcount)) {
- pagetable_pmd_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
}
diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
index 3745425280808..3f28e4acd920b 100644
--- a/arch/powerpc/mm/book3s64/pgtable.c
+++ b/arch/powerpc/mm/book3s64/pgtable.c
@@ -477,7 +477,7 @@ void pmd_fragment_free(unsigned long *pmd)
BUG_ON(atomic_read(&ptdesc->pt_frag_refcount) <= 0);
if (atomic_dec_and_test(&ptdesc->pt_frag_refcount)) {
- pagetable_pmd_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
}
diff --git a/arch/powerpc/mm/pgtable-frag.c b/arch/powerpc/mm/pgtable-frag.c
index e89f64a0f24ae..713268ccb1a0e 100644
--- a/arch/powerpc/mm/pgtable-frag.c
+++ b/arch/powerpc/mm/pgtable-frag.c
@@ -25,7 +25,7 @@ void pte_frag_destroy(void *pte_frag)
count = ((unsigned long)pte_frag & ~PAGE_MASK) >> PTE_FRAG_SIZE_SHIFT;
/* We allow PTE_FRAG_NR fragments from a PTE page */
if (atomic_sub_and_test(PTE_FRAG_NR - count, &ptdesc->pt_frag_refcount)) {
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
}
@@ -111,7 +111,7 @@ static void pte_free_now(struct rcu_head *head)
struct ptdesc *ptdesc;
ptdesc = container_of(head, struct ptdesc, pt_rcu_head);
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h
index 3466fbe2e508d..b6793c5c99296 100644
--- a/arch/riscv/include/asm/pgalloc.h
+++ b/arch/riscv/include/asm/pgalloc.h
@@ -100,7 +100,7 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
if (pgtable_l4_enabled) {
struct ptdesc *ptdesc = virt_to_ptdesc(pud);
- pagetable_pud_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
riscv_tlb_remove_ptdesc(tlb, ptdesc);
}
}
@@ -111,7 +111,7 @@ static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
if (pgtable_l5_enabled) {
struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
- pagetable_p4d_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
}
}
@@ -144,7 +144,7 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
{
struct ptdesc *ptdesc = virt_to_ptdesc(pmd);
- pagetable_pmd_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
riscv_tlb_remove_ptdesc(tlb, ptdesc);
}
@@ -155,7 +155,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
{
struct ptdesc *ptdesc = page_ptdesc(pte);
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
riscv_tlb_remove_ptdesc(tlb, ptdesc);
}
#endif /* CONFIG_MMU */
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index fc53ce748c804..8d703fb51b1dc 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -1558,7 +1558,7 @@ static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
return;
}
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
if (PageReserved(page))
free_reserved_page(page);
else
@@ -1580,7 +1580,7 @@ static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, bool is_vmemm
}
if (!is_vmemmap)
- pagetable_pmd_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
if (PageReserved(page))
free_reserved_page(page);
else
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index a0c1ca5d8423c..5fced6d3c36b0 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -66,7 +66,7 @@ static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
if (mm_p4d_folded(mm))
return;
- pagetable_p4d_dtor(virt_to_ptdesc(p4d));
+ pagetable_dtor(virt_to_ptdesc(p4d));
crst_table_free(mm, (unsigned long *) p4d);
}
@@ -87,7 +87,7 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
if (mm_pud_folded(mm))
return;
- pagetable_pud_dtor(virt_to_ptdesc(pud));
+ pagetable_dtor(virt_to_ptdesc(pud));
crst_table_free(mm, (unsigned long *) pud);
}
@@ -109,7 +109,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
{
if (mm_pmd_folded(mm))
return;
- pagetable_pmd_dtor(virt_to_ptdesc(pmd));
+ pagetable_dtor(virt_to_ptdesc(pmd));
crst_table_free(mm, (unsigned long *) pmd);
}
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index b946964afce8e..74b6fba4c2ee3 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -102,7 +102,7 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
{
if (mm_pmd_folded(tlb->mm))
return;
- pagetable_pmd_dtor(virt_to_ptdesc(pmd));
+ pagetable_dtor(virt_to_ptdesc(pmd));
__tlb_adjust_range(tlb, address, PAGE_SIZE);
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
@@ -122,7 +122,7 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
{
if (mm_pud_folded(tlb->mm))
return;
- pagetable_pud_dtor(virt_to_ptdesc(pud));
+ pagetable_dtor(virt_to_ptdesc(pud));
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
tlb->cleared_p4ds = 1;
@@ -141,7 +141,7 @@ static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
{
if (mm_p4d_folded(tlb->mm))
return;
- pagetable_p4d_dtor(virt_to_ptdesc(p4d));
+ pagetable_dtor(virt_to_ptdesc(p4d));
__tlb_adjust_range(tlb, address, PAGE_SIZE);
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index 58696a0c4e4ac..569de24d33761 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -182,7 +182,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
static void pagetable_pte_dtor_free(struct ptdesc *ptdesc)
{
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
diff --git a/arch/sh/include/asm/pgalloc.h b/arch/sh/include/asm/pgalloc.h
index 5d8577ab15911..96d938fdf2244 100644
--- a/arch/sh/include/asm/pgalloc.h
+++ b/arch/sh/include/asm/pgalloc.h
@@ -34,7 +34,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_pte_dtor(page_ptdesc(pte)); \
+ pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 21f8cbbd0581c..05882bca5b732 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -2915,7 +2915,7 @@ static void __pte_free(pgtable_t pte)
{
struct ptdesc *ptdesc = virt_to_ptdesc(pte);
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 9df51a62333d6..e3a72c884b867 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -372,7 +372,7 @@ void pte_free(struct mm_struct *mm, pgtable_t ptep)
page = pfn_to_page(__nocache_pa((unsigned long)ptep) >> PAGE_SHIFT);
spin_lock(&mm->page_table_lock);
if (page_ref_dec_return(page) == 1)
- pagetable_pte_dtor(page_ptdesc(page));
+ pagetable_dtor(page_ptdesc(page));
spin_unlock(&mm->page_table_lock);
srmmu_free_nocache(ptep, SRMMU_PTE_TABLE_SIZE);
diff --git a/arch/um/include/asm/pgalloc.h b/arch/um/include/asm/pgalloc.h
index 04fb4e6969a46..f0af23c3aeb2b 100644
--- a/arch/um/include/asm/pgalloc.h
+++ b/arch/um/include/asm/pgalloc.h
@@ -27,7 +27,7 @@ extern pgd_t *pgd_alloc(struct mm_struct *);
#define __pte_free_tlb(tlb, pte, address) \
do { \
- pagetable_pte_dtor(page_ptdesc(pte)); \
+ pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
@@ -35,7 +35,7 @@ do { \
#define __pmd_free_tlb(tlb, pmd, address) \
do { \
- pagetable_pmd_dtor(virt_to_ptdesc(pmd)); \
+ pagetable_dtor(virt_to_ptdesc(pmd)); \
tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pmd)); \
} while (0)
@@ -43,7 +43,7 @@ do { \
#define __pud_free_tlb(tlb, pud, address) \
do { \
- pagetable_pud_dtor(virt_to_ptdesc(pud)); \
+ pagetable_dtor(virt_to_ptdesc(pud)); \
tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pud)); \
} while (0)
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 3d6e84da45b24..a6cd9660e29ec 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -60,7 +60,7 @@ early_param("userpte", setup_userpte);
void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
{
- pagetable_pte_dtor(page_ptdesc(pte));
+ pagetable_dtor(page_ptdesc(pte));
paravirt_release_pte(page_to_pfn(pte));
paravirt_tlb_remove_table(tlb, pte);
}
@@ -77,7 +77,7 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
#ifdef CONFIG_X86_PAE
tlb->need_flush_all = 1;
#endif
- pagetable_pmd_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
paravirt_tlb_remove_table(tlb, ptdesc_page(ptdesc));
}
@@ -86,7 +86,7 @@ void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
{
struct ptdesc *ptdesc = virt_to_ptdesc(pud);
- pagetable_pud_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
paravirt_tlb_remove_table(tlb, virt_to_page(pud));
}
@@ -96,7 +96,7 @@ void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d)
{
struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
- pagetable_p4d_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
paravirt_release_p4d(__pa(p4d) >> PAGE_SHIFT);
paravirt_tlb_remove_table(tlb, virt_to_page(p4d));
}
@@ -233,7 +233,7 @@ static void free_pmds(struct mm_struct *mm, pmd_t *pmds[], int count)
if (pmds[i]) {
ptdesc = virt_to_ptdesc(pmds[i]);
- pagetable_pmd_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
mm_dec_nr_pmds(mm);
}
@@ -867,7 +867,7 @@ int pud_free_pmd_page(pud_t *pud, unsigned long addr)
free_page((unsigned long)pmd_sv);
- pagetable_pmd_dtor(virt_to_ptdesc(pmd));
+ pagetable_dtor(virt_to_ptdesc(pmd));
free_page((unsigned long)pmd);
return 1;
diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h
index bb482eeca0c3e..4afb346eae255 100644
--- a/include/asm-generic/pgalloc.h
+++ b/include/asm-generic/pgalloc.h
@@ -109,7 +109,7 @@ static inline void pte_free(struct mm_struct *mm, struct page *pte_page)
{
struct ptdesc *ptdesc = page_ptdesc(pte_page);
- pagetable_pte_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
@@ -153,7 +153,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
struct ptdesc *ptdesc = virt_to_ptdesc(pmd);
BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
- pagetable_pmd_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
#endif
@@ -202,7 +202,7 @@ static inline void __pud_free(struct mm_struct *mm, pud_t *pud)
struct ptdesc *ptdesc = virt_to_ptdesc(pud);
BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
- pagetable_pud_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
@@ -248,7 +248,7 @@ static inline void __p4d_free(struct mm_struct *mm, p4d_t *p4d)
struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
- pagetable_p4d_dtor(ptdesc);
+ pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
}
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5d82f42ddd5cc..cad11fa10c192 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2992,6 +2992,15 @@ static inline bool ptlock_init(struct ptdesc *ptdesc) { return true; }
static inline void ptlock_free(struct ptdesc *ptdesc) {}
#endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */
+static inline void pagetable_dtor(struct ptdesc *ptdesc)
+{
+ struct folio *folio = ptdesc_folio(ptdesc);
+
+ ptlock_free(ptdesc);
+ __folio_clear_pgtable(folio);
+ lruvec_stat_sub_folio(folio, NR_PAGETABLE);
+}
+
static inline bool pagetable_pte_ctor(struct ptdesc *ptdesc)
{
struct folio *folio = ptdesc_folio(ptdesc);
@@ -3003,15 +3012,6 @@ static inline bool pagetable_pte_ctor(struct ptdesc *ptdesc)
return true;
}
-static inline void pagetable_pte_dtor(struct ptdesc *ptdesc)
-{
- struct folio *folio = ptdesc_folio(ptdesc);
-
- ptlock_free(ptdesc);
- __folio_clear_pgtable(folio);
- lruvec_stat_sub_folio(folio, NR_PAGETABLE);
-}
-
pte_t *___pte_offset_map(pmd_t *pmd, unsigned long addr, pmd_t *pmdvalp);
static inline pte_t *__pte_offset_map(pmd_t *pmd, unsigned long addr,
pmd_t *pmdvalp)
@@ -3088,14 +3088,6 @@ static inline bool pmd_ptlock_init(struct ptdesc *ptdesc)
return ptlock_init(ptdesc);
}
-static inline void pmd_ptlock_free(struct ptdesc *ptdesc)
-{
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
- VM_BUG_ON_PAGE(ptdesc->pmd_huge_pte, ptdesc_page(ptdesc));
-#endif
- ptlock_free(ptdesc);
-}
-
#define pmd_huge_pte(mm, pmd) (pmd_ptdesc(pmd)->pmd_huge_pte)
#else
@@ -3106,7 +3098,6 @@ static inline spinlock_t *pmd_lockptr(struct mm_struct *mm, pmd_t *pmd)
}
static inline bool pmd_ptlock_init(struct ptdesc *ptdesc) { return true; }
-static inline void pmd_ptlock_free(struct ptdesc *ptdesc) {}
#define pmd_huge_pte(mm, pmd) ((mm)->pmd_huge_pte)
@@ -3131,15 +3122,6 @@ static inline bool pagetable_pmd_ctor(struct ptdesc *ptdesc)
return true;
}
-static inline void pagetable_pmd_dtor(struct ptdesc *ptdesc)
-{
- struct folio *folio = ptdesc_folio(ptdesc);
-
- pmd_ptlock_free(ptdesc);
- __folio_clear_pgtable(folio);
- lruvec_stat_sub_folio(folio, NR_PAGETABLE);
-}
-
/*
* No scalability reason to split PUD locks yet, but follow the same pattern
* as the PMD locks to make it easier if we decide to. The VM should not be
@@ -3167,14 +3149,6 @@ static inline void pagetable_pud_ctor(struct ptdesc *ptdesc)
lruvec_stat_add_folio(folio, NR_PAGETABLE);
}
-static inline void pagetable_pud_dtor(struct ptdesc *ptdesc)
-{
- struct folio *folio = ptdesc_folio(ptdesc);
-
- __folio_clear_pgtable(folio);
- lruvec_stat_sub_folio(folio, NR_PAGETABLE);
-}
-
static inline void pagetable_p4d_ctor(struct ptdesc *ptdesc)
{
struct folio *folio = ptdesc_folio(ptdesc);
@@ -3183,14 +3157,6 @@ static inline void pagetable_p4d_ctor(struct ptdesc *ptdesc)
lruvec_stat_add_folio(folio, NR_PAGETABLE);
}
-static inline void pagetable_p4d_dtor(struct ptdesc *ptdesc)
-{
- struct folio *folio = ptdesc_folio(ptdesc);
-
- __folio_clear_pgtable(folio);
- lruvec_stat_sub_folio(folio, NR_PAGETABLE);
-}
-
extern void __init pagecache_init(void);
extern void free_initmem(void);
diff --git a/mm/memory.c b/mm/memory.c
index 9423967b24180..ad871e564568b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -7051,7 +7051,8 @@ bool ptlock_alloc(struct ptdesc *ptdesc)
void ptlock_free(struct ptdesc *ptdesc)
{
- kmem_cache_free(page_ptl_cachep, ptdesc->ptl);
+ if (ptdesc->ptl)
+ kmem_cache_free(page_ptl_cachep, ptdesc->ptl);
}
#endif
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 08/15] arm: pgtable: move pagetable_dtor() to __tlb_remove_table()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (6 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor() Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2024-12-30 9:07 ` [PATCH v4 09/15] arm64: " Qi Zheng
` (8 subsequent siblings)
16 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
Move pagetable_dtor() to __tlb_remove_table(), so that ptlock and page
table pages can be freed together (regardless of whether RCU is used).
This prevents the use-after-free problem where the ptlock is freed
immediately but the page table pages is freed later via RCU.
Page tables shouldn't have swap cache, so use pagetable_free() instead of
free_page_and_swap_cache() to free page table pages.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: linux-arm-kernel@lists.infradead.org
---
arch/arm/include/asm/tlb.h | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index ef79bf1e8563f..264ab635e807a 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -26,12 +26,14 @@
#else /* !CONFIG_MMU */
-#include <linux/swap.h>
#include <asm/tlbflush.h>
static inline void __tlb_remove_table(void *_table)
{
- free_page_and_swap_cache((struct page *)_table);
+ struct ptdesc *ptdesc = (struct ptdesc *)_table;
+
+ pagetable_dtor(ptdesc);
+ pagetable_free(ptdesc);
}
#include <asm-generic/tlb.h>
@@ -41,8 +43,6 @@ __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr)
{
struct ptdesc *ptdesc = page_ptdesc(pte);
- pagetable_dtor(ptdesc);
-
#ifndef CONFIG_ARM_LPAE
/*
* With the classic ARM MMU, a pte page has two corresponding pmd
@@ -61,7 +61,6 @@ __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)
#ifdef CONFIG_ARM_LPAE
struct ptdesc *ptdesc = virt_to_ptdesc(pmdp);
- pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
#endif
}
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 09/15] arm64: pgtable: move pagetable_dtor() to __tlb_remove_table()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (7 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 08/15] arm: pgtable: move pagetable_dtor() to __tlb_remove_table() Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2024-12-30 9:07 ` [PATCH v4 10/15] riscv: " Qi Zheng
` (7 subsequent siblings)
16 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
Move pagetable_dtor() to __tlb_remove_table(), so that ptlock and page
table pages can be freed together (regardless of whether RCU is used).
This prevents the use-after-free problem where the ptlock is freed
immediately but the page table pages is freed later via RCU.
Page tables shouldn't have swap cache, so use pagetable_free() instead of
free_page_and_swap_cache() to free page table pages.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: linux-arm-kernel@lists.infradead.org
---
arch/arm64/include/asm/tlb.h | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index 408d0f36a8a8f..93591a80b5bfb 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -9,11 +9,13 @@
#define __ASM_TLB_H
#include <linux/pagemap.h>
-#include <linux/swap.h>
static inline void __tlb_remove_table(void *_table)
{
- free_page_and_swap_cache((struct page *)_table);
+ struct ptdesc *ptdesc = (struct ptdesc *)_table;
+
+ pagetable_dtor(ptdesc);
+ pagetable_free(ptdesc);
}
#define tlb_flush tlb_flush
@@ -82,7 +84,6 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
{
struct ptdesc *ptdesc = page_ptdesc(pte);
- pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
}
@@ -92,7 +93,6 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
{
struct ptdesc *ptdesc = virt_to_ptdesc(pmdp);
- pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
}
#endif
@@ -106,7 +106,6 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pudp,
if (!pgtable_l4_enabled())
return;
- pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
}
#endif
@@ -120,7 +119,6 @@ static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4dp,
if (!pgtable_l5_enabled())
return;
- pagetable_dtor(ptdesc);
tlb_remove_ptdesc(tlb, ptdesc);
}
#endif
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (8 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 09/15] arm64: " Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2025-01-02 16:53 ` Kevin Brodsky
2024-12-30 9:07 ` [PATCH v4 11/15] x86: " Qi Zheng
` (6 subsequent siblings)
16 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
Move pagetable_dtor() to __tlb_remove_table(), so that ptlock and page
table pages can be freed together (regardless of whether RCU is used).
This prevents the use-after-free problem where the ptlock is freed
immediately but the page table pages is freed later via RCU.
Page tables shouldn't have swap cache, so use pagetable_free() instead of
free_page_and_swap_cache() to free page table pages.
By the way, move the comment above __tlb_remove_table() to
riscv_tlb_remove_ptdesc(), it will be more appropriate.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: linux-riscv@lists.infradead.org
---
arch/riscv/include/asm/pgalloc.h | 38 ++++++++++++++------------------
arch/riscv/include/asm/tlb.h | 14 ++++--------
2 files changed, 21 insertions(+), 31 deletions(-)
diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h
index b6793c5c99296..c8907b8317115 100644
--- a/arch/riscv/include/asm/pgalloc.h
+++ b/arch/riscv/include/asm/pgalloc.h
@@ -15,12 +15,22 @@
#define __HAVE_ARCH_PUD_FREE
#include <asm-generic/pgalloc.h>
+/*
+ * While riscv platforms with riscv_ipi_for_rfence as true require an IPI to
+ * perform TLB shootdown, some platforms with riscv_ipi_for_rfence as false use
+ * SBI to perform TLB shootdown. To keep software pagetable walkers safe in this
+ * case we switch to RCU based table free (MMU_GATHER_RCU_TABLE_FREE). See the
+ * comment below 'ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE' in include/asm-generic/tlb.h
+ * for more details.
+ */
static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt)
{
- if (riscv_use_sbi_for_rfence())
+ if (riscv_use_sbi_for_rfence()) {
tlb_remove_ptdesc(tlb, pt);
- else
+ } else {
+ pagetable_dtor(pt);
tlb_remove_page_ptdesc(tlb, pt);
+ }
}
static inline void pmd_populate_kernel(struct mm_struct *mm,
@@ -97,23 +107,15 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
unsigned long addr)
{
- if (pgtable_l4_enabled) {
- struct ptdesc *ptdesc = virt_to_ptdesc(pud);
-
- pagetable_dtor(ptdesc);
- riscv_tlb_remove_ptdesc(tlb, ptdesc);
- }
+ if (pgtable_l4_enabled)
+ riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(pud));
}
static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
unsigned long addr)
{
- if (pgtable_l5_enabled) {
- struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
-
- pagetable_dtor(ptdesc);
+ if (pgtable_l5_enabled)
riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
- }
}
#endif /* __PAGETABLE_PMD_FOLDED */
@@ -142,10 +144,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
unsigned long addr)
{
- struct ptdesc *ptdesc = virt_to_ptdesc(pmd);
-
- pagetable_dtor(ptdesc);
- riscv_tlb_remove_ptdesc(tlb, ptdesc);
+ riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(pmd));
}
#endif /* __PAGETABLE_PMD_FOLDED */
@@ -153,10 +152,7 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
unsigned long addr)
{
- struct ptdesc *ptdesc = page_ptdesc(pte);
-
- pagetable_dtor(ptdesc);
- riscv_tlb_remove_ptdesc(tlb, ptdesc);
+ riscv_tlb_remove_ptdesc(tlb, page_ptdesc(pte));
}
#endif /* CONFIG_MMU */
diff --git a/arch/riscv/include/asm/tlb.h b/arch/riscv/include/asm/tlb.h
index 1f6c38420d8e0..ded8724b3c4f7 100644
--- a/arch/riscv/include/asm/tlb.h
+++ b/arch/riscv/include/asm/tlb.h
@@ -11,19 +11,13 @@ struct mmu_gather;
static void tlb_flush(struct mmu_gather *tlb);
#ifdef CONFIG_MMU
-#include <linux/swap.h>
-/*
- * While riscv platforms with riscv_ipi_for_rfence as true require an IPI to
- * perform TLB shootdown, some platforms with riscv_ipi_for_rfence as false use
- * SBI to perform TLB shootdown. To keep software pagetable walkers safe in this
- * case we switch to RCU based table free (MMU_GATHER_RCU_TABLE_FREE). See the
- * comment below 'ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE' in include/asm-generic/tlb.h
- * for more details.
- */
static inline void __tlb_remove_table(void *table)
{
- free_page_and_swap_cache(table);
+ struct ptdesc *ptdesc = (struct ptdesc *)table;
+
+ pagetable_dtor(ptdesc);
+ pagetable_free(ptdesc);
}
#endif /* CONFIG_MMU */
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 11/15] x86: pgtable: move pagetable_dtor() to __tlb_remove_table()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (9 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 10/15] riscv: " Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2024-12-30 9:07 ` [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD " Qi Zheng
` (5 subsequent siblings)
16 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
Move pagetable_dtor() to __tlb_remove_table(), so that ptlock and page
table pages can be freed together (regardless of whether RCU is used).
This prevents the use-after-free problem where the ptlock is freed
immediately but the page table pages is freed later via RCU.
Page tables shouldn't have swap cache, so use pagetable_free() instead of
free_page_and_swap_cache() to free page table pages.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: x86@kernel.org
---
arch/x86/include/asm/tlb.h | 17 ++++++++++-------
arch/x86/kernel/paravirt.c | 1 +
arch/x86/mm/pgtable.c | 12 ++----------
3 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
index 73f0786181cc9..f64730be5ad67 100644
--- a/arch/x86/include/asm/tlb.h
+++ b/arch/x86/include/asm/tlb.h
@@ -31,24 +31,27 @@ static inline void tlb_flush(struct mmu_gather *tlb)
*/
static inline void __tlb_remove_table(void *table)
{
- free_page_and_swap_cache(table);
+ struct ptdesc *ptdesc = (struct ptdesc *)table;
+
+ pagetable_dtor(ptdesc);
+ pagetable_free(ptdesc);
}
#ifdef CONFIG_PT_RECLAIM
static inline void __tlb_remove_table_one_rcu(struct rcu_head *head)
{
- struct page *page;
+ struct ptdesc *ptdesc;
- page = container_of(head, struct page, rcu_head);
- put_page(page);
+ ptdesc = container_of(head, struct ptdesc, pt_rcu_head);
+ __tlb_remove_table(ptdesc);
}
static inline void __tlb_remove_table_one(void *table)
{
- struct page *page;
+ struct ptdesc *ptdesc;
- page = table;
- call_rcu(&page->rcu_head, __tlb_remove_table_one_rcu);
+ ptdesc = table;
+ call_rcu(&ptdesc->pt_rcu_head, __tlb_remove_table_one_rcu);
}
#define __tlb_remove_table_one __tlb_remove_table_one
#endif /* CONFIG_PT_RECLAIM */
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 7bdcf152778c0..46d5d325483b0 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -62,6 +62,7 @@ void __init native_pv_lock_init(void)
#ifndef CONFIG_PT_RECLAIM
static void native_tlb_remove_table(struct mmu_gather *tlb, void *table)
{
+ pagetable_dtor(table);
tlb_remove_page(tlb, table);
}
#else
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index a6cd9660e29ec..a0b0e501ba663 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -23,6 +23,7 @@ EXPORT_SYMBOL(physical_mask);
static inline
void paravirt_tlb_remove_table(struct mmu_gather *tlb, void *table)
{
+ pagetable_dtor(table);
tlb_remove_page(tlb, table);
}
#else
@@ -60,7 +61,6 @@ early_param("userpte", setup_userpte);
void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
{
- pagetable_dtor(page_ptdesc(pte));
paravirt_release_pte(page_to_pfn(pte));
paravirt_tlb_remove_table(tlb, pte);
}
@@ -68,7 +68,6 @@ void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
#if CONFIG_PGTABLE_LEVELS > 2
void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
{
- struct ptdesc *ptdesc = virt_to_ptdesc(pmd);
paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
/*
* NOTE! For PAE, any changes to the top page-directory-pointer-table
@@ -77,16 +76,12 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
#ifdef CONFIG_X86_PAE
tlb->need_flush_all = 1;
#endif
- pagetable_dtor(ptdesc);
- paravirt_tlb_remove_table(tlb, ptdesc_page(ptdesc));
+ paravirt_tlb_remove_table(tlb, virt_to_page(pmd));
}
#if CONFIG_PGTABLE_LEVELS > 3
void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
{
- struct ptdesc *ptdesc = virt_to_ptdesc(pud);
-
- pagetable_dtor(ptdesc);
paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
paravirt_tlb_remove_table(tlb, virt_to_page(pud));
}
@@ -94,9 +89,6 @@ void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
#if CONFIG_PGTABLE_LEVELS > 4
void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d)
{
- struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
-
- pagetable_dtor(ptdesc);
paravirt_release_p4d(__pa(p4d) >> PAGE_SHIFT);
paravirt_tlb_remove_table(tlb, virt_to_page(p4d));
}
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD to __tlb_remove_table()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (10 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 11/15] x86: " Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2025-01-06 10:36 ` Alexander Gordeev
2024-12-30 9:07 ` [PATCH v4 13/15] mm: pgtable: introduce generic __tlb_remove_table() Qi Zheng
` (4 subsequent siblings)
16 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
To unify the PxD and PTE TLB free path, also move the pagetable_dtor() of
PMD|PUD|P4D to __tlb_remove_table().
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: linux-s390@vger.kernel.org
---
arch/s390/include/asm/tlb.h | 3 ---
arch/s390/mm/pgalloc.c | 14 ++++----------
2 files changed, 4 insertions(+), 13 deletions(-)
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index 74b6fba4c2ee3..79df7c0932c56 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -102,7 +102,6 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
{
if (mm_pmd_folded(tlb->mm))
return;
- pagetable_dtor(virt_to_ptdesc(pmd));
__tlb_adjust_range(tlb, address, PAGE_SIZE);
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
@@ -122,7 +121,6 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
{
if (mm_pud_folded(tlb->mm))
return;
- pagetable_dtor(virt_to_ptdesc(pud));
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
tlb->cleared_p4ds = 1;
@@ -141,7 +139,6 @@ static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
{
if (mm_p4d_folded(tlb->mm))
return;
- pagetable_dtor(virt_to_ptdesc(p4d));
__tlb_adjust_range(tlb, address, PAGE_SIZE);
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index 569de24d33761..c73b89811a264 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -180,7 +180,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
return table;
}
-static void pagetable_pte_dtor_free(struct ptdesc *ptdesc)
+static void pagetable_dtor_free(struct ptdesc *ptdesc)
{
pagetable_dtor(ptdesc);
pagetable_free(ptdesc);
@@ -190,20 +190,14 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
{
struct ptdesc *ptdesc = virt_to_ptdesc(table);
- pagetable_pte_dtor_free(ptdesc);
+ pagetable_dtor_free(ptdesc);
}
void __tlb_remove_table(void *table)
{
struct ptdesc *ptdesc = virt_to_ptdesc(table);
- struct page *page = ptdesc_page(ptdesc);
- if (compound_order(page) == CRST_ALLOC_ORDER) {
- /* pmd, pud, or p4d */
- pagetable_free(ptdesc);
- return;
- }
- pagetable_pte_dtor_free(ptdesc);
+ pagetable_dtor_free(ptdesc);
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -211,7 +205,7 @@ static void pte_free_now(struct rcu_head *head)
{
struct ptdesc *ptdesc = container_of(head, struct ptdesc, pt_rcu_head);
- pagetable_pte_dtor_free(ptdesc);
+ pagetable_dtor_free(ptdesc);
}
void pte_free_defer(struct mm_struct *mm, pgtable_t pgtable)
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 13/15] mm: pgtable: introduce generic __tlb_remove_table()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (11 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD " Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2025-01-07 12:32 ` Andreas Larsson
2025-01-07 14:20 ` Alexander Gordeev
2024-12-30 9:07 ` [PATCH v4 14/15] mm: pgtable: move __tlb_remove_table_one() in x86 to generic file Qi Zheng
` (3 subsequent siblings)
16 siblings, 2 replies; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
Several architectures (arm, arm64, riscv and x86) define exactly the
same __tlb_remove_table(), just introduce generic __tlb_remove_table() to
eliminate these duplications.
The s390 __tlb_remove_table() is nearly the same, so also make s390
__tlb_remove_table() version generic.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
---
arch/arm/include/asm/tlb.h | 9 ---------
arch/arm64/include/asm/tlb.h | 7 -------
arch/powerpc/include/asm/tlb.h | 1 +
arch/riscv/include/asm/tlb.h | 12 ------------
arch/s390/include/asm/tlb.h | 9 ++++-----
arch/s390/mm/pgalloc.c | 7 -------
arch/sparc/include/asm/tlb_32.h | 1 +
arch/sparc/include/asm/tlb_64.h | 1 +
arch/x86/include/asm/tlb.h | 17 -----------------
include/asm-generic/tlb.h | 15 +++++++++++++--
10 files changed, 20 insertions(+), 59 deletions(-)
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index 264ab635e807a..ea4fbe7b17f6f 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -27,15 +27,6 @@
#else /* !CONFIG_MMU */
#include <asm/tlbflush.h>
-
-static inline void __tlb_remove_table(void *_table)
-{
- struct ptdesc *ptdesc = (struct ptdesc *)_table;
-
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
-}
-
#include <asm-generic/tlb.h>
static inline void
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index 93591a80b5bfb..8d762607285cc 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -10,13 +10,6 @@
#include <linux/pagemap.h>
-static inline void __tlb_remove_table(void *_table)
-{
- struct ptdesc *ptdesc = (struct ptdesc *)_table;
-
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
-}
#define tlb_flush tlb_flush
static void tlb_flush(struct mmu_gather *tlb);
diff --git a/arch/powerpc/include/asm/tlb.h b/arch/powerpc/include/asm/tlb.h
index 1ca7d4c4b90db..2058e8d3e0138 100644
--- a/arch/powerpc/include/asm/tlb.h
+++ b/arch/powerpc/include/asm/tlb.h
@@ -37,6 +37,7 @@ extern void tlb_flush(struct mmu_gather *tlb);
*/
#define tlb_needs_table_invalidate() radix_enabled()
+#define __HAVE_ARCH_TLB_REMOVE_TABLE
/* Get the generic bits... */
#include <asm-generic/tlb.h>
diff --git a/arch/riscv/include/asm/tlb.h b/arch/riscv/include/asm/tlb.h
index ded8724b3c4f7..50b63b5c15bd8 100644
--- a/arch/riscv/include/asm/tlb.h
+++ b/arch/riscv/include/asm/tlb.h
@@ -10,18 +10,6 @@ struct mmu_gather;
static void tlb_flush(struct mmu_gather *tlb);
-#ifdef CONFIG_MMU
-
-static inline void __tlb_remove_table(void *table)
-{
- struct ptdesc *ptdesc = (struct ptdesc *)table;
-
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
-}
-
-#endif /* CONFIG_MMU */
-
#define tlb_flush tlb_flush
#include <asm-generic/tlb.h>
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index 79df7c0932c56..da4a7d175f69c 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -22,7 +22,6 @@
* Pages used for the page tables is a different story. FIXME: more
*/
-void __tlb_remove_table(void *_table);
static inline void tlb_flush(struct mmu_gather *tlb);
static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
struct page *page, bool delay_rmap, int page_size);
@@ -87,7 +86,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
tlb->cleared_pmds = 1;
if (mm_alloc_pgste(tlb->mm))
gmap_unlink(tlb->mm, (unsigned long *)pte, address);
- tlb_remove_ptdesc(tlb, pte);
+ tlb_remove_ptdesc(tlb, virt_to_ptdesc(pte));
}
/*
@@ -106,7 +105,7 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
tlb->cleared_puds = 1;
- tlb_remove_ptdesc(tlb, pmd);
+ tlb_remove_ptdesc(tlb, virt_to_ptdesc(pmd));
}
/*
@@ -124,7 +123,7 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
tlb->cleared_p4ds = 1;
- tlb_remove_ptdesc(tlb, pud);
+ tlb_remove_ptdesc(tlb, virt_to_ptdesc(pud));
}
/*
@@ -142,7 +141,7 @@ static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
__tlb_adjust_range(tlb, address, PAGE_SIZE);
tlb->mm->context.flush_mm = 1;
tlb->freed_tables = 1;
- tlb_remove_ptdesc(tlb, p4d);
+ tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
}
#endif /* _S390_TLB_H */
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index c73b89811a264..3e002dea6278f 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -193,13 +193,6 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
pagetable_dtor_free(ptdesc);
}
-void __tlb_remove_table(void *table)
-{
- struct ptdesc *ptdesc = virt_to_ptdesc(table);
-
- pagetable_dtor_free(ptdesc);
-}
-
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static void pte_free_now(struct rcu_head *head)
{
diff --git a/arch/sparc/include/asm/tlb_32.h b/arch/sparc/include/asm/tlb_32.h
index 5cd28a8793e39..910254867dfbd 100644
--- a/arch/sparc/include/asm/tlb_32.h
+++ b/arch/sparc/include/asm/tlb_32.h
@@ -2,6 +2,7 @@
#ifndef _SPARC_TLB_H
#define _SPARC_TLB_H
+#define __HAVE_ARCH_TLB_REMOVE_TABLE
#include <asm-generic/tlb.h>
#endif /* _SPARC_TLB_H */
diff --git a/arch/sparc/include/asm/tlb_64.h b/arch/sparc/include/asm/tlb_64.h
index 3037187482db7..1a6e694418e39 100644
--- a/arch/sparc/include/asm/tlb_64.h
+++ b/arch/sparc/include/asm/tlb_64.h
@@ -33,6 +33,7 @@ void flush_tlb_pending(void);
#define tlb_needs_table_invalidate() (false)
#endif
+#define __HAVE_ARCH_TLB_REMOVE_TABLE
#include <asm-generic/tlb.h>
#endif /* _SPARC64_TLB_H */
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
index f64730be5ad67..3858dbf75880e 100644
--- a/arch/x86/include/asm/tlb.h
+++ b/arch/x86/include/asm/tlb.h
@@ -20,23 +20,6 @@ static inline void tlb_flush(struct mmu_gather *tlb)
flush_tlb_mm_range(tlb->mm, start, end, stride_shift, tlb->freed_tables);
}
-/*
- * While x86 architecture in general requires an IPI to perform TLB
- * shootdown, enablement code for several hypervisors overrides
- * .flush_tlb_others hook in pv_mmu_ops and implements it by issuing
- * a hypercall. To keep software pagetable walkers safe in this case we
- * switch to RCU based table free (MMU_GATHER_RCU_TABLE_FREE). See the comment
- * below 'ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE' in include/asm-generic/tlb.h
- * for more details.
- */
-static inline void __tlb_remove_table(void *table)
-{
- struct ptdesc *ptdesc = (struct ptdesc *)table;
-
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
-}
-
#ifdef CONFIG_PT_RECLAIM
static inline void __tlb_remove_table_one_rcu(struct rcu_head *head)
{
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index 709830274b756..69de47c7ef3c5 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -153,8 +153,9 @@
*
* Useful if your architecture has non-page page directories.
*
- * When used, an architecture is expected to provide __tlb_remove_table()
- * which does the actual freeing of these pages.
+ * When used, an architecture is expected to provide __tlb_remove_table() or
+ * use the generic __tlb_remove_table(), which does the actual freeing of these
+ * pages.
*
* MMU_GATHER_RCU_TABLE_FREE
*
@@ -207,6 +208,16 @@ struct mmu_table_batch {
#define MAX_TABLE_BATCH \
((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *))
+#ifndef __HAVE_ARCH_TLB_REMOVE_TABLE
+static inline void __tlb_remove_table(void *table)
+{
+ struct ptdesc *ptdesc = (struct ptdesc *)table;
+
+ pagetable_dtor(ptdesc);
+ pagetable_free(ptdesc);
+}
+#endif
+
extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 14/15] mm: pgtable: move __tlb_remove_table_one() in x86 to generic file
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (12 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 13/15] mm: pgtable: introduce generic __tlb_remove_table() Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2024-12-30 9:07 ` [PATCH v4 15/15] mm: pgtable: introduce generic pagetable_dtor_free() Qi Zheng
` (2 subsequent siblings)
16 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
The __tlb_remove_table_one() in x86 does not contain architecture-specific
content, so move it to the generic file.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
---
arch/x86/include/asm/tlb.h | 19 -------------------
mm/mmu_gather.c | 20 ++++++++++++++++++--
2 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
index 3858dbf75880e..77f52bc1578a7 100644
--- a/arch/x86/include/asm/tlb.h
+++ b/arch/x86/include/asm/tlb.h
@@ -20,25 +20,6 @@ static inline void tlb_flush(struct mmu_gather *tlb)
flush_tlb_mm_range(tlb->mm, start, end, stride_shift, tlb->freed_tables);
}
-#ifdef CONFIG_PT_RECLAIM
-static inline void __tlb_remove_table_one_rcu(struct rcu_head *head)
-{
- struct ptdesc *ptdesc;
-
- ptdesc = container_of(head, struct ptdesc, pt_rcu_head);
- __tlb_remove_table(ptdesc);
-}
-
-static inline void __tlb_remove_table_one(void *table)
-{
- struct ptdesc *ptdesc;
-
- ptdesc = table;
- call_rcu(&ptdesc->pt_rcu_head, __tlb_remove_table_one_rcu);
-}
-#define __tlb_remove_table_one __tlb_remove_table_one
-#endif /* CONFIG_PT_RECLAIM */
-
static inline void invlpg(unsigned long addr)
{
asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
diff --git a/mm/mmu_gather.c b/mm/mmu_gather.c
index 1e21022bcf339..7aa6f18c500b2 100644
--- a/mm/mmu_gather.c
+++ b/mm/mmu_gather.c
@@ -311,13 +311,29 @@ static inline void tlb_table_invalidate(struct mmu_gather *tlb)
}
}
-#ifndef __tlb_remove_table_one
+#ifdef CONFIG_PT_RECLAIM
+static inline void __tlb_remove_table_one_rcu(struct rcu_head *head)
+{
+ struct ptdesc *ptdesc;
+
+ ptdesc = container_of(head, struct ptdesc, pt_rcu_head);
+ __tlb_remove_table(ptdesc);
+}
+
+static inline void __tlb_remove_table_one(void *table)
+{
+ struct ptdesc *ptdesc;
+
+ ptdesc = table;
+ call_rcu(&ptdesc->pt_rcu_head, __tlb_remove_table_one_rcu);
+}
+#else
static inline void __tlb_remove_table_one(void *table)
{
tlb_remove_table_sync_one();
__tlb_remove_table(table);
}
-#endif
+#endif /* CONFIG_PT_RECLAIM */
static void tlb_remove_table_one(void *table)
{
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v4 15/15] mm: pgtable: introduce generic pagetable_dtor_free()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (13 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 14/15] mm: pgtable: move __tlb_remove_table_one() in x86 to generic file Qi Zheng
@ 2024-12-30 9:07 ` Qi Zheng
2025-01-07 14:22 ` Alexander Gordeev
2024-12-31 0:24 ` [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Andrew Morton
2025-01-02 17:00 ` Kevin Brodsky
16 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2024-12-30 9:07 UTC (permalink / raw)
To: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Qi Zheng
The pte_free(), pmd_free(), __pud_free() and __p4d_free() in
asm-generic/pgalloc.h and the generic __tlb_remove_table() are basically
the same, so let's introduce pagetable_dtor_free() to deduplicate them.
In addition, the pagetable_dtor_free() in s390 does the same thing, so
let's s390 also calls generic pagetable_dtor_free().
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
arch/s390/mm/pgalloc.c | 6 ------
include/asm-generic/pgalloc.h | 12 ++++--------
include/asm-generic/tlb.h | 3 +--
include/linux/mm.h | 6 ++++++
4 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index 3e002dea6278f..a4e7619020931 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -180,12 +180,6 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
return table;
}
-static void pagetable_dtor_free(struct ptdesc *ptdesc)
-{
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
-}
-
void page_table_free(struct mm_struct *mm, unsigned long *table)
{
struct ptdesc *ptdesc = virt_to_ptdesc(table);
diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h
index 4afb346eae255..e3977ddca15e4 100644
--- a/include/asm-generic/pgalloc.h
+++ b/include/asm-generic/pgalloc.h
@@ -109,8 +109,7 @@ static inline void pte_free(struct mm_struct *mm, struct page *pte_page)
{
struct ptdesc *ptdesc = page_ptdesc(pte_page);
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
+ pagetable_dtor_free(ptdesc);
}
@@ -153,8 +152,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
struct ptdesc *ptdesc = virt_to_ptdesc(pmd);
BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
+ pagetable_dtor_free(ptdesc);
}
#endif
@@ -202,8 +200,7 @@ static inline void __pud_free(struct mm_struct *mm, pud_t *pud)
struct ptdesc *ptdesc = virt_to_ptdesc(pud);
BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
+ pagetable_dtor_free(ptdesc);
}
#ifndef __HAVE_ARCH_PUD_FREE
@@ -248,8 +245,7 @@ static inline void __p4d_free(struct mm_struct *mm, p4d_t *p4d)
struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
+ pagetable_dtor_free(ptdesc);
}
#ifndef __HAVE_ARCH_P4D_FREE
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index 69de47c7ef3c5..a96d4b440f3da 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -213,8 +213,7 @@ static inline void __tlb_remove_table(void *table)
{
struct ptdesc *ptdesc = (struct ptdesc *)table;
- pagetable_dtor(ptdesc);
- pagetable_free(ptdesc);
+ pagetable_dtor_free(ptdesc);
}
#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index cad11fa10c192..94078c488e904 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3001,6 +3001,12 @@ static inline void pagetable_dtor(struct ptdesc *ptdesc)
lruvec_stat_sub_folio(folio, NR_PAGETABLE);
}
+static inline void pagetable_dtor_free(struct ptdesc *ptdesc)
+{
+ pagetable_dtor(ptdesc);
+ pagetable_free(ptdesc);
+}
+
static inline bool pagetable_pte_ctor(struct ptdesc *ptdesc)
{
struct folio *folio = ptdesc_folio(ptdesc);
--
2.20.1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (14 preceding siblings ...)
2024-12-30 9:07 ` [PATCH v4 15/15] mm: pgtable: introduce generic pagetable_dtor_free() Qi Zheng
@ 2024-12-31 0:24 ` Andrew Morton
2025-01-02 17:00 ` Kevin Brodsky
16 siblings, 0 replies; 54+ messages in thread
From: Andrew Morton @ 2024-12-31 0:24 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts, linux-mm, linux-arm-kernel,
linuxppc-dev, linux-riscv, linux-s390, sparclinux, linux-kernel,
x86, linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, 30 Dec 2024 17:07:35 +0800 Qi Zheng <zhengqi.arch@bytedance.com> wrote:
> Changes in v4:
> - remove [PATCH v3 15/17] and [PATCH v3 16/17] (Mike Rapoport)
> (the tlb_remove_page_ptdesc() and tlb_remove_ptdesc() are intermediate
> products of the project: https://kernelnewbies.org/MatthewWilcox/Memdescs,
> so keep them)
> - collect Acked-by
Thanks, I've updated mm.git to v5.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 04/15] mm: pgtable: add statistics for P4D level page table
2024-12-30 9:07 ` [PATCH v4 04/15] mm: pgtable: add statistics for P4D level page table Qi Zheng
@ 2025-01-02 16:53 ` Kevin Brodsky
2025-01-03 3:53 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-02 16:53 UTC (permalink / raw)
To: Qi Zheng, peterz, agordeev, palmer, tglx, david, jannh, hughd,
yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um
On 30/12/2024 10:07, Qi Zheng wrote:
> diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h
> index 551d614d3369c..3466fbe2e508d 100644
> --- a/arch/riscv/include/asm/pgalloc.h
> +++ b/arch/riscv/include/asm/pgalloc.h
> @@ -108,8 +108,12 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
> static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
> unsigned long addr)
> {
> - if (pgtable_l5_enabled)
> + if (pgtable_l5_enabled) {
> + struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
> +
> + pagetable_p4d_dtor(ptdesc);
> riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
Nit: could use the new ptdesc variable here instead of calling
virt_to_ptdesc().
- Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2024-12-30 9:07 ` [PATCH v4 10/15] riscv: " Qi Zheng
@ 2025-01-02 16:53 ` Kevin Brodsky
2025-01-03 3:48 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-02 16:53 UTC (permalink / raw)
To: Qi Zheng, peterz, agordeev, palmer, tglx, david, jannh, hughd,
yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um
On 30/12/2024 10:07, Qi Zheng wrote:
> static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt)
> {
> - if (riscv_use_sbi_for_rfence())
> + if (riscv_use_sbi_for_rfence()) {
> tlb_remove_ptdesc(tlb, pt);
> - else
> + } else {
> + pagetable_dtor(pt);
> tlb_remove_page_ptdesc(tlb, pt);
I find the imbalance pretty confusing: pagetable_dtor() is called
explicitly before using tlb_remove_page() but not tlb_remove_ptdesc().
Doesn't that assume that CONFIG_MMU_GATHER_HAVE_TABLE_FREE is selected?
Could we not call pagetable_dtor() from __tlb_batch_free_encoded_pages()
to ensure that the dtor is always called just before freeing, and remove
the extra handling from arch code? I may well be missing something, I'm
not super familiar with the tlb handling code.
- Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table()
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
` (15 preceding siblings ...)
2024-12-31 0:24 ` [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Andrew Morton
@ 2025-01-02 17:00 ` Kevin Brodsky
2025-01-03 3:56 ` Qi Zheng
16 siblings, 1 reply; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-02 17:00 UTC (permalink / raw)
To: Qi Zheng, peterz, agordeev, palmer, tglx, david, jannh, hughd,
yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um
On 30/12/2024 10:07, Qi Zheng wrote:
> Qi Zheng (13):
> Revert "mm: pgtable: make ptlock be freed by RCU"
> mm: pgtable: add statistics for P4D level page table
> arm64: pgtable: use mmu gather to free p4d level page table
> s390: pgtable: add statistics for PUD and P4D level page table
> mm: pgtable: introduce pagetable_dtor()
> arm: pgtable: move pagetable_dtor() to __tlb_remove_table()
> arm64: pgtable: move pagetable_dtor() to __tlb_remove_table()
> riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
> x86: pgtable: move pagetable_dtor() to __tlb_remove_table()
> s390: pgtable: also move pagetable_dtor() of PxD to
> __tlb_remove_table()
> mm: pgtable: introduce generic __tlb_remove_table()
> mm: pgtable: move __tlb_remove_table_one() in x86 to generic file
> mm: pgtable: introduce generic pagetable_dtor_free()
Aside from the nit on patch 4 and the request for clarification on patch
10, this is looking good to me, so for the whole series (aside from my
own patches of course):
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
And happy new year!
Cheers,
- Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-02 16:53 ` Kevin Brodsky
@ 2025-01-03 3:48 ` Qi Zheng
2025-01-03 8:02 ` Kevin Brodsky
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-03 3:48 UTC (permalink / raw)
To: Kevin Brodsky
Cc: peterz, agordeev, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
Hi Kevin,
On 2025/1/3 00:53, Kevin Brodsky wrote:
> On 30/12/2024 10:07, Qi Zheng wrote:
>> static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt)
>> {
>> - if (riscv_use_sbi_for_rfence())
>> + if (riscv_use_sbi_for_rfence()) {
>> tlb_remove_ptdesc(tlb, pt);
>> - else
>> + } else {
>> + pagetable_dtor(pt);
>> tlb_remove_page_ptdesc(tlb, pt);
>
> I find the imbalance pretty confusing: pagetable_dtor() is called
> explicitly before using tlb_remove_page() but not tlb_remove_ptdesc().
> Doesn't that assume that CONFIG_MMU_GATHER_HAVE_TABLE_FREE is selected?
> Could we not call pagetable_dtor() from __tlb_batch_free_encoded_pages()
> to ensure that the dtor is always called just before freeing, and remove
In __tlb_batch_free_encoded_pages(), we can indeed detect PageTable()
and call pagetable_dtor() to dtor the page table pages.
But __tlb_batch_free_encoded_pages() is also used to free normal pages
(not page table pages), so I don't want to add overhead there.
But now I think maybe we can do this in tlb_remove_page_ptdesc(), like
this:
diff --git a/arch/csky/include/asm/pgalloc.h
b/arch/csky/include/asm/pgalloc.h
index f1ce5b7b28f22..e45c7e91dcbf9 100644
--- a/arch/csky/include/asm/pgalloc.h
+++ b/arch/csky/include/asm/pgalloc.h
@@ -63,7 +63,6 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
#define __pte_free_tlb(tlb, pte, address) \
do { \
- pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc(tlb, page_ptdesc(pte)); \
} while (0)
diff --git a/arch/hexagon/include/asm/pgalloc.h
b/arch/hexagon/include/asm/pgalloc.h
index 40e42a0e71673..9903449f45cff 100644
--- a/arch/hexagon/include/asm/pgalloc.h
+++ b/arch/hexagon/include/asm/pgalloc.h
@@ -89,7 +89,6 @@ static inline void pmd_populate_kernel(struct
mm_struct *mm, pmd_t *pmd,
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_dtor((page_ptdesc(pte))); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
diff --git a/arch/loongarch/include/asm/pgalloc.h
b/arch/loongarch/include/asm/pgalloc.h
index 7211dff8c969e..de5b3f5c85d1c 100644
--- a/arch/loongarch/include/asm/pgalloc.h
+++ b/arch/loongarch/include/asm/pgalloc.h
@@ -57,7 +57,6 @@ static inline pte_t *pte_alloc_one_kernel(struct
mm_struct *mm)
#define __pte_free_tlb(tlb, pte, address) \
do { \
- pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), page_ptdesc(pte)); \
} while (0)
diff --git a/arch/m68k/include/asm/sun3_pgalloc.h
b/arch/m68k/include/asm/sun3_pgalloc.h
index 2b626cb3ad0ae..731cc8f0731d3 100644
--- a/arch/m68k/include/asm/sun3_pgalloc.h
+++ b/arch/m68k/include/asm/sun3_pgalloc.h
@@ -19,7 +19,6 @@ extern const char bad_pmd_string[];
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), page_ptdesc(pte)); \
} while (0)
diff --git a/arch/mips/include/asm/pgalloc.h
b/arch/mips/include/asm/pgalloc.h
index 36d9805033c4b..964ad514be281 100644
--- a/arch/mips/include/asm/pgalloc.h
+++ b/arch/mips/include/asm/pgalloc.h
@@ -56,7 +56,6 @@ static inline void pgd_free(struct mm_struct *mm,
pgd_t *pgd)
#define __pte_free_tlb(tlb, pte, address) \
do { \
- pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), page_ptdesc(pte)); \
} while (0)
diff --git a/arch/nios2/include/asm/pgalloc.h
b/arch/nios2/include/asm/pgalloc.h
index 12a536b7bfbd4..ef6b4b8301ac6 100644
--- a/arch/nios2/include/asm/pgalloc.h
+++ b/arch/nios2/include/asm/pgalloc.h
@@ -30,7 +30,6 @@ extern pgd_t *pgd_alloc(struct mm_struct *mm);
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
diff --git a/arch/openrisc/include/asm/pgalloc.h
b/arch/openrisc/include/asm/pgalloc.h
index 596e2355824e3..9361205610910 100644
--- a/arch/openrisc/include/asm/pgalloc.h
+++ b/arch/openrisc/include/asm/pgalloc.h
@@ -68,7 +68,6 @@ extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm);
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
diff --git a/arch/riscv/include/asm/pgalloc.h
b/arch/riscv/include/asm/pgalloc.h
index c8907b8317115..61c26576614da 100644
--- a/arch/riscv/include/asm/pgalloc.h
+++ b/arch/riscv/include/asm/pgalloc.h
@@ -25,12 +25,10 @@
*/
static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb,
void *pt)
{
- if (riscv_use_sbi_for_rfence()) {
+ if (riscv_use_sbi_for_rfence())
tlb_remove_ptdesc(tlb, pt);
- } else {
- pagetable_dtor(pt);
+ else
tlb_remove_page_ptdesc(tlb, pt);
- }
}
static inline void pmd_populate_kernel(struct mm_struct *mm,
diff --git a/arch/sh/include/asm/pgalloc.h b/arch/sh/include/asm/pgalloc.h
index 96d938fdf2244..5b5c73e9fdb4b 100644
--- a/arch/sh/include/asm/pgalloc.h
+++ b/arch/sh/include/asm/pgalloc.h
@@ -34,7 +34,6 @@ static inline void pmd_populate(struct mm_struct *mm,
pmd_t *pmd,
#define __pte_free_tlb(tlb, pte, addr) \
do { \
- pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
diff --git a/arch/um/include/asm/pgalloc.h b/arch/um/include/asm/pgalloc.h
index f0af23c3aeb2b..4fd59fb184818 100644
--- a/arch/um/include/asm/pgalloc.h
+++ b/arch/um/include/asm/pgalloc.h
@@ -27,7 +27,6 @@ extern pgd_t *pgd_alloc(struct mm_struct *);
#define __pte_free_tlb(tlb, pte, address) \
do { \
- pagetable_dtor(page_ptdesc(pte)); \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
@@ -35,7 +34,6 @@ do {
\
#define __pmd_free_tlb(tlb, pmd, address) \
do { \
- pagetable_dtor(virt_to_ptdesc(pmd)); \
tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pmd)); \
} while (0)
@@ -43,7 +41,6 @@ do {
\
#define __pud_free_tlb(tlb, pud, address) \
do { \
- pagetable_dtor(virt_to_ptdesc(pud)); \
tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pud)); \
} while (0)
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index a96d4b440f3da..a59205863f431 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -506,6 +506,7 @@ static inline void tlb_remove_ptdesc(struct
mmu_gather *tlb, void *pt)
/* Like tlb_remove_ptdesc, but for page-like page directories. */
static inline void tlb_remove_page_ptdesc(struct mmu_gather *tlb,
struct ptdesc *pt)
{
+ pagetable_dtor(pt);
tlb_remove_page(tlb, ptdesc_page(pt));
}
This avoids explicitly calling pagetable_dtor() in the architecture
code. If that makes sense, I can send a formal separate patch to do
this.
Thanks,
Qi
> the extra handling from arch code? I may well be missing something, I'm
> not super familiar with the tlb handling code >
> - Kevin
^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [PATCH v4 04/15] mm: pgtable: add statistics for P4D level page table
2025-01-02 16:53 ` Kevin Brodsky
@ 2025-01-03 3:53 ` Qi Zheng
2025-01-03 7:46 ` Kevin Brodsky
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-03 3:53 UTC (permalink / raw)
To: Kevin Brodsky
Cc: peterz, agordeev, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/3 00:53, Kevin Brodsky wrote:
> On 30/12/2024 10:07, Qi Zheng wrote:
>> diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h
>> index 551d614d3369c..3466fbe2e508d 100644
>> --- a/arch/riscv/include/asm/pgalloc.h
>> +++ b/arch/riscv/include/asm/pgalloc.h
>> @@ -108,8 +108,12 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
>> static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
>> unsigned long addr)
>> {
>> - if (pgtable_l5_enabled)
>> + if (pgtable_l5_enabled) {
>> + struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
>> +
>> + pagetable_p4d_dtor(ptdesc);
>> riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
>
> Nit: could use the new ptdesc variable here instead of calling
> virt_to_ptdesc().
Right, but we will remove pagetable_p4d_dtor() in patch #10, so this
may not matter.
Thanks!
>
> - Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table()
2025-01-02 17:00 ` Kevin Brodsky
@ 2025-01-03 3:56 ` Qi Zheng
0 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2025-01-03 3:56 UTC (permalink / raw)
To: Kevin Brodsky
Cc: peterz, agordeev, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/3 01:00, Kevin Brodsky wrote:
> On 30/12/2024 10:07, Qi Zheng wrote:
>> Qi Zheng (13):
>> Revert "mm: pgtable: make ptlock be freed by RCU"
>> mm: pgtable: add statistics for P4D level page table
>> arm64: pgtable: use mmu gather to free p4d level page table
>> s390: pgtable: add statistics for PUD and P4D level page table
>> mm: pgtable: introduce pagetable_dtor()
>> arm: pgtable: move pagetable_dtor() to __tlb_remove_table()
>> arm64: pgtable: move pagetable_dtor() to __tlb_remove_table()
>> riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
>> x86: pgtable: move pagetable_dtor() to __tlb_remove_table()
>> s390: pgtable: also move pagetable_dtor() of PxD to
>> __tlb_remove_table()
>> mm: pgtable: introduce generic __tlb_remove_table()
>> mm: pgtable: move __tlb_remove_table_one() in x86 to generic file
>> mm: pgtable: introduce generic pagetable_dtor_free()
>
> Aside from the nit on patch 4 and the request for clarification on patch
> 10, this is looking good to me, so for the whole series (aside from my
> own patches of course):
>
> Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Thanks for your review!
>
> And happy new year!
Happy New Year!! :)
>
> Cheers,
> - Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 04/15] mm: pgtable: add statistics for P4D level page table
2025-01-03 3:53 ` Qi Zheng
@ 2025-01-03 7:46 ` Kevin Brodsky
0 siblings, 0 replies; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-03 7:46 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, agordeev, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 03/01/2025 04:53, Qi Zheng wrote:
> On 2025/1/3 00:53, Kevin Brodsky wrote:
>> On 30/12/2024 10:07, Qi Zheng wrote:
>>> diff --git a/arch/riscv/include/asm/pgalloc.h
>>> b/arch/riscv/include/asm/pgalloc.h
>>> index 551d614d3369c..3466fbe2e508d 100644
>>> --- a/arch/riscv/include/asm/pgalloc.h
>>> +++ b/arch/riscv/include/asm/pgalloc.h
>>> @@ -108,8 +108,12 @@ static inline void __pud_free_tlb(struct
>>> mmu_gather *tlb, pud_t *pud,
>>> static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
>>> unsigned long addr)
>>> {
>>> - if (pgtable_l5_enabled)
>>> + if (pgtable_l5_enabled) {
>>> + struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
>>> +
>>> + pagetable_p4d_dtor(ptdesc);
>>> riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
>>
>> Nit: could use the new ptdesc variable here instead of calling
>> virt_to_ptdesc().
>
> Right, but we will remove pagetable_p4d_dtor() in patch #10, so this
> may not matter.
You're right, I missed that. Makes sense not to create a diff that's
reverted later then :)
- Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-03 3:48 ` Qi Zheng
@ 2025-01-03 8:02 ` Kevin Brodsky
2025-01-03 9:13 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-03 8:02 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, agordeev, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 03/01/2025 04:48, Qi Zheng wrote:
> Hi Kevin,
>
> On 2025/1/3 00:53, Kevin Brodsky wrote:
>> On 30/12/2024 10:07, Qi Zheng wrote:
>>> static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb,
>>> void *pt)
>>> {
>>> - if (riscv_use_sbi_for_rfence())
>>> + if (riscv_use_sbi_for_rfence()) {
>>> tlb_remove_ptdesc(tlb, pt);
>>> - else
>>> + } else {
>>> + pagetable_dtor(pt);
>>> tlb_remove_page_ptdesc(tlb, pt);
>>
>> I find the imbalance pretty confusing: pagetable_dtor() is called
>> explicitly before using tlb_remove_page() but not tlb_remove_ptdesc().
>> Doesn't that assume that CONFIG_MMU_GATHER_HAVE_TABLE_FREE is selected?
>> Could we not call pagetable_dtor() from __tlb_batch_free_encoded_pages()
>> to ensure that the dtor is always called just before freeing, and remove
>
> In __tlb_batch_free_encoded_pages(), we can indeed detect PageTable()
> and call pagetable_dtor() to dtor the page table pages.
> But __tlb_batch_free_encoded_pages() is also used to free normal pages
> (not page table pages), so I don't want to add overhead there.
Interesting, can a tlb batch refer to pages than are not PTPs then?
>
> But now I think maybe we can do this in tlb_remove_page_ptdesc(), like
> this:
>
> diff --git a/arch/csky/include/asm/pgalloc.h
> b/arch/csky/include/asm/pgalloc.h
> index f1ce5b7b28f22..e45c7e91dcbf9 100644
> --- a/arch/csky/include/asm/pgalloc.h
> +++ b/arch/csky/include/asm/pgalloc.h
> @@ -63,7 +63,6 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
>
> #define __pte_free_tlb(tlb, pte, address) \
> do { \
> - pagetable_dtor(page_ptdesc(pte)); \
> tlb_remove_page_ptdesc(tlb, page_ptdesc(pte)); \
> } while (0)
>
> [...]
>
> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
> index a96d4b440f3da..a59205863f431 100644
> --- a/include/asm-generic/tlb.h
> +++ b/include/asm-generic/tlb.h
> @@ -506,6 +506,7 @@ static inline void tlb_remove_ptdesc(struct
> mmu_gather *tlb, void *pt)
> /* Like tlb_remove_ptdesc, but for page-like page directories. */
> static inline void tlb_remove_page_ptdesc(struct mmu_gather *tlb,
> struct ptdesc *pt)
> {
> + pagetable_dtor(pt);
> tlb_remove_page(tlb, ptdesc_page(pt));
> }
I think this is an interesting idea, it does make arch code easier to
follow. OTOH it would have been more natural to me to call
pagetable_dtor() from tlb_remove_page(). I can however see that this
doesn't work, because tlb_remove_table() is defined as tlb_remove_page()
if CONFIG_MMU_GATHER_HAVE_TABLE_FREE isn't selected. Which brings me
back to my earlier question: in that case, aren't we missing a call to
pagetable_dtor() when using tlb_remove_table() (or tlb_remove_ptdesc())?
- Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-03 8:02 ` Kevin Brodsky
@ 2025-01-03 9:13 ` Qi Zheng
2025-01-03 9:35 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-03 9:13 UTC (permalink / raw)
To: Kevin Brodsky
Cc: peterz, agordeev, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/3 16:02, Kevin Brodsky wrote:
> On 03/01/2025 04:48, Qi Zheng wrote:
>> Hi Kevin,
>>
>> On 2025/1/3 00:53, Kevin Brodsky wrote:
>>> On 30/12/2024 10:07, Qi Zheng wrote:
>>>> static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb,
>>>> void *pt)
>>>> {
>>>> - if (riscv_use_sbi_for_rfence())
>>>> + if (riscv_use_sbi_for_rfence()) {
>>>> tlb_remove_ptdesc(tlb, pt);
>>>> - else
>>>> + } else {
>>>> + pagetable_dtor(pt);
>>>> tlb_remove_page_ptdesc(tlb, pt);
>>>
>>> I find the imbalance pretty confusing: pagetable_dtor() is called
>>> explicitly before using tlb_remove_page() but not tlb_remove_ptdesc().
>>> Doesn't that assume that CONFIG_MMU_GATHER_HAVE_TABLE_FREE is selected?
>>> Could we not call pagetable_dtor() from __tlb_batch_free_encoded_pages()
>>> to ensure that the dtor is always called just before freeing, and remove
>>
>> In __tlb_batch_free_encoded_pages(), we can indeed detect PageTable()
>> and call pagetable_dtor() to dtor the page table pages.
>> But __tlb_batch_free_encoded_pages() is also used to free normal pages
>> (not page table pages), so I don't want to add overhead there.
>
> Interesting, can a tlb batch refer to pages than are not PTPs then?
Yes, you can see the caller of __tlb_remove_folio_pages() or
tlb_remove_page_size().
>
>>
>> But now I think maybe we can do this in tlb_remove_page_ptdesc(), like
>> this:
>>
>> diff --git a/arch/csky/include/asm/pgalloc.h
>> b/arch/csky/include/asm/pgalloc.h
>> index f1ce5b7b28f22..e45c7e91dcbf9 100644
>> --- a/arch/csky/include/asm/pgalloc.h
>> +++ b/arch/csky/include/asm/pgalloc.h
>> @@ -63,7 +63,6 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
>>
>> #define __pte_free_tlb(tlb, pte, address) \
>> do { \
>> - pagetable_dtor(page_ptdesc(pte)); \
>> tlb_remove_page_ptdesc(tlb, page_ptdesc(pte)); \
>> } while (0)
>>
>> [...]
>>
>> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
>> index a96d4b440f3da..a59205863f431 100644
>> --- a/include/asm-generic/tlb.h
>> +++ b/include/asm-generic/tlb.h
>> @@ -506,6 +506,7 @@ static inline void tlb_remove_ptdesc(struct
>> mmu_gather *tlb, void *pt)
>> /* Like tlb_remove_ptdesc, but for page-like page directories. */
>> static inline void tlb_remove_page_ptdesc(struct mmu_gather *tlb,
>> struct ptdesc *pt)
>> {
>> + pagetable_dtor(pt);
>> tlb_remove_page(tlb, ptdesc_page(pt));
>> }
>
> I think this is an interesting idea, it does make arch code easier to
> follow. OTOH it would have been more natural to me to call
> pagetable_dtor() from tlb_remove_page(). I can however see that this
> doesn't work, because tlb_remove_table() is defined as tlb_remove_page()
> if CONFIG_MMU_GATHER_HAVE_TABLE_FREE isn't selected. Which brings me
> back to my earlier question: in that case, aren't we missing a call to
> pagetable_dtor() when using tlb_remove_table() (or tlb_remove_ptdesc())?
Thank you for pointing this out!
Now, there are the following architectures selected
CONFIG_MMU_GATHER_RCU_TABLE_FREE:
1. arm: select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE
2. arm64: select MMU_GATHER_RCU_TABLE_FREE
3. powerpc: select MMU_GATHER_RCU_TABLE_FREE
4. riscv: select MMU_GATHER_RCU_TABLE_FREE if SMP && MMU
5. s390: select MMU_GATHER_RCU_TABLE_FREE
6. sparc: select MMU_GATHER_RCU_TABLE_FREE if SMP
7. x86: select MMU_GATHER_RCU_TABLE_FREE if PARAVIRT
If CONFIG_MMU_GATHER_TABLE_FREE is selected, an architecture is expected
to provide __tlb_remove_table(). This patch series modifies the
__tlb_remove_table() in arm, arm64, riscv, s390 and x86. Among them,
arm64 and s390 unconditionally select MMU_GATHER_RCU_TABLE_FREE, so we
only need to double-check arm, riscv and x86.
For x86, it was called tlb_remove_page() in the non-PARAVIRT case, and I
added pagetable_dtor() for it explicitly (see patch #11), so this should
be no problem.
For riscv, it will only call tlb_remove_ptdesc() in the case of
SMP && MMU, so this should be no problem.
For arm, the call to pagetable_dtor() is indeed missed in the
non-MMU_GATHER_RCU_TABLE_FREE case. This needs to be fixed. But we
can't fix this by adding pagetable_dtor() to tlb_remove_table(),
because some architectures call tlb_remove_table() but don't support
page table statistics, like sparc.
So a more direct fix might be:
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index a59205863f431..0a131444a18ca 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -500,6 +500,9 @@ static inline void tlb_remove_page(struct mmu_gather
*tlb, struct page *page)
static inline void tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt)
{
+#ifndef CONFIG_MMU_GATHER_TABLE_FREE
+ pagetable_dtor(pt);
+#endif
tlb_remove_table(tlb, pt);
}
Or fix it directly in arm? Like the following:
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index ea4fbe7b17f6f..cf5d0ca021440 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -43,6 +43,9 @@ __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
unsigned long addr)
__tlb_adjust_range(tlb, addr - PAGE_SIZE, 2 * PAGE_SIZE);
#endif
+#ifndef CONFIG_MMU_GATHER_TABLE_FREE
+ pagetable_dtor(ptdesc);
+#endif
tlb_remove_ptdesc(tlb, ptdesc);
}
Thanks,
Qi
>
> - Kevin
^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-03 9:13 ` Qi Zheng
@ 2025-01-03 9:35 ` Qi Zheng
2025-01-03 13:27 ` Kevin Brodsky
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-03 9:35 UTC (permalink / raw)
To: Kevin Brodsky, peterz
Cc: agordeev, palmer, tglx, david, jannh, hughd, yuzhao, willy,
muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/3 17:13, Qi Zheng wrote:
>
>
> On 2025/1/3 16:02, Kevin Brodsky wrote:
>> On 03/01/2025 04:48, Qi Zheng wrote:
>>> Hi Kevin,
>>>
>>> On 2025/1/3 00:53, Kevin Brodsky wrote:
>>>> On 30/12/2024 10:07, Qi Zheng wrote:
>>>>> static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb,
>>>>> void *pt)
>>>>> {
>>>>> - if (riscv_use_sbi_for_rfence())
>>>>> + if (riscv_use_sbi_for_rfence()) {
>>>>> tlb_remove_ptdesc(tlb, pt);
>>>>> - else
>>>>> + } else {
>>>>> + pagetable_dtor(pt);
>>>>> tlb_remove_page_ptdesc(tlb, pt);
>>>>
>>>> I find the imbalance pretty confusing: pagetable_dtor() is called
>>>> explicitly before using tlb_remove_page() but not tlb_remove_ptdesc().
>>>> Doesn't that assume that CONFIG_MMU_GATHER_HAVE_TABLE_FREE is selected?
>>>> Could we not call pagetable_dtor() from
>>>> __tlb_batch_free_encoded_pages()
>>>> to ensure that the dtor is always called just before freeing, and
>>>> remove
>>>
>>> In __tlb_batch_free_encoded_pages(), we can indeed detect PageTable()
>>> and call pagetable_dtor() to dtor the page table pages.
>>> But __tlb_batch_free_encoded_pages() is also used to free normal pages
>>> (not page table pages), so I don't want to add overhead there.
>>
>> Interesting, can a tlb batch refer to pages than are not PTPs then?
>
> Yes, you can see the caller of __tlb_remove_folio_pages() or
> tlb_remove_page_size().
>
>>
>>>
>>> But now I think maybe we can do this in tlb_remove_page_ptdesc(), like
>>> this:
>>>
>>> diff --git a/arch/csky/include/asm/pgalloc.h
>>> b/arch/csky/include/asm/pgalloc.h
>>> index f1ce5b7b28f22..e45c7e91dcbf9 100644
>>> --- a/arch/csky/include/asm/pgalloc.h
>>> +++ b/arch/csky/include/asm/pgalloc.h
>>> @@ -63,7 +63,6 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
>>>
>>> #define __pte_free_tlb(tlb, pte, address) \
>>> do { \
>>> - pagetable_dtor(page_ptdesc(pte)); \
>>> tlb_remove_page_ptdesc(tlb, page_ptdesc(pte)); \
>>> } while (0)
>>>
>>> [...]
>>>
>>> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
>>> index a96d4b440f3da..a59205863f431 100644
>>> --- a/include/asm-generic/tlb.h
>>> +++ b/include/asm-generic/tlb.h
>>> @@ -506,6 +506,7 @@ static inline void tlb_remove_ptdesc(struct
>>> mmu_gather *tlb, void *pt)
>>> /* Like tlb_remove_ptdesc, but for page-like page directories. */
>>> static inline void tlb_remove_page_ptdesc(struct mmu_gather *tlb,
>>> struct ptdesc *pt)
>>> {
>>> + pagetable_dtor(pt);
>>> tlb_remove_page(tlb, ptdesc_page(pt));
>>> }
>>
>> I think this is an interesting idea, it does make arch code easier to
>> follow. OTOH it would have been more natural to me to call
>> pagetable_dtor() from tlb_remove_page(). I can however see that this
>> doesn't work, because tlb_remove_table() is defined as tlb_remove_page()
>> if CONFIG_MMU_GATHER_HAVE_TABLE_FREE isn't selected. Which brings me
>> back to my earlier question: in that case, aren't we missing a call to
>> pagetable_dtor() when using tlb_remove_table() (or tlb_remove_ptdesc())?
>
> Thank you for pointing this out!
>
> Now, there are the following architectures selected
> CONFIG_MMU_GATHER_RCU_TABLE_FREE:
>
> 1. arm: select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE
> 2. arm64: select MMU_GATHER_RCU_TABLE_FREE
> 3. powerpc: select MMU_GATHER_RCU_TABLE_FREE
> 4. riscv: select MMU_GATHER_RCU_TABLE_FREE if SMP && MMU
> 5. s390: select MMU_GATHER_RCU_TABLE_FREE
> 6. sparc: select MMU_GATHER_RCU_TABLE_FREE if SMP
> 7. x86: select MMU_GATHER_RCU_TABLE_FREE if PARAVIRT
>
> If CONFIG_MMU_GATHER_TABLE_FREE is selected, an architecture is expected
> to provide __tlb_remove_table(). This patch series modifies the
> __tlb_remove_table() in arm, arm64, riscv, s390 and x86. Among them,
> arm64 and s390 unconditionally select MMU_GATHER_RCU_TABLE_FREE, so we
> only need to double-check arm, riscv and x86.
>
> For x86, it was called tlb_remove_page() in the non-PARAVIRT case, and I
> added pagetable_dtor() for it explicitly (see patch #11), so this should
> be no problem.
>
> For riscv, it will only call tlb_remove_ptdesc() in the case of
> SMP && MMU, so this should be no problem.
>
> For arm, the call to pagetable_dtor() is indeed missed in the
> non-MMU_GATHER_RCU_TABLE_FREE case. This needs to be fixed. But we
> can't fix this by adding pagetable_dtor() to tlb_remove_table(),
> because some architectures call tlb_remove_table() but don't support
> page table statistics, like sparc.
>
> So a more direct fix might be:
>
> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
> index a59205863f431..0a131444a18ca 100644
> --- a/include/asm-generic/tlb.h
> +++ b/include/asm-generic/tlb.h
> @@ -500,6 +500,9 @@ static inline void tlb_remove_page(struct mmu_gather
> *tlb, struct page *page)
>
> static inline void tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt)
> {
> +#ifndef CONFIG_MMU_GATHER_TABLE_FREE
> + pagetable_dtor(pt);
> +#endif
> tlb_remove_table(tlb, pt);
> }
>
> Or fix it directly in arm? Like the following:
>
> diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
> index ea4fbe7b17f6f..cf5d0ca021440 100644
> --- a/arch/arm/include/asm/tlb.h
> +++ b/arch/arm/include/asm/tlb.h
> @@ -43,6 +43,9 @@ __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
> unsigned long addr)
> __tlb_adjust_range(tlb, addr - PAGE_SIZE, 2 * PAGE_SIZE);
> #endif
>
> +#ifndef CONFIG_MMU_GATHER_TABLE_FREE
> + pagetable_dtor(ptdesc);
> +#endif
> tlb_remove_ptdesc(tlb, ptdesc);
> }
Or can we just not let tlb_remove_table() fall back to
tlb_remove_page()? Like the following:
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index a59205863f431..354ffaa4bd120 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -195,8 +195,6 @@
* various ptep_get_and_clear() functions.
*/
-#ifdef CONFIG_MMU_GATHER_TABLE_FREE
-
struct mmu_table_batch {
#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
struct rcu_head rcu;
@@ -219,16 +217,6 @@ static inline void __tlb_remove_table(void *table)
extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
-#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
-
-/*
- * Without MMU_GATHER_TABLE_FREE the architecture is assumed to have
page based
- * page directories and we can use the normal page batching to free them.
- */
-#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
-
-#endif /* CONFIG_MMU_GATHER_TABLE_FREE */
-
#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
/*
* This allows an architecture that does not use the linux page-tables for
>
> Thanks,
> Qi
>
>>
>> - Kevin
^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-03 9:35 ` Qi Zheng
@ 2025-01-03 13:27 ` Kevin Brodsky
2025-01-06 3:49 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-03 13:27 UTC (permalink / raw)
To: Qi Zheng, peterz
Cc: agordeev, palmer, tglx, david, jannh, hughd, yuzhao, willy,
muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 03/01/2025 10:35, Qi Zheng wrote:
> On 2025/1/3 17:13, Qi Zheng wrote:
>> On 2025/1/3 16:02, Kevin Brodsky wrote:
>>> On 03/01/2025 04:48, Qi Zheng wrote:
>>>> [...]
>>>>
>>>> In __tlb_batch_free_encoded_pages(), we can indeed detect PageTable()
>>>> and call pagetable_dtor() to dtor the page table pages.
>>>> But __tlb_batch_free_encoded_pages() is also used to free normal pages
>>>> (not page table pages), so I don't want to add overhead there.
>>>
>>> Interesting, can a tlb batch refer to pages than are not PTPs then?
>>
>> Yes, you can see the caller of __tlb_remove_folio_pages() or
>> tlb_remove_page_size().
I had a brief look but clearly not a good enough one! I hadn't realised
that "table" in tlb_remove_table() means PTP, while "page" in
tlb_remove_page() can mean any page, and it's making more sense now.
[...]
>>
>> For arm, the call to pagetable_dtor() is indeed missed in the
>> non-MMU_GATHER_RCU_TABLE_FREE case. This needs to be fixed. But we
>> can't fix this by adding pagetable_dtor() to tlb_remove_table(),
>> because some architectures call tlb_remove_table() but don't support
>> page table statistics, like sparc.
When I investigated this for my own series, I found that the only case
where ctor/dtor are not called for page-sized page tables is 32-bit
sparc (see table at the end of [1]). However only 64-bit sparc makes use
of tlb_remove_table() (at PTE level, where ctor/dtor are already called).
So really calling pagetable_dtor() from tlb_remove_table() in the
non-MMU_GATHER_TABLE_FREE case seems to be the obvious thing to do.
Once this is done, we should be able to replace all those confusing
calls to tlb_remove_page() on PTPs with tlb_remove_table() and remove
the explicit call to pagetable_dtor(). AIUI this is essentially what
Peter suggested on v3 [2].
[1]
https://lore.kernel.org/linux-mm/20241219164425.2277022-1-kevin.brodsky@arm.com/
[2]
https://lore.kernel.org/linux-mm/20250103111457.GC22934@noisy.programming.kicks-ass.net/
[...]
> Or can we just not let tlb_remove_table() fall back to
> tlb_remove_page()? Like the following:
>
> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
> index a59205863f431..354ffaa4bd120 100644
> --- a/include/asm-generic/tlb.h
> +++ b/include/asm-generic/tlb.h
> @@ -195,8 +195,6 @@
> * various ptep_get_and_clear() functions.
> */
>
> -#ifdef CONFIG_MMU_GATHER_TABLE_FREE
> -
> struct mmu_table_batch {
> #ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
> struct rcu_head rcu;
> @@ -219,16 +217,6 @@ static inline void __tlb_remove_table(void *table)
>
> extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
>
> -#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
> -
> -/*
> - * Without MMU_GATHER_TABLE_FREE the architecture is assumed to have
> page based
> - * page directories and we can use the normal page batching to free
> them.
> - */
> -#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
We still need a different implementation of tlb_remove_table() in this
case. We could define it inline here:
static inline void tlb_remove_table(struct mmu_gather *tlb, void *table)
{
struct page *page = table;
pagetable_dtor(page_ptdesc(page));
tlb_remove_page(page);
}
- Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-03 13:27 ` Kevin Brodsky
@ 2025-01-06 3:49 ` Qi Zheng
2025-01-07 9:57 ` Kevin Brodsky
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-06 3:49 UTC (permalink / raw)
To: Kevin Brodsky, peterz, akpm
Cc: agordeev, palmer, tglx, david, jannh, hughd, yuzhao, willy,
muchun.song, vbabka, lorenzo.stoakes, rientjes, vishal.moola,
arnd, will, aneesh.kumar, npiggin, dave.hansen, rppt,
ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
Hi Kevin,
On 2025/1/3 21:27, Kevin Brodsky wrote:
> On 03/01/2025 10:35, Qi Zheng wrote:
>> On 2025/1/3 17:13, Qi Zheng wrote:
>>> On 2025/1/3 16:02, Kevin Brodsky wrote:
>>>> On 03/01/2025 04:48, Qi Zheng wrote:
>>>>> [...]
>>>>>
>>>>> In __tlb_batch_free_encoded_pages(), we can indeed detect PageTable()
>>>>> and call pagetable_dtor() to dtor the page table pages.
>>>>> But __tlb_batch_free_encoded_pages() is also used to free normal pages
>>>>> (not page table pages), so I don't want to add overhead there.
>>>>
>>>> Interesting, can a tlb batch refer to pages than are not PTPs then?
>>>
>>> Yes, you can see the caller of __tlb_remove_folio_pages() or
>>> tlb_remove_page_size().
>
> I had a brief look but clearly not a good enough one! I hadn't realised
> that "table" in tlb_remove_table() means PTP, while "page" in
> tlb_remove_page() can mean any page, and it's making more sense now.
>
> [...]
>
>>>
>>> For arm, the call to pagetable_dtor() is indeed missed in the
>>> non-MMU_GATHER_RCU_TABLE_FREE case. This needs to be fixed. But we
>>> can't fix this by adding pagetable_dtor() to tlb_remove_table(),
>>> because some architectures call tlb_remove_table() but don't support
>>> page table statistics, like sparc.
>
> When I investigated this for my own series, I found that the only case
> where ctor/dtor are not called for page-sized page tables is 32-bit
> sparc (see table at the end of [1]). However only 64-bit sparc makes use
> of tlb_remove_table() (at PTE level, where ctor/dtor are already called).
Thanks for providing this information.
>
> So really calling pagetable_dtor() from tlb_remove_table() in the
> non-MMU_GATHER_TABLE_FREE case seems to be the obvious thing to do.
Right. Currently, only powerpc, sparc and x86 will directly call
tlb_remove_table(), and all of them are in the MMU_GATHER_TABLE_FREE
case. Therefore, I think the modification you mentioned below is
feasible.
In summary, currently only arm calls tlb_remove_table() in the
non-MMU_GATHER_RCU_TABLE_FREE case. So I think we can add this fix
directly to patch #8. If I haven't missed anything, I'll send an
updated patch #8.
>
> Once this is done, we should be able to replace all those confusing
> calls to tlb_remove_page() on PTPs with tlb_remove_table() and remove
> the explicit call to pagetable_dtor(). AIUI this is essentially what
> Peter suggested on v3 [2].
Since this patch series is mainly for bug fix, I think that these things
can be done in separate patch series later.
>
> [1]
> https://lore.kernel.org/linux-mm/20241219164425.2277022-1-kevin.brodsky@arm.com/
> [2]
> https://lore.kernel.org/linux-mm/20250103111457.GC22934@noisy.programming.kicks-ass.net/
>
> [...]
>
>> Or can we just not let tlb_remove_table() fall back to
>> tlb_remove_page()? Like the following:
>>
>> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
>> index a59205863f431..354ffaa4bd120 100644
>> --- a/include/asm-generic/tlb.h
>> +++ b/include/asm-generic/tlb.h
>> @@ -195,8 +195,6 @@
>> * various ptep_get_and_clear() functions.
>> */
>>
>> -#ifdef CONFIG_MMU_GATHER_TABLE_FREE
>> -
>> struct mmu_table_batch {
>> #ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
>> struct rcu_head rcu;
>> @@ -219,16 +217,6 @@ static inline void __tlb_remove_table(void *table)
>>
>> extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
>>
>> -#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
>> -
>> -/*
>> - * Without MMU_GATHER_TABLE_FREE the architecture is assumed to have
>> page based
>> - * page directories and we can use the normal page batching to free
>> them.
>> - */
>> -#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
>
> We still need a different implementation of tlb_remove_table() in this
> case. We could define it inline here:
>
> static inline void tlb_remove_table(struct mmu_gather *tlb, void *table)
> {
> struct page *page = table;
>
> pagetable_dtor(page_ptdesc(page));
> tlb_remove_page(page);
> }
Right. As I said above, will add this to the updated patch #8.
Thanks!
>
> - Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 06/15] s390: pgtable: add statistics for PUD and P4D level page table
2024-12-30 9:07 ` [PATCH v4 06/15] s390: pgtable: add statistics for PUD and P4D " Qi Zheng
@ 2025-01-06 10:32 ` Alexander Gordeev
2025-01-06 11:05 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Alexander Gordeev @ 2025-01-06 10:32 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, Dec 30, 2024 at 05:07:41PM +0800, Qi Zheng wrote:
> Like PMD and PTE level page table, also add statistics for PUD and P4D
> page table.
...
> diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
> index e95b2c8081eb8..b946964afce8e 100644
> --- a/arch/s390/include/asm/tlb.h
> +++ b/arch/s390/include/asm/tlb.h
> @@ -110,24 +110,6 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
> tlb_remove_ptdesc(tlb, pmd);
> }
>
> -/*
> - * p4d_free_tlb frees a pud table and clears the CRSTE for the
> - * region second table entry from the tlb.
> - * If the mm uses a four level page table the single p4d is freed
> - * as the pgd. p4d_free_tlb checks the asce_limit against 8PB
> - * to avoid the double free of the p4d in this case.
> - */
> -static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
> - unsigned long address)
> -{
> - if (mm_p4d_folded(tlb->mm))
> - return;
> - __tlb_adjust_range(tlb, address, PAGE_SIZE);
> - tlb->mm->context.flush_mm = 1;
> - tlb->freed_tables = 1;
> - tlb_remove_ptdesc(tlb, p4d);
> -}
> -
> /*
> * pud_free_tlb frees a pud table and clears the CRSTE for the
> * region third table entry from the tlb.
> @@ -140,11 +122,30 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
> {
> if (mm_pud_folded(tlb->mm))
> return;
> + pagetable_pud_dtor(virt_to_ptdesc(pud));
> tlb->mm->context.flush_mm = 1;
> tlb->freed_tables = 1;
> tlb->cleared_p4ds = 1;
> tlb_remove_ptdesc(tlb, pud);
> }
>
> +/*
> + * p4d_free_tlb frees a p4d table and clears the CRSTE for the
> + * region second table entry from the tlb.
> + * If the mm uses a four level page table the single p4d is freed
> + * as the pgd. p4d_free_tlb checks the asce_limit against 8PB
> + * to avoid the double free of the p4d in this case.
> + */
> +static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
> + unsigned long address)
> +{
> + if (mm_p4d_folded(tlb->mm))
> + return;
> + pagetable_p4d_dtor(virt_to_ptdesc(p4d));
> + __tlb_adjust_range(tlb, address, PAGE_SIZE);
> + tlb->mm->context.flush_mm = 1;
> + tlb->freed_tables = 1;
> + tlb_remove_ptdesc(tlb, p4d);
> +}
I understand that you want to sort p.._free_tlb() routines, but please
do not move the code around or make a separate follow-up patch.
Thanks!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor()
2024-12-30 9:07 ` [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor() Qi Zheng
@ 2025-01-06 10:34 ` Alexander Gordeev
2025-01-06 10:55 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Alexander Gordeev @ 2025-01-06 10:34 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, Dec 30, 2024 at 05:07:42PM +0800, Qi Zheng wrote:
> The pagetable_p*_dtor() are exactly the same except for the handling of
> ptlock. If we make ptlock_free() handle the case where ptdesc->ptl is
> NULL and remove VM_BUG_ON_PAGE() from pmd_ptlock_free(), we can unify
> pagetable_p*_dtor() into one function. Let's introduce pagetable_dtor()
> to do this.
>
> Later, pagetable_dtor() will be moved to tlb_remove_ptdesc(), so that
> ptlock and page table pages can be freed together (regardless of whether
> RCU is used). This prevents the use-after-free problem where the ptlock
> is freed immediately but the page table pages is freed later via RCU.
>
> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
> Originally-by: Peter Zijlstra (Intel) <peterz@infradead.org>
...
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 5d82f42ddd5cc..cad11fa10c192 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2992,6 +2992,15 @@ static inline bool ptlock_init(struct ptdesc *ptdesc) { return true; }
> static inline void ptlock_free(struct ptdesc *ptdesc) {}
> #endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */
>
> +static inline void pagetable_dtor(struct ptdesc *ptdesc)
> +{
> + struct folio *folio = ptdesc_folio(ptdesc);
> +
> + ptlock_free(ptdesc);
> + __folio_clear_pgtable(folio);
> + lruvec_stat_sub_folio(folio, NR_PAGETABLE);
> +}
> +
If I am not mistaken, it is just pagetable_pte_dtor() rename.
What is the point in moving the code around?
> static inline bool pagetable_pte_ctor(struct ptdesc *ptdesc)
> {
> struct folio *folio = ptdesc_folio(ptdesc);
> @@ -3003,15 +3012,6 @@ static inline bool pagetable_pte_ctor(struct ptdesc *ptdesc)
> return true;
> }
>
> -static inline void pagetable_pte_dtor(struct ptdesc *ptdesc)
> -{
> - struct folio *folio = ptdesc_folio(ptdesc);
> -
> - ptlock_free(ptdesc);
> - __folio_clear_pgtable(folio);
> - lruvec_stat_sub_folio(folio, NR_PAGETABLE);
> -}
> -
> pte_t *___pte_offset_map(pmd_t *pmd, unsigned long addr, pmd_t *pmdvalp);
> static inline pte_t *__pte_offset_map(pmd_t *pmd, unsigned long addr,
> pmd_t *pmdvalp)
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD to __tlb_remove_table()
2024-12-30 9:07 ` [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD " Qi Zheng
@ 2025-01-06 10:36 ` Alexander Gordeev
2025-01-06 11:02 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Alexander Gordeev @ 2025-01-06 10:36 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, Dec 30, 2024 at 05:07:47PM +0800, Qi Zheng wrote:
> To unify the PxD and PTE TLB free path, also move the pagetable_dtor() of
> PMD|PUD|P4D to __tlb_remove_table().
The above and Subject are still incorrect: pagetable_dtor() is
called from pagetable_dtor_free(), not from __tlb_remove_table().
...
> diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
> index 569de24d33761..c73b89811a264 100644
> --- a/arch/s390/mm/pgalloc.c
> +++ b/arch/s390/mm/pgalloc.c
> @@ -180,7 +180,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
> return table;
> }
>
> -static void pagetable_pte_dtor_free(struct ptdesc *ptdesc)
> +static void pagetable_dtor_free(struct ptdesc *ptdesc)
> {
> pagetable_dtor(ptdesc);
> pagetable_free(ptdesc);
> @@ -190,20 +190,14 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
> {
> struct ptdesc *ptdesc = virt_to_ptdesc(table);
>
> - pagetable_pte_dtor_free(ptdesc);
> + pagetable_dtor_free(ptdesc);
> }
>
> void __tlb_remove_table(void *table)
> {
> struct ptdesc *ptdesc = virt_to_ptdesc(table);
> - struct page *page = ptdesc_page(ptdesc);
>
> - if (compound_order(page) == CRST_ALLOC_ORDER) {
> - /* pmd, pud, or p4d */
> - pagetable_free(ptdesc);
> - return;
> - }
> - pagetable_pte_dtor_free(ptdesc);
> + pagetable_dtor_free(ptdesc);
> }
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor()
2025-01-06 10:34 ` Alexander Gordeev
@ 2025-01-06 10:55 ` Qi Zheng
2025-01-06 12:36 ` Alexander Gordeev
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-06 10:55 UTC (permalink / raw)
To: Alexander Gordeev
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/6 18:34, Alexander Gordeev wrote:
> On Mon, Dec 30, 2024 at 05:07:42PM +0800, Qi Zheng wrote:
>> The pagetable_p*_dtor() are exactly the same except for the handling of
>> ptlock. If we make ptlock_free() handle the case where ptdesc->ptl is
>> NULL and remove VM_BUG_ON_PAGE() from pmd_ptlock_free(), we can unify
>> pagetable_p*_dtor() into one function. Let's introduce pagetable_dtor()
>> to do this.
>>
>> Later, pagetable_dtor() will be moved to tlb_remove_ptdesc(), so that
>> ptlock and page table pages can be freed together (regardless of whether
>> RCU is used). This prevents the use-after-free problem where the ptlock
>> is freed immediately but the page table pages is freed later via RCU.
>>
>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
>> Originally-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> ...
>> diff --git a/include/linux/mm.h b/include/linux/mm.h
>> index 5d82f42ddd5cc..cad11fa10c192 100644
>> --- a/include/linux/mm.h
>> +++ b/include/linux/mm.h
>> @@ -2992,6 +2992,15 @@ static inline bool ptlock_init(struct ptdesc *ptdesc) { return true; }
>> static inline void ptlock_free(struct ptdesc *ptdesc) {}
>> #endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */
>>
>> +static inline void pagetable_dtor(struct ptdesc *ptdesc)
>> +{
>> + struct folio *folio = ptdesc_folio(ptdesc);
>> +
>> + ptlock_free(ptdesc);
>> + __folio_clear_pgtable(folio);
>> + lruvec_stat_sub_folio(folio, NR_PAGETABLE);
>> +}
>> +
>
> If I am not mistaken, it is just pagetable_pte_dtor() rename.
> What is the point in moving the code around?
No, this is to unify pagetable_p*_dtor() into pagetable_dtor(), so
that we can move pagetable_dtor() to __tlb_remove_table(), and then
ptlock and PTE page can be freed together through RCU, which is
also the main purpose of this patch series.
Thanks!
>
>> static inline bool pagetable_pte_ctor(struct ptdesc *ptdesc)
>> {
>> struct folio *folio = ptdesc_folio(ptdesc);
>> @@ -3003,15 +3012,6 @@ static inline bool pagetable_pte_ctor(struct ptdesc *ptdesc)
>> return true;
>> }
>>
>> -static inline void pagetable_pte_dtor(struct ptdesc *ptdesc)
>> -{
>> - struct folio *folio = ptdesc_folio(ptdesc);
>> -
>> - ptlock_free(ptdesc);
>> - __folio_clear_pgtable(folio);
>> - lruvec_stat_sub_folio(folio, NR_PAGETABLE);
>> -}
>> -
>> pte_t *___pte_offset_map(pmd_t *pmd, unsigned long addr, pmd_t *pmdvalp);
>> static inline pte_t *__pte_offset_map(pmd_t *pmd, unsigned long addr,
>> pmd_t *pmdvalp)
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD to __tlb_remove_table()
2025-01-06 10:36 ` Alexander Gordeev
@ 2025-01-06 11:02 ` Qi Zheng
2025-01-06 12:44 ` Alexander Gordeev
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-06 11:02 UTC (permalink / raw)
To: Alexander Gordeev
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/6 18:36, Alexander Gordeev wrote:
> On Mon, Dec 30, 2024 at 05:07:47PM +0800, Qi Zheng wrote:
>> To unify the PxD and PTE TLB free path, also move the pagetable_dtor() of
>> PMD|PUD|P4D to __tlb_remove_table().
>
> The above and Subject are still incorrect: pagetable_dtor() is
> called from pagetable_dtor_free(), not from __tlb_remove_table().
Hmm, __tlb_remove_table() calls pagetable_dtor_free(), so moving to
pagetable_dtor_free() means moving to __tlb_remove_table(). Right?
And the main purpose of this patch is also to move pagetable_dtor()
to __tlb_remove_table(). So I think this description makes sense?
>
> ...
>> diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
>> index 569de24d33761..c73b89811a264 100644
>> --- a/arch/s390/mm/pgalloc.c
>> +++ b/arch/s390/mm/pgalloc.c
>> @@ -180,7 +180,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
>> return table;
>> }
>>
>> -static void pagetable_pte_dtor_free(struct ptdesc *ptdesc)
>> +static void pagetable_dtor_free(struct ptdesc *ptdesc)
>> {
>> pagetable_dtor(ptdesc);
>> pagetable_free(ptdesc);
>> @@ -190,20 +190,14 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
>> {
>> struct ptdesc *ptdesc = virt_to_ptdesc(table);
>>
>> - pagetable_pte_dtor_free(ptdesc);
>> + pagetable_dtor_free(ptdesc);
>> }
>>
>> void __tlb_remove_table(void *table)
>> {
>> struct ptdesc *ptdesc = virt_to_ptdesc(table);
>> - struct page *page = ptdesc_page(ptdesc);
>>
>> - if (compound_order(page) == CRST_ALLOC_ORDER) {
>> - /* pmd, pud, or p4d */
>> - pagetable_free(ptdesc);
>> - return;
>> - }
>> - pagetable_pte_dtor_free(ptdesc);
>> + pagetable_dtor_free(ptdesc);
>> }
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 06/15] s390: pgtable: add statistics for PUD and P4D level page table
2025-01-06 10:32 ` Alexander Gordeev
@ 2025-01-06 11:05 ` Qi Zheng
2025-01-06 13:34 ` Alexander Gordeev
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-06 11:05 UTC (permalink / raw)
To: Alexander Gordeev
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/6 18:32, Alexander Gordeev wrote:
> On Mon, Dec 30, 2024 at 05:07:41PM +0800, Qi Zheng wrote:
>> Like PMD and PTE level page table, also add statistics for PUD and P4D
>> page table.
> ...
>> diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
>> index e95b2c8081eb8..b946964afce8e 100644
>> --- a/arch/s390/include/asm/tlb.h
>> +++ b/arch/s390/include/asm/tlb.h
>> @@ -110,24 +110,6 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
>> tlb_remove_ptdesc(tlb, pmd);
>> }
>>
>> -/*
>> - * p4d_free_tlb frees a pud table and clears the CRSTE for the
>> - * region second table entry from the tlb.
>> - * If the mm uses a four level page table the single p4d is freed
>> - * as the pgd. p4d_free_tlb checks the asce_limit against 8PB
>> - * to avoid the double free of the p4d in this case.
>> - */
>> -static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
>> - unsigned long address)
>> -{
>> - if (mm_p4d_folded(tlb->mm))
>> - return;
>> - __tlb_adjust_range(tlb, address, PAGE_SIZE);
>> - tlb->mm->context.flush_mm = 1;
>> - tlb->freed_tables = 1;
>> - tlb_remove_ptdesc(tlb, p4d);
>> -}
>> -
>> /*
>> * pud_free_tlb frees a pud table and clears the CRSTE for the
>> * region third table entry from the tlb.
>> @@ -140,11 +122,30 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
>> {
>> if (mm_pud_folded(tlb->mm))
>> return;
>> + pagetable_pud_dtor(virt_to_ptdesc(pud));
>> tlb->mm->context.flush_mm = 1;
>> tlb->freed_tables = 1;
>> tlb->cleared_p4ds = 1;
>> tlb_remove_ptdesc(tlb, pud);
>> }
>>
>> +/*
>> + * p4d_free_tlb frees a p4d table and clears the CRSTE for the
>> + * region second table entry from the tlb.
>> + * If the mm uses a four level page table the single p4d is freed
>> + * as the pgd. p4d_free_tlb checks the asce_limit against 8PB
>> + * to avoid the double free of the p4d in this case.
>> + */
>> +static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
>> + unsigned long address)
>> +{
>> + if (mm_p4d_folded(tlb->mm))
>> + return;
>> + pagetable_p4d_dtor(virt_to_ptdesc(p4d));
>> + __tlb_adjust_range(tlb, address, PAGE_SIZE);
>> + tlb->mm->context.flush_mm = 1;
>> + tlb->freed_tables = 1;
>> + tlb_remove_ptdesc(tlb, p4d);
>> +}
>
> I understand that you want to sort p.._free_tlb() routines, but please
Yes, I thought it was a minor change, so I just did it.
> do not move the code around or make a separate follow-up patch.
Well, if you have a strong opinion about this, I can send an updated
patch.
Thanks!
>
> Thanks!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 02/15] riscv: mm: Skip pgtable level check in {pud,p4d}_alloc_one
2024-12-30 9:07 ` [PATCH v4 02/15] riscv: mm: Skip pgtable level check in {pud,p4d}_alloc_one Qi Zheng
@ 2025-01-06 11:20 ` Alexandre Ghiti
0 siblings, 0 replies; 54+ messages in thread
From: Alexandre Ghiti @ 2025-01-06 11:20 UTC (permalink / raw)
To: Qi Zheng, peterz, agordeev, kevin.brodsky, palmer, tglx, david,
jannh, hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes,
akpm, rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um, Palmer Dabbelt
Hi Qi,
On 30/12/2024 10:07, Qi Zheng wrote:
> From: Kevin Brodsky <kevin.brodsky@arm.com>
>
> {pmd,pud,p4d}_alloc_one() is never called if the corresponding page
> table level is folded, as {pmd,pud,p4d}_alloc() already does the
> required check. We can therefore remove the runtime page table level
> checks in {pud,p4d}_alloc_one. The PUD helper becomes equivalent to
> the generic version, so we remove it altogether.
>
> This is consistent with the way arm64 and x86 handle this situation
> (runtime check in p4d_free() only).
>
> Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
> Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
> Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
> ---
> arch/riscv/include/asm/pgalloc.h | 22 ++++------------------
> 1 file changed, 4 insertions(+), 18 deletions(-)
>
> diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h
> index f52264304f772..8ad0bbe838a24 100644
> --- a/arch/riscv/include/asm/pgalloc.h
> +++ b/arch/riscv/include/asm/pgalloc.h
> @@ -12,7 +12,6 @@
> #include <asm/tlb.h>
>
> #ifdef CONFIG_MMU
> -#define __HAVE_ARCH_PUD_ALLOC_ONE
> #define __HAVE_ARCH_PUD_FREE
> #include <asm-generic/pgalloc.h>
>
> @@ -88,15 +87,6 @@ static inline void pgd_populate_safe(struct mm_struct *mm, pgd_t *pgd,
> }
> }
>
> -#define pud_alloc_one pud_alloc_one
> -static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
> -{
> - if (pgtable_l4_enabled)
> - return __pud_alloc_one(mm, addr);
> -
> - return NULL;
> -}
> -
> #define pud_free pud_free
> static inline void pud_free(struct mm_struct *mm, pud_t *pud)
> {
> @@ -118,15 +108,11 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
> #define p4d_alloc_one p4d_alloc_one
> static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long addr)
> {
> - if (pgtable_l5_enabled) {
> - gfp_t gfp = GFP_PGTABLE_USER;
> -
> - if (mm == &init_mm)
> - gfp = GFP_PGTABLE_KERNEL;
> - return (p4d_t *)get_zeroed_page(gfp);
> - }
> + gfp_t gfp = GFP_PGTABLE_USER;
>
> - return NULL;
> + if (mm == &init_mm)
> + gfp = GFP_PGTABLE_KERNEL;
> + return (p4d_t *)get_zeroed_page(gfp);
> }
>
> static inline void __p4d_free(struct mm_struct *mm, p4d_t *p4d)
You can add:
Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Thanks,
Alex
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor()
2025-01-06 10:55 ` Qi Zheng
@ 2025-01-06 12:36 ` Alexander Gordeev
2025-01-06 13:23 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Alexander Gordeev @ 2025-01-06 12:36 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, Jan 06, 2025 at 06:55:58PM +0800, Qi Zheng wrote:
> > > +static inline void pagetable_dtor(struct ptdesc *ptdesc)
> > > +{
> > > + struct folio *folio = ptdesc_folio(ptdesc);
> > > +
> > > + ptlock_free(ptdesc);
> > > + __folio_clear_pgtable(folio);
> > > + lruvec_stat_sub_folio(folio, NR_PAGETABLE);
> > > +}
> > > +
> >
> > If I am not mistaken, it is just pagetable_pte_dtor() rename.
> > What is the point in moving the code around?
>
> No, this is to unify pagetable_p*_dtor() into pagetable_dtor(), so
> that we can move pagetable_dtor() to __tlb_remove_table(), and then
> ptlock and PTE page can be freed together through RCU, which is
> also the main purpose of this patch series.
I am only talking about this patch. pagetable_dtor() code above is
the same pagetable_pte_dtor() below - it is only the function name
that changed. So why to move the function body? Anyway, that is
just a nit.
> Thanks!
> > > -static inline void pagetable_pte_dtor(struct ptdesc *ptdesc)
> > > -{
> > > - struct folio *folio = ptdesc_folio(ptdesc);
> > > -
> > > - ptlock_free(ptdesc);
> > > - __folio_clear_pgtable(folio);
> > > - lruvec_stat_sub_folio(folio, NR_PAGETABLE);
> > > -}
Thank you!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD to __tlb_remove_table()
2025-01-06 11:02 ` Qi Zheng
@ 2025-01-06 12:44 ` Alexander Gordeev
2025-01-06 13:34 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Alexander Gordeev @ 2025-01-06 12:44 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, Jan 06, 2025 at 07:02:17PM +0800, Qi Zheng wrote:
> > On Mon, Dec 30, 2024 at 05:07:47PM +0800, Qi Zheng wrote:
> > > To unify the PxD and PTE TLB free path, also move the pagetable_dtor() of
> > > PMD|PUD|P4D to __tlb_remove_table().
> >
> > The above and Subject are still incorrect: pagetable_dtor() is
> > called from pagetable_dtor_free(), not from __tlb_remove_table().
>
> Hmm, __tlb_remove_table() calls pagetable_dtor_free(), so moving to
> pagetable_dtor_free() means moving to __tlb_remove_table(). Right?
Right. But you Subject and description claim "... also move the
pagetable_dtor()" not to pagetable_dtor_free() - which is another
function.
> And the main purpose of this patch is also to move pagetable_dtor()
> to __tlb_remove_table(). So I think this description makes sense?
The patch makes sense, but the description it is incorrect ;)
Thanks!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor()
2025-01-06 12:36 ` Alexander Gordeev
@ 2025-01-06 13:23 ` Qi Zheng
2025-01-07 9:23 ` Kevin Brodsky
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-06 13:23 UTC (permalink / raw)
To: Alexander Gordeev
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/6 20:36, Alexander Gordeev wrote:
> On Mon, Jan 06, 2025 at 06:55:58PM +0800, Qi Zheng wrote:
>>>> +static inline void pagetable_dtor(struct ptdesc *ptdesc)
>>>> +{
>>>> + struct folio *folio = ptdesc_folio(ptdesc);
>>>> +
>>>> + ptlock_free(ptdesc);
>>>> + __folio_clear_pgtable(folio);
>>>> + lruvec_stat_sub_folio(folio, NR_PAGETABLE);
>>>> +}
>>>> +
>>>
>>> If I am not mistaken, it is just pagetable_pte_dtor() rename.
>>> What is the point in moving the code around?
>>
>> No, this is to unify pagetable_p*_dtor() into pagetable_dtor(), so
>> that we can move pagetable_dtor() to __tlb_remove_table(), and then
>> ptlock and PTE page can be freed together through RCU, which is
>> also the main purpose of this patch series.
>
> I am only talking about this patch. pagetable_dtor() code above is
> the same pagetable_pte_dtor() below - it is only the function name
> that changed. So why to move the function body? Anyway, that is
Ah, I just don't want to put pagetable_dtor() in between
pagetable_pte_ctor() and ___pte_offset_map(), so I moved it above
pagetable_pte_ctor(). No other special reason. ;)
Thanks!
> just a nit.
>
>> Thanks!
>
>>>> -static inline void pagetable_pte_dtor(struct ptdesc *ptdesc)
>>>> -{
>>>> - struct folio *folio = ptdesc_folio(ptdesc);
>>>> -
>>>> - ptlock_free(ptdesc);
>>>> - __folio_clear_pgtable(folio);
>>>> - lruvec_stat_sub_folio(folio, NR_PAGETABLE);
>>>> -}
>
> Thank you!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 06/15] s390: pgtable: add statistics for PUD and P4D level page table
2025-01-06 11:05 ` Qi Zheng
@ 2025-01-06 13:34 ` Alexander Gordeev
2025-01-06 13:37 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Alexander Gordeev @ 2025-01-06 13:34 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, Jan 06, 2025 at 07:05:16PM +0800, Qi Zheng wrote:
> > I understand that you want to sort p.._free_tlb() routines, but please
>
> Yes, I thought it was a minor change, so I just did it.
>
> > do not move the code around or make a separate follow-up patch.
>
> Well, if you have a strong opinion about this, I can send an updated
> patch.
If you ever send v5, then please update this patch.
> Thanks!
Thank you!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD to __tlb_remove_table()
2025-01-06 12:44 ` Alexander Gordeev
@ 2025-01-06 13:34 ` Qi Zheng
2025-01-06 14:35 ` Alexander Gordeev
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-06 13:34 UTC (permalink / raw)
To: Alexander Gordeev
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/6 20:44, Alexander Gordeev wrote:
> On Mon, Jan 06, 2025 at 07:02:17PM +0800, Qi Zheng wrote:
>>> On Mon, Dec 30, 2024 at 05:07:47PM +0800, Qi Zheng wrote:
>>>> To unify the PxD and PTE TLB free path, also move the pagetable_dtor() of
>>>> PMD|PUD|P4D to __tlb_remove_table().
>>>
>>> The above and Subject are still incorrect: pagetable_dtor() is
>>> called from pagetable_dtor_free(), not from __tlb_remove_table().
>>
>> Hmm, __tlb_remove_table() calls pagetable_dtor_free(), so moving to
>> pagetable_dtor_free() means moving to __tlb_remove_table(). Right?
>
> Right. But you Subject and description claim "... also move the
> pagetable_dtor()" not to pagetable_dtor_free() - which is another
> function.
OK, will change the subject and description to:
s390: pgtable: also move pagetable_dtor() of PxD to pagetable_dtor_free()
To unify the PxD and PTE TLB free path, also move the pagetable_dtor() of
PMD|PUD|P4D to pagetable_dtor_free().
But pagetable_dtor_free() is newly introduced in this patch, should it
be changed to 'move ... to pagetable_pte_dtor_free()'? But this seems
strange. :(
>
>> And the main purpose of this patch is also to move pagetable_dtor()
>> to __tlb_remove_table(). So I think this description makes sense?
>
> The patch makes sense, but the description it is incorrect ;)
>
> Thanks!
Thanks!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 06/15] s390: pgtable: add statistics for PUD and P4D level page table
2025-01-06 13:34 ` Alexander Gordeev
@ 2025-01-06 13:37 ` Qi Zheng
0 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2025-01-06 13:37 UTC (permalink / raw)
To: Alexander Gordeev
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/6 21:34, Alexander Gordeev wrote:
> On Mon, Jan 06, 2025 at 07:05:16PM +0800, Qi Zheng wrote:
>>> I understand that you want to sort p.._free_tlb() routines, but please
>>
>> Yes, I thought it was a minor change, so I just did it.
>>
>>> do not move the code around or make a separate follow-up patch.
>>
>> Well, if you have a strong opinion about this, I can send an updated
>> patch.
>
> If you ever send v5, then please update this patch.
OK, will do.
>
>> Thanks!
>
> Thank you!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD to __tlb_remove_table()
2025-01-06 13:34 ` Qi Zheng
@ 2025-01-06 14:35 ` Alexander Gordeev
2025-01-06 14:44 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Alexander Gordeev @ 2025-01-06 14:35 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, Jan 06, 2025 at 09:34:55PM +0800, Qi Zheng wrote:
> OK, will change the subject and description to:
>
> s390: pgtable: also move pagetable_dtor() of PxD to pagetable_dtor_free()
>
> To unify the PxD and PTE TLB free path, also move the pagetable_dtor() of
> PMD|PUD|P4D to pagetable_dtor_free().
>
> But pagetable_dtor_free() is newly introduced in this patch, should it
> be changed to 'move ... to pagetable_pte_dtor_free()'? But this seems
> strange. :(
s390: pgtable: consolidate PxD and PTE TLB free paths
Call pagetable_dtor() for PMD|PUD|P4D tables just before ptdesc is
freed - same as it is done for PTE tables. That allows consolidating
TLB free paths for all table types.
Makes sense?
> Thanks!
Thank you!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD to __tlb_remove_table()
2025-01-06 14:35 ` Alexander Gordeev
@ 2025-01-06 14:44 ` Qi Zheng
0 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2025-01-06 14:44 UTC (permalink / raw)
To: Alexander Gordeev
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/6 22:35, Alexander Gordeev wrote:
> On Mon, Jan 06, 2025 at 09:34:55PM +0800, Qi Zheng wrote:
>> OK, will change the subject and description to:
>>
>> s390: pgtable: also move pagetable_dtor() of PxD to pagetable_dtor_free()
>>
>> To unify the PxD and PTE TLB free path, also move the pagetable_dtor() of
>> PMD|PUD|P4D to pagetable_dtor_free().
>>
>> But pagetable_dtor_free() is newly introduced in this patch, should it
>> be changed to 'move ... to pagetable_pte_dtor_free()'? But this seems
>> strange. :(
>
> s390: pgtable: consolidate PxD and PTE TLB free paths
>
> Call pagetable_dtor() for PMD|PUD|P4D tables just before ptdesc is
> freed - same as it is done for PTE tables. That allows consolidating
> TLB free paths for all table types.
>
> Makes sense?
Ah, make sense. Many thanks to you!
Will do it in v5.
>
>> Thanks!
>
> Thank you!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor()
2025-01-06 13:23 ` Qi Zheng
@ 2025-01-07 9:23 ` Kevin Brodsky
0 siblings, 0 replies; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-07 9:23 UTC (permalink / raw)
To: Qi Zheng, Alexander Gordeev
Cc: peterz, palmer, tglx, david, jannh, hughd, yuzhao, willy,
muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 06/01/2025 14:23, Qi Zheng wrote:
> On 2025/1/6 20:36, Alexander Gordeev wrote:
>> On Mon, Jan 06, 2025 at 06:55:58PM +0800, Qi Zheng wrote:
>>>>> +static inline void pagetable_dtor(struct ptdesc *ptdesc)
>>>>> +{
>>>>> + struct folio *folio = ptdesc_folio(ptdesc);
>>>>> +
>>>>> + ptlock_free(ptdesc);
>>>>> + __folio_clear_pgtable(folio);
>>>>> + lruvec_stat_sub_folio(folio, NR_PAGETABLE);
>>>>> +}
>>>>> +
>>>>
>>>> If I am not mistaken, it is just pagetable_pte_dtor() rename.
>>>> What is the point in moving the code around?
>>>
>>> No, this is to unify pagetable_p*_dtor() into pagetable_dtor(), so
>>> that we can move pagetable_dtor() to __tlb_remove_table(), and then
>>> ptlock and PTE page can be freed together through RCU, which is
>>> also the main purpose of this patch series.
>>
>> I am only talking about this patch. pagetable_dtor() code above is
>> the same pagetable_pte_dtor() below - it is only the function name
>> that changed. So why to move the function body? Anyway, that is
>
> Ah, I just don't want to put pagetable_dtor() in between
> pagetable_pte_ctor() and ___pte_offset_map(), so I moved it above
> pagetable_pte_ctor(). No other special reason. 😉
I think inserting pagetable_dtor() there makes sense. I wouldn't say
that pagetable_pte_dtor() is being renamed to pagetable_dtor(), because
in fact this patch replaces all of pagetable_{pte,pmd,pud}_dtor() with
pagetable_dtor(), and it is arguably clearer to insert the latter higher
up in mm.h.
FWIW my follow-up series introduces a common __pagetable_dtor(),
inserted below pagetable_ctor() [1].
- Kevin
[1]
https://lore.kernel.org/linux-mm/20250103184415.2744423-2-kevin.brodsky@arm.com/
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-06 3:49 ` Qi Zheng
@ 2025-01-07 9:57 ` Kevin Brodsky
2025-01-07 10:51 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-07 9:57 UTC (permalink / raw)
To: Qi Zheng
Cc: agordeev, palmer, tglx, david, jannh, hughd, yuzhao, willy,
muchun.song, vbabka, lorenzo.stoakes, rientjes, vishal.moola,
arnd, will, aneesh.kumar, npiggin, dave.hansen, rppt,
ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um, peterz, akpm
On 06/01/2025 04:49, Qi Zheng wrote:
> [...]
>
>> Once this is done, we should be able to replace all those confusing
>> calls to tlb_remove_page() on PTPs with tlb_remove_table() and remove
>> the explicit call to pagetable_dtor(). AIUI this is essentially what
>> Peter suggested on v3 [2].
>
> Since this patch series is mainly for bug fix, I think that these things
> can be done in separate patch series later.
Sure that's fair.
>
>>
>> [...]
>>
>>> Or can we just not let tlb_remove_table() fall back to
>>> tlb_remove_page()? Like the following:
>>>
>>> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
>>> index a59205863f431..354ffaa4bd120 100644
>>> --- a/include/asm-generic/tlb.h
>>> +++ b/include/asm-generic/tlb.h
>>> @@ -195,8 +195,6 @@
>>> * various ptep_get_and_clear() functions.
>>> */
>>>
>>> -#ifdef CONFIG_MMU_GATHER_TABLE_FREE
>>> -
>>> struct mmu_table_batch {
>>> #ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
>>> struct rcu_head rcu;
>>> @@ -219,16 +217,6 @@ static inline void __tlb_remove_table(void *table)
>>>
>>> extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
>>>
>>> -#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
>>> -
>>> -/*
>>> - * Without MMU_GATHER_TABLE_FREE the architecture is assumed to have
>>> page based
>>> - * page directories and we can use the normal page batching to free
>>> them.
>>> - */
>>> -#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
>>
>> We still need a different implementation of tlb_remove_table() in this
>> case. We could define it inline here:
>>
>> static inline void tlb_remove_table(struct mmu_gather *tlb, void *table)
>> {
>> struct page *page = table;
>>
>> pagetable_dtor(page_ptdesc(page));
>> tlb_remove_page(page);
>> }
>
> Right. As I said above, will add this to the updated patch #8.
I think it would be preferable to make it a standalone patch, because
this is a change to generic code that could in principle impact other
arch's too.
- Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-07 9:57 ` Kevin Brodsky
@ 2025-01-07 10:51 ` Qi Zheng
2025-01-07 11:58 ` Kevin Brodsky
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-07 10:51 UTC (permalink / raw)
To: Kevin Brodsky
Cc: agordeev, palmer, tglx, david, jannh, hughd, yuzhao, willy,
muchun.song, vbabka, lorenzo.stoakes, rientjes, vishal.moola,
arnd, will, aneesh.kumar, npiggin, dave.hansen, rppt,
ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um, peterz, akpm
On 2025/1/7 17:57, Kevin Brodsky wrote:
> On 06/01/2025 04:49, Qi Zheng wrote:
>> [...]
>>
>>> Once this is done, we should be able to replace all those confusing
>>> calls to tlb_remove_page() on PTPs with tlb_remove_table() and remove
>>> the explicit call to pagetable_dtor(). AIUI this is essentially what
>>> Peter suggested on v3 [2].
>>
>> Since this patch series is mainly for bug fix, I think that these things
>> can be done in separate patch series later.
>
> Sure that's fair.
>
>>
>>>
>>> [...]
>>>
>>>> Or can we just not let tlb_remove_table() fall back to
>>>> tlb_remove_page()? Like the following:
>>>>
>>>> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
>>>> index a59205863f431..354ffaa4bd120 100644
>>>> --- a/include/asm-generic/tlb.h
>>>> +++ b/include/asm-generic/tlb.h
>>>> @@ -195,8 +195,6 @@
>>>> * various ptep_get_and_clear() functions.
>>>> */
>>>>
>>>> -#ifdef CONFIG_MMU_GATHER_TABLE_FREE
>>>> -
>>>> struct mmu_table_batch {
>>>> #ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
>>>> struct rcu_head rcu;
>>>> @@ -219,16 +217,6 @@ static inline void __tlb_remove_table(void *table)
>>>>
>>>> extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
>>>>
>>>> -#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
>>>> -
>>>> -/*
>>>> - * Without MMU_GATHER_TABLE_FREE the architecture is assumed to have
>>>> page based
>>>> - * page directories and we can use the normal page batching to free
>>>> them.
>>>> - */
>>>> -#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
>>>
>>> We still need a different implementation of tlb_remove_table() in this
>>> case. We could define it inline here:
>>>
>>> static inline void tlb_remove_table(struct mmu_gather *tlb, void *table)
>>> {
>>> struct page *page = table;
>>>
>>> pagetable_dtor(page_ptdesc(page));
>>> tlb_remove_page(page);
>>> }
>>
>> Right. As I said above, will add this to the updated patch #8.
>
> I think it would be preferable to make it a standalone patch, because
> this is a change to generic code that could in principle impact other
> arch's too.
Agree, I have done that:
```
Author: Qi Zheng <zhengqi.arch@bytedance.com>
Date: Fri Dec 13 17:13:48 2024 +0800
mm: pgtable: completely move pagetable_dtor() to generic
tlb_remove_table()
For the generic tlb_remove_table(), it is implemented in the
following two
forms:
1) CONFIG_MMU_GATHER_TABLE_FREE is enabled
tlb_remove_table
--> generic __tlb_remove_table()
2) CONFIG_MMU_GATHER_TABLE_FREE is disabled
tlb_remove_table
--> tlb_remove_page
For case 1), the pagetable_dtor() has already been moved to generic
__tlb_remove_table().
For case 2), now only arm will call
tlb_remove_table()/tlb_remove_ptdesc()
when CONFIG_MMU_GATHER_TABLE_FREE is disabled. Let's move
pagetable_dtor()
completely to generic tlb_remove_table(), so that the architectures can
follow more easily.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index b8eebdb598631..ea4fbe7b17f6f 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -34,10 +34,6 @@ __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
unsigned long addr)
{
struct ptdesc *ptdesc = page_ptdesc(pte);
-#ifndef CONFIG_MMU_GATHER_TABLE_FREE
- pagetable_dtor(ptdesc);
-#endif
-
#ifndef CONFIG_ARM_LPAE
/*
* With the classic ARM MMU, a pte page has two corresponding pmd
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index 69de47c7ef3c5..53ae7748f555b 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -220,14 +220,20 @@ static inline void __tlb_remove_table(void *table)
extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
-#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
+#else /* !CONFIG_MMU_GATHER_TABLE_FREE */
+static inline void tlb_remove_page(struct mmu_gather *tlb, struct page
*page);
/*
* Without MMU_GATHER_TABLE_FREE the architecture is assumed to have
page based
* page directories and we can use the normal page batching to free them.
*/
-#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
+static inline void tlb_remove_table(struct mmu_gather *tlb, void *table)
+{
+ struct page *page = (struct page *)table;
+ pagetable_dtor(page_ptdesc(page));
+ tlb_remove_page(tlb, page);
+}
#endif /* CONFIG_MMU_GATHER_TABLE_FREE */
#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
```
and will send v5 later.
Thanks!
>
> - Kevin
^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-07 10:51 ` Qi Zheng
@ 2025-01-07 11:58 ` Kevin Brodsky
2025-01-07 12:31 ` Qi Zheng
0 siblings, 1 reply; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-07 11:58 UTC (permalink / raw)
To: Qi Zheng
Cc: agordeev, palmer, tglx, david, jannh, hughd, yuzhao, willy,
muchun.song, vbabka, lorenzo.stoakes, rientjes, vishal.moola,
arnd, will, aneesh.kumar, npiggin, dave.hansen, rppt,
ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um, peterz, akpm
On 07/01/2025 11:51, Qi Zheng wrote:
> [...]
>
> Author: Qi Zheng <zhengqi.arch@bytedance.com>
> Date: Fri Dec 13 17:13:48 2024 +0800
>
> mm: pgtable: completely move pagetable_dtor() to generic
> tlb_remove_table()
>
> For the generic tlb_remove_table(), it is implemented in the
> following two
> forms:
>
> 1) CONFIG_MMU_GATHER_TABLE_FREE is enabled
>
> tlb_remove_table
> --> generic __tlb_remove_table()
>
> 2) CONFIG_MMU_GATHER_TABLE_FREE is disabled
>
> tlb_remove_table
> --> tlb_remove_page
>
> For case 1), the pagetable_dtor() has already been moved to generic
> __tlb_remove_table().
>
> For case 2), now only arm will call
> tlb_remove_table()/tlb_remove_ptdesc()
> when CONFIG_MMU_GATHER_TABLE_FREE is disabled. Let's move
> pagetable_dtor()
> completely to generic tlb_remove_table(), so that the
> architectures can
> follow more easily.
>
> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
>
> diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
> index b8eebdb598631..ea4fbe7b17f6f 100644
> --- a/arch/arm/include/asm/tlb.h
> +++ b/arch/arm/include/asm/tlb.h
> @@ -34,10 +34,6 @@ __pte_free_tlb(struct mmu_gather *tlb, pgtable_t
> pte, unsigned long addr)
> {
> struct ptdesc *ptdesc = page_ptdesc(pte);
>
> -#ifndef CONFIG_MMU_GATHER_TABLE_FREE
> - pagetable_dtor(ptdesc);
> -#endif
I guess this hunk will disappear since this call isn't present to start
with.
> -
> #ifndef CONFIG_ARM_LPAE
> /*
> * With the classic ARM MMU, a pte page has two corresponding pmd
> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
> index 69de47c7ef3c5..53ae7748f555b 100644
> --- a/include/asm-generic/tlb.h
> +++ b/include/asm-generic/tlb.h
> @@ -220,14 +220,20 @@ static inline void __tlb_remove_table(void *table)
>
> extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
>
> -#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
> +#else /* !CONFIG_MMU_GATHER_TABLE_FREE */
Good catch!
>
> +static inline void tlb_remove_page(struct mmu_gather *tlb, struct
> page *page);
Nit: might be better to move the declaration up, e.g. above #ifdef
CONFIG_MMU_GATHER_TABLE_FREE.
> /*
> * Without MMU_GATHER_TABLE_FREE the architecture is assumed to have
> page based
> * page directories and we can use the normal page batching to free
> them.
> */
> -#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
> +static inline void tlb_remove_table(struct mmu_gather *tlb, void *table)
> +{
> + struct page *page = (struct page *)table;
>
> + pagetable_dtor(page_ptdesc(page));
> + tlb_remove_page(tlb, page);
> +}
> #endif /* CONFIG_MMU_GATHER_TABLE_FREE */
>
> #ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
Looks good to me otherwise.
- Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-07 11:58 ` Kevin Brodsky
@ 2025-01-07 12:31 ` Qi Zheng
2025-01-07 14:17 ` Kevin Brodsky
0 siblings, 1 reply; 54+ messages in thread
From: Qi Zheng @ 2025-01-07 12:31 UTC (permalink / raw)
To: Kevin Brodsky
Cc: agordeev, palmer, tglx, david, jannh, hughd, yuzhao, willy,
muchun.song, vbabka, lorenzo.stoakes, rientjes, vishal.moola,
arnd, will, aneesh.kumar, npiggin, dave.hansen, rppt,
ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um, peterz, akpm
On 2025/1/7 19:58, Kevin Brodsky wrote:
> On 07/01/2025 11:51, Qi Zheng wrote:
>> [...]
>>
>> Author: Qi Zheng <zhengqi.arch@bytedance.com>
>> Date: Fri Dec 13 17:13:48 2024 +0800
>>
>> mm: pgtable: completely move pagetable_dtor() to generic
>> tlb_remove_table()
>>
>> For the generic tlb_remove_table(), it is implemented in the
>> following two
>> forms:
>>
>> 1) CONFIG_MMU_GATHER_TABLE_FREE is enabled
>>
>> tlb_remove_table
>> --> generic __tlb_remove_table()
>>
>> 2) CONFIG_MMU_GATHER_TABLE_FREE is disabled
>>
>> tlb_remove_table
>> --> tlb_remove_page
>>
>> For case 1), the pagetable_dtor() has already been moved to generic
>> __tlb_remove_table().
>>
>> For case 2), now only arm will call
>> tlb_remove_table()/tlb_remove_ptdesc()
>> when CONFIG_MMU_GATHER_TABLE_FREE is disabled. Let's move
>> pagetable_dtor()
>> completely to generic tlb_remove_table(), so that the
>> architectures can
>> follow more easily.
>>
>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
I missed your Suggested-by, will add it in v5.
>>
>> diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
>> index b8eebdb598631..ea4fbe7b17f6f 100644
>> --- a/arch/arm/include/asm/tlb.h
>> +++ b/arch/arm/include/asm/tlb.h
>> @@ -34,10 +34,6 @@ __pte_free_tlb(struct mmu_gather *tlb, pgtable_t
>> pte, unsigned long addr)
>> {
>> struct ptdesc *ptdesc = page_ptdesc(pte);
>>
>> -#ifndef CONFIG_MMU_GATHER_TABLE_FREE
>> - pagetable_dtor(ptdesc);
>> -#endif
>
> I guess this hunk will disappear since this call isn't present to start
> with.
Yes, I plan to add this in the patch #8, and remove it in this patch.
>
>> -
>> #ifndef CONFIG_ARM_LPAE
>> /*
>> * With the classic ARM MMU, a pte page has two corresponding pmd
>> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
>> index 69de47c7ef3c5..53ae7748f555b 100644
>> --- a/include/asm-generic/tlb.h
>> +++ b/include/asm-generic/tlb.h
>> @@ -220,14 +220,20 @@ static inline void __tlb_remove_table(void *table)
>>
>> extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
>>
>> -#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
>> +#else /* !CONFIG_MMU_GATHER_TABLE_FREE */
>
> Good catch!
>
>>
>> +static inline void tlb_remove_page(struct mmu_gather *tlb, struct
>> page *page);
>
> Nit: might be better to move the declaration up, e.g. above #ifdef
> CONFIG_MMU_GATHER_TABLE_FREE.
Now only the tlb_remove_table() below calls it, maybe it's better to
keep the impact to minimum?
>
>> /*
>> * Without MMU_GATHER_TABLE_FREE the architecture is assumed to have
>> page based
>> * page directories and we can use the normal page batching to free
>> them.
>> */
>> -#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
>> +static inline void tlb_remove_table(struct mmu_gather *tlb, void *table)
>> +{
>> + struct page *page = (struct page *)table;
>>
>> + pagetable_dtor(page_ptdesc(page));
>> + tlb_remove_page(tlb, page);
>> +}
>> #endif /* CONFIG_MMU_GATHER_TABLE_FREE */
>>
>> #ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
>
> Looks good to me otherwise.
I will add your Reviewed-by to all patches (except yours) in v5, can
I also add it to this new added patch? (if we agree with the discussion
above) ;)
Thanks!
>
> - Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 13/15] mm: pgtable: introduce generic __tlb_remove_table()
2024-12-30 9:07 ` [PATCH v4 13/15] mm: pgtable: introduce generic __tlb_remove_table() Qi Zheng
@ 2025-01-07 12:32 ` Andreas Larsson
2025-01-07 12:34 ` Qi Zheng
2025-01-07 14:20 ` Alexander Gordeev
1 sibling, 1 reply; 54+ messages in thread
From: Andreas Larsson @ 2025-01-07 12:32 UTC (permalink / raw)
To: Qi Zheng, peterz, agordeev, kevin.brodsky, palmer, tglx, david,
jannh, hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes,
akpm, rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts
Cc: linux-mm, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390,
sparclinux, linux-kernel, x86, linux-arch, linux-csky,
linux-hexagon, loongarch, linux-m68k, linux-mips, linux-openrisc,
linux-sh, linux-um
On 2024-12-30 10:07, Qi Zheng wrote:
> diff --git a/arch/sparc/include/asm/tlb_32.h b/arch/sparc/include/asm/tlb_32.h
> index 5cd28a8793e39..910254867dfbd 100644
> --- a/arch/sparc/include/asm/tlb_32.h
> +++ b/arch/sparc/include/asm/tlb_32.h
> @@ -2,6 +2,7 @@
> #ifndef _SPARC_TLB_H
> #define _SPARC_TLB_H
>
> +#define __HAVE_ARCH_TLB_REMOVE_TABLE
sparc32 does not select MMU_GATHER_TABLE_FREE, and therefore does not
have (nor need) __tlb_remove_table, so this define should not be added.
> #include <asm-generic/tlb.h>
>
> #endif /* _SPARC_TLB_H */
> diff --git a/arch/sparc/include/asm/tlb_64.h b/arch/sparc/include/asm/tlb_64.h
> index 3037187482db7..1a6e694418e39 100644
> --- a/arch/sparc/include/asm/tlb_64.h
> +++ b/arch/sparc/include/asm/tlb_64.h
> @@ -33,6 +33,7 @@ void flush_tlb_pending(void);
> #define tlb_needs_table_invalidate() (false)
> #endif
>
> +#define __HAVE_ARCH_TLB_REMOVE_TABLE
> #include <asm-generic/tlb.h>
>
> #endif /* _SPARC64_TLB_H */
LGTM.
With the removal of the define for sparc32 in v5:
Acked-by: Andreas Larsson <andreas@gaisler.com> # sparc
Thanks,
Andreas
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 13/15] mm: pgtable: introduce generic __tlb_remove_table()
2025-01-07 12:32 ` Andreas Larsson
@ 2025-01-07 12:34 ` Qi Zheng
0 siblings, 0 replies; 54+ messages in thread
From: Qi Zheng @ 2025-01-07 12:34 UTC (permalink / raw)
To: Andreas Larsson
Cc: peterz, agordeev, kevin.brodsky, palmer, tglx, david, jannh,
hughd, yuzhao, willy, muchun.song, vbabka, lorenzo.stoakes, akpm,
rientjes, vishal.moola, arnd, will, aneesh.kumar, npiggin,
dave.hansen, rppt, ryan.roberts, linux-mm, linux-arm-kernel,
linuxppc-dev, linux-riscv, linux-s390, sparclinux, linux-kernel,
x86, linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On 2025/1/7 20:32, Andreas Larsson wrote:
> On 2024-12-30 10:07, Qi Zheng wrote:
>> diff --git a/arch/sparc/include/asm/tlb_32.h b/arch/sparc/include/asm/tlb_32.h
>> index 5cd28a8793e39..910254867dfbd 100644
>> --- a/arch/sparc/include/asm/tlb_32.h
>> +++ b/arch/sparc/include/asm/tlb_32.h
>> @@ -2,6 +2,7 @@
>> #ifndef _SPARC_TLB_H
>> #define _SPARC_TLB_H
>>
>> +#define __HAVE_ARCH_TLB_REMOVE_TABLE
>
> sparc32 does not select MMU_GATHER_TABLE_FREE, and therefore does not
> have (nor need) __tlb_remove_table, so this define should not be added.
Got it. Will remove it in v5.
>
>
>> #include <asm-generic/tlb.h>
>>
>> #endif /* _SPARC_TLB_H */
>> diff --git a/arch/sparc/include/asm/tlb_64.h b/arch/sparc/include/asm/tlb_64.h
>> index 3037187482db7..1a6e694418e39 100644
>> --- a/arch/sparc/include/asm/tlb_64.h
>> +++ b/arch/sparc/include/asm/tlb_64.h
>> @@ -33,6 +33,7 @@ void flush_tlb_pending(void);
>> #define tlb_needs_table_invalidate() (false)
>> #endif
>>
>> +#define __HAVE_ARCH_TLB_REMOVE_TABLE
>> #include <asm-generic/tlb.h>
>>
>> #endif /* _SPARC64_TLB_H */
> LGTM.
>
>
> With the removal of the define for sparc32 in v5:
>
> Acked-by: Andreas Larsson <andreas@gaisler.com> # sparc
Thanks!
>
> Thanks,
> Andreas
>
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 10/15] riscv: pgtable: move pagetable_dtor() to __tlb_remove_table()
2025-01-07 12:31 ` Qi Zheng
@ 2025-01-07 14:17 ` Kevin Brodsky
0 siblings, 0 replies; 54+ messages in thread
From: Kevin Brodsky @ 2025-01-07 14:17 UTC (permalink / raw)
To: Qi Zheng
Cc: agordeev, palmer, tglx, david, jannh, hughd, yuzhao, willy,
muchun.song, vbabka, lorenzo.stoakes, rientjes, vishal.moola,
arnd, will, aneesh.kumar, npiggin, dave.hansen, rppt,
ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um, peterz, akpm
On 07/01/2025 13:31, Qi Zheng wrote:
> On 2025/1/7 19:58, Kevin Brodsky wrote:
>> On 07/01/2025 11:51, Qi Zheng wrote:
>>> [...]
>>>
>>> Author: Qi Zheng <zhengqi.arch@bytedance.com>
>>> Date: Fri Dec 13 17:13:48 2024 +0800
>>>
>>> mm: pgtable: completely move pagetable_dtor() to generic
>>> tlb_remove_table()
>>>
>>> For the generic tlb_remove_table(), it is implemented in the
>>> following two
>>> forms:
>>>
>>> 1) CONFIG_MMU_GATHER_TABLE_FREE is enabled
>>>
>>> tlb_remove_table
>>> --> generic __tlb_remove_table()
>>>
>>> 2) CONFIG_MMU_GATHER_TABLE_FREE is disabled
>>>
>>> tlb_remove_table
>>> --> tlb_remove_page
>>>
>>> For case 1), the pagetable_dtor() has already been moved to
>>> generic
>>> __tlb_remove_table().
>>>
>>> For case 2), now only arm will call
>>> tlb_remove_table()/tlb_remove_ptdesc()
>>> when CONFIG_MMU_GATHER_TABLE_FREE is disabled. Let's move
>>> pagetable_dtor()
>>> completely to generic tlb_remove_table(), so that the
>>> architectures can
>>> follow more easily.
>>>
>>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
>
> I missed your Suggested-by, will add it in v5.
Ah yes thanks!
>
>>>
>>> diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
>>> index b8eebdb598631..ea4fbe7b17f6f 100644
>>> --- a/arch/arm/include/asm/tlb.h
>>> +++ b/arch/arm/include/asm/tlb.h
>>> @@ -34,10 +34,6 @@ __pte_free_tlb(struct mmu_gather *tlb, pgtable_t
>>> pte, unsigned long addr)
>>> {
>>> struct ptdesc *ptdesc = page_ptdesc(pte);
>>>
>>> -#ifndef CONFIG_MMU_GATHER_TABLE_FREE
>>> - pagetable_dtor(ptdesc);
>>> -#endif
>>
>> I guess this hunk will disappear since this call isn't present to start
>> with.
>
> Yes, I plan to add this in the patch #8, and remove it in this patch.
Right I guess this is required to keep patch 8 self-contained, makes sense.
>
>>
>>> -
>>> #ifndef CONFIG_ARM_LPAE
>>> /*
>>> * With the classic ARM MMU, a pte page has two
>>> corresponding pmd
>>> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
>>> index 69de47c7ef3c5..53ae7748f555b 100644
>>> --- a/include/asm-generic/tlb.h
>>> +++ b/include/asm-generic/tlb.h
>>> @@ -220,14 +220,20 @@ static inline void __tlb_remove_table(void
>>> *table)
>>>
>>> extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
>>>
>>> -#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
>>> +#else /* !CONFIG_MMU_GATHER_TABLE_FREE */
>>
>> Good catch!
>>
>>>
>>> +static inline void tlb_remove_page(struct mmu_gather *tlb, struct
>>> page *page);
>>
>> Nit: might be better to move the declaration up, e.g. above #ifdef
>> CONFIG_MMU_GATHER_TABLE_FREE.
>
> Now only the tlb_remove_table() below calls it, maybe it's better to
> keep the impact to minimum?
I feel it might be better to make the declaration unconditional, but
this is really a detail, I don't mind either way.
>
>>
>>> /*
>>> * Without MMU_GATHER_TABLE_FREE the architecture is assumed to have
>>> page based
>>> * page directories and we can use the normal page batching to free
>>> them.
>>> */
>>> -#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
>>> +static inline void tlb_remove_table(struct mmu_gather *tlb, void
>>> *table)
>>> +{
>>> + struct page *page = (struct page *)table;
>>>
>>> + pagetable_dtor(page_ptdesc(page));
>>> + tlb_remove_page(tlb, page);
>>> +}
>>> #endif /* CONFIG_MMU_GATHER_TABLE_FREE */
>>>
>>> #ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
>>
>> Looks good to me otherwise.
>
> I will add your Reviewed-by to all patches (except yours) in v5, can
> I also add it to this new added patch? (if we agree with the discussion
> above) ;)
Yes please do, thanks!
- Kevin
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 13/15] mm: pgtable: introduce generic __tlb_remove_table()
2024-12-30 9:07 ` [PATCH v4 13/15] mm: pgtable: introduce generic __tlb_remove_table() Qi Zheng
2025-01-07 12:32 ` Andreas Larsson
@ 2025-01-07 14:20 ` Alexander Gordeev
1 sibling, 0 replies; 54+ messages in thread
From: Alexander Gordeev @ 2025-01-07 14:20 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, Dec 30, 2024 at 05:07:48PM +0800, Qi Zheng wrote:
> Several architectures (arm, arm64, riscv and x86) define exactly the
> same __tlb_remove_table(), just introduce generic __tlb_remove_table() to
> eliminate these duplications.
>
> The s390 __tlb_remove_table() is nearly the same, so also make s390
> __tlb_remove_table() version generic.
>
> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
> ---
> arch/arm/include/asm/tlb.h | 9 ---------
> arch/arm64/include/asm/tlb.h | 7 -------
> arch/powerpc/include/asm/tlb.h | 1 +
> arch/riscv/include/asm/tlb.h | 12 ------------
> arch/s390/include/asm/tlb.h | 9 ++++-----
> arch/s390/mm/pgalloc.c | 7 -------
> arch/sparc/include/asm/tlb_32.h | 1 +
> arch/sparc/include/asm/tlb_64.h | 1 +
> arch/x86/include/asm/tlb.h | 17 -----------------
> include/asm-generic/tlb.h | 15 +++++++++++++--
> 10 files changed, 20 insertions(+), 59 deletions(-)
...
> diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
> index 79df7c0932c56..da4a7d175f69c 100644
> --- a/arch/s390/include/asm/tlb.h
> +++ b/arch/s390/include/asm/tlb.h
> @@ -22,7 +22,6 @@
> * Pages used for the page tables is a different story. FIXME: more
> */
>
> -void __tlb_remove_table(void *_table);
> static inline void tlb_flush(struct mmu_gather *tlb);
> static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
> struct page *page, bool delay_rmap, int page_size);
> @@ -87,7 +86,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
> tlb->cleared_pmds = 1;
> if (mm_alloc_pgste(tlb->mm))
> gmap_unlink(tlb->mm, (unsigned long *)pte, address);
> - tlb_remove_ptdesc(tlb, pte);
> + tlb_remove_ptdesc(tlb, virt_to_ptdesc(pte));
> }
>
> /*
> @@ -106,7 +105,7 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
> tlb->mm->context.flush_mm = 1;
> tlb->freed_tables = 1;
> tlb->cleared_puds = 1;
> - tlb_remove_ptdesc(tlb, pmd);
> + tlb_remove_ptdesc(tlb, virt_to_ptdesc(pmd));
> }
>
> /*
> @@ -124,7 +123,7 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
> tlb->mm->context.flush_mm = 1;
> tlb->freed_tables = 1;
> tlb->cleared_p4ds = 1;
> - tlb_remove_ptdesc(tlb, pud);
> + tlb_remove_ptdesc(tlb, virt_to_ptdesc(pud));
> }
>
> /*
> @@ -142,7 +141,7 @@ static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
> __tlb_adjust_range(tlb, address, PAGE_SIZE);
> tlb->mm->context.flush_mm = 1;
> tlb->freed_tables = 1;
> - tlb_remove_ptdesc(tlb, p4d);
> + tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
> }
>
> #endif /* _S390_TLB_H */
> diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
> index c73b89811a264..3e002dea6278f 100644
> --- a/arch/s390/mm/pgalloc.c
> +++ b/arch/s390/mm/pgalloc.c
> @@ -193,13 +193,6 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
> pagetable_dtor_free(ptdesc);
> }
>
> -void __tlb_remove_table(void *table)
> -{
> - struct ptdesc *ptdesc = virt_to_ptdesc(table);
> -
> - pagetable_dtor_free(ptdesc);
> -}
> -
> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> static void pte_free_now(struct rcu_head *head)
> {
...
> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
> index 709830274b756..69de47c7ef3c5 100644
> --- a/include/asm-generic/tlb.h
> +++ b/include/asm-generic/tlb.h
> @@ -153,8 +153,9 @@
> *
> * Useful if your architecture has non-page page directories.
> *
> - * When used, an architecture is expected to provide __tlb_remove_table()
> - * which does the actual freeing of these pages.
> + * When used, an architecture is expected to provide __tlb_remove_table() or
> + * use the generic __tlb_remove_table(), which does the actual freeing of these
> + * pages.
> *
> * MMU_GATHER_RCU_TABLE_FREE
> *
> @@ -207,6 +208,16 @@ struct mmu_table_batch {
> #define MAX_TABLE_BATCH \
> ((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *))
>
> +#ifndef __HAVE_ARCH_TLB_REMOVE_TABLE
> +static inline void __tlb_remove_table(void *table)
> +{
> + struct ptdesc *ptdesc = (struct ptdesc *)table;
> +
> + pagetable_dtor(ptdesc);
> + pagetable_free(ptdesc);
> +}
> +#endif
> +
> extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
>
> #else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
For s390:
Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
Thanks!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v4 15/15] mm: pgtable: introduce generic pagetable_dtor_free()
2024-12-30 9:07 ` [PATCH v4 15/15] mm: pgtable: introduce generic pagetable_dtor_free() Qi Zheng
@ 2025-01-07 14:22 ` Alexander Gordeev
0 siblings, 0 replies; 54+ messages in thread
From: Alexander Gordeev @ 2025-01-07 14:22 UTC (permalink / raw)
To: Qi Zheng
Cc: peterz, kevin.brodsky, palmer, tglx, david, jannh, hughd, yuzhao,
willy, muchun.song, vbabka, lorenzo.stoakes, akpm, rientjes,
vishal.moola, arnd, will, aneesh.kumar, npiggin, dave.hansen,
rppt, ryan.roberts, linux-mm, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-kernel, x86,
linux-arch, linux-csky, linux-hexagon, loongarch, linux-m68k,
linux-mips, linux-openrisc, linux-sh, linux-um
On Mon, Dec 30, 2024 at 05:07:50PM +0800, Qi Zheng wrote:
> The pte_free(), pmd_free(), __pud_free() and __p4d_free() in
> asm-generic/pgalloc.h and the generic __tlb_remove_table() are basically
> the same, so let's introduce pagetable_dtor_free() to deduplicate them.
>
> In addition, the pagetable_dtor_free() in s390 does the same thing, so
> let's s390 also calls generic pagetable_dtor_free().
>
> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
> Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> ---
> arch/s390/mm/pgalloc.c | 6 ------
> include/asm-generic/pgalloc.h | 12 ++++--------
> include/asm-generic/tlb.h | 3 +--
> include/linux/mm.h | 6 ++++++
> 4 files changed, 11 insertions(+), 16 deletions(-)
>
> diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
> index 3e002dea6278f..a4e7619020931 100644
> --- a/arch/s390/mm/pgalloc.c
> +++ b/arch/s390/mm/pgalloc.c
> @@ -180,12 +180,6 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
> return table;
> }
>
> -static void pagetable_dtor_free(struct ptdesc *ptdesc)
> -{
> - pagetable_dtor(ptdesc);
> - pagetable_free(ptdesc);
> -}
> -
> void page_table_free(struct mm_struct *mm, unsigned long *table)
> {
> struct ptdesc *ptdesc = virt_to_ptdesc(table);
> diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h
> index 4afb346eae255..e3977ddca15e4 100644
> --- a/include/asm-generic/pgalloc.h
> +++ b/include/asm-generic/pgalloc.h
> @@ -109,8 +109,7 @@ static inline void pte_free(struct mm_struct *mm, struct page *pte_page)
> {
> struct ptdesc *ptdesc = page_ptdesc(pte_page);
>
> - pagetable_dtor(ptdesc);
> - pagetable_free(ptdesc);
> + pagetable_dtor_free(ptdesc);
> }
>
>
> @@ -153,8 +152,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
> struct ptdesc *ptdesc = virt_to_ptdesc(pmd);
>
> BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
> - pagetable_dtor(ptdesc);
> - pagetable_free(ptdesc);
> + pagetable_dtor_free(ptdesc);
> }
> #endif
>
> @@ -202,8 +200,7 @@ static inline void __pud_free(struct mm_struct *mm, pud_t *pud)
> struct ptdesc *ptdesc = virt_to_ptdesc(pud);
>
> BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
> - pagetable_dtor(ptdesc);
> - pagetable_free(ptdesc);
> + pagetable_dtor_free(ptdesc);
> }
>
> #ifndef __HAVE_ARCH_PUD_FREE
> @@ -248,8 +245,7 @@ static inline void __p4d_free(struct mm_struct *mm, p4d_t *p4d)
> struct ptdesc *ptdesc = virt_to_ptdesc(p4d);
>
> BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
> - pagetable_dtor(ptdesc);
> - pagetable_free(ptdesc);
> + pagetable_dtor_free(ptdesc);
> }
>
> #ifndef __HAVE_ARCH_P4D_FREE
> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
> index 69de47c7ef3c5..a96d4b440f3da 100644
> --- a/include/asm-generic/tlb.h
> +++ b/include/asm-generic/tlb.h
> @@ -213,8 +213,7 @@ static inline void __tlb_remove_table(void *table)
> {
> struct ptdesc *ptdesc = (struct ptdesc *)table;
>
> - pagetable_dtor(ptdesc);
> - pagetable_free(ptdesc);
> + pagetable_dtor_free(ptdesc);
> }
> #endif
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index cad11fa10c192..94078c488e904 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -3001,6 +3001,12 @@ static inline void pagetable_dtor(struct ptdesc *ptdesc)
> lruvec_stat_sub_folio(folio, NR_PAGETABLE);
> }
>
> +static inline void pagetable_dtor_free(struct ptdesc *ptdesc)
> +{
> + pagetable_dtor(ptdesc);
> + pagetable_free(ptdesc);
> +}
> +
> static inline bool pagetable_pte_ctor(struct ptdesc *ptdesc)
> {
> struct folio *folio = ptdesc_folio(ptdesc);
For s390:
Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
Thanks!
^ permalink raw reply [flat|nested] 54+ messages in thread
end of thread, other threads:[~2025-01-07 14:23 UTC | newest]
Thread overview: 54+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-30 9:07 [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Qi Zheng
2024-12-30 9:07 ` [PATCH v4 01/15] Revert "mm: pgtable: make ptlock be freed by RCU" Qi Zheng
2024-12-30 9:07 ` [PATCH v4 02/15] riscv: mm: Skip pgtable level check in {pud,p4d}_alloc_one Qi Zheng
2025-01-06 11:20 ` Alexandre Ghiti
2024-12-30 9:07 ` [PATCH v4 03/15] asm-generic: pgalloc: Provide generic p4d_{alloc_one,free} Qi Zheng
2024-12-30 9:07 ` [PATCH v4 04/15] mm: pgtable: add statistics for P4D level page table Qi Zheng
2025-01-02 16:53 ` Kevin Brodsky
2025-01-03 3:53 ` Qi Zheng
2025-01-03 7:46 ` Kevin Brodsky
2024-12-30 9:07 ` [PATCH v4 05/15] arm64: pgtable: use mmu gather to free p4d " Qi Zheng
2024-12-30 9:07 ` [PATCH v4 06/15] s390: pgtable: add statistics for PUD and P4D " Qi Zheng
2025-01-06 10:32 ` Alexander Gordeev
2025-01-06 11:05 ` Qi Zheng
2025-01-06 13:34 ` Alexander Gordeev
2025-01-06 13:37 ` Qi Zheng
2024-12-30 9:07 ` [PATCH v4 07/15] mm: pgtable: introduce pagetable_dtor() Qi Zheng
2025-01-06 10:34 ` Alexander Gordeev
2025-01-06 10:55 ` Qi Zheng
2025-01-06 12:36 ` Alexander Gordeev
2025-01-06 13:23 ` Qi Zheng
2025-01-07 9:23 ` Kevin Brodsky
2024-12-30 9:07 ` [PATCH v4 08/15] arm: pgtable: move pagetable_dtor() to __tlb_remove_table() Qi Zheng
2024-12-30 9:07 ` [PATCH v4 09/15] arm64: " Qi Zheng
2024-12-30 9:07 ` [PATCH v4 10/15] riscv: " Qi Zheng
2025-01-02 16:53 ` Kevin Brodsky
2025-01-03 3:48 ` Qi Zheng
2025-01-03 8:02 ` Kevin Brodsky
2025-01-03 9:13 ` Qi Zheng
2025-01-03 9:35 ` Qi Zheng
2025-01-03 13:27 ` Kevin Brodsky
2025-01-06 3:49 ` Qi Zheng
2025-01-07 9:57 ` Kevin Brodsky
2025-01-07 10:51 ` Qi Zheng
2025-01-07 11:58 ` Kevin Brodsky
2025-01-07 12:31 ` Qi Zheng
2025-01-07 14:17 ` Kevin Brodsky
2024-12-30 9:07 ` [PATCH v4 11/15] x86: " Qi Zheng
2024-12-30 9:07 ` [PATCH v4 12/15] s390: pgtable: also move pagetable_dtor() of PxD " Qi Zheng
2025-01-06 10:36 ` Alexander Gordeev
2025-01-06 11:02 ` Qi Zheng
2025-01-06 12:44 ` Alexander Gordeev
2025-01-06 13:34 ` Qi Zheng
2025-01-06 14:35 ` Alexander Gordeev
2025-01-06 14:44 ` Qi Zheng
2024-12-30 9:07 ` [PATCH v4 13/15] mm: pgtable: introduce generic __tlb_remove_table() Qi Zheng
2025-01-07 12:32 ` Andreas Larsson
2025-01-07 12:34 ` Qi Zheng
2025-01-07 14:20 ` Alexander Gordeev
2024-12-30 9:07 ` [PATCH v4 14/15] mm: pgtable: move __tlb_remove_table_one() in x86 to generic file Qi Zheng
2024-12-30 9:07 ` [PATCH v4 15/15] mm: pgtable: introduce generic pagetable_dtor_free() Qi Zheng
2025-01-07 14:22 ` Alexander Gordeev
2024-12-31 0:24 ` [PATCH v4 00/15] move pagetable_*_dtor() to __tlb_remove_table() Andrew Morton
2025-01-02 17:00 ` Kevin Brodsky
2025-01-03 3:56 ` Qi Zheng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).