* [PATCH v3 0/4] mm: Fix page-table teardown during memory hot-remove
@ 2026-10-23 6:34 Muchun Song
2026-10-23 6:34 ` [PATCH v3 1/4] mm: fix missing page-table destructor in pagetable_free() Muchun Song
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Muchun Song @ 2026-10-23 6:34 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Oscar Salvador, Dave Hansen, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel,
Catalin Marinas, Will Deacon, Mark Rutland, Kevin Brodsky,
Alexander Gordeev, Alistair Popple, linux-mm, linux-riscv,
linux-arm-kernel, linux-kernel, stable, Muchun Song, Muchun Song
Memory hot-remove can free page-table pages allocated through paths with
different constructor state. Some paths run the page-table constructor,
while generic sparse-vmemmap population may not. The x86, RISC-V, and
arm64 teardown paths did not handle that distinction consistently,
leaving constructor/destructor accounting unbalanced.
Make pagetable_free() handle any remaining constructor state before
freeing a page-table page. Callers that already ran pagetable_dtor()
have cleared that state, so the destructor is not run twice. The RISC-V
and arm64 fixes then use this common helper for their memory-hot-remove
paths.
The architecture fixes depend on the common MM change in patch 1, so
this remains a single series. I expect it to go through the MM tree,
with review or acks from the relevant architecture maintainers.
v3:
- Explain why pagetable_free() does not run the destructor twice.
- Add the x86 stable prerequisites noted by Jose A. Perez de Azpillaga.
- Collect Acked-by and Reviewed-by tags from reviewers.
v2: https://lore.kernel.org/20261010112457.49485-1-songmuchun@bytedance.com/
- Move the destructor decision from x86 into pagetable_free(), as
suggested by David Hildenbrand.
- Use pagetable_free() for non-reserved RISC-V page-table pages and
simplify reserved-page handling.
- Collect David Hildenbrand's Acked-by on the RISC-V PUD fix.
- Use pagetable_free() for arm64 intermediate page-table pages, as
suggested by David Hildenbrand.
- Trim and update the commit messages, as requested by Dave Hansen.
v1: https://lore.kernel.org/20261008073021.2512665-1-songmuchun@bytedance.com/
Muchun Song (4):
mm: fix missing page-table destructor in pagetable_free()
riscv/mm: fix hotplug page-table destructor handling
riscv/mm: fix missing destructor for hotplug PUD tables
arm64/mm: fix destructor for unconstructed hotplug page tables
arch/arm64/mm/mmu.c | 3 +--
arch/riscv/mm/init.c | 32 +++++++++++++-------------------
include/linux/mm.h | 37 ++++++++++++++++++++-----------------
3 files changed, 34 insertions(+), 38 deletions(-)
base-commit: 26d7e34b4226709084461a07bf28d9066fa96d8c
--
2.54.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 1/4] mm: fix missing page-table destructor in pagetable_free()
2026-10-23 6:34 [PATCH v3 0/4] mm: Fix page-table teardown during memory hot-remove Muchun Song
@ 2026-10-23 6:34 ` Muchun Song
2026-10-23 10:18 ` Anshuman Khandual
2026-10-23 6:34 ` [PATCH v3 2/4] riscv/mm: fix hotplug page-table destructor handling Muchun Song
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Muchun Song @ 2026-10-23 6:34 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Oscar Salvador, Dave Hansen, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel,
Catalin Marinas, Will Deacon, Mark Rutland, Kevin Brodsky,
Alexander Gordeev, Alistair Popple, linux-mm, linux-riscv,
linux-arm-kernel, linux-kernel, stable, Muchun Song, Muchun Song
Since commit 49f599666420 ("mm: call ctor/dtor for kernel PTEs"),
pte_alloc_one_kernel() runs the page-table constructor for kernel PTE
tables.
HVO (HugeTLB Vmemmap Optimization) uses pte_alloc_one_kernel() when
splitting a PMD. Restoring the vmemmap backing pages does not collapse
the PTE table, so a later memory hot-remove eventually frees it through
pagetable_free() on x86-64. That releases the page without running the
matching destructor and leaves NR_PAGETABLE elevated.
Make pagetable_free() the common free-side primitive for page-table
pages. It checks PageTable() and runs the destructor only when the
constructor state is still present. Callers that explicitly ran
pagetable_dtor() have already cleared PageTable(), so they are not
destructed twice; pages that never ran a constructor are freed directly.
Fixes: 49f599666420 ("mm: call ctor/dtor for kernel PTEs")
Cc: stable@vger.kernel.org # bf9e4e30f353: x86/mm: use pagetable_free()
Cc: stable@vger.kernel.org # 39406c05f8f1: x86/mm: Fix freeing of PMD-sized vmemmap pages
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Acked-by: Dave Hansen <dave.hansen@intel.com>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
---
v3:
- Explain why pagetable_free() does not run the destructor twice
(requested by Kevin Brodsky)
- Add x86 stable prerequisites (suggested by
Jose A. Perez de Azpillaga)
- Collect Acked-by from Dave Hansen and David Hildenbrand
- Collect Reviewed-by from Jose A. Perez de Azpillaga and Kevin
Brodsky
v2:
- Move destructor handling from x86 into pagetable_free() (suggested by
David Hildenbrand)
- Trim and update the commit message (requested by Dave Hansen)
---
include/linux/mm.h | 37 ++++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index dd09c438fa23..466875c5908b 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3812,23 +3812,6 @@ static inline void pagetable_free_kernel(struct ptdesc *pt)
__pagetable_free(pt);
}
#endif
-/**
- * pagetable_free - Free pagetables
- * @pt: The page table descriptor
- *
- * pagetable_free frees the memory of all page tables described by a page
- * table descriptor and the memory for the descriptor itself.
- */
-static inline void pagetable_free(struct ptdesc *pt)
-{
- if (ptdesc_test_kernel(pt)) {
- ptdesc_clear_kernel(pt);
- pagetable_free_kernel(pt);
- } else {
- __pagetable_free(pt);
- }
-}
-
#if defined(CONFIG_SPLIT_PTE_PTLOCKS)
#if ALLOC_SPLIT_PTLOCKS
void __init ptlock_cache_init(void);
@@ -3921,6 +3904,26 @@ static inline void pagetable_dtor(struct ptdesc *ptdesc)
lruvec_stat_sub_folio(folio, NR_PAGETABLE);
}
+/**
+ * pagetable_free - Free pagetables
+ * @pt: The page table descriptor
+ *
+ * pagetable_free frees the memory of all page tables described by a page
+ * table descriptor and the memory for the descriptor itself.
+ */
+static inline void pagetable_free(struct ptdesc *pt)
+{
+ if (PageTable(ptdesc_page(pt)))
+ pagetable_dtor(pt);
+
+ if (ptdesc_test_kernel(pt)) {
+ ptdesc_clear_kernel(pt);
+ pagetable_free_kernel(pt);
+ } else {
+ __pagetable_free(pt);
+ }
+}
+
static inline void pagetable_dtor_free(struct ptdesc *ptdesc)
{
pagetable_dtor(ptdesc);
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 2/4] riscv/mm: fix hotplug page-table destructor handling
2026-10-23 6:34 [PATCH v3 0/4] mm: Fix page-table teardown during memory hot-remove Muchun Song
2026-10-23 6:34 ` [PATCH v3 1/4] mm: fix missing page-table destructor in pagetable_free() Muchun Song
@ 2026-10-23 6:34 ` Muchun Song
2026-10-23 6:34 ` [PATCH v3 3/4] riscv/mm: fix missing destructor for hotplug PUD tables Muchun Song
2026-10-23 6:34 ` [PATCH v3 4/4] arm64/mm: fix destructor for unconstructed hotplug page tables Muchun Song
3 siblings, 0 replies; 8+ messages in thread
From: Muchun Song @ 2026-10-23 6:34 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Oscar Salvador, Dave Hansen, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel,
Catalin Marinas, Will Deacon, Mark Rutland, Kevin Brodsky,
Alexander Gordeev, Alistair Popple, linux-mm, linux-riscv,
linux-arm-kernel, linux-kernel, stable, Muchun Song, Muchun Song
RISC-V uses the same memory-hotplug teardown code for linear-map and
vmemmap page tables. Late linear-map allocations run page-table
constructors, while vmemmap and early allocations may not.
free_pte_table() unconditionally calls pagetable_dtor(), corrupting
NR_PAGETABLE accounting for constructor-free tables. free_pmd_table()
avoids that for vmemmap using is_vmemmap, but mapping type is not a
reliable proxy for constructor state. In particular, it becomes invalid
once runtime vmemmap tables use the normal pgalloc helpers.
Introduce free_pgtable_page() to select free_reserved_page() for reserved
pages and pagetable_free() otherwise. The latter runs the destructor only
when PageTable() is set, handling both constructor-backed and
constructor-free tables.
Fixes: c75a74f4ba19 ("riscv: mm: Add memory hotplugging support")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Reviewed-by: Björn Töpel <bjorn@kernel.org>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
---
v3:
- Collect Acked-by from David Hildenbrand
- Collect Reviewed-by from Björn Töpel and Kevin Brodsky
v2:
- Use pagetable_free() for non-reserved tables (suggested by David
Hildenbrand)
- Simplify reserved-page handling
---
arch/riscv/mm/init.c | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index fb37b0b67efe..e111d25e18e1 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -1485,10 +1485,17 @@ struct execmem_info __init *execmem_arch_setup(void)
#endif /* CONFIG_EXECMEM */
#ifdef CONFIG_MEMORY_HOTPLUG
+static void __meminit free_pgtable_page(struct page *page)
+{
+ if (PageReserved(page))
+ free_reserved_page(page);
+ else
+ pagetable_free(page_ptdesc(page));
+}
+
static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
{
struct page *page = pmd_page(*pmd);
- struct ptdesc *ptdesc = page_ptdesc(page);
pte_t *pte;
int i;
@@ -1498,18 +1505,13 @@ static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
return;
}
- pagetable_dtor(ptdesc);
- if (PageReserved(page))
- free_reserved_page(page);
- else
- pagetable_free(ptdesc);
+ free_pgtable_page(page);
pmd_clear(pmd);
}
-static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, bool is_vmemmap)
+static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
{
struct page *page = pud_page(*pud);
- struct ptdesc *ptdesc = page_ptdesc(page);
pmd_t *pmd;
int i;
@@ -1519,12 +1521,7 @@ static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, bool is_vmemm
return;
}
- if (!is_vmemmap)
- pagetable_dtor(ptdesc);
- if (PageReserved(page))
- free_reserved_page(page);
- else
- pagetable_free(ptdesc);
+ free_pgtable_page(page);
pud_clear(pud);
}
@@ -1644,7 +1641,7 @@ static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long addr, un
remove_pmd_mapping(pmd_base, addr, next, is_vmemmap, altmap);
if (pgtable_l4_enabled)
- free_pmd_table(pmd_base, pudp, is_vmemmap);
+ free_pmd_table(pmd_base, pudp);
}
}
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 3/4] riscv/mm: fix missing destructor for hotplug PUD tables
2026-10-23 6:34 [PATCH v3 0/4] mm: Fix page-table teardown during memory hot-remove Muchun Song
2026-10-23 6:34 ` [PATCH v3 1/4] mm: fix missing page-table destructor in pagetable_free() Muchun Song
2026-10-23 6:34 ` [PATCH v3 2/4] riscv/mm: fix hotplug page-table destructor handling Muchun Song
@ 2026-10-23 6:34 ` Muchun Song
2026-10-23 6:34 ` [PATCH v3 4/4] arm64/mm: fix destructor for unconstructed hotplug page tables Muchun Song
3 siblings, 0 replies; 8+ messages in thread
From: Muchun Song @ 2026-10-23 6:34 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Oscar Salvador, Dave Hansen, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel,
Catalin Marinas, Will Deacon, Mark Rutland, Kevin Brodsky,
Alexander Gordeev, Alistair Popple, linux-mm, linux-riscv,
linux-arm-kernel, linux-kernel, stable, Muchun Song, Muchun Song
Commit 8472cc4503eb ("riscv: mm: call PUD/P4D ctor in special kernel
pgtable alloc") made alloc_pud_late() run the PUD page-table constructor.
However, free_pud_table() still frees non-reserved PUD tables directly
without decrementing NR_PAGETABLE.
Free PUD tables through the common free_pgtable_page() helper so that
constructor-backed tables run the matching destructor before being
freed.
Fixes: 8472cc4503eb ("riscv: mm: call PUD/P4D ctor in special kernel pgtable alloc")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Reviewed-by: Björn Töpel <bjorn@kernel.org>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
---
v3:
- Collect Reviewed-by from Björn Töpel and Kevin Brodsky
v2:
- Collect Acked-by from David Hildenbrand
---
arch/riscv/mm/init.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index e111d25e18e1..f35fe4cda89c 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -1537,10 +1537,7 @@ static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d)
return;
}
- if (PageReserved(page))
- free_reserved_page(page);
- else
- __free_pages(page, 0);
+ free_pgtable_page(page);
p4d_clear(p4d);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 4/4] arm64/mm: fix destructor for unconstructed hotplug page tables
2026-10-23 6:34 [PATCH v3 0/4] mm: Fix page-table teardown during memory hot-remove Muchun Song
` (2 preceding siblings ...)
2026-10-23 6:34 ` [PATCH v3 3/4] riscv/mm: fix missing destructor for hotplug PUD tables Muchun Song
@ 2026-10-23 6:34 ` Muchun Song
2026-10-23 10:18 ` Anshuman Khandual
2026-10-27 17:06 ` Catalin Marinas
3 siblings, 2 replies; 8+ messages in thread
From: Muchun Song @ 2026-10-23 6:34 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Oscar Salvador, Dave Hansen, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel,
Catalin Marinas, Will Deacon, Mark Rutland, Kevin Brodsky,
Alexander Gordeev, Alistair Popple, linux-mm, linux-riscv,
linux-arm-kernel, linux-kernel, stable, Muchun Song, Muchun Song
Commit c594b83457cc ("arm64: mm: call pagetable dtor when freeing
hot-removed page tables") made free_hotplug_pgtable_page()
unconditionally run the page-table destructor. This matches page tables
allocated by the arm64 mapping code, which runs the corresponding
constructors.
However, arm64 also uses the generic sparse-vmemmap population code.
Runtime intermediate page tables allocated by that code do not run a
page-table constructor. Freeing one during memory hot-remove therefore
runs a destructor without a matching constructor and corrupts
NR_PAGETABLE accounting.
Free intermediate page-table pages through pagetable_free(). It runs the
destructor only for constructor-backed pages and then releases the page
through the page-table freeing path.
Fixes: c594b83457cc ("arm64: mm: call pagetable dtor when freeing hot-removed page tables")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
---
v3:
- Collect Acked-by from David Hildenbrand
- Collect Reviewed-by from Kevin Brodsky
v2:
- Free intermediate tables through pagetable_free() (suggested by David
Hildenbrand)
- Update the commit message for the page-table freeing path
---
arch/arm64/mm/mmu.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 79d90226fd5d..4dce8fa227c3 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1495,8 +1495,7 @@ static void free_hotplug_page_range(struct page *page, size_t size,
static void free_hotplug_pgtable_page(struct page *page)
{
- pagetable_dtor(page_ptdesc(page));
- free_hotplug_page_range(page, PAGE_SIZE, NULL);
+ pagetable_free(page_ptdesc(page));
}
static bool pgtable_range_aligned(unsigned long start, unsigned long end,
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/4] mm: fix missing page-table destructor in pagetable_free()
2026-10-23 6:34 ` [PATCH v3 1/4] mm: fix missing page-table destructor in pagetable_free() Muchun Song
@ 2026-10-23 10:18 ` Anshuman Khandual
0 siblings, 0 replies; 8+ messages in thread
From: Anshuman Khandual @ 2026-10-23 10:18 UTC (permalink / raw)
To: Muchun Song
Cc: Andrew Morton, David Hildenbrand, Oscar Salvador, Dave Hansen,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Björn Töpel, Catalin Marinas, Will Deacon, Mark Rutland,
Kevin Brodsky, Alexander Gordeev, Alistair Popple, linux-mm,
linux-riscv, linux-arm-kernel, linux-kernel, stable, Muchun Song
On Fri, Oct 23, 2026 at 02:34:25PM +0800, Muchun Song wrote:
> Since commit 49f599666420 ("mm: call ctor/dtor for kernel PTEs"),
> pte_alloc_one_kernel() runs the page-table constructor for kernel PTE
> tables.
>
> HVO (HugeTLB Vmemmap Optimization) uses pte_alloc_one_kernel() when
> splitting a PMD. Restoring the vmemmap backing pages does not collapse
> the PTE table, so a later memory hot-remove eventually frees it through
> pagetable_free() on x86-64. That releases the page without running the
> matching destructor and leaves NR_PAGETABLE elevated.
>
> Make pagetable_free() the common free-side primitive for page-table
> pages. It checks PageTable() and runs the destructor only when the
> constructor state is still present. Callers that explicitly ran
> pagetable_dtor() have already cleared PageTable(), so they are not
> destructed twice; pages that never ran a constructor are freed directly.
>
> Fixes: 49f599666420 ("mm: call ctor/dtor for kernel PTEs")
> Cc: stable@vger.kernel.org # bf9e4e30f353: x86/mm: use pagetable_free()
> Cc: stable@vger.kernel.org # 39406c05f8f1: x86/mm: Fix freeing of PMD-sized vmemmap pages
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com>
> Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
> Acked-by: Dave Hansen <dave.hansen@intel.com>
> Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
> ---
> v3:
> - Explain why pagetable_free() does not run the destructor twice
> (requested by Kevin Brodsky)
> - Add x86 stable prerequisites (suggested by
> Jose A. Perez de Azpillaga)
> - Collect Acked-by from Dave Hansen and David Hildenbrand
> - Collect Reviewed-by from Jose A. Perez de Azpillaga and Kevin
> Brodsky
>
> v2:
> - Move destructor handling from x86 into pagetable_free() (suggested by
> David Hildenbrand)
> - Trim and update the commit message (requested by Dave Hansen)
> ---
> include/linux/mm.h | 37 ++++++++++++++++++++-----------------
> 1 file changed, 20 insertions(+), 17 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index dd09c438fa23..466875c5908b 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -3812,23 +3812,6 @@ static inline void pagetable_free_kernel(struct ptdesc *pt)
> __pagetable_free(pt);
> }
> #endif
> -/**
> - * pagetable_free - Free pagetables
> - * @pt: The page table descriptor
> - *
> - * pagetable_free frees the memory of all page tables described by a page
> - * table descriptor and the memory for the descriptor itself.
> - */
> -static inline void pagetable_free(struct ptdesc *pt)
> -{
> - if (ptdesc_test_kernel(pt)) {
> - ptdesc_clear_kernel(pt);
> - pagetable_free_kernel(pt);
> - } else {
> - __pagetable_free(pt);
> - }
> -}
> -
> #if defined(CONFIG_SPLIT_PTE_PTLOCKS)
> #if ALLOC_SPLIT_PTLOCKS
> void __init ptlock_cache_init(void);
> @@ -3921,6 +3904,26 @@ static inline void pagetable_dtor(struct ptdesc *ptdesc)
> lruvec_stat_sub_folio(folio, NR_PAGETABLE);
> }
>
> +/**
> + * pagetable_free - Free pagetables
> + * @pt: The page table descriptor
> + *
> + * pagetable_free frees the memory of all page tables described by a page
> + * table descriptor and the memory for the descriptor itself.
> + */
> +static inline void pagetable_free(struct ptdesc *pt)
> +{
> + if (PageTable(ptdesc_page(pt)))
> + pagetable_dtor(pt);
> +
> + if (ptdesc_test_kernel(pt)) {
> + ptdesc_clear_kernel(pt);
> + pagetable_free_kernel(pt);
> + } else {
> + __pagetable_free(pt);
> + }
> +}
> +
> static inline void pagetable_dtor_free(struct ptdesc *ptdesc)
> {
> pagetable_dtor(ptdesc);
> --
> 2.54.0
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 4/4] arm64/mm: fix destructor for unconstructed hotplug page tables
2026-10-23 6:34 ` [PATCH v3 4/4] arm64/mm: fix destructor for unconstructed hotplug page tables Muchun Song
@ 2026-10-23 10:18 ` Anshuman Khandual
2026-10-27 17:06 ` Catalin Marinas
1 sibling, 0 replies; 8+ messages in thread
From: Anshuman Khandual @ 2026-10-23 10:18 UTC (permalink / raw)
To: Muchun Song
Cc: Andrew Morton, David Hildenbrand, Oscar Salvador, Dave Hansen,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Björn Töpel, Catalin Marinas, Will Deacon, Mark Rutland,
Kevin Brodsky, Alexander Gordeev, Alistair Popple, linux-mm,
linux-riscv, linux-arm-kernel, linux-kernel, stable, Muchun Song
On Fri, Oct 23, 2026 at 02:34:28PM +0800, Muchun Song wrote:
> Commit c594b83457cc ("arm64: mm: call pagetable dtor when freeing
> hot-removed page tables") made free_hotplug_pgtable_page()
> unconditionally run the page-table destructor. This matches page tables
> allocated by the arm64 mapping code, which runs the corresponding
> constructors.
>
> However, arm64 also uses the generic sparse-vmemmap population code.
> Runtime intermediate page tables allocated by that code do not run a
> page-table constructor. Freeing one during memory hot-remove therefore
> runs a destructor without a matching constructor and corrupts
> NR_PAGETABLE accounting.
>
> Free intermediate page-table pages through pagetable_free(). It runs the
> destructor only for constructor-backed pages and then releases the page
> through the page-table freeing path.
>
> Fixes: c594b83457cc ("arm64: mm: call pagetable dtor when freeing hot-removed page tables")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
> Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
> Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
> ---
> v3:
> - Collect Acked-by from David Hildenbrand
> - Collect Reviewed-by from Kevin Brodsky
>
> v2:
> - Free intermediate tables through pagetable_free() (suggested by David
> Hildenbrand)
> - Update the commit message for the page-table freeing path
> ---
> arch/arm64/mm/mmu.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 79d90226fd5d..4dce8fa227c3 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -1495,8 +1495,7 @@ static void free_hotplug_page_range(struct page *page, size_t size,
>
> static void free_hotplug_pgtable_page(struct page *page)
> {
> - pagetable_dtor(page_ptdesc(page));
> - free_hotplug_page_range(page, PAGE_SIZE, NULL);
> + pagetable_free(page_ptdesc(page));
> }
>
> static bool pgtable_range_aligned(unsigned long start, unsigned long end,
> --
> 2.54.0
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 4/4] arm64/mm: fix destructor for unconstructed hotplug page tables
2026-10-23 6:34 ` [PATCH v3 4/4] arm64/mm: fix destructor for unconstructed hotplug page tables Muchun Song
2026-10-23 10:18 ` Anshuman Khandual
@ 2026-10-27 17:06 ` Catalin Marinas
1 sibling, 0 replies; 8+ messages in thread
From: Catalin Marinas @ 2026-10-27 17:06 UTC (permalink / raw)
To: Muchun Song
Cc: Andrew Morton, David Hildenbrand, Oscar Salvador, Dave Hansen,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Björn Töpel, Will Deacon, Mark Rutland, Kevin Brodsky,
Alexander Gordeev, Alistair Popple, linux-mm, linux-riscv,
linux-arm-kernel, linux-kernel, stable, Muchun Song
On Fri, Oct 23, 2026 at 02:34:28PM +0800, Muchun Song wrote:
> Commit c594b83457cc ("arm64: mm: call pagetable dtor when freeing
> hot-removed page tables") made free_hotplug_pgtable_page()
> unconditionally run the page-table destructor. This matches page tables
> allocated by the arm64 mapping code, which runs the corresponding
> constructors.
>
> However, arm64 also uses the generic sparse-vmemmap population code.
> Runtime intermediate page tables allocated by that code do not run a
> page-table constructor. Freeing one during memory hot-remove therefore
> runs a destructor without a matching constructor and corrupts
> NR_PAGETABLE accounting.
>
> Free intermediate page-table pages through pagetable_free(). It runs the
> destructor only for constructor-backed pages and then releases the page
> through the page-table freeing path.
>
> Fixes: c594b83457cc ("arm64: mm: call pagetable dtor when freeing hot-removed page tables")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
> Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
> Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-27 17:06 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-23 6:34 [PATCH v3 0/4] mm: Fix page-table teardown during memory hot-remove Muchun Song
2026-10-23 6:34 ` [PATCH v3 1/4] mm: fix missing page-table destructor in pagetable_free() Muchun Song
2026-10-23 10:18 ` Anshuman Khandual
2026-10-23 6:34 ` [PATCH v3 2/4] riscv/mm: fix hotplug page-table destructor handling Muchun Song
2026-10-23 6:34 ` [PATCH v3 3/4] riscv/mm: fix missing destructor for hotplug PUD tables Muchun Song
2026-10-23 6:34 ` [PATCH v3 4/4] arm64/mm: fix destructor for unconstructed hotplug page tables Muchun Song
2026-10-23 10:18 ` Anshuman Khandual
2026-10-27 17:06 ` Catalin Marinas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox