* [PATCH v2 0/5] mm: Simplify device DAX vmemmap optimization plumbing
@ 2026-11-05 6:12 Muchun Song
2026-11-05 6:12 ` [PATCH v2 1/5] powerpc/mm: make vmemmap_populate_compound_pages() static Muchun Song
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Muchun Song @ 2026-11-05 6:12 UTC (permalink / raw)
To: David Hildenbrand, Madhavan Srinivasan, Mike Rapoport,
Andrew Morton
Cc: Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng,
Muchun Song, Huacai Chen, WANG Xuerui, linux-mm, linuxppc-dev,
linux-kernel, linux-arm-kernel, linux-riscv, x86, loongarch,
linux-s390, Muchun Song
Hi,
This series is split out from the earlier, larger series "mm: Generalize
HVO for HugeTLB and device DAX" [1]. While the parent series generalizes
vmemmap optimization across HugeTLB and device DAX, this subset addresses
a single, self-contained step: simplifying the device DAX vmemmap
optimization plumbing.
After device DAX was converted to section-based vmemmap optimization,
whether a mapping can be optimized is carried in mem_section, and the
architecture-specific population path can handle any remaining fallback.
The code still retains the DAX-specific vmemmap_can_optimize() helper, a
PowerPC override, and @pgmap arguments threaded through lower-level
vmemmap population and memory-removal interfaces. These duplicate the
section-order policy and keep otherwise generic paths coupled to
dev_pagemap.
This series removes that obsolete plumbing by consolidating the
optimization policy around memory-section metadata and simplifying the
generic and architecture-specific population paths. This also eliminates
dependencies that are no longer needed once the optimization state is
carried by the memory section.
This leaves the section compound order as the single source of truth for
vmemmap optimization and decouples the generic sparse-vmemmap and
memory-hotplug paths from device DAX.
This is another smaller step toward the broader HVO generalization.
[1] https://lore.kernel.org/20260513130542.35604-1-songmuchun@bytedance.com/
v2:
- Rebase onto mm-new at dba8aba0a9a0
- Add section_vmemmap_optimization_disable() and use it for PowerPC,
LoongArch, and altmap fallbacks.
- Add a LoongArch patch that keeps device DAX vmemmap optimization
disabled while leaving HugeTLB HVO unchanged.
- Ignore section compound orders that cannot be optimized.
- Add direct vmemmap-optimization.h includes for architecture users.
v1: https://lore.kernel.org/20261030140720.1256062-1-songmuchun@bytedance.com/
Muchun Song (5):
powerpc/mm: make vmemmap_populate_compound_pages() static
powerpc/mm: drop powerpc vmemmap_can_optimize()
loongarch/mm: disable device DAX vmemmap optimization
mm/sparse-vmemmap: drop vmemmap_can_optimize()
mm/sparse-vmemmap: drop @pgmap from vmemmap population APIs
arch/arm64/mm/mmu.c | 5 +-
arch/loongarch/mm/init.c | 7 +--
arch/powerpc/include/asm/book3s/64/radix.h | 12 -----
arch/powerpc/mm/book3s64/radix_pgtable.c | 23 +++------
arch/powerpc/mm/init_64.c | 2 +
arch/powerpc/mm/mem.c | 5 +-
arch/riscv/mm/init.c | 5 +-
arch/s390/mm/init.c | 5 +-
arch/x86/mm/init_64.c | 5 +-
include/linux/memory_hotplug.h | 8 ++--
include/linux/mm.h | 40 +---------------
include/linux/vmemmap-optimization.h | 56 +++++++++++++++++-----
mm/memory_hotplug.c | 16 +++----
mm/memremap.c | 4 +-
mm/sparse-vmemmap.c | 29 ++++++-----
mm/sparse.c | 6 +--
mm/sparse.h | 5 --
17 files changed, 97 insertions(+), 136 deletions(-)
base-commit: dba8aba0a9a00ff781c03d82ae534fc6f8c2e263
--
2.54.0
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v2 1/5] powerpc/mm: make vmemmap_populate_compound_pages() static 2026-11-05 6:12 [PATCH v2 0/5] mm: Simplify device DAX vmemmap optimization plumbing Muchun Song @ 2026-11-05 6:12 ` Muchun Song 2026-11-05 6:12 ` [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() Muchun Song ` (3 subsequent siblings) 4 siblings, 0 replies; 11+ messages in thread From: Muchun Song @ 2026-11-05 6:12 UTC (permalink / raw) To: David Hildenbrand, Madhavan Srinivasan, Mike Rapoport, Andrew Morton Cc: Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy, Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng, Muchun Song, Huacai Chen, WANG Xuerui, linux-mm, linuxppc-dev, linux-kernel, linux-arm-kernel, linux-riscv, x86, loongarch, linux-s390, Muchun Song vmemmap_populate_compound_pages() is no longer used outside radix_pgtable.c. Make it static and drop the unused dev_pagemap argument from its only remaining caller to simplify the code. Signed-off-by: Muchun Song <songmuchun@bytedance.com> Acked-by: Qi Zheng <qi.zheng@linux.dev> --- arch/powerpc/include/asm/book3s/64/radix.h | 6 ------ arch/powerpc/mm/book3s64/radix_pgtable.c | 13 +++++++------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h index da954e779744..8452a2714cb1 100644 --- a/arch/powerpc/include/asm/book3s/64/radix.h +++ b/arch/powerpc/include/asm/book3s/64/radix.h @@ -356,11 +356,5 @@ int radix__remove_section_mapping(unsigned long start, unsigned long end); #define vmemmap_can_optimize vmemmap_can_optimize bool vmemmap_can_optimize(struct vmem_altmap *altmap, struct dev_pagemap *pgmap); #endif - -#define vmemmap_populate_compound_pages vmemmap_populate_compound_pages -int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn, - unsigned long start, - unsigned long end, int node, - struct dev_pagemap *pgmap); #endif /* __ASSEMBLER__ */ #endif diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index ebac5f9058f6..2924604fbb38 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -1117,7 +1117,9 @@ static inline pte_t *vmemmap_pte_alloc(pmd_t *pmdp, int node, return pte_offset_kernel(pmdp, address); } - +static int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn, + unsigned long start, + unsigned long end, int node); int __meminit radix__vmemmap_populate(unsigned long start, unsigned long end, int node, struct vmem_altmap *altmap) @@ -1132,7 +1134,7 @@ int __meminit radix__vmemmap_populate(unsigned long start, unsigned long end, in unsigned long pfn = page_to_pfn((struct page *)start); if (vmemmap_optimizable_order(pfn_to_section_compound_order(pfn))) - return vmemmap_populate_compound_pages(pfn, start, end, node, NULL); + return vmemmap_populate_compound_pages(pfn, start, end, node); /* * If altmap is present, Make sure we align the start vmemmap addr * to PAGE_SIZE so that we calculate the correct start_pfn in @@ -1228,10 +1230,9 @@ int __meminit radix__vmemmap_populate(unsigned long start, unsigned long end, in return 0; } -int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn, - unsigned long start, - unsigned long end, int node, - struct dev_pagemap *pgmap) +static int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn, + unsigned long start, + unsigned long end, int node) { /* * we want to map things as base page size mapping so that -- 2.54.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() 2026-11-05 6:12 [PATCH v2 0/5] mm: Simplify device DAX vmemmap optimization plumbing Muchun Song 2026-11-05 6:12 ` [PATCH v2 1/5] powerpc/mm: make vmemmap_populate_compound_pages() static Muchun Song @ 2026-11-05 6:12 ` Muchun Song 2026-11-05 7:16 ` sashiko-bot 2026-11-05 12:13 ` kernel test robot 2026-11-05 6:12 ` [PATCH v2 3/5] loongarch/mm: disable device DAX vmemmap optimization Muchun Song ` (2 subsequent siblings) 4 siblings, 2 replies; 11+ messages in thread From: Muchun Song @ 2026-11-05 6:12 UTC (permalink / raw) To: David Hildenbrand, Madhavan Srinivasan, Mike Rapoport, Andrew Morton Cc: Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy, Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng, Muchun Song, Huacai Chen, WANG Xuerui, linux-mm, linuxppc-dev, linux-kernel, linux-arm-kernel, linux-riscv, x86, loongarch, linux-s390, Muchun Song Whether the optimized mapping can be used is now decided in the architecture-specific vmemmap_populate() path. When PowerPC has to fall back, such as on Hash MMU, it can disable optimization for the populated vmemmap range there. Add section_vmemmap_optimization_disable() to centralize this fallback, use it in the Hash MMU path, and drop the radix-specific vmemmap_can_optimize() override. Signed-off-by: Muchun Song <songmuchun@bytedance.com> --- v2: - Add section_vmemmap_optimization_disable() for architecture fallbacks - Use the helper for the PowerPC Hash MMU path - Include vmemmap-optimization.h directly (reported by Sashiko) --- arch/powerpc/include/asm/book3s/64/radix.h | 5 ---- arch/powerpc/mm/book3s64/radix_pgtable.c | 10 ------- arch/powerpc/mm/init_64.c | 2 ++ include/linux/vmemmap-optimization.h | 31 ++++++++++++++++++++++ mm/sparse.h | 5 ---- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h index 8452a2714cb1..df67209b0c5b 100644 --- a/arch/powerpc/include/asm/book3s/64/radix.h +++ b/arch/powerpc/include/asm/book3s/64/radix.h @@ -351,10 +351,5 @@ int radix__create_section_mapping(unsigned long start, unsigned long end, int nid, pgprot_t prot); int radix__remove_section_mapping(unsigned long start, unsigned long end); #endif /* CONFIG_MEMORY_HOTPLUG */ - -#ifdef CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP -#define vmemmap_can_optimize vmemmap_can_optimize -bool vmemmap_can_optimize(struct vmem_altmap *altmap, struct dev_pagemap *pgmap); -#endif #endif /* __ASSEMBLER__ */ #endif diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index 2924604fbb38..63f369d296b4 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -978,16 +978,6 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start, return 0; } -#ifdef CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP -bool vmemmap_can_optimize(struct vmem_altmap *altmap, struct dev_pagemap *pgmap) -{ - if (radix_enabled()) - return __vmemmap_can_optimize(altmap, pgmap); - - return false; -} -#endif - int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node, unsigned long addr, unsigned long next) { diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 0e777d7dc332..4d6928f717cf 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -24,6 +24,7 @@ #include <linux/types.h> #include <linux/mman.h> #include <linux/mm.h> +#include <linux/vmemmap-optimization.h> #include <linux/swap.h> #include <linux/stddef.h> #include <linux/vmalloc.h> @@ -282,6 +283,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, return radix__vmemmap_populate(start, end, node, altmap); #endif + section_vmemmap_optimization_disable(start, end); return __vmemmap_populate(start, end, node, altmap); } diff --git a/include/linux/vmemmap-optimization.h b/include/linux/vmemmap-optimization.h index 858311a71b0c..5c09da4df4d8 100644 --- a/include/linux/vmemmap-optimization.h +++ b/include/linux/vmemmap-optimization.h @@ -57,6 +57,27 @@ static inline void section_set_compound_order_range(unsigned long pfn, section_set_compound_order(__nr_to_section(section_nr + i), order); } +static inline bool section_vmemmap_optimizable(const struct mem_section *section) +{ + return vmemmap_optimizable_order(section_compound_order(section)); +} + +static inline void section_vmemmap_optimization_disable(unsigned long start, + unsigned long end) +{ + unsigned long pfn = page_to_pfn((struct page *)start); + unsigned long nr_pages = (end - start) / sizeof(struct page); + struct mem_section *section = __pfn_to_section(pfn); + + if (nr_pages < PAGES_PER_SECTION) { + VM_WARN_ON_ONCE(section_vmemmap_optimizable(section)); + return; + } + + VM_WARN_ON_ONCE(!IS_ALIGNED(pfn | nr_pages, PAGES_PER_SECTION)); + section_set_compound_order(section, 0); +} + static inline unsigned int pfn_to_section_compound_order(unsigned long pfn) { return section_compound_order(__pfn_to_section(pfn)); @@ -79,6 +100,16 @@ static inline void section_set_compound_order_range(unsigned long pfn, { } +static inline bool section_vmemmap_optimizable(const struct mem_section *section) +{ + return false; +} + +static inline void section_vmemmap_optimization_disable(unsigned long start, + unsigned long end) +{ +} + static inline unsigned int pfn_to_section_compound_order(unsigned long pfn) { return 0; diff --git a/mm/sparse.h b/mm/sparse.h index fdbc4cacf91d..9b81a549d928 100644 --- a/mm/sparse.h +++ b/mm/sparse.h @@ -46,11 +46,6 @@ static inline size_t mem_section_usage_size(void) return struct_size_t(struct mem_section_usage, pageblock_flags, BITS_TO_LONGS(SECTION_BLOCKFLAGS_BITS)); } - -static inline bool section_vmemmap_optimizable(const struct mem_section *ms) -{ - return vmemmap_optimizable_order(section_compound_order(ms)); -} #else static inline void sparse_init(void) {} static inline void sparse_sections_init(void) {} -- 2.54.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() 2026-11-05 6:12 ` [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() Muchun Song @ 2026-11-05 7:16 ` sashiko-bot 2026-11-05 8:02 ` Lance Yang 2026-11-05 12:13 ` kernel test robot 1 sibling, 1 reply; 11+ messages in thread From: sashiko-bot @ 2026-11-05 7:16 UTC (permalink / raw) To: Muchun Song, David Hildenbrand, Madhavan Srinivasan, Mike Rapoport, Andrew Morton Cc: Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy, Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng, Muchun Song, Huacai Chen, WANG Xuerui, linux-mm, x86, linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Christian Borntraeger Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Low] mm: undeclared vmemmap in section_vmemmap_optimization_disable() - [Low] mm: define vmemmap_optimizable_order() before section_vmemmap_optimizable() -- commit e51c76b2ae2d335e25edd03780c815eb467b564b Author: Muchun Song <muchun.song@linux.dev> powerpc/mm: drop powerpc vmemmap_can_optimize() This commit adds section_vmemmap_optimization_disable() to disable vmemmap optimization in architecture fallback paths such as PowerPC Hash MMU, and removes the PowerPC-specific vmemmap_can_optimize() override. [ ... ] > diff --git a/include/linux/vmemmap-optimization.h b/include/linux/vmemmap-optimization.h > index 858311a71b0cc..5c09da4df4d83 100644 > --- a/include/linux/vmemmap-optimization.h > +++ b/include/linux/vmemmap-optimization.h > @@ -57,6 +57,27 @@ static inline void section_set_compound_order_range(unsigned long pfn, > section_set_compound_order(__nr_to_section(section_nr + i), order); > } > > +static inline bool section_vmemmap_optimizable(const struct mem_section *section) > +{ > + return vmemmap_optimizable_order(section_compound_order(section)); > +} [Severity: Low] Will moving section_vmemmap_optimizable() here break the build at this commit when CONFIG_VMEMMAP_OPTIMIZATION is enabled? At this point in include/linux/vmemmap-optimization.h, vmemmap_optimizable_order() has not been declared yet and is only defined at the end of the header after the #endif for CONFIG_VMEMMAP_OPTIMIZATION: include/linux/vmemmap-optimization.h: static inline bool vmemmap_optimizable_order(unsigned int order) { if (!IS_ENABLED(CONFIG_VMEMMAP_OPTIMIZATION)) return false; ... } Compiling translation units that include linux/vmemmap-optimization.h with CONFIG_VMEMMAP_OPTIMIZATION=y fails with an implicit declaration of vmemmap_optimizable_order() followed by a static declaration following a non-static declaration. A later commit in the series ("mm/sparse-vmemmap: drop vmemmap_can_optimize()") moves vmemmap_optimizable_order() above the #ifdef CONFIG_VMEMMAP_OPTIMIZATION block. Could that move of vmemmap_optimizable_order() be done in this patch instead to keep the series bisectable? > + > +static inline void section_vmemmap_optimization_disable(unsigned long start, > + unsigned long end) > +{ > + unsigned long pfn = page_to_pfn((struct page *)start); [Severity: Low] Could calling page_to_pfn() inside section_vmemmap_optimization_disable() cause a build failure on architectures such as LoongArch that include linux/vmemmap-optimization.h before defining vmemmap? When CONFIG_VMEMMAP_OPTIMIZATION (and therefore CONFIG_SPARSEMEM_VMEMMAP) is enabled, page_to_pfn() in include/asm-generic/memory_model.h expands to reference vmemmap: #define __pfn_to_page(pfn) (vmemmap + (pfn)) #define __page_to_pfn(page) (unsigned long)((page) - vmemmap) However, include/linux/vmemmap-optimization.h does not include a header that defines vmemmap, and arch/loongarch/include/asm/pgtable.h includes linux/vmemmap-optimization.h to obtain MAX_FOLIO_VMEMMAP_ALIGN before it defines the vmemmap macro: arch/loongarch/include/asm/pgtable.h: #include <linux/mm_types.h> #include <linux/mmzone.h> #include <linux/vmemmap-optimization.h> #include <asm/fixmap.h> #include <asm/sparsemem.h> ... #define VMEMMAP_ALIGN max(PMD_SIZE, MAX_FOLIO_VMEMMAP_ALIGN) #define vmemmap ((struct page *)(ALIGN(VMALLOC_END, VMEMMAP_ALIGN))) Because section_vmemmap_optimization_disable() is a static inline function parsed before the vmemmap macro is defined, doesn't vmemmap remain an undeclared identifier in page_to_pfn() when compiling on LoongArch with CONFIG_VMEMMAP_OPTIMIZATION enabled? -- Sashiko AI review · https://sashiko.dev/#/patchset/20261105061217.13302-1-songmuchun@bytedance.com?part=2 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() 2026-11-05 7:16 ` sashiko-bot @ 2026-11-05 8:02 ` Lance Yang 0 siblings, 0 replies; 11+ messages in thread From: Lance Yang @ 2026-11-05 8:02 UTC (permalink / raw) To: sashiko-bot, songmuchun Cc: david, maddy, rppt, akpm, lance.yang, mpe, npiggin, chleroy, ritesh.list, sshegde, osalvador, qi.zheng, muchun.song, chenhuacai, kernel, linux-mm, x86, linux-s390, hca, gor, agordeev, borntraeger On Thu, Nov 05, 2026 at 07:16:48AM +0000, sashiko-bot@kernel.org wrote: >Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: >- [Low] mm: undeclared vmemmap in section_vmemmap_optimization_disable() >- [Low] mm: define vmemmap_optimizable_order() before section_vmemmap_optimizable() >-- IIUC, on LoongArch, asm/pgtable.h includes vmemmap-optimization.h before defining vmemmap. How about taking a PFN and page count instead, and leaving the conversion to the callers? ---8<--- diff --git a/arch/loongarch/mm/init.c b/arch/loongarch/mm/init.c index c91afce46136..5a3a225135be 100644 --- a/arch/loongarch/mm/init.c +++ b/arch/loongarch/mm/init.c @@ -143,7 +143,8 @@ void __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node, int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, struct vmem_altmap *altmap) { - section_vmemmap_optimization_disable(start, end); + section_vmemmap_optimization_disable(page_to_pfn((struct page *)start), + (end - start) / sizeof(struct page)); #if CONFIG_PGTABLE_LEVELS == 2 return vmemmap_populate_basepages(start, end, node, NULL); #else diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 4d6928f717cf..43c98aec29aa 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -283,7 +283,8 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, return radix__vmemmap_populate(start, end, node, altmap); #endif - section_vmemmap_optimization_disable(start, end); + section_vmemmap_optimization_disable(page_to_pfn((struct page *)start), + (end - start) / sizeof(struct page)); return __vmemmap_populate(start, end, node, altmap); } diff --git a/include/linux/vmemmap-optimization.h b/include/linux/vmemmap-optimization.h index 9d9f7a67d195..0501234ab16b 100644 --- a/include/linux/vmemmap-optimization.h +++ b/include/linux/vmemmap-optimization.h @@ -76,11 +76,9 @@ static inline bool section_vmemmap_optimizable(const struct mem_section *section return vmemmap_optimizable_order(section_compound_order(section)); } -static inline void section_vmemmap_optimization_disable(unsigned long start, - unsigned long end) +static inline void section_vmemmap_optimization_disable(unsigned long pfn, + unsigned long nr_pages) { - unsigned long pfn = page_to_pfn((struct page *)start); - unsigned long nr_pages = (end - start) / sizeof(struct page); struct mem_section *section = __pfn_to_section(pfn); if (nr_pages < PAGES_PER_SECTION) { @@ -119,8 +117,8 @@ static inline bool section_vmemmap_optimizable(const struct mem_section *section return false; } -static inline void section_vmemmap_optimization_disable(unsigned long start, - unsigned long end) +static inline void section_vmemmap_optimization_disable(unsigned long pfn, + unsigned long nr_pages) { } diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index 5777f2e29684..64bc346d0fc5 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -474,7 +474,7 @@ struct page * __meminit __populate_section_memmap(unsigned long pfn, /* Altmap-backed vmemmap pages cannot be optimized. */ if (altmap) - section_vmemmap_optimization_disable(start, end); + section_vmemmap_optimization_disable(pfn, nr_pages); r = vmemmap_populate(start, end, nid, altmap); if (r < 0) return NULL; --- Cheers, Lance ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() 2026-11-05 6:12 ` [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() Muchun Song 2026-11-05 7:16 ` sashiko-bot @ 2026-11-05 12:13 ` kernel test robot 1 sibling, 0 replies; 11+ messages in thread From: kernel test robot @ 2026-11-05 12:13 UTC (permalink / raw) To: Muchun Song, David Hildenbrand, Madhavan Srinivasan, Mike Rapoport, Andrew Morton Cc: llvm, oe-kbuild-all, Linux Memory Management List, Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy, Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng, Muchun Song, Huacai Chen, WANG Xuerui, linuxppc-dev, linux-kernel, linux-arm-kernel, linux-riscv, x86, loongarch, linux-s390 Hi Muchun, kernel test robot noticed the following build errors: [auto build test ERROR on dba8aba0a9a00ff781c03d82ae534fc6f8c2e263] url: https://github.com/intel-lab-lkp/linux/commits/Muchun-Song/powerpc-mm-make-vmemmap_populate_compound_pages-static/20261105-141213 base: dba8aba0a9a00ff781c03d82ae534fc6f8c2e263 patch link: https://lore.kernel.org/r/20261105061217.13302-3-songmuchun%40bytedance.com patch subject: [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20261105/202611052055.TcIXFI7V-lkp@intel.com/config) compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261105/202611052055.TcIXFI7V-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202611052055.TcIXFI7V-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:31: In file included from include/linux/pgtable.h:6: In file included from arch/loongarch/include/asm/pgtable.h:75: include/linux/vmemmap-optimization.h:62:9: error: call to undeclared function 'vmemmap_optimizable_order'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] 62 | return vmemmap_optimizable_order(section_compound_order(section)); | ^ >> include/linux/vmemmap-optimization.h:68:22: error: use of undeclared identifier 'vmemmap'; did you mean 'mem_map'? 68 | unsigned long pfn = page_to_pfn((struct page *)start); | ^ include/asm-generic/memory_model.h:73:21: note: expanded from macro 'page_to_pfn' 73 | #define page_to_pfn __page_to_pfn | ^ include/asm-generic/memory_model.h:47:54: note: expanded from macro '__page_to_pfn' 47 | #define __page_to_pfn(page) (unsigned long)((page) - vmemmap) | ^ include/linux/mmzone.h:1452:21: note: 'mem_map' declared here 1452 | extern struct page *mem_map; | ^ In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:31: In file included from include/linux/pgtable.h:6: In file included from arch/loongarch/include/asm/pgtable.h:75: include/linux/vmemmap-optimization.h:138:20: error: conflicting types for 'vmemmap_optimizable_order' 138 | static inline bool vmemmap_optimizable_order(unsigned int order) | ^ include/linux/vmemmap-optimization.h:62:9: note: previous implicit declaration is here 62 | return vmemmap_optimizable_order(section_compound_order(section)); | ^ In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:36: In file included from include/linux/rcuwait.h:6: In file included from include/linux/sched/signal.h:7: include/linux/signal.h:98:11: warning: array index 3 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds] 98 | return (set->sig[3] | set->sig[2] | | ^ ~ include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here 62 | unsigned long sig[_NSIG_WORDS]; | ^ In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:36: In file included from include/linux/rcuwait.h:6: In file included from include/linux/sched/signal.h:7: include/linux/signal.h:98:25: warning: array index 2 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds] 98 | return (set->sig[3] | set->sig[2] | | ^ ~ include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here 62 | unsigned long sig[_NSIG_WORDS]; | ^ In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:36: In file included from include/linux/rcuwait.h:6: In file included from include/linux/sched/signal.h:7: include/linux/signal.h:99:4: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds] 99 | set->sig[1] | set->sig[0]) == 0; | ^ ~ include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here 62 | unsigned long sig[_NSIG_WORDS]; | ^ In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:36: In file included from include/linux/rcuwait.h:6: In file included from include/linux/sched/signal.h:7: include/linux/signal.h:101:11: warning: array index 1 is past the end of the array (that has type 'unsigned long[1]') [-Warray-bounds] 101 | return (set->sig[1] | set->sig[0]) == 0; | ^ ~ include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here 62 | unsigned long sig[_NSIG_WORDS]; | ^ In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:36: In file included from include/linux/rcuwait.h:6: In file included from include/linux/sched/signal.h:7: include/linux/signal.h:114:11: warning: array index 3 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds] 114 | return (set1->sig[3] == set2->sig[3]) && | ^ ~ include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here 62 | unsigned long sig[_NSIG_WORDS]; | ^ In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:36: In file included from include/linux/rcuwait.h:6: In file included from include/linux/sched/signal.h:7: include/linux/signal.h:114:27: warning: array index 3 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds] 114 | return (set1->sig[3] == set2->sig[3]) && | ^ ~ include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here 62 | unsigned long sig[_NSIG_WORDS]; | ^ In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:36: In file included from include/linux/rcuwait.h:6: In file included from include/linux/sched/signal.h:7: include/linux/signal.h:115:5: warning: array index 2 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds] 115 | (set1->sig[2] == set2->sig[2]) && | ^ ~ include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here 62 | unsigned long sig[_NSIG_WORDS]; | ^ In file included from arch/loongarch/kernel/asm-offsets.c:11: In file included from include/linux/mm.h:36: In file included from include/linux/rcuwait.h:6: In file included from include/linux/sched/signal.h:7: include/linux/signal.h:115:21: warning: array index 2 is past the end of the array (that has type 'const unsigned long[1]') [-Warray-bounds] 115 | (set1->sig[2] == set2->sig[2]) && | ^ ~ include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here 62 | unsigned long sig[_NSIG_WORDS]; vim +68 include/linux/vmemmap-optimization.h 64 65 static inline void section_vmemmap_optimization_disable(unsigned long start, 66 unsigned long end) 67 { > 68 unsigned long pfn = page_to_pfn((struct page *)start); 69 unsigned long nr_pages = (end - start) / sizeof(struct page); 70 struct mem_section *section = __pfn_to_section(pfn); 71 72 if (nr_pages < PAGES_PER_SECTION) { 73 VM_WARN_ON_ONCE(section_vmemmap_optimizable(section)); 74 return; 75 } 76 77 VM_WARN_ON_ONCE(!IS_ALIGNED(pfn | nr_pages, PAGES_PER_SECTION)); 78 section_set_compound_order(section, 0); 79 } 80 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 3/5] loongarch/mm: disable device DAX vmemmap optimization 2026-11-05 6:12 [PATCH v2 0/5] mm: Simplify device DAX vmemmap optimization plumbing Muchun Song 2026-11-05 6:12 ` [PATCH v2 1/5] powerpc/mm: make vmemmap_populate_compound_pages() static Muchun Song 2026-11-05 6:12 ` [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() Muchun Song @ 2026-11-05 6:12 ` Muchun Song 2026-11-05 6:12 ` [PATCH v2 4/5] mm/sparse-vmemmap: drop vmemmap_can_optimize() Muchun Song 2026-11-05 6:12 ` [PATCH v2 5/5] mm/sparse-vmemmap: drop @pgmap from vmemmap population APIs Muchun Song 4 siblings, 0 replies; 11+ messages in thread From: Muchun Song @ 2026-11-05 6:12 UTC (permalink / raw) To: David Hildenbrand, Madhavan Srinivasan, Mike Rapoport, Andrew Morton Cc: Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy, Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng, Muchun Song, Huacai Chen, WANG Xuerui, linux-mm, linuxppc-dev, linux-kernel, linux-arm-kernel, linux-riscv, x86, loongarch, linux-s390, Muchun Song LoongArch selects ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP but not ARCH_WANT_OPTIMIZE_DAX_VMEMMAP. Its vmemmap_free() implementation is also empty, so it cannot tear down optimized Device DAX mappings. A later change removes the generic Device DAX architecture gate and lets vmemmap_populate() decide whether a section can use optimization. Clear the section compound order in the LoongArch path so Device DAX keeps using unoptimized mappings. This does not affect HugeTLB HVO: LoongArch does not support gigantic pages, so HugeTLB does not use section-based vmemmap optimization there. Signed-off-by: Muchun Song <songmuchun@bytedance.com> --- v2: - New patch using section_vmemmap_optimization_disable() to keep Device DAX vmemmap optimization disabled on LoongArch (reported by Sashiko) --- arch/loongarch/mm/init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/loongarch/mm/init.c b/arch/loongarch/mm/init.c index f801f7097f03..ea769e479241 100644 --- a/arch/loongarch/mm/init.c +++ b/arch/loongarch/mm/init.c @@ -15,6 +15,7 @@ #include <linux/memblock.h> #include <linux/memremap.h> #include <linux/mm.h> +#include <linux/vmemmap-optimization.h> #include <linux/mman.h> #include <linux/highmem.h> #include <linux/swap.h> @@ -143,6 +144,7 @@ void __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node, int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, struct vmem_altmap *altmap) { + section_vmemmap_optimization_disable(start, end); #if CONFIG_PGTABLE_LEVELS == 2 return vmemmap_populate_basepages(start, end, node, NULL); #else -- 2.54.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 4/5] mm/sparse-vmemmap: drop vmemmap_can_optimize() 2026-11-05 6:12 [PATCH v2 0/5] mm: Simplify device DAX vmemmap optimization plumbing Muchun Song ` (2 preceding siblings ...) 2026-11-05 6:12 ` [PATCH v2 3/5] loongarch/mm: disable device DAX vmemmap optimization Muchun Song @ 2026-11-05 6:12 ` Muchun Song 2026-11-05 7:16 ` sashiko-bot 2026-11-05 6:12 ` [PATCH v2 5/5] mm/sparse-vmemmap: drop @pgmap from vmemmap population APIs Muchun Song 4 siblings, 1 reply; 11+ messages in thread From: Muchun Song @ 2026-11-05 6:12 UTC (permalink / raw) To: David Hildenbrand, Madhavan Srinivasan, Mike Rapoport, Andrew Morton Cc: Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy, Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng, Muchun Song, Huacai Chen, WANG Xuerui, linux-mm, linuxppc-dev, linux-kernel, linux-arm-kernel, linux-riscv, x86, loongarch, linux-s390, Muchun Song section_vmemmap_optimizable() can already decide whether a section uses vmemmap optimization based on the section compound order. The DAX-specific vmemmap_can_optimize() helper duplicates that policy, so remove it to simplify the code. Signed-off-by: Muchun Song <songmuchun@bytedance.com> --- v2: - Ignore non-optimizable nonzero section orders while retaining zero as the reset value (reported by Sashiko) - Use section_vmemmap_optimization_disable() for the altmap fallback - Move vmemmap_optimizable_order() before its first caller --- include/linux/mm.h | 37 ---------------------------- include/linux/vmemmap-optimization.h | 25 ++++++++++--------- mm/sparse-vmemmap.c | 6 +++-- 3 files changed, 18 insertions(+), 50 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index a060a7150401..2fa5ce73b382 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -38,7 +38,6 @@ #include <linux/bitops.h> #include <linux/iommu-debug-pagealloc.h> #include <linux/kcsan-checks.h> -#include <linux/vmemmap-optimization.h> struct mempolicy; struct anon_vma; @@ -5366,42 +5365,6 @@ static inline void vmem_altmap_free(struct vmem_altmap *altmap, } #endif -#ifdef CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP -static inline bool __vmemmap_can_optimize(struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) -{ - unsigned long nr_pages; - unsigned long nr_vmemmap_pages; - - if (!IS_ENABLED(CONFIG_VMEMMAP_OPTIMIZATION)) - return false; - - if (!pgmap || !is_power_of_2(sizeof(struct page))) - return false; - - nr_pages = pgmap_vmemmap_nr(pgmap); - nr_vmemmap_pages = ((nr_pages * sizeof(struct page)) >> PAGE_SHIFT); - /* - * For vmemmap optimization with DAX we need minimum 2 vmemmap - * pages. See layout diagram in Documentation/mm/vmemmap_dedup.rst - */ - return !altmap && (nr_vmemmap_pages > VMEMMAP_OPTIMIZATION_PAGES); -} -/* - * If we don't have an architecture override, use the generic rule - */ -#ifndef vmemmap_can_optimize -#define vmemmap_can_optimize __vmemmap_can_optimize -#endif - -#else -static inline bool vmemmap_can_optimize(struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) -{ - return false; -} -#endif - enum mf_flags { MF_COUNT_INCREASED = 1 << 0, MF_ACTION_REQUIRED = 1 << 1, diff --git a/include/linux/vmemmap-optimization.h b/include/linux/vmemmap-optimization.h index 5c09da4df4d8..9d9f7a67d195 100644 --- a/include/linux/vmemmap-optimization.h +++ b/include/linux/vmemmap-optimization.h @@ -31,6 +31,17 @@ #define VMEMMAP_OPTIMIZATION_NR_STRUCT_PAGES (VMEMMAP_OPTIMIZATION_SIZE / sizeof(struct page)) #define VMEMMAP_OPTIMIZATION_MIN_ORDER (ilog2(VMEMMAP_OPTIMIZATION_NR_STRUCT_PAGES) + 1) +static inline bool vmemmap_optimizable_order(unsigned int order) +{ + if (!IS_ENABLED(CONFIG_VMEMMAP_OPTIMIZATION)) + return false; + + if (!is_power_of_2(sizeof(struct page))) + return false; + + return order >= VMEMMAP_OPTIMIZATION_MIN_ORDER; +} + #ifdef CONFIG_VMEMMAP_OPTIMIZATION static inline unsigned int section_compound_order(const struct mem_section *section) { @@ -40,6 +51,9 @@ static inline unsigned int section_compound_order(const struct mem_section *sect static inline void section_set_compound_order(struct mem_section *section, unsigned int order) { + if (order && !vmemmap_optimizable_order(order)) + return; + VM_WARN_ON(section_compound_order(section) && order && section_compound_order(section) != order); section->compound_page_order = order; @@ -134,15 +148,4 @@ static inline bool vmemmap_optimizable_pfn(unsigned long pfn, unsigned int order return (pfn & (nr_pages - 1)) >= VMEMMAP_OPTIMIZATION_NR_STRUCT_PAGES; } - -static inline bool vmemmap_optimizable_order(unsigned int order) -{ - if (!IS_ENABLED(CONFIG_VMEMMAP_OPTIMIZATION)) - return false; - - if (!is_power_of_2(sizeof(struct page))) - return false; - - return order >= VMEMMAP_OPTIMIZATION_MIN_ORDER; -} #endif /* _LINUX_VMEMMAP_OPTIMIZATION_H */ diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index b8b55e12f5ba..71a927d67a9f 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -473,6 +473,9 @@ struct page * __meminit __populate_section_memmap(unsigned long pfn, !IS_ALIGNED(nr_pages, PAGES_PER_SUBSECTION))) return NULL; + /* Altmap-backed vmemmap pages cannot be optimized. */ + if (altmap) + section_vmemmap_optimization_disable(start, end); r = vmemmap_populate(start, end, nid, altmap); if (r < 0) return NULL; @@ -700,10 +703,9 @@ static struct page * __meminit section_activate(int nid, unsigned long pfn, struct mem_section *ms = __pfn_to_section(pfn); struct mem_section_usage *usage = NULL; struct page *memmap; - unsigned int order; + unsigned int order = pgmap ? pgmap->vmemmap_shift : 0; int rc; - order = vmemmap_can_optimize(altmap, pgmap) ? pgmap->vmemmap_shift : 0; if (nr_pages < PAGES_PER_SECTION && section_compound_order(ms)) return ERR_PTR(-EOPNOTSUPP); -- 2.54.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 4/5] mm/sparse-vmemmap: drop vmemmap_can_optimize() 2026-11-05 6:12 ` [PATCH v2 4/5] mm/sparse-vmemmap: drop vmemmap_can_optimize() Muchun Song @ 2026-11-05 7:16 ` sashiko-bot 0 siblings, 0 replies; 11+ messages in thread From: sashiko-bot @ 2026-11-05 7:16 UTC (permalink / raw) To: Muchun Song, David Hildenbrand, Madhavan Srinivasan, Mike Rapoport, Andrew Morton Cc: Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy, Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng, Muchun Song, Huacai Chen, WANG Xuerui, linux-mm, x86, linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Christian Borntraeger Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] mm/vmemmap: undeclared vmemmap in section_vmemmap_optimization_disable() -- commit f0544b0eb7001e7264ebe693d049cf0cf0631ccd Author: Muchun Song <muchun.song@linux.dev> mm/sparse-vmemmap: drop vmemmap_can_optimize() This commit removes the DAX-specific vmemmap_can_optimize() helper and relies on section_vmemmap_optimizable() and section_vmemmap_optimization_disable() to decide whether a section uses vmemmap optimization. > diff --git a/include/linux/mm.h b/include/linux/mm.h > index a060a71504015..2fa5ce73b382a 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -38,7 +38,6 @@ > #include <linux/bitops.h> > #include <linux/iommu-debug-pagealloc.h> > #include <linux/kcsan-checks.h> > -#include <linux/vmemmap-optimization.h> [Severity: Low] Does this cause a build regression on LoongArch 64-bit configurations with CONFIG_VMEMMAP_OPTIMIZATION enabled (such as loongson64_defconfig), or when linux/vmemmap-optimization.h is included before asm/pgtable.h defines vmemmap? In arch/loongarch/include/asm/pgtable.h, asm/page.h (which pulls in include/asm-generic/memory_model.h) is included first, defining: #define __page_to_pfn(page) (unsigned long)((page) - vmemmap) Later in arch/loongarch/include/asm/pgtable.h, linux/vmemmap-optimization.h is included so MAX_FOLIO_VMEMMAP_ALIGN is available before defining vmemmap: #include <linux/mm_types.h> #include <linux/mmzone.h> #include <linux/vmemmap-optimization.h> ... #define VMEMMAP_ALIGN max(PMD_SIZE, MAX_FOLIO_VMEMMAP_ALIGN) #define vmemmap ((struct page *)(ALIGN(VMALLOC_END, VMEMMAP_ALIGN))) Because section_vmemmap_optimization_disable() in include/linux/vmemmap-optimization.h is a static inline function that calls page_to_pfn(): static inline void section_vmemmap_optimization_disable(unsigned long start, unsigned long end) { unsigned long pfn = page_to_pfn((struct page *)start); the preprocessor expands page_to_pfn() at the point where linux/vmemmap-optimization.h is included, before the vmemmap macro is defined, leaving an undeclared vmemmap identifier in the function body. Additionally, removing the linux/vmemmap-optimization.h include from include/linux/mm.h (where it was placed after linux/pgtable.h) means any translation unit that includes linux/vmemmap-optimization.h before asm/pgtable.h on architectures where vmemmap is defined in asm/pgtable.h will hit the same undeclared vmemmap error. -- Sashiko AI review · https://sashiko.dev/#/patchset/20261105061217.13302-1-songmuchun@bytedance.com?part=4 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 5/5] mm/sparse-vmemmap: drop @pgmap from vmemmap population APIs 2026-11-05 6:12 [PATCH v2 0/5] mm: Simplify device DAX vmemmap optimization plumbing Muchun Song ` (3 preceding siblings ...) 2026-11-05 6:12 ` [PATCH v2 4/5] mm/sparse-vmemmap: drop vmemmap_can_optimize() Muchun Song @ 2026-11-05 6:12 ` Muchun Song 2026-11-05 7:16 ` sashiko-bot 4 siblings, 1 reply; 11+ messages in thread From: Muchun Song @ 2026-11-05 6:12 UTC (permalink / raw) To: David Hildenbrand, Madhavan Srinivasan, Mike Rapoport, Andrew Morton Cc: Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy, Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng, Muchun Song, Huacai Chen, WANG Xuerui, linux-mm, linuxppc-dev, linux-kernel, linux-arm-kernel, linux-riscv, x86, loongarch, linux-s390, Muchun Song The vmemmap population and memory hotplug paths no longer need @pgmap to decide whether a mapping can be optimized. That state is now carried in mem_section, and the architecture-specific population code can make the remaining decisions internally. Drop the @pgmap parameter from the vmemmap population helpers and the related memory hotplug interfaces, and remove the remaining dev_pagemap-specific coupling from those call chains. Signed-off-by: Muchun Song <songmuchun@bytedance.com> --- arch/arm64/mm/mmu.c | 5 ++--- arch/loongarch/mm/init.c | 5 ++--- arch/powerpc/include/asm/book3s/64/radix.h | 1 - arch/powerpc/mm/mem.c | 5 ++--- arch/riscv/mm/init.c | 5 ++--- arch/s390/mm/init.c | 5 ++--- arch/x86/mm/init_64.c | 5 ++--- include/linux/memory_hotplug.h | 8 +++----- include/linux/mm.h | 3 +-- mm/memory_hotplug.c | 16 +++++++-------- mm/memremap.c | 4 ++-- mm/sparse-vmemmap.c | 23 ++++++++++------------ mm/sparse.c | 6 ++---- 13 files changed, 37 insertions(+), 54 deletions(-) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 19459a4a870a..a6b5774005b6 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -2038,13 +2038,12 @@ int arch_add_memory(int nid, u64 start, u64 size, return ret; } -void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) +void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) { unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; - __remove_pages(start_pfn, nr_pages, altmap, pgmap); + __remove_pages(start_pfn, nr_pages, altmap); __remove_pgd_mapping(swapper_pg_dir, __phys_to_virt(start), size); } diff --git a/arch/loongarch/mm/init.c b/arch/loongarch/mm/init.c index ea769e479241..c91afce46136 100644 --- a/arch/loongarch/mm/init.c +++ b/arch/loongarch/mm/init.c @@ -120,13 +120,12 @@ int arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *params) return ret; } -void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) +void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) { unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; - __remove_pages(start_pfn, nr_pages, altmap, pgmap); + __remove_pages(start_pfn, nr_pages, altmap); } #endif diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h index df67209b0c5b..0c9195dd50c9 100644 --- a/arch/powerpc/include/asm/book3s/64/radix.h +++ b/arch/powerpc/include/asm/book3s/64/radix.h @@ -316,7 +316,6 @@ static inline int radix__has_transparent_pud_hugepage(void) #endif struct vmem_altmap; -struct dev_pagemap; extern int __meminit radix__vmemmap_create_mapping(unsigned long start, unsigned long page_size, unsigned long phys); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index b617b69452cd..2432ff888c03 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -158,13 +158,12 @@ int __ref arch_add_memory(int nid, u64 start, u64 size, return rc; } -void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) +void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) { unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; - __remove_pages(start_pfn, nr_pages, altmap, pgmap); + __remove_pages(start_pfn, nr_pages, altmap); arch_remove_linear_mapping(start, size); } #endif diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index e822fce0af4b..6f064875ce8d 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -1749,10 +1749,9 @@ int __ref arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *param return ret; } -void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) +void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) { - __remove_pages(start >> PAGE_SHIFT, size >> PAGE_SHIFT, altmap, pgmap); + __remove_pages(start >> PAGE_SHIFT, size >> PAGE_SHIFT, altmap); remove_linear_mapping(start, size); flush_tlb_all(); } diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index be7e009e7b59..91c0edccbb12 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -293,13 +293,12 @@ int arch_add_memory(int nid, u64 start, u64 size, return rc; } -void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) +void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) { unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; - __remove_pages(start_pfn, nr_pages, altmap, pgmap); + __remove_pages(start_pfn, nr_pages, altmap); vmem_remove_mapping(start, size); } #endif /* CONFIG_MEMORY_HOTPLUG */ diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 8b6d86fb5a42..2a635b7f78ea 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -1273,13 +1273,12 @@ kernel_physical_mapping_remove(unsigned long start, unsigned long end) remove_pagetable(start, end, true, NULL); } -void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) +void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) { unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; - __remove_pages(start_pfn, nr_pages, altmap, pgmap); + __remove_pages(start_pfn, nr_pages, altmap); kernel_physical_mapping_remove(start, start + size); } #endif /* CONFIG_MEMORY_HOTPLUG */ diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index b39605d30896..ec71debc0673 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -136,10 +136,9 @@ static inline bool movable_node_is_enabled(void) return movable_node_enabled; } -extern void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap); +extern void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap); extern void __remove_pages(unsigned long start_pfn, unsigned long nr_pages, - struct vmem_altmap *altmap, struct dev_pagemap *pgmap); + struct vmem_altmap *altmap); /* reasonably generic interface to expand the physical pages */ extern int __add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages, @@ -320,8 +319,7 @@ extern int sparse_add_section(int nid, unsigned long pfn, unsigned long nr_pages, struct vmem_altmap *altmap, struct dev_pagemap *pgmap); extern void sparse_remove_section(unsigned long pfn, unsigned long nr_pages, - struct vmem_altmap *altmap, - struct dev_pagemap *pgmap); + struct vmem_altmap *altmap); extern struct zone *zone_for_pfn_range(enum mmop online_type, int nid, struct memory_group *group, unsigned long start_pfn, unsigned long nr_pages); diff --git a/include/linux/mm.h b/include/linux/mm.h index 2fa5ce73b382..eb11212be0d4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -5316,8 +5316,7 @@ static inline void print_vma_addr(char *prefix, unsigned long rip) #endif struct page * __populate_section_memmap(unsigned long pfn, - unsigned long nr_pages, int nid, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap); + unsigned long nr_pages, int nid, struct vmem_altmap *altmap); void *vmemmap_alloc_block(unsigned long size, int node); struct vmem_altmap; void *vmemmap_alloc_block_buf(unsigned long size, int node, diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 1bfd1f4daeb2..f04a248d8ada 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -416,8 +416,7 @@ int __add_pages(int nid, unsigned long pfn, unsigned long nr_pages, err = sparse_add_section(nid, pfn, cur_nr_pages, altmap, params->pgmap); if (err) { - __remove_pages(start_pfn, pfn - start_pfn, altmap, - params->pgmap); + __remove_pages(start_pfn, pfn - start_pfn, altmap); break; } cond_resched(); @@ -565,7 +564,6 @@ void remove_pfn_range_from_zone(struct zone *zone, * @pfn: starting pageframe (must be aligned to start of a section) * @nr_pages: number of pages to remove (must be multiple of section size) * @altmap: alternative device page map or %NULL if default memmap is used - * @pgmap: device page map or %NULL if not ZONE_DEVICE * * Generic helper function to remove section mappings and sysfs entries * for the section of the memory we are removing. Caller needs to make @@ -573,7 +571,7 @@ void remove_pfn_range_from_zone(struct zone *zone, * calling offline_pages(). */ void __remove_pages(unsigned long pfn, unsigned long nr_pages, - struct vmem_altmap *altmap, struct dev_pagemap *pgmap) + struct vmem_altmap *altmap) { const unsigned long end_pfn = pfn + nr_pages; unsigned long cur_nr_pages; @@ -588,7 +586,7 @@ void __remove_pages(unsigned long pfn, unsigned long nr_pages, /* Select all remaining pages up to the next section boundary */ cur_nr_pages = min(end_pfn - pfn, SECTION_ALIGN_UP(pfn + 1) - pfn); - sparse_remove_section(pfn, cur_nr_pages, altmap, pgmap); + sparse_remove_section(pfn, cur_nr_pages, altmap); } } @@ -1421,7 +1419,7 @@ static void remove_memory_blocks_and_altmaps(u64 start, u64 size) memory_block_put(mem); remove_memory_block_devices(cur_start, memblock_size); - arch_remove_memory(cur_start, memblock_size, altmap, NULL); + arch_remove_memory(cur_start, memblock_size, altmap); altmap_free(altmap); } } @@ -1461,7 +1459,7 @@ static int create_altmaps_and_memory_blocks(int nid, struct memory_group *group, ret = create_memory_block_devices(cur_start, memblock_size, nid, params.altmap, group); if (ret) { - arch_remove_memory(cur_start, memblock_size, params.altmap, NULL); + arch_remove_memory(cur_start, memblock_size, params.altmap); altmap_free(params.altmap); goto out; } @@ -1548,7 +1546,7 @@ static int __add_memory_resource(int nid, struct resource *res, mhp_t mhp_flags, /* create memory block devices after memory was added */ ret = create_memory_block_devices(start, size, nid, NULL, group); if (ret) { - arch_remove_memory(start, size, params.altmap, NULL); + arch_remove_memory(start, size, params.altmap); goto error; } } @@ -2309,7 +2307,7 @@ static int try_remove_memory(u64 start, u64 size) * No altmaps present, do the removal directly */ remove_memory_block_devices(start, size); - arch_remove_memory(start, size, NULL, NULL); + arch_remove_memory(start, size, NULL); } else { /* all memblocks in the range have altmaps */ remove_memory_blocks_and_altmaps(start, size); diff --git a/mm/memremap.c b/mm/memremap.c index accba23aef28..683a77dd679d 100644 --- a/mm/memremap.c +++ b/mm/memremap.c @@ -97,10 +97,10 @@ static void pageunmap_range(struct dev_pagemap *pgmap, int range_id) PHYS_PFN(range_len(range))); if (pgmap->type == MEMORY_DEVICE_PRIVATE) { __remove_pages(PHYS_PFN(range->start), - PHYS_PFN(range_len(range)), NULL, pgmap); + PHYS_PFN(range_len(range)), NULL); } else { arch_remove_memory(range->start, range_len(range), - pgmap_altmap(pgmap), pgmap); + pgmap_altmap(pgmap)); kasan_remove_zero_shadow(__va(range->start), range_len(range)); } mem_hotplug_done(); diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index 71a927d67a9f..5777f2e29684 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -462,8 +462,7 @@ int __meminit vmemmap_populate_hugepages(unsigned long start, unsigned long end, } struct page * __meminit __populate_section_memmap(unsigned long pfn, - unsigned long nr_pages, int nid, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) + unsigned long nr_pages, int nid, struct vmem_altmap *altmap) { unsigned long start = (unsigned long) pfn_to_page(pfn); unsigned long end = start + nr_pages * sizeof(struct page); @@ -555,11 +554,9 @@ void offline_mem_sections(unsigned long start_pfn, unsigned long end_pfn) } static struct page * __meminit populate_section_memmap(unsigned long pfn, - unsigned long nr_pages, int nid, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) + unsigned long nr_pages, int nid, struct vmem_altmap *altmap) { - struct page *page = __populate_section_memmap(pfn, nr_pages, nid, altmap, - pgmap); + struct page *page = __populate_section_memmap(pfn, nr_pages, nid, altmap); memmap_pages_add(section_nr_vmemmap_pages(pfn, nr_pages)); @@ -567,7 +564,7 @@ static struct page * __meminit populate_section_memmap(unsigned long pfn, } static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages, - struct vmem_altmap *altmap, struct dev_pagemap *pgmap) + struct vmem_altmap *altmap) { unsigned long start = (unsigned long) pfn_to_page(pfn); unsigned long end = start + nr_pages * sizeof(struct page); @@ -648,7 +645,7 @@ static int fill_subsection_map(unsigned long pfn, unsigned long nr_pages) * usage map, but still need to free the vmemmap range. */ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, - struct vmem_altmap *altmap, struct dev_pagemap *pgmap) + struct vmem_altmap *altmap) { struct mem_section *ms = __pfn_to_section(pfn); bool section_is_early = early_section(ms); @@ -686,7 +683,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, * section_activate() and pfn_valid() . */ if (!section_is_early) - depopulate_section_memmap(pfn, nr_pages, altmap, pgmap); + depopulate_section_memmap(pfn, nr_pages, altmap); else if (memmap) free_map_bootmem(memmap); @@ -735,9 +732,9 @@ static struct page * __meminit section_activate(int nid, unsigned long pfn, return pfn_to_page(pfn); section_set_compound_order_range(pfn, nr_pages, order); - memmap = populate_section_memmap(pfn, nr_pages, nid, altmap, pgmap); + memmap = populate_section_memmap(pfn, nr_pages, nid, altmap); if (!memmap) { - section_deactivate(pfn, nr_pages, altmap, pgmap); + section_deactivate(pfn, nr_pages, altmap); return ERR_PTR(-ENOMEM); } @@ -801,13 +798,13 @@ int __meminit sparse_add_section(int nid, unsigned long start_pfn, } void sparse_remove_section(unsigned long pfn, unsigned long nr_pages, - struct vmem_altmap *altmap, struct dev_pagemap *pgmap) + struct vmem_altmap *altmap) { struct mem_section *ms = __pfn_to_section(pfn); if (WARN_ON_ONCE(!valid_section(ms))) return; - section_deactivate(pfn, nr_pages, altmap, pgmap); + section_deactivate(pfn, nr_pages, altmap); } #endif /* CONFIG_MEMORY_HOTPLUG */ diff --git a/mm/sparse.c b/mm/sparse.c index 6acb628c8a73..0b9a6c23a227 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -204,8 +204,7 @@ void __init sparse_sections_init(void) } #ifndef CONFIG_SPARSEMEM_VMEMMAP struct page __init *__populate_section_memmap(unsigned long pfn, - unsigned long nr_pages, int nid, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) + unsigned long nr_pages, int nid, struct vmem_altmap *altmap) { const unsigned long size = PAGE_ALIGN(sizeof(struct page) * PAGES_PER_SECTION); @@ -236,8 +235,7 @@ static void __init sparse_metadata_init_nid(int nid, if (section_nr >= end_section_nr) break; - mem_map = __populate_section_memmap(pfn, PAGES_PER_SECTION, nid, - NULL, NULL); + mem_map = __populate_section_memmap(pfn, PAGES_PER_SECTION, nid, NULL); if (!mem_map) panic("Failed to allocate memmap for section %lu\n", section_nr); -- 2.54.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 5/5] mm/sparse-vmemmap: drop @pgmap from vmemmap population APIs 2026-11-05 6:12 ` [PATCH v2 5/5] mm/sparse-vmemmap: drop @pgmap from vmemmap population APIs Muchun Song @ 2026-11-05 7:16 ` sashiko-bot 0 siblings, 0 replies; 11+ messages in thread From: sashiko-bot @ 2026-11-05 7:16 UTC (permalink / raw) To: Muchun Song, David Hildenbrand, Madhavan Srinivasan, Mike Rapoport, Andrew Morton Cc: Lance Yang, Michael Ellerman, Nicholas Piggin, Christophe Leroy, Ritesh Harjani, Shrikanth Hegde, Oscar Salvador, Qi Zheng, Muchun Song, Huacai Chen, WANG Xuerui, linux-mm, x86, linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Christian Borntraeger Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] mm: undeclared vmemmap in section_vmemmap_optimization_disable() -- commit b9ce7eece3f26dd29a5fe079915770aa843f9257 Author: Muchun Song <muchun.song@linux.dev> mm/sparse-vmemmap: drop @pgmap from vmemmap population APIs This commit removes the @pgmap parameter from the vmemmap population helpers and related memory hotplug interfaces, relying instead on mem_section state and internal architecture-specific checks. > diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c > index 71a927d67a9f9..5777f2e296845 100644 > --- a/mm/sparse-vmemmap.c > +++ b/mm/sparse-vmemmap.c > @@ -462,8 +462,7 @@ int __meminit vmemmap_populate_hugepages(unsigned long start, unsigned long end, > } > > struct page * __meminit __populate_section_memmap(unsigned long pfn, > - unsigned long nr_pages, int nid, struct vmem_altmap *altmap, > - struct dev_pagemap *pgmap) > + unsigned long nr_pages, int nid, struct vmem_altmap *altmap) > { > unsigned long start = (unsigned long) pfn_to_page(pfn); > unsigned long end = start + nr_pages * sizeof(struct page); [Severity: Low] Does section_vmemmap_optimization_disable() (called right below here in __populate_section_memmap()) cause a build failure on 64-bit LoongArch when CONFIG_VMEMMAP_OPTIMIZATION is enabled? In include/linux/vmemmap-optimization.h, section_vmemmap_optimization_disable() is a static inline function that calls page_to_pfn(): include/linux/vmemmap-optimization.h: static inline void section_vmemmap_optimization_disable(unsigned long start, unsigned long end) { unsigned long pfn = page_to_pfn((struct page *)start); Under CONFIG_SPARSEMEM_VMEMMAP, page_to_pfn() expands via include/asm-generic/memory_model.h to ((unsigned long)((page) - vmemmap)). However, include/linux/vmemmap-optimization.h does not include linux/pgtable.h or asm/pgtable.h where vmemmap is defined. On 64-bit LoongArch, arch/loongarch/include/asm/pgtable.h includes linux/vmemmap-optimization.h before defining the vmemmap macro: arch/loongarch/include/asm/pgtable.h: #include <linux/mm_types.h> #include <linux/mmzone.h> #include <linux/vmemmap-optimization.h> ... #define VMEMMAP_ALIGN max(PMD_SIZE, MAX_FOLIO_VMEMMAP_ALIGN) #define vmemmap ((struct page *)(ALIGN(VMALLOC_END, VMEMMAP_ALIGN))) Because section_vmemmap_optimization_disable() is a static inline function, the preprocessor expands page_to_pfn() inside linux/vmemmap-optimization.h before vmemmap is defined, leaving vmemmap as an undeclared identifier when compiling any translation unit that includes asm/pgtable.h with CONFIG_VMEMMAP_OPTIMIZATION=y. -- Sashiko AI review · https://sashiko.dev/#/patchset/20261105061217.13302-1-songmuchun@bytedance.com?part=5 ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-11-05 12:14 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-05 6:12 [PATCH v2 0/5] mm: Simplify device DAX vmemmap optimization plumbing Muchun Song 2026-11-05 6:12 ` [PATCH v2 1/5] powerpc/mm: make vmemmap_populate_compound_pages() static Muchun Song 2026-11-05 6:12 ` [PATCH v2 2/5] powerpc/mm: drop powerpc vmemmap_can_optimize() Muchun Song 2026-11-05 7:16 ` sashiko-bot 2026-11-05 8:02 ` Lance Yang 2026-11-05 12:13 ` kernel test robot 2026-11-05 6:12 ` [PATCH v2 3/5] loongarch/mm: disable device DAX vmemmap optimization Muchun Song 2026-11-05 6:12 ` [PATCH v2 4/5] mm/sparse-vmemmap: drop vmemmap_can_optimize() Muchun Song 2026-11-05 7:16 ` sashiko-bot 2026-11-05 6:12 ` [PATCH v2 5/5] mm/sparse-vmemmap: drop @pgmap from vmemmap population APIs Muchun Song 2026-11-05 7:16 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox