linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups
@ 2026-09-09 13:32 David Hildenbrand (Arm)
  2026-09-09 13:32 ` [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init() David Hildenbrand (Arm)
                   ` (11 more replies)
  0 siblings, 12 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:32 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

SECTION_MARKED_PRESENT is really only needed during boot, where we
can instead just rely on SECTION_IS_EARLY_BIT by setting that flag
earlier.

Some preparations for doing that conversion and some cleanups in the same
(sparse) area.

Tested on x86 with and without memory hotplug through virtio-mem.

This is based on mm-unstable which carries Muchun's

	"[PATCH v5 00/17] mm: Introduce section-based vmemmap optimization
	 for HugeTLB" [1]

A (possible) resend from Muchun should only result in smaller conflicts.

[1] https://lore.kernel.org/r/20260825084608.47437-1-songmuchun@bytedance.com 

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
David Hildenbrand (Arm) (12):
      mm/sparse: move mem_section init to sparse_extreme_init()
      mm/sparse: refactor sparse_sections_init()
      mm/sparse: move initialization of section metadata to sparse_metadata_init()
      mm/sparse: rename and cleanup sparse_init_nid()
      mm/sparse: cleanup sparse_init_one_section()
      mm/sparse: rename __highest_present_section_nr to __highest_used_section_nr
      mm/sparse: remove pfn_in_present_section()
      mm/sparse: move __highest_used_section_nr handling
      mm/sparse: remove SECTION_MARKED_PRESENT
      mm/sparse: remove flags parameter from sparse_init_one_section()
      fs/proc/page: clarify comment in get_max_dump_pfn()
      mm/memory_hotplug: drop CONFIG_HAVE_ARCH_PFN_VALID handling from pfn_to_online_page()

 drivers/base/memory.c   |   2 +-
 fs/proc/page.c          |   7 +--
 include/linux/cache.h   |   1 +
 include/linux/mmzone.h  |  43 ++++---------
 mm/compaction.c         |   2 +-
 mm/memory_hotplug.c     |   9 +--
 mm/sparse-vmemmap.c     |   3 +-
 mm/sparse.c             | 160 +++++++++++++++++++++++-------------------------
 mm/sparse.h             |  21 +++----
 scripts/gdb/linux/mm.py |   2 +-
 10 files changed, 107 insertions(+), 143 deletions(-)

---

base-commit: b02c77c78ff74d3d88ea614335ae833e01ed5d30

change-id: 20260814-b4-sparsemem_cleanups-8bc4b47014c3

--

Cheers,

David


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

* [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init()
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
@ 2026-09-09 13:32 ` David Hildenbrand (Arm)
  2026-09-09 17:02   ` Oscar Salvador (SUSE)
  2026-09-10 12:52   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:32 ` [PATCH 02/12] mm/sparse: refactor sparse_sections_init() David Hildenbrand (Arm)
                   ` (10 subsequent siblings)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:32 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

Let's just avoid another pair of ifdef inside a function. While at it,
switch to INTERNODE_CACHE_BYTES by just defining a fallback in cache.h
as well, given that the x86 variant already provides one.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 include/linux/cache.h |  1 +
 mm/sparse.c           | 19 ++++++++++++-------
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/include/linux/cache.h b/include/linux/cache.h
index e69768f50d532..b6e857b985bca 100644
--- a/include/linux/cache.h
+++ b/include/linux/cache.h
@@ -89,6 +89,7 @@
  */
 #ifndef INTERNODE_CACHE_SHIFT
 #define INTERNODE_CACHE_SHIFT L1_CACHE_SHIFT
+#define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)
 #endif
 
 #if !defined(____cacheline_internodealigned_in_smp)
diff --git a/mm/sparse.c b/mm/sparse.c
index 9349ed6326c01..6a6d258862904 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -103,11 +103,22 @@ int __meminit sparse_index_init(unsigned long section_nr, int nid)
 
 	return 0;
 }
+
+static void __init sparse_extreme_init(void)
+{
+	const unsigned long size = sizeof(struct mem_section *) * NR_SECTION_ROOTS;
+
+	mem_section = memblock_alloc_or_panic(size, INTERNODE_CACHE_BYTES);
+}
 #else /* !SPARSEMEM_EXTREME */
 int __meminit sparse_index_init(unsigned long section_nr, int nid)
 {
 	return 0;
 }
+
+static void __init sparse_extreme_init(void)
+{
+}
 #endif
 
 /*
@@ -197,13 +208,7 @@ void __init sparse_sections_init(void)
 	unsigned long start, end;
 	int i, nid;
 
-#ifdef CONFIG_SPARSEMEM_EXTREME
-	unsigned long size, align;
-
-	size = sizeof(struct mem_section *) * NR_SECTION_ROOTS;
-	align = 1 << (INTERNODE_CACHE_SHIFT);
-	mem_section = memblock_alloc_or_panic(size, align);
-#endif
+	sparse_extreme_init();
 
 	for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid)
 		memory_present(nid, start, end);

-- 
2.43.0


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

* [PATCH 02/12] mm/sparse: refactor sparse_sections_init()
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
  2026-09-09 13:32 ` [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init() David Hildenbrand (Arm)
@ 2026-09-09 13:32 ` David Hildenbrand (Arm)
  2026-09-09 17:09   ` Oscar Salvador (SUSE)
  2026-09-10 13:29   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:32 ` [PATCH 03/12] mm/sparse: move initialization of section metadata to sparse_metadata_init() David Hildenbrand (Arm)
                   ` (9 subsequent siblings)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:32 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

memory_present() really identifies+prepares all early sections so the
initialization in sparse_init() can properly iterating them to
initialize metadata.

Let's just inline memory_present() into sparse_sections_init() and
cleaning up the code a bit while at it: make it clear that we are operating
on pfns.

Note that we call set_section_nid() now only if the section
was not already created earlier. Now, there is no more inconsistency
between what we (temporarily) store in ms->section_mem_map and what
we store in our section->nid array.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 mm/sparse.c | 41 +++++++++++++++++------------------------
 1 file changed, 17 insertions(+), 24 deletions(-)

diff --git a/mm/sparse.c b/mm/sparse.c
index 6a6d258862904..36e3d854febc5 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -179,22 +179,27 @@ static inline unsigned long first_present_section_nr(void)
 	return next_present_section_nr(-1);
 }
 
-/* Record a memory area against a node. */
-static void __init memory_present(int nid, unsigned long start, unsigned long end)
+void __init sparse_sections_init(void)
 {
-	unsigned long pfn;
+	unsigned long pfn, start_pfn, end_pfn;
+	int i, nid;
+
+	sparse_extreme_init();
 
-	start &= PAGE_SECTION_MASK;
-	mminit_validate_memmodel_limits(&start, &end);
-	for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
-		unsigned long section_nr = pfn_to_section_nr(pfn);
-		struct mem_section *ms;
+	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
+		start_pfn &= PAGE_SECTION_MASK;
+		mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
 
-		sparse_index_init(section_nr, nid);
-		set_section_nid(section_nr, nid);
+		for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+			unsigned long section_nr = pfn_to_section_nr(pfn);
+			struct mem_section *ms;
 
-		ms = __nr_to_section(section_nr);
-		if (!ms->section_mem_map) {
+			sparse_index_init(section_nr, nid);
+			ms = __nr_to_section(section_nr);
+			if (ms->section_mem_map)
+				continue;
+
+			set_section_nid(section_nr, nid);
 			ms->section_mem_map = sparse_encode_early_nid(nid) |
 							SECTION_IS_ONLINE;
 			__section_mark_present(ms, section_nr);
@@ -202,18 +207,6 @@ static void __init memory_present(int nid, unsigned long start, unsigned long en
 	}
 }
 
-/* Initialize memory section metadata for all system memory. */
-void __init sparse_sections_init(void)
-{
-	unsigned long start, end;
-	int i, nid;
-
-	sparse_extreme_init();
-
-	for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid)
-		memory_present(nid, start, end);
-}
-
 #ifndef CONFIG_SPARSEMEM_VMEMMAP
 struct page __init *__populate_section_memmap(unsigned long pfn,
 		unsigned long nr_pages, int nid, struct vmem_altmap *altmap,

-- 
2.43.0


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

* [PATCH 03/12] mm/sparse: move initialization of section metadata to sparse_metadata_init()
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
  2026-09-09 13:32 ` [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init() David Hildenbrand (Arm)
  2026-09-09 13:32 ` [PATCH 02/12] mm/sparse: refactor sparse_sections_init() David Hildenbrand (Arm)
@ 2026-09-09 13:32 ` David Hildenbrand (Arm)
  2026-09-09 17:22   ` Oscar Salvador (SUSE)
  2026-09-10 13:43   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:32 ` [PATCH 04/12] mm/sparse: rename and cleanup sparse_init_nid() David Hildenbrand (Arm)
                   ` (8 subsequent siblings)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:32 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

Let's move the code responsible for initializing sparse metadata (usemap,
memmap) into a helper. Cleanup the variable while at it (e.g.,
"map_count").

Drop the rather obvious code comments.

No functional change intended.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 mm/sparse.c | 43 ++++++++++++++++++++++---------------------
 1 file changed, 22 insertions(+), 21 deletions(-)

diff --git a/mm/sparse.c b/mm/sparse.c
index 36e3d854febc5..a85a9c3840f6c 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -257,38 +257,39 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
 	}
 }
 
+static void __init sparse_metadata_init(void)
+{
+	unsigned long start_section_nr = first_present_section_nr();
+	int nid_begin = sparse_early_nid(__nr_to_section(start_section_nr));
+	unsigned long section_nr, nr_sections = 1;
+
+	for_each_present_section_nr(start_section_nr + 1, section_nr) {
+		const int nid = sparse_early_nid(__nr_to_section(section_nr));
+
+		if (nid == nid_begin) {
+			nr_sections++;
+			continue;
+		}
+		sparse_init_nid(nid_begin, start_section_nr, section_nr, nr_sections);
+		nid_begin = nid;
+		start_section_nr = section_nr;
+		nr_sections = 1;
+	}
+	sparse_init_nid(nid_begin, start_section_nr, section_nr, nr_sections);
+}
+
 /*
  * Allocate the accumulated non-linear sections, allocate a mem_map
  * for each and record the physical to section mapping.
  */
 void __init sparse_init(void)
 {
-	unsigned long pnum_end, pnum_begin, map_count = 1;
-	int nid_begin;
-
 	if (compound_info_has_mask()) {
 		VM_WARN_ON_ONCE(!IS_ALIGNED((unsigned long) pfn_to_page(0),
 				    MAX_FOLIO_VMEMMAP_ALIGN));
 	}
 
-	pnum_begin = first_present_section_nr();
-	nid_begin = sparse_early_nid(__nr_to_section(pnum_begin));
-
-	for_each_present_section_nr(pnum_begin + 1, pnum_end) {
-		int nid = sparse_early_nid(__nr_to_section(pnum_end));
-
-		if (nid == nid_begin) {
-			map_count++;
-			continue;
-		}
-		/* Init node with sections in range [pnum_begin, pnum_end) */
-		sparse_init_nid(nid_begin, pnum_begin, pnum_end, map_count);
-		nid_begin = nid;
-		pnum_begin = pnum_end;
-		map_count = 1;
-	}
-	/* cover the last node */
-	sparse_init_nid(nid_begin, pnum_begin, pnum_end, map_count);
+	sparse_metadata_init();
 	sparse_init_subsection_map();
 	vmemmap_populate_print_last();
 }

-- 
2.43.0


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

* [PATCH 04/12] mm/sparse: rename and cleanup sparse_init_nid()
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
                   ` (2 preceding siblings ...)
  2026-09-09 13:32 ` [PATCH 03/12] mm/sparse: move initialization of section metadata to sparse_metadata_init() David Hildenbrand (Arm)
@ 2026-09-09 13:32 ` David Hildenbrand (Arm)
  2026-09-10  7:41   ` Oscar Salvador (SUSE)
  2026-09-10 13:46   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:32 ` [PATCH 05/12] mm/sparse: cleanup sparse_init_one_section() David Hildenbrand (Arm)
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:32 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

Let's rename it to "sparse_metadata_init_nid", avoid the "pnum" terminology
and drop the function comment. Further, rename the "map" variable to
"mem_map" for consistency with other functions.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 mm/sparse.c | 41 ++++++++++++++++++++---------------------
 1 file changed, 20 insertions(+), 21 deletions(-)

diff --git a/mm/sparse.c b/mm/sparse.c
index a85a9c3840f6c..f84bfceb53060 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -222,37 +222,34 @@ void __weak __meminit vmemmap_populate_print_last(void)
 {
 }
 
-/*
- * Initialize sparse on a specific node. The node spans [pnum_begin, pnum_end)
- * And number of present sections in this node is map_count.
- */
-static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
-				   unsigned long pnum_end,
-				   unsigned long map_count)
+static void __init sparse_metadata_init_nid(int nid,
+		unsigned long start_section_nr, unsigned long end_section_nr,
+		unsigned long nr_sections)
 {
-	unsigned long pnum;
 	struct mem_section_usage *usage;
+	unsigned long section_nr;
 
-	usage = memblock_alloc_node(map_count * mem_section_usage_size(),
+	usage = memblock_alloc_node(nr_sections * mem_section_usage_size(),
 				    SMP_CACHE_BYTES, nid);
 	if (!usage)
 		panic("Failed to allocate usemap for node %d\n", nid);
 
-	for_each_present_section_nr(pnum_begin, pnum) {
-		unsigned long pfn = section_nr_to_pfn(pnum);
-		struct page *map;
+	for_each_present_section_nr(start_section_nr, section_nr) {
+		unsigned long pfn = section_nr_to_pfn(section_nr);
+		struct page *mem_map;
 
-		if (pnum >= pnum_end)
+		if (section_nr >= end_section_nr)
 			break;
 
-		map = __populate_section_memmap(pfn, PAGES_PER_SECTION,
-						nid, NULL, NULL);
-		if (!map)
-			panic("Failed to allocate memmap for section %lu\n", pnum);
+		mem_map = __populate_section_memmap(pfn, PAGES_PER_SECTION, nid,
+						    NULL, NULL);
+		if (!mem_map)
+			panic("Failed to allocate memmap for section %lu\n",
+			      section_nr);
 		memmap_boot_pages_add(section_nr_vmemmap_pages(pfn, PAGES_PER_SECTION,
 							       NULL, NULL));
-		sparse_init_one_section(__nr_to_section(pnum), pnum, map, usage,
-					SECTION_IS_EARLY);
+		sparse_init_one_section(__nr_to_section(section_nr), section_nr,
+					mem_map, usage, SECTION_IS_EARLY);
 		usage = (void *)usage + mem_section_usage_size();
 	}
 }
@@ -270,12 +267,14 @@ static void __init sparse_metadata_init(void)
 			nr_sections++;
 			continue;
 		}
-		sparse_init_nid(nid_begin, start_section_nr, section_nr, nr_sections);
+		sparse_metadata_init_nid(nid_begin, start_section_nr,
+					 section_nr, nr_sections);
 		nid_begin = nid;
 		start_section_nr = section_nr;
 		nr_sections = 1;
 	}
-	sparse_init_nid(nid_begin, start_section_nr, section_nr, nr_sections);
+	sparse_metadata_init_nid(nid_begin, start_section_nr, section_nr,
+				 nr_sections);
 }
 
 /*

-- 
2.43.0


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

* [PATCH 05/12] mm/sparse: cleanup sparse_init_one_section()
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
                   ` (3 preceding siblings ...)
  2026-09-09 13:32 ` [PATCH 04/12] mm/sparse: rename and cleanup sparse_init_nid() David Hildenbrand (Arm)
@ 2026-09-09 13:32 ` David Hildenbrand (Arm)
  2026-09-10  7:45   ` Oscar Salvador (SUSE)
  2026-09-10 13:47   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:32 ` [PATCH 06/12] mm/sparse: rename __highest_present_section_nr to __highest_used_section_nr David Hildenbrand (Arm)
                   ` (6 subsequent siblings)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:32 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

Let's avoid the "pnum" terminology.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 mm/sparse.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/sparse.h b/mm/sparse.h
index 049272aba84e5..744ae29002f5e 100644
--- a/mm/sparse.h
+++ b/mm/sparse.h
@@ -90,7 +90,7 @@ void sparse_sections_init(void);
 int sparse_index_init(unsigned long section_nr, int nid);
 
 static inline void sparse_init_one_section(struct mem_section *ms,
-		unsigned long pnum, struct page *mem_map,
+		unsigned long section_nr, struct page *mem_map,
 		struct mem_section_usage *usage, unsigned long flags)
 {
 	unsigned long coded_mem_map;
@@ -102,7 +102,7 @@ static inline void sparse_init_one_section(struct mem_section *ms,
 	 * page_to_pfn() on !CONFIG_SPARSEMEM_VMEMMAP can simply subtract it
 	 * from the page pointer to obtain the PFN.
 	 */
-	coded_mem_map = (unsigned long)(mem_map - section_nr_to_pfn(pnum));
+	coded_mem_map = (unsigned long)(mem_map - section_nr_to_pfn(section_nr));
 	VM_WARN_ON_ONCE(coded_mem_map & ~SECTION_MAP_MASK);
 
 	ms->section_mem_map &= ~SECTION_MAP_MASK;

-- 
2.43.0


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

* [PATCH 06/12] mm/sparse: rename __highest_present_section_nr to __highest_used_section_nr
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
                   ` (4 preceding siblings ...)
  2026-09-09 13:32 ` [PATCH 05/12] mm/sparse: cleanup sparse_init_one_section() David Hildenbrand (Arm)
@ 2026-09-09 13:32 ` David Hildenbrand (Arm)
  2026-09-10  7:56   ` Oscar Salvador (SUSE)
  2026-09-10 13:49   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:33 ` [PATCH 07/12] mm/sparse: remove pfn_in_present_section() David Hildenbrand (Arm)
                   ` (5 subsequent siblings)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:32 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

In preparation for getting rid of SECTION_MARKED_PRESENT, rename
__highest_present_section_nr and clarify the comment.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 include/linux/mmzone.h |  6 +++---
 mm/compaction.c        |  2 +-
 mm/sparse.c            | 12 ++++--------
 mm/sparse.h            |  4 ++--
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index c9ae7991a8b20..19296e8ef44f8 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -2170,7 +2170,7 @@ static inline struct mem_section *__pfn_to_section(unsigned long pfn)
 	return __nr_to_section(pfn_to_section_nr(pfn));
 }
 
-extern unsigned long __highest_present_section_nr;
+extern unsigned long __highest_used_section_nr;
 
 static inline int subsection_map_index(unsigned long pfn)
 {
@@ -2269,7 +2269,7 @@ static inline unsigned long first_valid_pfn(unsigned long pfn, unsigned long end
 
 	rcu_read_lock_sched();
 
-	while (nr <= __highest_present_section_nr && pfn < end_pfn) {
+	while (nr <= __highest_used_section_nr && pfn < end_pfn) {
 		struct mem_section *ms = __pfn_to_section(pfn);
 
 		if (valid_section(ms) &&
@@ -2324,7 +2324,7 @@ static inline int pfn_in_present_section(unsigned long pfn)
 
 static inline unsigned long next_present_section_nr(unsigned long section_nr)
 {
-	while (++section_nr <= __highest_present_section_nr) {
+	while (++section_nr <= __highest_used_section_nr) {
 		if (present_section_nr(section_nr))
 			return section_nr;
 	}
diff --git a/mm/compaction.c b/mm/compaction.c
index 4994e200bbecd..f1b2060eb2016 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -216,7 +216,7 @@ static unsigned long skip_offline_sections(unsigned long start_pfn)
 	if (online_section_nr(start_nr))
 		return 0;
 
-	while (++start_nr <= __highest_present_section_nr) {
+	while (++start_nr <= __highest_used_section_nr) {
 		if (online_section_nr(start_nr))
 			return section_nr_to_pfn(start_nr);
 	}
diff --git a/mm/sparse.c b/mm/sparse.c
index f84bfceb53060..2b41ae36f20b8 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -164,15 +164,11 @@ static void __init mminit_validate_memmodel_limits(unsigned long *start_pfn,
 }
 
 /*
- * There are a number of times that we loop over NR_MEM_SECTIONS,
- * looking for section_present() on each.  But, when we have very
- * large physical address spaces, NR_MEM_SECTIONS can also be
- * very large which makes the loops quite long.
- *
- * Keeping track of this gives us an easy way to break out of
- * those loops early.
+ * Looping over all memory sections is expensive, especially if NR_MEM_SECTIONS
+ * is large but only a fraction is actually used. Keep track of the highest
+ * section number we ever used.
  */
-unsigned long __highest_present_section_nr;
+unsigned long __highest_used_section_nr;
 
 static inline unsigned long first_present_section_nr(void)
 {
diff --git a/mm/sparse.h b/mm/sparse.h
index 744ae29002f5e..7c5d82ceb7142 100644
--- a/mm/sparse.h
+++ b/mm/sparse.h
@@ -114,8 +114,8 @@ static inline void sparse_init_one_section(struct mem_section *ms,
 static inline void __section_mark_present(struct mem_section *ms,
 		unsigned long section_nr)
 {
-	if (section_nr > __highest_present_section_nr)
-		__highest_present_section_nr = section_nr;
+	if (section_nr > __highest_used_section_nr)
+		__highest_used_section_nr = section_nr;
 
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 }

-- 
2.43.0


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

* [PATCH 07/12] mm/sparse: remove pfn_in_present_section()
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
                   ` (5 preceding siblings ...)
  2026-09-09 13:32 ` [PATCH 06/12] mm/sparse: rename __highest_present_section_nr to __highest_used_section_nr David Hildenbrand (Arm)
@ 2026-09-09 13:33 ` David Hildenbrand (Arm)
  2026-09-10  7:59   ` Oscar Salvador (SUSE)
  2026-09-10 13:50   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:33 ` [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling David Hildenbrand (Arm)
                   ` (4 subsequent siblings)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:33 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

Unused, let's remove it.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 include/linux/mmzone.h | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 19296e8ef44f8..e0fac344f6ac2 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -2315,13 +2315,6 @@ static inline unsigned long next_valid_pfn(unsigned long pfn, unsigned long end_
 
 #endif
 
-static inline int pfn_in_present_section(unsigned long pfn)
-{
-	if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
-		return 0;
-	return present_section(__pfn_to_section(pfn));
-}
-
 static inline unsigned long next_present_section_nr(unsigned long section_nr)
 {
 	while (++section_nr <= __highest_used_section_nr) {
@@ -2351,9 +2344,6 @@ static inline unsigned long next_present_section_nr(unsigned long section_nr)
 #else
 #define pfn_to_nid(pfn)		(0)
 #endif
-
-#else
-#define pfn_in_present_section pfn_valid
 #endif /* CONFIG_SPARSEMEM */
 
 /*

-- 
2.43.0


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

* [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
                   ` (6 preceding siblings ...)
  2026-09-09 13:33 ` [PATCH 07/12] mm/sparse: remove pfn_in_present_section() David Hildenbrand (Arm)
@ 2026-09-09 13:33 ` David Hildenbrand (Arm)
  2026-09-09 14:44   ` David Hildenbrand (Arm)
                     ` (2 more replies)
  2026-09-09 13:33 ` [PATCH 09/12] mm/sparse: remove SECTION_MARKED_PRESENT David Hildenbrand (Arm)
                   ` (3 subsequent siblings)
  11 siblings, 3 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:33 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

Let's move it to sparse_init_one_section(). However, to keep early
boot processing working, we also have to initialize it in
sparse_sections_init().

Should we use READ_ONCE/WRITE_ONCE with __highest_used_section_nr?
Probably, something for another day.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 mm/sparse.c | 5 +++--
 mm/sparse.h | 6 +++---
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/mm/sparse.c b/mm/sparse.c
index 2b41ae36f20b8..2d0f2db34f4cf 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -177,7 +177,7 @@ static inline unsigned long first_present_section_nr(void)
 
 void __init sparse_sections_init(void)
 {
-	unsigned long pfn, start_pfn, end_pfn;
+	unsigned long pfn, start_pfn, end_pfn, section_nr;
 	int i, nid;
 
 	sparse_extreme_init();
@@ -187,9 +187,9 @@ void __init sparse_sections_init(void)
 		mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
 
 		for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
-			unsigned long section_nr = pfn_to_section_nr(pfn);
 			struct mem_section *ms;
 
+			section_nr = pfn_to_section_nr(pfn);
 			sparse_index_init(section_nr, nid);
 			ms = __nr_to_section(section_nr);
 			if (ms->section_mem_map)
@@ -201,6 +201,7 @@ void __init sparse_sections_init(void)
 			__section_mark_present(ms, section_nr);
 		}
 	}
+	__highest_used_section_nr = section_nr;
 }
 
 #ifndef CONFIG_SPARSEMEM_VMEMMAP
diff --git a/mm/sparse.h b/mm/sparse.h
index 7c5d82ceb7142..a3af4967fd5c5 100644
--- a/mm/sparse.h
+++ b/mm/sparse.h
@@ -97,6 +97,9 @@ static inline void sparse_init_one_section(struct mem_section *ms,
 
 	BUILD_BUG_ON(SECTION_MAP_LAST_BIT > PFN_SECTION_SHIFT);
 
+	if (section_nr > __highest_used_section_nr)
+		__highest_used_section_nr = section_nr;
+
 	/*
 	 * We encode the start PFN of the section into the mem_map such that
 	 * page_to_pfn() on !CONFIG_SPARSEMEM_VMEMMAP can simply subtract it
@@ -114,9 +117,6 @@ static inline void sparse_init_one_section(struct mem_section *ms,
 static inline void __section_mark_present(struct mem_section *ms,
 		unsigned long section_nr)
 {
-	if (section_nr > __highest_used_section_nr)
-		__highest_used_section_nr = section_nr;
-
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 }
 

-- 
2.43.0


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

* [PATCH 09/12] mm/sparse: remove SECTION_MARKED_PRESENT
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
                   ` (7 preceding siblings ...)
  2026-09-09 13:33 ` [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling David Hildenbrand (Arm)
@ 2026-09-09 13:33 ` David Hildenbrand (Arm)
  2026-09-10 12:15   ` Oscar Salvador (SUSE)
  2026-09-10 14:32   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:33 ` [PATCH 10/12] mm/sparse: remove flags parameter from sparse_init_one_section() David Hildenbrand (Arm)
                   ` (2 subsequent siblings)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:33 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

All present section iterators run before memory hotplug added any
further memory sections, Therefore, we can simply use the SECTION_IS_EARLY
flag by setting that flag earlier in sparse_prepare_early_sections().

Get rid of SECTION_MARKED_PRESENT entirely and rename
for_each_present_section_nr() to for_each_early_section_nr().

Also update the gdb script to use the updated value for
SECTION_IS_EARLY.

No functional change intended.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 drivers/base/memory.c   |  2 +-
 include/linux/mmzone.h  | 27 ++++++++++-----------------
 mm/sparse-vmemmap.c     |  1 -
 mm/sparse.c             | 17 ++++++++---------
 mm/sparse.h             |  6 ------
 scripts/gdb/linux/mm.py |  2 +-
 6 files changed, 20 insertions(+), 35 deletions(-)

diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 5eead3346f1e3..b0338de2f1d82 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -972,7 +972,7 @@ void __init memory_dev_init(void)
 	 * block so that it can be covered.
 	 */
 	block_id = ULONG_MAX;
-	for_each_present_section_nr(0, nr) {
+	for_each_early_section_nr(0, nr) {
 		if (block_id != ULONG_MAX && memory_block_id(nr) == block_id)
 			continue;
 
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index e0fac344f6ac2..62cff59dd80c4 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -2084,7 +2084,6 @@ static inline struct mem_section *__nr_to_section(unsigned long nr)
  * accommodate SECTION_MAP_LAST_BIT. We use BUILD_BUG_ON() to ensure this.
  */
 enum {
-	SECTION_MARKED_PRESENT_BIT,
 	SECTION_HAS_MEM_MAP_BIT,
 	SECTION_IS_ONLINE_BIT,
 	SECTION_IS_EARLY_BIT,
@@ -2094,7 +2093,6 @@ enum {
 	SECTION_MAP_LAST_BIT,
 };
 
-#define SECTION_MARKED_PRESENT		BIT(SECTION_MARKED_PRESENT_BIT)
 #define SECTION_HAS_MEM_MAP		BIT(SECTION_HAS_MEM_MAP_BIT)
 #define SECTION_IS_ONLINE		BIT(SECTION_IS_ONLINE_BIT)
 #define SECTION_IS_EARLY		BIT(SECTION_IS_EARLY_BIT)
@@ -2111,16 +2109,6 @@ static inline struct page *__section_mem_map_addr(struct mem_section *section)
 	return (struct page *)map;
 }
 
-static inline int present_section(const struct mem_section *section)
-{
-	return (section && (section->section_mem_map & SECTION_MARKED_PRESENT));
-}
-
-static inline int present_section_nr(unsigned long nr)
-{
-	return present_section(__nr_to_section(nr));
-}
-
 static inline int valid_section(const struct mem_section *section)
 {
 	return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP));
@@ -2136,6 +2124,11 @@ static inline int valid_section_nr(unsigned long nr)
 	return valid_section(__nr_to_section(nr));
 }
 
+static inline int early_section_nr(unsigned long nr)
+{
+	return early_section(__nr_to_section(nr));
+}
+
 static inline int online_section(const struct mem_section *section)
 {
 	return (section && (section->section_mem_map & SECTION_IS_ONLINE));
@@ -2315,20 +2308,20 @@ static inline unsigned long next_valid_pfn(unsigned long pfn, unsigned long end_
 
 #endif
 
-static inline unsigned long next_present_section_nr(unsigned long section_nr)
+static inline unsigned long next_early_section_nr(unsigned long section_nr)
 {
 	while (++section_nr <= __highest_used_section_nr) {
-		if (present_section_nr(section_nr))
+		if (early_section_nr(section_nr))
 			return section_nr;
 	}
 
 	return -1;
 }
 
-#define for_each_present_section_nr(start, section_nr)		\
-	for (section_nr = next_present_section_nr(start - 1);	\
+#define for_each_early_section_nr(start, section_nr)		\
+	for (section_nr = next_early_section_nr(start - 1);	\
 	     section_nr != -1;					\
-	     section_nr = next_present_section_nr(section_nr))
+	     section_nr = next_early_section_nr(section_nr))
 
 /*
  * These are _only_ used during initialisation, therefore they
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index e62e6aa07f126..5aba058df6b67 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -890,7 +890,6 @@ int __meminit sparse_add_section(int nid, unsigned long start_pfn,
 	page_init_poison(memmap, sizeof(struct page) * nr_pages);
 
 	ms = __nr_to_section(section_nr);
-	__section_mark_present(ms, section_nr);
 
 	/* Align memmap to section boundary in the subsection case */
 	if (section_nr_to_pfn(section_nr) != start_pfn)
diff --git a/mm/sparse.c b/mm/sparse.c
index 2d0f2db34f4cf..344acaaed94db 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -170,13 +170,14 @@ static void __init mminit_validate_memmodel_limits(unsigned long *start_pfn,
  */
 unsigned long __highest_used_section_nr;
 
-static inline unsigned long first_present_section_nr(void)
+static inline unsigned long first_early_section_nr(void)
 {
-	return next_present_section_nr(-1);
+	return next_early_section_nr(-1);
 }
 
 void __init sparse_sections_init(void)
 {
+	const unsigned long flags = SECTION_IS_EARLY | SECTION_IS_ONLINE;
 	unsigned long pfn, start_pfn, end_pfn, section_nr;
 	int i, nid;
 
@@ -196,9 +197,7 @@ void __init sparse_sections_init(void)
 				continue;
 
 			set_section_nid(section_nr, nid);
-			ms->section_mem_map = sparse_encode_early_nid(nid) |
-							SECTION_IS_ONLINE;
-			__section_mark_present(ms, section_nr);
+			ms->section_mem_map = sparse_encode_early_nid(nid) | flags;
 		}
 	}
 	__highest_used_section_nr = section_nr;
@@ -231,7 +230,7 @@ static void __init sparse_metadata_init_nid(int nid,
 	if (!usage)
 		panic("Failed to allocate usemap for node %d\n", nid);
 
-	for_each_present_section_nr(start_section_nr, section_nr) {
+	for_each_early_section_nr(start_section_nr, section_nr) {
 		unsigned long pfn = section_nr_to_pfn(section_nr);
 		struct page *mem_map;
 
@@ -246,18 +245,18 @@ static void __init sparse_metadata_init_nid(int nid,
 		memmap_boot_pages_add(section_nr_vmemmap_pages(pfn, PAGES_PER_SECTION,
 							       NULL, NULL));
 		sparse_init_one_section(__nr_to_section(section_nr), section_nr,
-					mem_map, usage, SECTION_IS_EARLY);
+					mem_map, usage, 0);
 		usage = (void *)usage + mem_section_usage_size();
 	}
 }
 
 static void __init sparse_metadata_init(void)
 {
-	unsigned long start_section_nr = first_present_section_nr();
+	unsigned long start_section_nr = first_early_section_nr();
 	int nid_begin = sparse_early_nid(__nr_to_section(start_section_nr));
 	unsigned long section_nr, nr_sections = 1;
 
-	for_each_present_section_nr(start_section_nr + 1, section_nr) {
+	for_each_early_section_nr(start_section_nr + 1, section_nr) {
 		const int nid = sparse_early_nid(__nr_to_section(section_nr));
 
 		if (nid == nid_begin) {
diff --git a/mm/sparse.h b/mm/sparse.h
index a3af4967fd5c5..03351f2467e34 100644
--- a/mm/sparse.h
+++ b/mm/sparse.h
@@ -114,12 +114,6 @@ static inline void sparse_init_one_section(struct mem_section *ms,
 	ms->usage = usage;
 }
 
-static inline void __section_mark_present(struct mem_section *ms,
-		unsigned long section_nr)
-{
-	ms->section_mem_map |= SECTION_MARKED_PRESENT;
-}
-
 static inline size_t mem_section_usage_size(void)
 {
 	return struct_size_t(struct mem_section_usage, pageblock_flags,
diff --git a/scripts/gdb/linux/mm.py b/scripts/gdb/linux/mm.py
index 193a88d763abf..73d637d28c8e6 100644
--- a/scripts/gdb/linux/mm.py
+++ b/scripts/gdb/linux/mm.py
@@ -76,7 +76,7 @@ class x86_page_ops():
             self.SECTION_IS_EARLY = 1 << int(gdb.parse_and_eval('SECTION_IS_EARLY_BIT'))
         except:
             self.SECTION_HAS_MEM_MAP = 1 << 0
-            self.SECTION_IS_EARLY = 1 << 3
+            self.SECTION_IS_EARLY = 1 << 2
 
         self.SUBSECTION_SHIFT = 21
         self.PAGES_PER_SUBSECTION = 1 << (self.SUBSECTION_SHIFT - self.PAGE_SHIFT)

-- 
2.43.0


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

* [PATCH 10/12] mm/sparse: remove flags parameter from sparse_init_one_section()
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
                   ` (8 preceding siblings ...)
  2026-09-09 13:33 ` [PATCH 09/12] mm/sparse: remove SECTION_MARKED_PRESENT David Hildenbrand (Arm)
@ 2026-09-09 13:33 ` David Hildenbrand (Arm)
  2026-09-10 12:34   ` Oscar Salvador (SUSE)
  2026-09-10 14:34   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:33 ` [PATCH 11/12] fs/proc/page: clarify comment in get_max_dump_pfn() David Hildenbrand (Arm)
  2026-09-09 13:33 ` [PATCH 12/12] mm/memory_hotplug: drop CONFIG_HAVE_ARCH_PFN_VALID handling from pfn_to_online_page() David Hildenbrand (Arm)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:33 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

Unused, let's remove it.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 mm/sparse-vmemmap.c | 2 +-
 mm/sparse.c         | 2 +-
 mm/sparse.h         | 5 ++---
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index 5aba058df6b67..25d3472972363 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -894,7 +894,7 @@ int __meminit sparse_add_section(int nid, unsigned long start_pfn,
 	/* Align memmap to section boundary in the subsection case */
 	if (section_nr_to_pfn(section_nr) != start_pfn)
 		memmap = pfn_to_page(section_nr_to_pfn(section_nr));
-	sparse_init_one_section(ms, section_nr, memmap, ms->usage, 0);
+	sparse_init_one_section(ms, section_nr, memmap, ms->usage);
 
 	return 0;
 }
diff --git a/mm/sparse.c b/mm/sparse.c
index 344acaaed94db..d2e7c21319e27 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -245,7 +245,7 @@ static void __init sparse_metadata_init_nid(int nid,
 		memmap_boot_pages_add(section_nr_vmemmap_pages(pfn, PAGES_PER_SECTION,
 							       NULL, NULL));
 		sparse_init_one_section(__nr_to_section(section_nr), section_nr,
-					mem_map, usage, 0);
+					mem_map, usage);
 		usage = (void *)usage + mem_section_usage_size();
 	}
 }
diff --git a/mm/sparse.h b/mm/sparse.h
index 03351f2467e34..f45dd280db6ff 100644
--- a/mm/sparse.h
+++ b/mm/sparse.h
@@ -91,7 +91,7 @@ int sparse_index_init(unsigned long section_nr, int nid);
 
 static inline void sparse_init_one_section(struct mem_section *ms,
 		unsigned long section_nr, struct page *mem_map,
-		struct mem_section_usage *usage, unsigned long flags)
+		struct mem_section_usage *usage)
 {
 	unsigned long coded_mem_map;
 
@@ -109,8 +109,7 @@ static inline void sparse_init_one_section(struct mem_section *ms,
 	VM_WARN_ON_ONCE(coded_mem_map & ~SECTION_MAP_MASK);
 
 	ms->section_mem_map &= ~SECTION_MAP_MASK;
-	ms->section_mem_map |= coded_mem_map;
-	ms->section_mem_map |= flags | SECTION_HAS_MEM_MAP;
+	ms->section_mem_map |= coded_mem_map | SECTION_HAS_MEM_MAP;
 	ms->usage = usage;
 }
 

-- 
2.43.0


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

* [PATCH 11/12] fs/proc/page: clarify comment in get_max_dump_pfn()
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
                   ` (9 preceding siblings ...)
  2026-09-09 13:33 ` [PATCH 10/12] mm/sparse: remove flags parameter from sparse_init_one_section() David Hildenbrand (Arm)
@ 2026-09-09 13:33 ` David Hildenbrand (Arm)
  2026-09-10 12:46   ` Oscar Salvador (SUSE)
  2026-09-10 14:41   ` Lorenzo Stoakes (ARM)
  2026-09-09 13:33 ` [PATCH 12/12] mm/memory_hotplug: drop CONFIG_HAVE_ARCH_PFN_VALID handling from pfn_to_online_page() David Hildenbrand (Arm)
  11 siblings, 2 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:33 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

pfn_to_online_page() will only succeed on some PFNs within the same
section, not necessarily all. Let's make that clearer.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 fs/proc/page.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/fs/proc/page.c b/fs/proc/page.c
index 260772b20bd99..6856ff3e3cf28 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -31,10 +31,9 @@ static inline unsigned long get_max_dump_pfn(void)
 {
 #ifdef CONFIG_SPARSEMEM
 	/*
-	 * The memmap of early sections is completely populated and marked
-	 * online even if max_pfn does not fall on a section boundary -
-	 * pfn_to_online_page() will succeed on all pages. Allow inspecting
-	 * these memmaps.
+	 * If max_pfn does not fall on a section boundary, pfn_to_online_page()
+	 * can succeed on PFNs beyond max_pfn within the same section. Allow
+	 * inspecting these memmaps.
 	 */
 	return round_up(max_pfn, PAGES_PER_SECTION);
 #else

-- 
2.43.0


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

* [PATCH 12/12] mm/memory_hotplug: drop CONFIG_HAVE_ARCH_PFN_VALID handling from pfn_to_online_page()
  2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
                   ` (10 preceding siblings ...)
  2026-09-09 13:33 ` [PATCH 11/12] fs/proc/page: clarify comment in get_max_dump_pfn() David Hildenbrand (Arm)
@ 2026-09-09 13:33 ` David Hildenbrand (Arm)
  2026-09-10 14:47   ` Lorenzo Stoakes (ARM)
  11 siblings, 1 reply; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 13:33 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel,
	David Hildenbrand (Arm)

Drop CONFIG_HAVE_ARCH_PFN_VALID handling, as CONFIG_HAVE_ARCH_PFN_VALID
is never used with CONFIG_MEMORY_HOTPLUG, as the latter depends on
CONFIG_SPARSEMEM_VMEMMAP. Make sure it stays that way.

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 mm/memory_hotplug.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index b428da66d279c..58ce35cb48f57 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -344,6 +344,8 @@ struct page *pfn_to_online_page(unsigned long pfn)
 	struct dev_pagemap *pgmap;
 	struct mem_section *ms;
 
+	BUILD_BUG_ON(IS_ENABLED(CONFIG_HAVE_ARCH_PFN_VALID));
+
 	if (nr >= NR_MEM_SECTIONS)
 		return NULL;
 
@@ -351,13 +353,6 @@ struct page *pfn_to_online_page(unsigned long pfn)
 	if (!online_section(ms))
 		return NULL;
 
-	/*
-	 * Save some code text when online_section() +
-	 * pfn_section_valid() are sufficient.
-	 */
-	if (IS_ENABLED(CONFIG_HAVE_ARCH_PFN_VALID) && !pfn_valid(pfn))
-		return NULL;
-
 	if (!pfn_section_valid(ms, pfn))
 		return NULL;
 

-- 
2.43.0


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

* Re: [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling
  2026-09-09 13:33 ` [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling David Hildenbrand (Arm)
@ 2026-09-09 14:44   ` David Hildenbrand (Arm)
  2026-09-10  8:33   ` Oscar Salvador (SUSE)
  2026-09-10 14:16   ` Lorenzo Stoakes (ARM)
  2 siblings, 0 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 14:44 UTC (permalink / raw)
  To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham
  Cc: linux-kernel, linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/9/26 15:33, David Hildenbrand (Arm) wrote:
> Let's move it to sparse_init_one_section(). However, to keep early
> boot processing working, we also have to initialize it in
> sparse_sections_init().
> 
> Should we use READ_ONCE/WRITE_ONCE with __highest_used_section_nr?
> Probably, something for another day.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> ---
>  mm/sparse.c | 5 +++--
>  mm/sparse.h | 6 +++---
>  2 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/sparse.c b/mm/sparse.c
> index 2b41ae36f20b8..2d0f2db34f4cf 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -177,7 +177,7 @@ static inline unsigned long first_present_section_nr(void)
>  
>  void __init sparse_sections_init(void)
>  {
> -	unsigned long pfn, start_pfn, end_pfn;
> +	unsigned long pfn, start_pfn, end_pfn, section_nr;
>  	int i, nid;
>  
>  	sparse_extreme_init();
> @@ -187,9 +187,9 @@ void __init sparse_sections_init(void)
>  		mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
>  
>  		for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
> -			unsigned long section_nr = pfn_to_section_nr(pfn);
>  			struct mem_section *ms;
>  
> +			section_nr = pfn_to_section_nr(pfn);
>  			sparse_index_init(section_nr, nid);
>  			ms = __nr_to_section(section_nr);
>  			if (ms->section_mem_map)
> @@ -201,6 +201,7 @@ void __init sparse_sections_init(void)
>  			__section_mark_present(ms, section_nr);
>  		}
>  	}
> +	__highest_used_section_nr = section_nr;
>  }

Sashiko says that section_nr could be used uninitialized if the loop body
doesn't run.

Certainly a very high regression.

In a universe where a machine can boot without any memory?

"This could occur if mminit_validate_memmodel_limits() clamps
start_pfn and end_pfn to the same value, or if for_each_mem_pfn_range()
yields no memory ranges."

I think this can be ignored.


Sashiko also thinks it found a pre-existing issue when updating
ms->section_mem_map in sparse_init_one_section() when subsections already exist.

That would be the case during ZONE_DEVICE hotplug only. Likely we should skip
the sparse_init_one_section() if already initialized. I'll add this to my todo,
but it has low priority.

-- 
Cheers,

David

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

* Re: [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init()
  2026-09-09 13:32 ` [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init() David Hildenbrand (Arm)
@ 2026-09-09 17:02   ` Oscar Salvador (SUSE)
  2026-09-10 12:52   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-09 17:02 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:54PM +0200, David Hildenbrand (Arm) wrote:
> Let's just avoid another pair of ifdef inside a function. While at it,
> switch to INTERNODE_CACHE_BYTES by just defining a fallback in cache.h
> as well, given that the x86 variant already provides one.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Acked-by: Oscar Salvador <osalvador@suse.de>

 

-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 02/12] mm/sparse: refactor sparse_sections_init()
  2026-09-09 13:32 ` [PATCH 02/12] mm/sparse: refactor sparse_sections_init() David Hildenbrand (Arm)
@ 2026-09-09 17:09   ` Oscar Salvador (SUSE)
  2026-09-09 17:18     ` David Hildenbrand (Arm)
  2026-09-10 13:29   ` Lorenzo Stoakes (ARM)
  1 sibling, 1 reply; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-09 17:09 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:55PM +0200, David Hildenbrand (Arm) wrote:
> memory_present() really identifies+prepares all early sections so the
> initialization in sparse_init() can properly iterating them to
> initialize metadata.
> 
> Let's just inline memory_present() into sparse_sections_init() and
> cleaning up the code a bit while at it: make it clear that we are operating
> on pfns.
> 
> Note that we call set_section_nid() now only if the section
> was not already created earlier. Now, there is no more inconsistency
> between what we (temporarily) store in ms->section_mem_map and what
> we store in our section->nid array.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Acked-by: Oscar Salvador <osalvador@suse.de>

Not sure if it was intentional, but it seems we lost the "Initialize memory section ..."
comment.
Do we want to put it back? Maybe for the folks that are not really
familiar with all the memory section's inner stuff?

Besides that, nice cleanup :-)

 

-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 02/12] mm/sparse: refactor sparse_sections_init()
  2026-09-09 17:09   ` Oscar Salvador (SUSE)
@ 2026-09-09 17:18     ` David Hildenbrand (Arm)
  0 siblings, 0 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-09 17:18 UTC (permalink / raw)
  To: Oscar Salvador (SUSE)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/9/26 19:09, Oscar Salvador (SUSE) wrote:
> On Wed, Sep 09, 2026 at 03:32:55PM +0200, David Hildenbrand (Arm) wrote:
>> memory_present() really identifies+prepares all early sections so the
>> initialization in sparse_init() can properly iterating them to
>> initialize metadata.
>>
>> Let's just inline memory_present() into sparse_sections_init() and
>> cleaning up the code a bit while at it: make it clear that we are operating
>> on pfns.
>>
>> Note that we call set_section_nid() now only if the section
>> was not already created earlier. Now, there is no more inconsistency
>> between what we (temporarily) store in ms->section_mem_map and what
>> we store in our section->nid array.
>>
>> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> 
> Acked-by: Oscar Salvador <osalvador@suse.de>
> 
> Not sure if it was intentional, but it seems we lost the "Initialize memory section ..."
> comment.
> Do we want to put it back? Maybe for the folks that are not really
> familiar with all the memory section's inner stuff?

Munchus patch added it, and I asked him to remove that comment (as it's
imprecise). So I expect, once I rebase on top of his updated work, that that
comment will be gone right away :)

Thanks!

-- 
Cheers,

David

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

* Re: [PATCH 03/12] mm/sparse: move initialization of section metadata to sparse_metadata_init()
  2026-09-09 13:32 ` [PATCH 03/12] mm/sparse: move initialization of section metadata to sparse_metadata_init() David Hildenbrand (Arm)
@ 2026-09-09 17:22   ` Oscar Salvador (SUSE)
  2026-09-10 13:43   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-09 17:22 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:56PM +0200, David Hildenbrand (Arm) wrote:
> Let's move the code responsible for initializing sparse metadata (usemap,
> memmap) into a helper. Cleanup the variable while at it (e.g.,
> "map_count").
> 
> Drop the rather obvious code comments.
> 
> No functional change intended.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Acked-by: Oscar Salvador <osalvador@suse.de>


-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 04/12] mm/sparse: rename and cleanup sparse_init_nid()
  2026-09-09 13:32 ` [PATCH 04/12] mm/sparse: rename and cleanup sparse_init_nid() David Hildenbrand (Arm)
@ 2026-09-10  7:41   ` Oscar Salvador (SUSE)
  2026-09-10 13:46   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-10  7:41 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:57PM +0200, David Hildenbrand (Arm) wrote:
> Let's rename it to "sparse_metadata_init_nid", avoid the "pnum" terminology
> and drop the function comment. Further, rename the "map" variable to
> "mem_map" for consistency with other functions.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Yap, solid cleanup. I cannot remember what pnum was meant to be.

Acked-by: Oscar Salvador <osalvador@suse.de>

 

-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 05/12] mm/sparse: cleanup sparse_init_one_section()
  2026-09-09 13:32 ` [PATCH 05/12] mm/sparse: cleanup sparse_init_one_section() David Hildenbrand (Arm)
@ 2026-09-10  7:45   ` Oscar Salvador (SUSE)
  2026-09-10 13:47   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-10  7:45 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:58PM +0200, David Hildenbrand (Arm) wrote:
> Let's avoid the "pnum" terminology.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Acked-by: Oscar Salvador <osalvador@suse.de>

 

-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 06/12] mm/sparse: rename __highest_present_section_nr to __highest_used_section_nr
  2026-09-09 13:32 ` [PATCH 06/12] mm/sparse: rename __highest_present_section_nr to __highest_used_section_nr David Hildenbrand (Arm)
@ 2026-09-10  7:56   ` Oscar Salvador (SUSE)
  2026-09-10 13:49   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-10  7:56 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:59PM +0200, David Hildenbrand (Arm) wrote:
> In preparation for getting rid of SECTION_MARKED_PRESENT, rename
> __highest_present_section_nr and clarify the comment.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Acked-by: Oscar Salvador <osalvador@suse.de>

 

-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 07/12] mm/sparse: remove pfn_in_present_section()
  2026-09-09 13:33 ` [PATCH 07/12] mm/sparse: remove pfn_in_present_section() David Hildenbrand (Arm)
@ 2026-09-10  7:59   ` Oscar Salvador (SUSE)
  2026-09-10 13:50   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-10  7:59 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:00PM +0200, David Hildenbrand (Arm) wrote:
> Unused, let's remove it.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Acked-by: Oscar Salvador <osalvador@suse.de>

 

-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling
  2026-09-09 13:33 ` [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling David Hildenbrand (Arm)
  2026-09-09 14:44   ` David Hildenbrand (Arm)
@ 2026-09-10  8:33   ` Oscar Salvador (SUSE)
  2026-09-10  9:13     ` David Hildenbrand (Arm)
  2026-09-10 14:16   ` Lorenzo Stoakes (ARM)
  2 siblings, 1 reply; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-10  8:33 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:01PM +0200, David Hildenbrand (Arm) wrote:
> Let's move it to sparse_init_one_section(). However, to keep early
> boot processing working, we also have to initialize it in
> sparse_sections_init().
> 
> Should we use READ_ONCE/WRITE_ONCE with __highest_used_section_nr?
> Probably, something for another day.

What is the worry there?

sparse_init_one_section() calls should run sequentally due to the memhotplug
lock, so there should not be parallel updates there?
 

-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling
  2026-09-10  8:33   ` Oscar Salvador (SUSE)
@ 2026-09-10  9:13     ` David Hildenbrand (Arm)
  2026-09-10 12:08       ` Oscar Salvador (SUSE)
  0 siblings, 1 reply; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-10  9:13 UTC (permalink / raw)
  To: Oscar Salvador (SUSE)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/10/26 10:33, Oscar Salvador (SUSE) wrote:
> On Wed, Sep 09, 2026 at 03:33:01PM +0200, David Hildenbrand (Arm) wrote:
>> Let's move it to sparse_init_one_section(). However, to keep early
>> boot processing working, we also have to initialize it in
>> sparse_sections_init().
>>
>> Should we use READ_ONCE/WRITE_ONCE with __highest_used_section_nr?
>> Probably, something for another day.
> 
> What is the worry there?
> 
> sparse_init_one_section() calls should run sequentally due to the memhotplug
> lock, so there should not be parallel updates there?

If you have something consuming __highest_used_section_nr while concurrently
updating it, you might get torn reads/writes that mess up the value on the
reader side.

For example, mm/compaction.c consuming __highest_used_section_nr.

I don't think this is critical, so I decided to spell it out instead of fixing
it right away.

-- 
Cheers,

David

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

* Re: [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling
  2026-09-10  9:13     ` David Hildenbrand (Arm)
@ 2026-09-10 12:08       ` Oscar Salvador (SUSE)
  2026-09-10 13:33         ` David Hildenbrand (Arm)
  0 siblings, 1 reply; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-10 12:08 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Thu, Sep 10, 2026 at 11:13:18AM +0200, David Hildenbrand (Arm) wrote:
> If you have something consuming __highest_used_section_nr while concurrently
> updating it, you might get torn reads/writes that mess up the value on the
> reader side.
> 
> For example, mm/compaction.c consuming __highest_used_section_nr.

Right, but I guess that if we get a 'wild' value, at least we are
guarded by online_section_nr() performing the right thing?

Not really figthing anything here, just convincing myself :-)

But yes, I guess that we should fix this in case we add more consumers
of __highest_used_section_nr in the future.


-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 09/12] mm/sparse: remove SECTION_MARKED_PRESENT
  2026-09-09 13:33 ` [PATCH 09/12] mm/sparse: remove SECTION_MARKED_PRESENT David Hildenbrand (Arm)
@ 2026-09-10 12:15   ` Oscar Salvador (SUSE)
  2026-09-10 14:32   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-10 12:15 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:02PM +0200, David Hildenbrand (Arm) wrote:
> All present section iterators run before memory hotplug added any
> further memory sections, Therefore, we can simply use the SECTION_IS_EARLY
> flag by setting that flag earlier in sparse_prepare_early_sections().
> 
> Get rid of SECTION_MARKED_PRESENT entirely and rename
> for_each_present_section_nr() to for_each_early_section_nr().
> 
> Also update the gdb script to use the updated value for
> SECTION_IS_EARLY.
> 
> No functional change intended.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Acked-by: Oscar Salvador <osalvador@suse.de>

 

-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 10/12] mm/sparse: remove flags parameter from sparse_init_one_section()
  2026-09-09 13:33 ` [PATCH 10/12] mm/sparse: remove flags parameter from sparse_init_one_section() David Hildenbrand (Arm)
@ 2026-09-10 12:34   ` Oscar Salvador (SUSE)
  2026-09-10 14:34   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-10 12:34 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:03PM +0200, David Hildenbrand (Arm) wrote:
> Unused, let's remove it.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Acked-by: Oscar Salvador <osalvador@suse.de>


-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 11/12] fs/proc/page: clarify comment in get_max_dump_pfn()
  2026-09-09 13:33 ` [PATCH 11/12] fs/proc/page: clarify comment in get_max_dump_pfn() David Hildenbrand (Arm)
@ 2026-09-10 12:46   ` Oscar Salvador (SUSE)
  2026-09-10 14:41   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Oscar Salvador (SUSE) @ 2026-09-10 12:46 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:04PM +0200, David Hildenbrand (Arm) wrote:
> pfn_to_online_page() will only succeed on some PFNs within the same
> section, not necessarily all. Let's make that clearer.
> 
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Acked-by: Oscar Salvador <osalvador@suse.de>

 

-- 
Oscar Salvador
SUSE Labs

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

* Re: [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init()
  2026-09-09 13:32 ` [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init() David Hildenbrand (Arm)
  2026-09-09 17:02   ` Oscar Salvador (SUSE)
@ 2026-09-10 12:52   ` Lorenzo Stoakes (ARM)
  2026-09-10 13:13     ` David Hildenbrand (Arm)
  1 sibling, 1 reply; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 12:52 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:54PM +0200, David Hildenbrand (Arm) wrote:
> Let's just avoid another pair of ifdef inside a function. While at it,
> switch to INTERNODE_CACHE_BYTES by just defining a fallback in cache.h
> as well, given that the x86 variant already provides one.
>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Nic ecleanup, one nit below.

Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

> ---
>  include/linux/cache.h |  1 +
>  mm/sparse.c           | 19 ++++++++++++-------
>  2 files changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/include/linux/cache.h b/include/linux/cache.h
> index e69768f50d532..b6e857b985bca 100644
> --- a/include/linux/cache.h
> +++ b/include/linux/cache.h
> @@ -89,6 +89,7 @@
>   */
>  #ifndef INTERNODE_CACHE_SHIFT
>  #define INTERNODE_CACHE_SHIFT L1_CACHE_SHIFT
> +#define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)

NIT: 1UL?

>  #endif
>
>  #if !defined(____cacheline_internodealigned_in_smp)
> diff --git a/mm/sparse.c b/mm/sparse.c
> index 9349ed6326c01..6a6d258862904 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -103,11 +103,22 @@ int __meminit sparse_index_init(unsigned long section_nr, int nid)
>
>  	return 0;
>  }
> +
> +static void __init sparse_extreme_init(void)
> +{
> +	const unsigned long size = sizeof(struct mem_section *) * NR_SECTION_ROOTS;
> +
> +	mem_section = memblock_alloc_or_panic(size, INTERNODE_CACHE_BYTES);
> +}
>  #else /* !SPARSEMEM_EXTREME */
>  int __meminit sparse_index_init(unsigned long section_nr, int nid)
>  {
>  	return 0;
>  }
> +
> +static void __init sparse_extreme_init(void)
> +{
> +}
>  #endif
>
>  /*
> @@ -197,13 +208,7 @@ void __init sparse_sections_init(void)
>  	unsigned long start, end;
>  	int i, nid;
>
> -#ifdef CONFIG_SPARSEMEM_EXTREME
> -	unsigned long size, align;
> -
> -	size = sizeof(struct mem_section *) * NR_SECTION_ROOTS;
> -	align = 1 << (INTERNODE_CACHE_SHIFT);
> -	mem_section = memblock_alloc_or_panic(size, align);
> -#endif
> +	sparse_extreme_init();
>
>  	for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid)
>  		memory_present(nid, start, end);
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init()
  2026-09-10 12:52   ` Lorenzo Stoakes (ARM)
@ 2026-09-10 13:13     ` David Hildenbrand (Arm)
  2026-09-10 13:33       ` Lorenzo Stoakes (ARM)
  0 siblings, 1 reply; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-10 13:13 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/10/26 14:52, Lorenzo Stoakes (ARM) wrote:
> On Wed, Sep 09, 2026 at 03:32:54PM +0200, David Hildenbrand (Arm) wrote:
>> Let's just avoid another pair of ifdef inside a function. While at it,
>> switch to INTERNODE_CACHE_BYTES by just defining a fallback in cache.h
>> as well, given that the x86 variant already provides one.
>>
>> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> 
> Nic ecleanup, one nit below.
> 
> Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> 
>> ---
>>  include/linux/cache.h |  1 +
>>  mm/sparse.c           | 19 ++++++++++++-------
>>  2 files changed, 13 insertions(+), 7 deletions(-)
>>
>> diff --git a/include/linux/cache.h b/include/linux/cache.h
>> index e69768f50d532..b6e857b985bca 100644
>> --- a/include/linux/cache.h
>> +++ b/include/linux/cache.h
>> @@ -89,6 +89,7 @@
>>   */
>>  #ifndef INTERNODE_CACHE_SHIFT
>>  #define INTERNODE_CACHE_SHIFT L1_CACHE_SHIFT
>> +#define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)
> 
> NIT: 1UL?

I decided to replicate the existing

arch/x86/include/asm/cache.h:#define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)

If the shifted value would ever not fit into an int something would be 
going really wrong ;)

Thanks!

-- 
Cheers,

David

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

* Re: [PATCH 02/12] mm/sparse: refactor sparse_sections_init()
  2026-09-09 13:32 ` [PATCH 02/12] mm/sparse: refactor sparse_sections_init() David Hildenbrand (Arm)
  2026-09-09 17:09   ` Oscar Salvador (SUSE)
@ 2026-09-10 13:29   ` Lorenzo Stoakes (ARM)
  2026-09-10 14:30     ` David Hildenbrand (Arm)
  1 sibling, 1 reply; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 13:29 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:55PM +0200, David Hildenbrand (Arm) wrote:
> memory_present() really identifies+prepares all early sections so the
> initialization in sparse_init() can properly iterating them to
> initialize metadata.
>
> Let's just inline memory_present() into sparse_sections_init() and
> cleaning up the code a bit while at it: make it clear that we are operating
> on pfns.
>
> Note that we call set_section_nid() now only if the section
> was not already created earlier. Now, there is no more inconsistency
> between what we (temporarily) store in ms->section_mem_map and what
> we store in our section->nid array.
>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

In general please keep move/refactor steps separate. It makes it harder to
review when two things are going on at one time.

But I guess in this case the diff wouldn't be that different.

Anyway seems reasonable so:

Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

> ---
>  mm/sparse.c | 41 +++++++++++++++++------------------------
>  1 file changed, 17 insertions(+), 24 deletions(-)
>
> diff --git a/mm/sparse.c b/mm/sparse.c
> index 6a6d258862904..36e3d854febc5 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -179,22 +179,27 @@ static inline unsigned long first_present_section_nr(void)
>  	return next_present_section_nr(-1);
>  }
>
> -/* Record a memory area against a node. */
> -static void __init memory_present(int nid, unsigned long start, unsigned long end)
> +void __init sparse_sections_init(void)
>  {
> -	unsigned long pfn;
> +	unsigned long pfn, start_pfn, end_pfn;
> +	int i, nid;
> +
> +	sparse_extreme_init();
>
> -	start &= PAGE_SECTION_MASK;
> -	mminit_validate_memmodel_limits(&start, &end);
> -	for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
> -		unsigned long section_nr = pfn_to_section_nr(pfn);
> -		struct mem_section *ms;
> +	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
> +		start_pfn &= PAGE_SECTION_MASK;
> +		mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
>
> -		sparse_index_init(section_nr, nid);
> -		set_section_nid(section_nr, nid);
> +		for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
> +			unsigned long section_nr = pfn_to_section_nr(pfn);
> +			struct mem_section *ms;
>
> -		ms = __nr_to_section(section_nr);
> -		if (!ms->section_mem_map) {
> +			sparse_index_init(section_nr, nid);
> +			ms = __nr_to_section(section_nr);
> +			if (ms->section_mem_map)
> +				continue;
> +
> +			set_section_nid(section_nr, nid);

So the main change seems to be calling set_section_nid() only if
!ms->section_mem_map (and obv. calculating ms earlier), as described in the
commit msg.

>  			ms->section_mem_map = sparse_encode_early_nid(nid) |
>  							SECTION_IS_ONLINE;
>  			__section_mark_present(ms, section_nr);
> @@ -202,18 +207,6 @@ static void __init memory_present(int nid, unsigned long start, unsigned long en
>  	}
>  }
>
> -/* Initialize memory section metadata for all system memory. */
> -void __init sparse_sections_init(void)
> -{
> -	unsigned long start, end;
> -	int i, nid;
> -
> -	sparse_extreme_init();
> -
> -	for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid)
> -		memory_present(nid, start, end);
> -}
> -
>  #ifndef CONFIG_SPARSEMEM_VMEMMAP
>  struct page __init *__populate_section_memmap(unsigned long pfn,
>  		unsigned long nr_pages, int nid, struct vmem_altmap *altmap,
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init()
  2026-09-10 13:13     ` David Hildenbrand (Arm)
@ 2026-09-10 13:33       ` Lorenzo Stoakes (ARM)
  0 siblings, 0 replies; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 13:33 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Thu, Sep 10, 2026 at 03:13:26PM +0200, David Hildenbrand (Arm) wrote:
> On 9/10/26 14:52, Lorenzo Stoakes (ARM) wrote:
> > On Wed, Sep 09, 2026 at 03:32:54PM +0200, David Hildenbrand (Arm) wrote:
> >> Let's just avoid another pair of ifdef inside a function. While at it,
> >> switch to INTERNODE_CACHE_BYTES by just defining a fallback in cache.h
> >> as well, given that the x86 variant already provides one.
> >>
> >> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> >
> > Nic ecleanup, one nit below.
> >
> > Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> >
> >> ---
> >>  include/linux/cache.h |  1 +
> >>  mm/sparse.c           | 19 ++++++++++++-------
> >>  2 files changed, 13 insertions(+), 7 deletions(-)
> >>
> >> diff --git a/include/linux/cache.h b/include/linux/cache.h
> >> index e69768f50d532..b6e857b985bca 100644
> >> --- a/include/linux/cache.h
> >> +++ b/include/linux/cache.h
> >> @@ -89,6 +89,7 @@
> >>   */
> >>  #ifndef INTERNODE_CACHE_SHIFT
> >>  #define INTERNODE_CACHE_SHIFT L1_CACHE_SHIFT
> >> +#define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)
> >
> > NIT: 1UL?
>
> I decided to replicate the existing
>
> arch/x86/include/asm/cache.h:#define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)
>
> If the shifted value would ever not fit into an int something would be
> going really wrong ;)

Yup, fair enough!

>
> Thanks!
>
> --
> Cheers,
>
> David

--
Cheers, Lorenzo

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

* Re: [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling
  2026-09-10 12:08       ` Oscar Salvador (SUSE)
@ 2026-09-10 13:33         ` David Hildenbrand (Arm)
  0 siblings, 0 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-10 13:33 UTC (permalink / raw)
  To: Oscar Salvador (SUSE)
  Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Kairui Song,
	Qi Zheng, Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner,
	Zi Yan, Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/10/26 14:08, Oscar Salvador (SUSE) wrote:
> On Thu, Sep 10, 2026 at 11:13:18AM +0200, David Hildenbrand (Arm) wrote:
>> If you have something consuming __highest_used_section_nr while concurrently
>> updating it, you might get torn reads/writes that mess up the value on the
>> reader side.
>>
>> For example, mm/compaction.c consuming __highest_used_section_nr.
> 
> Right, but I guess that if we get a 'wild' value, at least we are
> guarded by online_section_nr() performing the right thing?

I guess so, I was assuming the only real scenario would be us missing to process
certain sections (which would usually not be the end of the world). Getting
larger values is unlikely when tearing reads/writes I think.

-- 
Cheers,

David

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

* Re: [PATCH 03/12] mm/sparse: move initialization of section metadata to sparse_metadata_init()
  2026-09-09 13:32 ` [PATCH 03/12] mm/sparse: move initialization of section metadata to sparse_metadata_init() David Hildenbrand (Arm)
  2026-09-09 17:22   ` Oscar Salvador (SUSE)
@ 2026-09-10 13:43   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 13:43 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:56PM +0200, David Hildenbrand (Arm) wrote:
> Let's move the code responsible for initializing sparse metadata (usemap,
> memmap) into a helper. Cleanup the variable while at it (e.g.,
> "map_count").
>
> Drop the rather obvious code comments.
>
> No functional change intended.
>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Similar comment to last, the move screws up the diff a bit, but staring at
git-delta it looks ok and the renames are good so:

Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

> ---
>  mm/sparse.c | 43 ++++++++++++++++++++++---------------------
>  1 file changed, 22 insertions(+), 21 deletions(-)
>
> diff --git a/mm/sparse.c b/mm/sparse.c
> index 36e3d854febc5..a85a9c3840f6c 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -257,38 +257,39 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
>  	}
>  }
>
> +static void __init sparse_metadata_init(void)
> +{
> +	unsigned long start_section_nr = first_present_section_nr();
> +	int nid_begin = sparse_early_nid(__nr_to_section(start_section_nr));
> +	unsigned long section_nr, nr_sections = 1;
> +
> +	for_each_present_section_nr(start_section_nr + 1, section_nr) {
> +		const int nid = sparse_early_nid(__nr_to_section(section_nr));
> +
> +		if (nid == nid_begin) {
> +			nr_sections++;
> +			continue;
> +		}
> +		sparse_init_nid(nid_begin, start_section_nr, section_nr, nr_sections);
> +		nid_begin = nid;
> +		start_section_nr = section_nr;
> +		nr_sections = 1;
> +	}
> +	sparse_init_nid(nid_begin, start_section_nr, section_nr, nr_sections);
> +}
> +
>  /*
>   * Allocate the accumulated non-linear sections, allocate a mem_map
>   * for each and record the physical to section mapping.
>   */
>  void __init sparse_init(void)
>  {
> -	unsigned long pnum_end, pnum_begin, map_count = 1;
> -	int nid_begin;
> -
>  	if (compound_info_has_mask()) {
>  		VM_WARN_ON_ONCE(!IS_ALIGNED((unsigned long) pfn_to_page(0),
>  				    MAX_FOLIO_VMEMMAP_ALIGN));
>  	}
>
> -	pnum_begin = first_present_section_nr();
> -	nid_begin = sparse_early_nid(__nr_to_section(pnum_begin));
> -
> -	for_each_present_section_nr(pnum_begin + 1, pnum_end) {
> -		int nid = sparse_early_nid(__nr_to_section(pnum_end));
> -
> -		if (nid == nid_begin) {
> -			map_count++;
> -			continue;
> -		}
> -		/* Init node with sections in range [pnum_begin, pnum_end) */
> -		sparse_init_nid(nid_begin, pnum_begin, pnum_end, map_count);
> -		nid_begin = nid;
> -		pnum_begin = pnum_end;
> -		map_count = 1;
> -	}
> -	/* cover the last node */
> -	sparse_init_nid(nid_begin, pnum_begin, pnum_end, map_count);
> +	sparse_metadata_init();
>  	sparse_init_subsection_map();
>  	vmemmap_populate_print_last();
>  }
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 04/12] mm/sparse: rename and cleanup sparse_init_nid()
  2026-09-09 13:32 ` [PATCH 04/12] mm/sparse: rename and cleanup sparse_init_nid() David Hildenbrand (Arm)
  2026-09-10  7:41   ` Oscar Salvador (SUSE)
@ 2026-09-10 13:46   ` Lorenzo Stoakes (ARM)
  2026-09-10 14:29     ` David Hildenbrand (Arm)
  1 sibling, 1 reply; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 13:46 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:57PM +0200, David Hildenbrand (Arm) wrote:
> Let's rename it to "sparse_metadata_init_nid", avoid the "pnum" terminology
> and drop the function comment. Further, rename the "map" variable to
> "mem_map" for consistency with other functions.
>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

LGTM, one nit below.

Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

> ---
>  mm/sparse.c | 41 ++++++++++++++++++++---------------------
>  1 file changed, 20 insertions(+), 21 deletions(-)
>
> diff --git a/mm/sparse.c b/mm/sparse.c
> index a85a9c3840f6c..f84bfceb53060 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -222,37 +222,34 @@ void __weak __meminit vmemmap_populate_print_last(void)
>  {
>  }
>
> -/*
> - * Initialize sparse on a specific node. The node spans [pnum_begin, pnum_end)
> - * And number of present sections in this node is map_count.
> - */
> -static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
> -				   unsigned long pnum_end,
> -				   unsigned long map_count)
> +static void __init sparse_metadata_init_nid(int nid,
> +		unsigned long start_section_nr, unsigned long end_section_nr,
> +		unsigned long nr_sections)
>  {
> -	unsigned long pnum;
>  	struct mem_section_usage *usage;
> +	unsigned long section_nr;
>
> -	usage = memblock_alloc_node(map_count * mem_section_usage_size(),
> +	usage = memblock_alloc_node(nr_sections * mem_section_usage_size(),
>  				    SMP_CACHE_BYTES, nid);
>  	if (!usage)
>  		panic("Failed to allocate usemap for node %d\n", nid);
>
> -	for_each_present_section_nr(pnum_begin, pnum) {
> -		unsigned long pfn = section_nr_to_pfn(pnum);
> -		struct page *map;
> +	for_each_present_section_nr(start_section_nr, section_nr) {
> +		unsigned long pfn = section_nr_to_pfn(section_nr);

NIT: Could be const?

> +		struct page *mem_map;
>
> -		if (pnum >= pnum_end)
> +		if (section_nr >= end_section_nr)
>  			break;
>
> -		map = __populate_section_memmap(pfn, PAGES_PER_SECTION,
> -						nid, NULL, NULL);
> -		if (!map)
> -			panic("Failed to allocate memmap for section %lu\n", pnum);
> +		mem_map = __populate_section_memmap(pfn, PAGES_PER_SECTION, nid,
> +						    NULL, NULL);
> +		if (!mem_map)
> +			panic("Failed to allocate memmap for section %lu\n",
> +			      section_nr);
>  		memmap_boot_pages_add(section_nr_vmemmap_pages(pfn, PAGES_PER_SECTION,
>  							       NULL, NULL));
> -		sparse_init_one_section(__nr_to_section(pnum), pnum, map, usage,
> -					SECTION_IS_EARLY);
> +		sparse_init_one_section(__nr_to_section(section_nr), section_nr,
> +					mem_map, usage, SECTION_IS_EARLY);
>  		usage = (void *)usage + mem_section_usage_size();
>  	}
>  }
> @@ -270,12 +267,14 @@ static void __init sparse_metadata_init(void)
>  			nr_sections++;
>  			continue;
>  		}
> -		sparse_init_nid(nid_begin, start_section_nr, section_nr, nr_sections);
> +		sparse_metadata_init_nid(nid_begin, start_section_nr,
> +					 section_nr, nr_sections);
>  		nid_begin = nid;
>  		start_section_nr = section_nr;
>  		nr_sections = 1;
>  	}
> -	sparse_init_nid(nid_begin, start_section_nr, section_nr, nr_sections);
> +	sparse_metadata_init_nid(nid_begin, start_section_nr, section_nr,
> +				 nr_sections);
>  }
>
>  /*
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 05/12] mm/sparse: cleanup sparse_init_one_section()
  2026-09-09 13:32 ` [PATCH 05/12] mm/sparse: cleanup sparse_init_one_section() David Hildenbrand (Arm)
  2026-09-10  7:45   ` Oscar Salvador (SUSE)
@ 2026-09-10 13:47   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 13:47 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:58PM +0200, David Hildenbrand (Arm) wrote:
> Let's avoid the "pnum" terminology.
>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Yup it's gross! LGTM so:

Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

> ---
>  mm/sparse.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/mm/sparse.h b/mm/sparse.h
> index 049272aba84e5..744ae29002f5e 100644
> --- a/mm/sparse.h
> +++ b/mm/sparse.h
> @@ -90,7 +90,7 @@ void sparse_sections_init(void);
>  int sparse_index_init(unsigned long section_nr, int nid);
>
>  static inline void sparse_init_one_section(struct mem_section *ms,
> -		unsigned long pnum, struct page *mem_map,
> +		unsigned long section_nr, struct page *mem_map,
>  		struct mem_section_usage *usage, unsigned long flags)
>  {
>  	unsigned long coded_mem_map;
> @@ -102,7 +102,7 @@ static inline void sparse_init_one_section(struct mem_section *ms,
>  	 * page_to_pfn() on !CONFIG_SPARSEMEM_VMEMMAP can simply subtract it
>  	 * from the page pointer to obtain the PFN.
>  	 */
> -	coded_mem_map = (unsigned long)(mem_map - section_nr_to_pfn(pnum));
> +	coded_mem_map = (unsigned long)(mem_map - section_nr_to_pfn(section_nr));
>  	VM_WARN_ON_ONCE(coded_mem_map & ~SECTION_MAP_MASK);
>
>  	ms->section_mem_map &= ~SECTION_MAP_MASK;
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 06/12] mm/sparse: rename __highest_present_section_nr to __highest_used_section_nr
  2026-09-09 13:32 ` [PATCH 06/12] mm/sparse: rename __highest_present_section_nr to __highest_used_section_nr David Hildenbrand (Arm)
  2026-09-10  7:56   ` Oscar Salvador (SUSE)
@ 2026-09-10 13:49   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 13:49 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:32:59PM +0200, David Hildenbrand (Arm) wrote:
> In preparation for getting rid of SECTION_MARKED_PRESENT, rename
> __highest_present_section_nr and clarify the comment.
>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Seems reasonable so:

Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

> ---
>  include/linux/mmzone.h |  6 +++---
>  mm/compaction.c        |  2 +-
>  mm/sparse.c            | 12 ++++--------
>  mm/sparse.h            |  4 ++--
>  4 files changed, 10 insertions(+), 14 deletions(-)
>
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index c9ae7991a8b20..19296e8ef44f8 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -2170,7 +2170,7 @@ static inline struct mem_section *__pfn_to_section(unsigned long pfn)
>  	return __nr_to_section(pfn_to_section_nr(pfn));
>  }
>
> -extern unsigned long __highest_present_section_nr;
> +extern unsigned long __highest_used_section_nr;
>
>  static inline int subsection_map_index(unsigned long pfn)
>  {
> @@ -2269,7 +2269,7 @@ static inline unsigned long first_valid_pfn(unsigned long pfn, unsigned long end
>
>  	rcu_read_lock_sched();
>
> -	while (nr <= __highest_present_section_nr && pfn < end_pfn) {
> +	while (nr <= __highest_used_section_nr && pfn < end_pfn) {
>  		struct mem_section *ms = __pfn_to_section(pfn);
>
>  		if (valid_section(ms) &&
> @@ -2324,7 +2324,7 @@ static inline int pfn_in_present_section(unsigned long pfn)
>
>  static inline unsigned long next_present_section_nr(unsigned long section_nr)
>  {
> -	while (++section_nr <= __highest_present_section_nr) {
> +	while (++section_nr <= __highest_used_section_nr) {
>  		if (present_section_nr(section_nr))
>  			return section_nr;
>  	}
> diff --git a/mm/compaction.c b/mm/compaction.c
> index 4994e200bbecd..f1b2060eb2016 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -216,7 +216,7 @@ static unsigned long skip_offline_sections(unsigned long start_pfn)
>  	if (online_section_nr(start_nr))
>  		return 0;
>
> -	while (++start_nr <= __highest_present_section_nr) {
> +	while (++start_nr <= __highest_used_section_nr) {
>  		if (online_section_nr(start_nr))
>  			return section_nr_to_pfn(start_nr);
>  	}
> diff --git a/mm/sparse.c b/mm/sparse.c
> index f84bfceb53060..2b41ae36f20b8 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -164,15 +164,11 @@ static void __init mminit_validate_memmodel_limits(unsigned long *start_pfn,
>  }
>
>  /*
> - * There are a number of times that we loop over NR_MEM_SECTIONS,
> - * looking for section_present() on each.  But, when we have very
> - * large physical address spaces, NR_MEM_SECTIONS can also be
> - * very large which makes the loops quite long.
> - *
> - * Keeping track of this gives us an easy way to break out of
> - * those loops early.
> + * Looping over all memory sections is expensive, especially if NR_MEM_SECTIONS
> + * is large but only a fraction is actually used. Keep track of the highest
> + * section number we ever used.
>   */
> -unsigned long __highest_present_section_nr;
> +unsigned long __highest_used_section_nr;
>
>  static inline unsigned long first_present_section_nr(void)
>  {
> diff --git a/mm/sparse.h b/mm/sparse.h
> index 744ae29002f5e..7c5d82ceb7142 100644
> --- a/mm/sparse.h
> +++ b/mm/sparse.h
> @@ -114,8 +114,8 @@ static inline void sparse_init_one_section(struct mem_section *ms,
>  static inline void __section_mark_present(struct mem_section *ms,
>  		unsigned long section_nr)
>  {
> -	if (section_nr > __highest_present_section_nr)
> -		__highest_present_section_nr = section_nr;
> +	if (section_nr > __highest_used_section_nr)
> +		__highest_used_section_nr = section_nr;
>
>  	ms->section_mem_map |= SECTION_MARKED_PRESENT;
>  }
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 07/12] mm/sparse: remove pfn_in_present_section()
  2026-09-09 13:33 ` [PATCH 07/12] mm/sparse: remove pfn_in_present_section() David Hildenbrand (Arm)
  2026-09-10  7:59   ` Oscar Salvador (SUSE)
@ 2026-09-10 13:50   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 13:50 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:00PM +0200, David Hildenbrand (Arm) wrote:
> Unused, let's remove it.
>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

LGTM so:

Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

> ---
>  include/linux/mmzone.h | 10 ----------
>  1 file changed, 10 deletions(-)
>
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index 19296e8ef44f8..e0fac344f6ac2 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -2315,13 +2315,6 @@ static inline unsigned long next_valid_pfn(unsigned long pfn, unsigned long end_
>
>  #endif
>
> -static inline int pfn_in_present_section(unsigned long pfn)
> -{
> -	if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
> -		return 0;
> -	return present_section(__pfn_to_section(pfn));
> -}
> -
>  static inline unsigned long next_present_section_nr(unsigned long section_nr)
>  {
>  	while (++section_nr <= __highest_used_section_nr) {
> @@ -2351,9 +2344,6 @@ static inline unsigned long next_present_section_nr(unsigned long section_nr)
>  #else
>  #define pfn_to_nid(pfn)		(0)
>  #endif
> -
> -#else
> -#define pfn_in_present_section pfn_valid
>  #endif /* CONFIG_SPARSEMEM */
>
>  /*
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling
  2026-09-09 13:33 ` [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling David Hildenbrand (Arm)
  2026-09-09 14:44   ` David Hildenbrand (Arm)
  2026-09-10  8:33   ` Oscar Salvador (SUSE)
@ 2026-09-10 14:16   ` Lorenzo Stoakes (ARM)
  2026-09-10 14:29     ` David Hildenbrand (Arm)
  2 siblings, 1 reply; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 14:16 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:01PM +0200, David Hildenbrand (Arm) wrote:
> Let's move it to sparse_init_one_section(). However, to keep early
> boot processing working, we also have to initialize it in
> sparse_sections_init().

A why might be nice :)

I guess preparing for removal of __section_mark_present()?

Also good to have arguments as to why this is equivalent of previous
behaviour.

E.g. higher pfn = higher section nr so naturally the highest is the one you
end up wtih at the end of sparse_sections_init()?

>
> Should we use READ_ONCE/WRITE_ONCE with __highest_used_section_nr?
> Probably, something for another day.

It might be worth expanding this a bit. Do multiple threads read/write this
concurrently?

No functional change intended here or is one intended? :)

Before it was:

mm_core_init_early() -> sparse_sections_init() -> __section_mark_present()
                          sparse_add_section() -> __section_mark_present()

Now:

                                                 mm_core_init_early() -> sparse_sections_init() [early]
                                                 sparse_add_section() -> sparse_init_one_section()

But also called from mm_core_init_early():

sparse_init() -> sparse_metadata_init() -> sparse_metadata_init_nid() -> sparse_init_one_section()

Are both required?

Might be worth digging into why a bit here.


>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> ---
>  mm/sparse.c | 5 +++--
>  mm/sparse.h | 6 +++---
>  2 files changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/mm/sparse.c b/mm/sparse.c
> index 2b41ae36f20b8..2d0f2db34f4cf 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -177,7 +177,7 @@ static inline unsigned long first_present_section_nr(void)
>
>  void __init sparse_sections_init(void)
>  {
> -	unsigned long pfn, start_pfn, end_pfn;
> +	unsigned long pfn, start_pfn, end_pfn, section_nr;
>  	int i, nid;
>
>  	sparse_extreme_init();
> @@ -187,9 +187,9 @@ void __init sparse_sections_init(void)
>  		mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
>
>  		for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
> -			unsigned long section_nr = pfn_to_section_nr(pfn);
>  			struct mem_section *ms;
>
> +			section_nr = pfn_to_section_nr(pfn);
>  			sparse_index_init(section_nr, nid);
>  			ms = __nr_to_section(section_nr);
>  			if (ms->section_mem_map)
> @@ -201,6 +201,7 @@ void __init sparse_sections_init(void)
>  			__section_mark_present(ms, section_nr);
>  		}
>  	}
> +	__highest_used_section_nr = section_nr;
>  }
>
>  #ifndef CONFIG_SPARSEMEM_VMEMMAP
> diff --git a/mm/sparse.h b/mm/sparse.h
> index 7c5d82ceb7142..a3af4967fd5c5 100644
> --- a/mm/sparse.h
> +++ b/mm/sparse.h
> @@ -97,6 +97,9 @@ static inline void sparse_init_one_section(struct mem_section *ms,
>
>  	BUILD_BUG_ON(SECTION_MAP_LAST_BIT > PFN_SECTION_SHIFT);
>
> +	if (section_nr > __highest_used_section_nr)
> +		__highest_used_section_nr = section_nr;
> +

Could also be:

	section_nr = max(section_nr, __highest_used_section_nr);

But not a big deal.


>  	/*
>  	 * We encode the start PFN of the section into the mem_map such that
>  	 * page_to_pfn() on !CONFIG_SPARSEMEM_VMEMMAP can simply subtract it
> @@ -114,9 +117,6 @@ static inline void sparse_init_one_section(struct mem_section *ms,
>  static inline void __section_mark_present(struct mem_section *ms,
>  		unsigned long section_nr)
>  {
> -	if (section_nr > __highest_used_section_nr)
> -		__highest_used_section_nr = section_nr;
> -
>  	ms->section_mem_map |= SECTION_MARKED_PRESENT;
>  }
>
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling
  2026-09-10 14:16   ` Lorenzo Stoakes (ARM)
@ 2026-09-10 14:29     ` David Hildenbrand (Arm)
  2026-09-10 14:51       ` Lorenzo Stoakes (ARM)
  0 siblings, 1 reply; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-10 14:29 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/10/26 16:16, Lorenzo Stoakes (ARM) wrote:
> On Wed, Sep 09, 2026 at 03:33:01PM +0200, David Hildenbrand (Arm) wrote:
>> Let's move it to sparse_init_one_section(). However, to keep early
>> boot processing working, we also have to initialize it in
>> sparse_sections_init().
> 
> A why might be nice :)

Agreed, I'll mention that.

> 
> I guess preparing for removal of __section_mark_present()?
> 

Right intuition :)

> Also good to have arguments as to why this is equivalent of previous
> behaviour.
> 
> E.g. higher pfn = higher section nr so naturally the highest is the one you
> end up wtih at the end of sparse_sections_init()?

We go over all sections, just earlier.

> 
>>
>> Should we use READ_ONCE/WRITE_ONCE with __highest_used_section_nr?
>> Probably, something for another day.
> 
> It might be worth expanding this a bit. Do multiple threads read/write this
> concurrently?

Hah, I'll probably just drop it. I was just stumbling over readers vs.
concurrent updates and thought "that looks suspicious".

> 
> No functional change intended here or is one intended? :)
> 

Certainly no change intended ;)

> Before it was:
> 
> mm_core_init_early() -> sparse_sections_init() -> __section_mark_present()
>                           sparse_add_section() -> __section_mark_present()
> 
> Now:
> 
>                                                  mm_core_init_early() -> sparse_sections_init() [early]
>                                                  sparse_add_section() -> sparse_init_one_section()
> 
> But also called from mm_core_init_early():
> 
> sparse_init() -> sparse_metadata_init() -> sparse_metadata_init_nid() -> sparse_init_one_section()
> 
> Are both required?

sparse_metadata_init() relies on __highest_used_section_nr in the
for_each_early_section_nr / for_each_present_section_nr, so it is required.

I could probable move the update on the hotplug side into sparse_add_section()
instead!

> 
> 
>>
>> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
>> ---
>>  mm/sparse.c | 5 +++--
>>  mm/sparse.h | 6 +++---
>>  2 files changed, 6 insertions(+), 5 deletions(-)
>>
>> diff --git a/mm/sparse.c b/mm/sparse.c
>> index 2b41ae36f20b8..2d0f2db34f4cf 100644
>> --- a/mm/sparse.c
>> +++ b/mm/sparse.c
>> @@ -177,7 +177,7 @@ static inline unsigned long first_present_section_nr(void)
>>
>>  void __init sparse_sections_init(void)
>>  {
>> -	unsigned long pfn, start_pfn, end_pfn;
>> +	unsigned long pfn, start_pfn, end_pfn, section_nr;
>>  	int i, nid;
>>
>>  	sparse_extreme_init();
>> @@ -187,9 +187,9 @@ void __init sparse_sections_init(void)
>>  		mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
>>
>>  		for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
>> -			unsigned long section_nr = pfn_to_section_nr(pfn);
>>  			struct mem_section *ms;
>>
>> +			section_nr = pfn_to_section_nr(pfn);
>>  			sparse_index_init(section_nr, nid);
>>  			ms = __nr_to_section(section_nr);
>>  			if (ms->section_mem_map)
>> @@ -201,6 +201,7 @@ void __init sparse_sections_init(void)
>>  			__section_mark_present(ms, section_nr);
>>  		}
>>  	}
>> +	__highest_used_section_nr = section_nr;
>>  }
>>
>>  #ifndef CONFIG_SPARSEMEM_VMEMMAP
>> diff --git a/mm/sparse.h b/mm/sparse.h
>> index 7c5d82ceb7142..a3af4967fd5c5 100644
>> --- a/mm/sparse.h
>> +++ b/mm/sparse.h
>> @@ -97,6 +97,9 @@ static inline void sparse_init_one_section(struct mem_section *ms,
>>
>>  	BUILD_BUG_ON(SECTION_MAP_LAST_BIT > PFN_SECTION_SHIFT);
>>
>> +	if (section_nr > __highest_used_section_nr)
>> +		__highest_used_section_nr = section_nr;
>> +
> 
> Could also be:
> 
> 	section_nr = max(section_nr, __highest_used_section_nr);

Ack!

-- 
Cheers,

David

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

* Re: [PATCH 04/12] mm/sparse: rename and cleanup sparse_init_nid()
  2026-09-10 13:46   ` Lorenzo Stoakes (ARM)
@ 2026-09-10 14:29     ` David Hildenbrand (Arm)
  0 siblings, 0 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-10 14:29 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/10/26 15:46, Lorenzo Stoakes (ARM) wrote:
> On Wed, Sep 09, 2026 at 03:32:57PM +0200, David Hildenbrand (Arm) wrote:
>> Let's rename it to "sparse_metadata_init_nid", avoid the "pnum" terminology
>> and drop the function comment. Further, rename the "map" variable to
>> "mem_map" for consistency with other functions.
>>
>> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> 
> LGTM, one nit below.
> 
> Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> 
>> ---
>>  mm/sparse.c | 41 ++++++++++++++++++++---------------------
>>  1 file changed, 20 insertions(+), 21 deletions(-)
>>
>> diff --git a/mm/sparse.c b/mm/sparse.c
>> index a85a9c3840f6c..f84bfceb53060 100644
>> --- a/mm/sparse.c
>> +++ b/mm/sparse.c
>> @@ -222,37 +222,34 @@ void __weak __meminit vmemmap_populate_print_last(void)
>>  {
>>  }
>>
>> -/*
>> - * Initialize sparse on a specific node. The node spans [pnum_begin, pnum_end)
>> - * And number of present sections in this node is map_count.
>> - */
>> -static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
>> -				   unsigned long pnum_end,
>> -				   unsigned long map_count)
>> +static void __init sparse_metadata_init_nid(int nid,
>> +		unsigned long start_section_nr, unsigned long end_section_nr,
>> +		unsigned long nr_sections)
>>  {
>> -	unsigned long pnum;
>>  	struct mem_section_usage *usage;
>> +	unsigned long section_nr;
>>
>> -	usage = memblock_alloc_node(map_count * mem_section_usage_size(),
>> +	usage = memblock_alloc_node(nr_sections * mem_section_usage_size(),
>>  				    SMP_CACHE_BYTES, nid);
>>  	if (!usage)
>>  		panic("Failed to allocate usemap for node %d\n", nid);
>>
>> -	for_each_present_section_nr(pnum_begin, pnum) {
>> -		unsigned long pfn = section_nr_to_pfn(pnum);
>> -		struct page *map;
>> +	for_each_present_section_nr(start_section_nr, section_nr) {
>> +		unsigned long pfn = section_nr_to_pfn(section_nr);
> 
> NIT: Could be const?

ack!

-- 
Cheers,

David

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

* Re: [PATCH 02/12] mm/sparse: refactor sparse_sections_init()
  2026-09-10 13:29   ` Lorenzo Stoakes (ARM)
@ 2026-09-10 14:30     ` David Hildenbrand (Arm)
  2026-09-10 14:38       ` Lorenzo Stoakes (ARM)
  0 siblings, 1 reply; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-10 14:30 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/10/26 15:29, Lorenzo Stoakes (ARM) wrote:
> On Wed, Sep 09, 2026 at 03:32:55PM +0200, David Hildenbrand (Arm) wrote:
>> memory_present() really identifies+prepares all early sections so the
>> initialization in sparse_init() can properly iterating them to
>> initialize metadata.
>>
>> Let's just inline memory_present() into sparse_sections_init() and
>> cleaning up the code a bit while at it: make it clear that we are operating
>> on pfns.
>>
>> Note that we call set_section_nid() now only if the section
>> was not already created earlier. Now, there is no more inconsistency
>> between what we (temporarily) store in ms->section_mem_map and what
>> we store in our section->nid array.
>>
>> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> 
> In general please keep move/refactor steps separate. It makes it harder to
> review when two things are going on at one time.
> 
> But I guess in this case the diff wouldn't be that different.

Yeah, I actually want back and forth here and decided to keep it simple.

> 
> Anyway seems reasonable so:
> 
> Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Thanks!

> 
>> ---
>>  mm/sparse.c | 41 +++++++++++++++++------------------------
>>  1 file changed, 17 insertions(+), 24 deletions(-)
>>
>> diff --git a/mm/sparse.c b/mm/sparse.c
>> index 6a6d258862904..36e3d854febc5 100644
>> --- a/mm/sparse.c
>> +++ b/mm/sparse.c
>> @@ -179,22 +179,27 @@ static inline unsigned long first_present_section_nr(void)
>>  	return next_present_section_nr(-1);
>>  }
>>
>> -/* Record a memory area against a node. */
>> -static void __init memory_present(int nid, unsigned long start, unsigned long end)
>> +void __init sparse_sections_init(void)
>>  {
>> -	unsigned long pfn;
>> +	unsigned long pfn, start_pfn, end_pfn;
>> +	int i, nid;
>> +
>> +	sparse_extreme_init();
>>
>> -	start &= PAGE_SECTION_MASK;
>> -	mminit_validate_memmodel_limits(&start, &end);
>> -	for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
>> -		unsigned long section_nr = pfn_to_section_nr(pfn);
>> -		struct mem_section *ms;
>> +	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
>> +		start_pfn &= PAGE_SECTION_MASK;
>> +		mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
>>
>> -		sparse_index_init(section_nr, nid);
>> -		set_section_nid(section_nr, nid);
>> +		for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
>> +			unsigned long section_nr = pfn_to_section_nr(pfn);
>> +			struct mem_section *ms;
>>
>> -		ms = __nr_to_section(section_nr);
>> -		if (!ms->section_mem_map) {
>> +			sparse_index_init(section_nr, nid);
>> +			ms = __nr_to_section(section_nr);
>> +			if (ms->section_mem_map)
>> +				continue;
>> +
>> +			set_section_nid(section_nr, nid);
> 
> So the main change seems to be calling set_section_nid() only if
> !ms->section_mem_map (and obv. calculating ms earlier), as described in the
> commit msg.

Yes! I also played with having that in a standalone patch but judged that it's
not really worth it. I can move it to a separate patch if you think it would be
better!

-- 
Cheers,

David

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

* Re: [PATCH 09/12] mm/sparse: remove SECTION_MARKED_PRESENT
  2026-09-09 13:33 ` [PATCH 09/12] mm/sparse: remove SECTION_MARKED_PRESENT David Hildenbrand (Arm)
  2026-09-10 12:15   ` Oscar Salvador (SUSE)
@ 2026-09-10 14:32   ` Lorenzo Stoakes (ARM)
  2026-09-10 15:11     ` David Hildenbrand (Arm)
  1 sibling, 1 reply; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 14:32 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:02PM +0200, David Hildenbrand (Arm) wrote:
> All present section iterators run before memory hotplug added any
> further memory sections, Therefore, we can simply use the SECTION_IS_EARLY
> flag by setting that flag earlier in sparse_prepare_early_sections().

Hmm? sparse_prepare_early_sections() doesn't seem to be a function that exists?

Do you mean sparse_sections_init()?

>
> Get rid of SECTION_MARKED_PRESENT entirely and rename
> for_each_present_section_nr() to for_each_early_section_nr().
>
> Also update the gdb script to use the updated value for
> SECTION_IS_EARLY.

The change seems fine.

>
> No functional change intended.
>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

With commit msg updated:

Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

One small question type comment below.

> ---
>  drivers/base/memory.c   |  2 +-
>  include/linux/mmzone.h  | 27 ++++++++++-----------------
>  mm/sparse-vmemmap.c     |  1 -
>  mm/sparse.c             | 17 ++++++++---------
>  mm/sparse.h             |  6 ------
>  scripts/gdb/linux/mm.py |  2 +-
>  6 files changed, 20 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/base/memory.c b/drivers/base/memory.c
> index 5eead3346f1e3..b0338de2f1d82 100644
> --- a/drivers/base/memory.c
> +++ b/drivers/base/memory.c
> @@ -972,7 +972,7 @@ void __init memory_dev_init(void)
>  	 * block so that it can be covered.
>  	 */
>  	block_id = ULONG_MAX;
> -	for_each_present_section_nr(0, nr) {
> +	for_each_early_section_nr(0, nr) {
>  		if (block_id != ULONG_MAX && memory_block_id(nr) == block_id)
>  			continue;
>
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index e0fac344f6ac2..62cff59dd80c4 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -2084,7 +2084,6 @@ static inline struct mem_section *__nr_to_section(unsigned long nr)
>   * accommodate SECTION_MAP_LAST_BIT. We use BUILD_BUG_ON() to ensure this.
>   */
>  enum {
> -	SECTION_MARKED_PRESENT_BIT,
>  	SECTION_HAS_MEM_MAP_BIT,
>  	SECTION_IS_ONLINE_BIT,
>  	SECTION_IS_EARLY_BIT,
> @@ -2094,7 +2093,6 @@ enum {
>  	SECTION_MAP_LAST_BIT,
>  };
>
> -#define SECTION_MARKED_PRESENT		BIT(SECTION_MARKED_PRESENT_BIT)
>  #define SECTION_HAS_MEM_MAP		BIT(SECTION_HAS_MEM_MAP_BIT)
>  #define SECTION_IS_ONLINE		BIT(SECTION_IS_ONLINE_BIT)
>  #define SECTION_IS_EARLY		BIT(SECTION_IS_EARLY_BIT)
> @@ -2111,16 +2109,6 @@ static inline struct page *__section_mem_map_addr(struct mem_section *section)
>  	return (struct page *)map;
>  }
>
> -static inline int present_section(const struct mem_section *section)
> -{
> -	return (section && (section->section_mem_map & SECTION_MARKED_PRESENT));
> -}
> -
> -static inline int present_section_nr(unsigned long nr)
> -{
> -	return present_section(__nr_to_section(nr));
> -}
> -
>  static inline int valid_section(const struct mem_section *section)
>  {
>  	return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP));
> @@ -2136,6 +2124,11 @@ static inline int valid_section_nr(unsigned long nr)
>  	return valid_section(__nr_to_section(nr));
>  }
>
> +static inline int early_section_nr(unsigned long nr)
> +{
> +	return early_section(__nr_to_section(nr));
> +}
> +
>  static inline int online_section(const struct mem_section *section)
>  {
>  	return (section && (section->section_mem_map & SECTION_IS_ONLINE));
> @@ -2315,20 +2308,20 @@ static inline unsigned long next_valid_pfn(unsigned long pfn, unsigned long end_
>
>  #endif
>
> -static inline unsigned long next_present_section_nr(unsigned long section_nr)
> +static inline unsigned long next_early_section_nr(unsigned long section_nr)
>  {
>  	while (++section_nr <= __highest_used_section_nr) {
> -		if (present_section_nr(section_nr))
> +		if (early_section_nr(section_nr))
>  			return section_nr;
>  	}
>
>  	return -1;
>  }
>
> -#define for_each_present_section_nr(start, section_nr)		\
> -	for (section_nr = next_present_section_nr(start - 1);	\
> +#define for_each_early_section_nr(start, section_nr)		\
> +	for (section_nr = next_early_section_nr(start - 1);	\
>  	     section_nr != -1;					\
> -	     section_nr = next_present_section_nr(section_nr))
> +	     section_nr = next_early_section_nr(section_nr))
>
>  /*
>   * These are _only_ used during initialisation, therefore they
> diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
> index e62e6aa07f126..5aba058df6b67 100644
> --- a/mm/sparse-vmemmap.c
> +++ b/mm/sparse-vmemmap.c
> @@ -890,7 +890,6 @@ int __meminit sparse_add_section(int nid, unsigned long start_pfn,
>  	page_init_poison(memmap, sizeof(struct page) * nr_pages);
>
>  	ms = __nr_to_section(section_nr);
> -	__section_mark_present(ms, section_nr);
>
>  	/* Align memmap to section boundary in the subsection case */
>  	if (section_nr_to_pfn(section_nr) != start_pfn)
> diff --git a/mm/sparse.c b/mm/sparse.c
> index 2d0f2db34f4cf..344acaaed94db 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -170,13 +170,14 @@ static void __init mminit_validate_memmodel_limits(unsigned long *start_pfn,
>   */
>  unsigned long __highest_used_section_nr;
>
> -static inline unsigned long first_present_section_nr(void)
> +static inline unsigned long first_early_section_nr(void)
>  {
> -	return next_present_section_nr(-1);
> +	return next_early_section_nr(-1);
>  }
>
>  void __init sparse_sections_init(void)
>  {
> +	const unsigned long flags = SECTION_IS_EARLY | SECTION_IS_ONLINE;
>  	unsigned long pfn, start_pfn, end_pfn, section_nr;
>  	int i, nid;
>
> @@ -196,9 +197,7 @@ void __init sparse_sections_init(void)
>  				continue;
>
>  			set_section_nid(section_nr, nid);
> -			ms->section_mem_map = sparse_encode_early_nid(nid) |
> -							SECTION_IS_ONLINE;
> -			__section_mark_present(ms, section_nr);
> +			ms->section_mem_map = sparse_encode_early_nid(nid) | flags;
>  		}
>  	}
>  	__highest_used_section_nr = section_nr;
> @@ -231,7 +230,7 @@ static void __init sparse_metadata_init_nid(int nid,
>  	if (!usage)
>  		panic("Failed to allocate usemap for node %d\n", nid);
>
> -	for_each_present_section_nr(start_section_nr, section_nr) {
> +	for_each_early_section_nr(start_section_nr, section_nr) {
>  		unsigned long pfn = section_nr_to_pfn(section_nr);
>  		struct page *mem_map;
>
> @@ -246,18 +245,18 @@ static void __init sparse_metadata_init_nid(int nid,
>  		memmap_boot_pages_add(section_nr_vmemmap_pages(pfn, PAGES_PER_SECTION,
>  							       NULL, NULL));
>  		sparse_init_one_section(__nr_to_section(section_nr), section_nr,
> -					mem_map, usage, SECTION_IS_EARLY);
> +					mem_map, usage, 0);
>  		usage = (void *)usage + mem_section_usage_size();
>  	}
>  }
>
>  static void __init sparse_metadata_init(void)
>  {
> -	unsigned long start_section_nr = first_present_section_nr();
> +	unsigned long start_section_nr = first_early_section_nr();
>  	int nid_begin = sparse_early_nid(__nr_to_section(start_section_nr));
>  	unsigned long section_nr, nr_sections = 1;
>
> -	for_each_present_section_nr(start_section_nr + 1, section_nr) {
> +	for_each_early_section_nr(start_section_nr + 1, section_nr) {
>  		const int nid = sparse_early_nid(__nr_to_section(section_nr));
>
>  		if (nid == nid_begin) {
> diff --git a/mm/sparse.h b/mm/sparse.h
> index a3af4967fd5c5..03351f2467e34 100644
> --- a/mm/sparse.h
> +++ b/mm/sparse.h
> @@ -114,12 +114,6 @@ static inline void sparse_init_one_section(struct mem_section *ms,
>  	ms->usage = usage;
>  }
>
> -static inline void __section_mark_present(struct mem_section *ms,
> -		unsigned long section_nr)
> -{
> -	ms->section_mem_map |= SECTION_MARKED_PRESENT;
> -}
> -
>  static inline size_t mem_section_usage_size(void)
>  {
>  	return struct_size_t(struct mem_section_usage, pageblock_flags,
> diff --git a/scripts/gdb/linux/mm.py b/scripts/gdb/linux/mm.py
> index 193a88d763abf..73d637d28c8e6 100644
> --- a/scripts/gdb/linux/mm.py
> +++ b/scripts/gdb/linux/mm.py
> @@ -76,7 +76,7 @@ class x86_page_ops():
>              self.SECTION_IS_EARLY = 1 << int(gdb.parse_and_eval('SECTION_IS_EARLY_BIT'))
>          except:
>              self.SECTION_HAS_MEM_MAP = 1 << 0
> -            self.SECTION_IS_EARLY = 1 << 3
> +            self.SECTION_IS_EARLY = 1 << 2

Seems a bit strage given the code is:

        try:
            self.SECTION_HAS_MEM_MAP = 1 << int(gdb.parse_and_eval('SECTION_HAS_MEM_MAP_BIT'))
            self.SECTION_IS_EARLY = 1 << int(gdb.parse_and_eval('SECTION_IS_EARLY_BIT'))
        except:
            self.SECTION_HAS_MEM_MAP = 1 << 0
            self.SECTION_IS_EARLY = 1 << 2

Whereas other variables must be available with no try, e.g.:

        self.PAGE_OFFSET = int(gdb.parse_and_eval("page_offset_base"))
        self.VMEMMAP_START = int(gdb.parse_and_eval("vmemmap_base"))
        self.PHYS_BASE = int(gdb.parse_and_eval("(unsigned long) phys_base"))

etc.

Is there some weirdness with gdb? Or is it maybe because there are some configs
without these symbols maybe?

>
>          self.SUBSECTION_SHIFT = 21
>          self.PAGES_PER_SUBSECTION = 1 << (self.SUBSECTION_SHIFT - self.PAGE_SHIFT)
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 10/12] mm/sparse: remove flags parameter from sparse_init_one_section()
  2026-09-09 13:33 ` [PATCH 10/12] mm/sparse: remove flags parameter from sparse_init_one_section() David Hildenbrand (Arm)
  2026-09-10 12:34   ` Oscar Salvador (SUSE)
@ 2026-09-10 14:34   ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 14:34 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:03PM +0200, David Hildenbrand (Arm) wrote:
> Unused, let's remove it.

Might be worth saying because of the changes ;)

>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

But this is a nice change, always good to remove params/code if possible... :)

Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>


> ---
>  mm/sparse-vmemmap.c | 2 +-
>  mm/sparse.c         | 2 +-
>  mm/sparse.h         | 5 ++---
>  3 files changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
> index 5aba058df6b67..25d3472972363 100644
> --- a/mm/sparse-vmemmap.c
> +++ b/mm/sparse-vmemmap.c
> @@ -894,7 +894,7 @@ int __meminit sparse_add_section(int nid, unsigned long start_pfn,
>  	/* Align memmap to section boundary in the subsection case */
>  	if (section_nr_to_pfn(section_nr) != start_pfn)
>  		memmap = pfn_to_page(section_nr_to_pfn(section_nr));
> -	sparse_init_one_section(ms, section_nr, memmap, ms->usage, 0);
> +	sparse_init_one_section(ms, section_nr, memmap, ms->usage);
>
>  	return 0;
>  }
> diff --git a/mm/sparse.c b/mm/sparse.c
> index 344acaaed94db..d2e7c21319e27 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -245,7 +245,7 @@ static void __init sparse_metadata_init_nid(int nid,
>  		memmap_boot_pages_add(section_nr_vmemmap_pages(pfn, PAGES_PER_SECTION,
>  							       NULL, NULL));
>  		sparse_init_one_section(__nr_to_section(section_nr), section_nr,
> -					mem_map, usage, 0);
> +					mem_map, usage);
>  		usage = (void *)usage + mem_section_usage_size();
>  	}
>  }
> diff --git a/mm/sparse.h b/mm/sparse.h
> index 03351f2467e34..f45dd280db6ff 100644
> --- a/mm/sparse.h
> +++ b/mm/sparse.h
> @@ -91,7 +91,7 @@ int sparse_index_init(unsigned long section_nr, int nid);
>
>  static inline void sparse_init_one_section(struct mem_section *ms,
>  		unsigned long section_nr, struct page *mem_map,
> -		struct mem_section_usage *usage, unsigned long flags)
> +		struct mem_section_usage *usage)
>  {
>  	unsigned long coded_mem_map;
>
> @@ -109,8 +109,7 @@ static inline void sparse_init_one_section(struct mem_section *ms,
>  	VM_WARN_ON_ONCE(coded_mem_map & ~SECTION_MAP_MASK);
>
>  	ms->section_mem_map &= ~SECTION_MAP_MASK;
> -	ms->section_mem_map |= coded_mem_map;
> -	ms->section_mem_map |= flags | SECTION_HAS_MEM_MAP;
> +	ms->section_mem_map |= coded_mem_map | SECTION_HAS_MEM_MAP;
>  	ms->usage = usage;
>  }
>
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 02/12] mm/sparse: refactor sparse_sections_init()
  2026-09-10 14:30     ` David Hildenbrand (Arm)
@ 2026-09-10 14:38       ` Lorenzo Stoakes (ARM)
  0 siblings, 0 replies; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 14:38 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Thu, Sep 10, 2026 at 04:30:43PM +0200, David Hildenbrand (Arm) wrote:
> On 9/10/26 15:29, Lorenzo Stoakes (ARM) wrote:
> > On Wed, Sep 09, 2026 at 03:32:55PM +0200, David Hildenbrand (Arm) wrote:
> >> memory_present() really identifies+prepares all early sections so the
> >> initialization in sparse_init() can properly iterating them to
> >> initialize metadata.
> >>
> >> Let's just inline memory_present() into sparse_sections_init() and
> >> cleaning up the code a bit while at it: make it clear that we are operating
> >> on pfns.
> >>
> >> Note that we call set_section_nid() now only if the section
> >> was not already created earlier. Now, there is no more inconsistency
> >> between what we (temporarily) store in ms->section_mem_map and what
> >> we store in our section->nid array.
> >>
> >> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> >
> > In general please keep move/refactor steps separate. It makes it harder to
> > review when two things are going on at one time.
> >
> > But I guess in this case the diff wouldn't be that different.
>
> Yeah, I actually want back and forth here and decided to keep it simple.

Yeah, this one's a bit of a blurry line but I think fine as it is!

>
> >
> > Anyway seems reasonable so:
> >
> > Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
>
> Thanks!
>
> >
> >> ---
> >>  mm/sparse.c | 41 +++++++++++++++++------------------------
> >>  1 file changed, 17 insertions(+), 24 deletions(-)
> >>
> >> diff --git a/mm/sparse.c b/mm/sparse.c
> >> index 6a6d258862904..36e3d854febc5 100644
> >> --- a/mm/sparse.c
> >> +++ b/mm/sparse.c
> >> @@ -179,22 +179,27 @@ static inline unsigned long first_present_section_nr(void)
> >>  	return next_present_section_nr(-1);
> >>  }
> >>
> >> -/* Record a memory area against a node. */
> >> -static void __init memory_present(int nid, unsigned long start, unsigned long end)
> >> +void __init sparse_sections_init(void)
> >>  {
> >> -	unsigned long pfn;
> >> +	unsigned long pfn, start_pfn, end_pfn;
> >> +	int i, nid;
> >> +
> >> +	sparse_extreme_init();
> >>
> >> -	start &= PAGE_SECTION_MASK;
> >> -	mminit_validate_memmodel_limits(&start, &end);
> >> -	for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
> >> -		unsigned long section_nr = pfn_to_section_nr(pfn);
> >> -		struct mem_section *ms;
> >> +	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
> >> +		start_pfn &= PAGE_SECTION_MASK;
> >> +		mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
> >>
> >> -		sparse_index_init(section_nr, nid);
> >> -		set_section_nid(section_nr, nid);
> >> +		for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
> >> +			unsigned long section_nr = pfn_to_section_nr(pfn);
> >> +			struct mem_section *ms;
> >>
> >> -		ms = __nr_to_section(section_nr);
> >> -		if (!ms->section_mem_map) {
> >> +			sparse_index_init(section_nr, nid);
> >> +			ms = __nr_to_section(section_nr);
> >> +			if (ms->section_mem_map)
> >> +				continue;
> >> +
> >> +			set_section_nid(section_nr, nid);
> >
> > So the main change seems to be calling set_section_nid() only if
> > !ms->section_mem_map (and obv. calculating ms earlier), as described in the
> > commit msg.
>
> Yes! I also played with having that in a standalone patch but judged that it's
> not really worth it. I can move it to a separate patch if you think it would be
> better!

No need, not really a big diff delta and you call it out in the commit msg!

>
> --
> Cheers,
>
> David

--
Cheers, Lorenzo

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

* Re: [PATCH 11/12] fs/proc/page: clarify comment in get_max_dump_pfn()
  2026-09-09 13:33 ` [PATCH 11/12] fs/proc/page: clarify comment in get_max_dump_pfn() David Hildenbrand (Arm)
  2026-09-10 12:46   ` Oscar Salvador (SUSE)
@ 2026-09-10 14:41   ` Lorenzo Stoakes (ARM)
  2026-09-10 15:14     ` David Hildenbrand (Arm)
  1 sibling, 1 reply; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 14:41 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:04PM +0200, David Hildenbrand (Arm) wrote:
> pfn_to_online_page() will only succeed on some PFNs within the same
> section, not necessarily all. Let's make that clearer.
>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

Nit on comment below, but LGTM so:

Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

> ---
>  fs/proc/page.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/fs/proc/page.c b/fs/proc/page.c
> index 260772b20bd99..6856ff3e3cf28 100644
> --- a/fs/proc/page.c
> +++ b/fs/proc/page.c
> @@ -31,10 +31,9 @@ static inline unsigned long get_max_dump_pfn(void)
>  {
>  #ifdef CONFIG_SPARSEMEM
>  	/*
> -	 * The memmap of early sections is completely populated and marked
> -	 * online even if max_pfn does not fall on a section boundary -
> -	 * pfn_to_online_page() will succeed on all pages. Allow inspecting
> -	 * these memmaps.
> +	 * If max_pfn does not fall on a section boundary, pfn_to_online_page()
> +	 * can succeed on PFNs beyond max_pfn within the same section. Allow
> +	 * inspecting these memmaps.

'Allow inspection of' these memmaps is clearer I think. But this odd turn of
phrase existed before this change also :)

>  	 */
>  	return round_up(max_pfn, PAGES_PER_SECTION);
>  #else
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 12/12] mm/memory_hotplug: drop CONFIG_HAVE_ARCH_PFN_VALID handling from pfn_to_online_page()
  2026-09-09 13:33 ` [PATCH 12/12] mm/memory_hotplug: drop CONFIG_HAVE_ARCH_PFN_VALID handling from pfn_to_online_page() David Hildenbrand (Arm)
@ 2026-09-10 14:47   ` Lorenzo Stoakes (ARM)
  2026-09-10 15:15     ` David Hildenbrand (Arm)
  0 siblings, 1 reply; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 14:47 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Wed, Sep 09, 2026 at 03:33:05PM +0200, David Hildenbrand (Arm) wrote:
> Drop CONFIG_HAVE_ARCH_PFN_VALID handling, as CONFIG_HAVE_ARCH_PFN_VALID
> is never used with CONFIG_MEMORY_HOTPLUG, as the latter depends on
> CONFIG_SPARSEMEM_VMEMMAP. Make sure it stays that way.

So argument is:

mm/Makefile:

memory-hotplug-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o

Is memory_hotplug.c even compiled at all?

mm/Kconfig:

menuconfig MEMORY_HOTPLUG
	bool "Memory hotplug"
	select MEMORY_ISOLATION
	depends on SPARSEMEM_VMEMMAP
	depends on ARCH_ENABLE_MEMORY_HOTPLUG
	depends on 64BIT
	select NUMA_KEEP_MEMINFO if NUMA

$ cd arch
$ rg HAVE_ARCH_PFN_VALID
Kconfig
1762:config HAVE_ARCH_PFN_VALID

arm/Kconfig
94:	select HAVE_ARCH_PFN_VALID

arm/mm/init.c
121:#ifdef CONFIG_HAVE_ARCH_PFN_VALID

arm/include/asm/page.h
178:#ifdef CONFIG_HAVE_ARCH_PFN_VALID

m68k/Kconfig.cpu
23:	select HAVE_ARCH_PFN_VALID
40:	select HAVE_ARCH_PFN_VALID

arc/Kconfig
463:	select HAVE_ARCH_PFN_VALID

All of arm, m68k and arc are 32-bit arches so by definition MEMORY_HOTPLUG
can't be selected.

>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

So LGTM and:

Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

> ---
>  mm/memory_hotplug.c | 9 ++-------
>  1 file changed, 2 insertions(+), 7 deletions(-)
>
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index b428da66d279c..58ce35cb48f57 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
> @@ -344,6 +344,8 @@ struct page *pfn_to_online_page(unsigned long pfn)
>  	struct dev_pagemap *pgmap;
>  	struct mem_section *ms;
>
> +	BUILD_BUG_ON(IS_ENABLED(CONFIG_HAVE_ARCH_PFN_VALID));

Haha nicest way of removing some later code I've seen. Just make it not compile
if such a thing happens :)

> +
>  	if (nr >= NR_MEM_SECTIONS)
>  		return NULL;
>
> @@ -351,13 +353,6 @@ struct page *pfn_to_online_page(unsigned long pfn)
>  	if (!online_section(ms))
>  		return NULL;
>
> -	/*
> -	 * Save some code text when online_section() +
> -	 * pfn_section_valid() are sufficient.
> -	 */
> -	if (IS_ENABLED(CONFIG_HAVE_ARCH_PFN_VALID) && !pfn_valid(pfn))
> -		return NULL;
> -
>  	if (!pfn_section_valid(ms, pfn))
>  		return NULL;
>
>
> --
> 2.43.0
>

--
Cheers, Lorenzo

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

* Re: [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling
  2026-09-10 14:29     ` David Hildenbrand (Arm)
@ 2026-09-10 14:51       ` Lorenzo Stoakes (ARM)
  0 siblings, 0 replies; 51+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-10 14:51 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On Thu, Sep 10, 2026 at 04:29:06PM +0200, David Hildenbrand (Arm) wrote:
> On 9/10/26 16:16, Lorenzo Stoakes (ARM) wrote:
> > On Wed, Sep 09, 2026 at 03:33:01PM +0200, David Hildenbrand (Arm) wrote:
> >> Let's move it to sparse_init_one_section(). However, to keep early
> >> boot processing working, we also have to initialize it in
> >> sparse_sections_init().
> >
> > A why might be nice :)
>
> Agreed, I'll mention that.
>
> >
> > I guess preparing for removal of __section_mark_present()?
> >
>
> Right intuition :)
>
> > Also good to have arguments as to why this is equivalent of previous
> > behaviour.
> >
> > E.g. higher pfn = higher section nr so naturally the highest is the one you
> > end up wtih at the end of sparse_sections_init()?
>
> We go over all sections, just earlier.
>
> >
> >>
> >> Should we use READ_ONCE/WRITE_ONCE with __highest_used_section_nr?
> >> Probably, something for another day.
> >
> > It might be worth expanding this a bit. Do multiple threads read/write this
> > concurrently?
>
> Hah, I'll probably just drop it. I was just stumbling over readers vs.
> concurrent updates and thought "that looks suspicious".

Ack. KCSAN will bring our sins back to bear if they matter anyway :>)

>
> >
> > No functional change intended here or is one intended? :)
> >
>
> Certainly no change intended ;)
>
> > Before it was:
> >
> > mm_core_init_early() -> sparse_sections_init() -> __section_mark_present()
> >                           sparse_add_section() -> __section_mark_present()
> >
> > Now:
> >
> >                                                  mm_core_init_early() -> sparse_sections_init() [early]
> >                                                  sparse_add_section() -> sparse_init_one_section()
> >
> > But also called from mm_core_init_early():
> >
> > sparse_init() -> sparse_metadata_init() -> sparse_metadata_init_nid() -> sparse_init_one_section()
> >
> > Are both required?
>
> sparse_metadata_init() relies on __highest_used_section_nr in the
> for_each_early_section_nr / for_each_present_section_nr, so it is required.

Ahh yeah, makes sense. Worth spelling that out :)

>
> I could probable move the update on the hotplug side into sparse_add_section()
> instead!

Ack yeah would separate things out a bit between the two!

>
> >
> >
> >>
> >> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> >> ---
> >>  mm/sparse.c | 5 +++--
> >>  mm/sparse.h | 6 +++---
> >>  2 files changed, 6 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/mm/sparse.c b/mm/sparse.c
> >> index 2b41ae36f20b8..2d0f2db34f4cf 100644
> >> --- a/mm/sparse.c
> >> +++ b/mm/sparse.c
> >> @@ -177,7 +177,7 @@ static inline unsigned long first_present_section_nr(void)
> >>
> >>  void __init sparse_sections_init(void)
> >>  {
> >> -	unsigned long pfn, start_pfn, end_pfn;
> >> +	unsigned long pfn, start_pfn, end_pfn, section_nr;
> >>  	int i, nid;
> >>
> >>  	sparse_extreme_init();
> >> @@ -187,9 +187,9 @@ void __init sparse_sections_init(void)
> >>  		mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
> >>
> >>  		for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
> >> -			unsigned long section_nr = pfn_to_section_nr(pfn);
> >>  			struct mem_section *ms;
> >>
> >> +			section_nr = pfn_to_section_nr(pfn);
> >>  			sparse_index_init(section_nr, nid);
> >>  			ms = __nr_to_section(section_nr);
> >>  			if (ms->section_mem_map)
> >> @@ -201,6 +201,7 @@ void __init sparse_sections_init(void)
> >>  			__section_mark_present(ms, section_nr);
> >>  		}
> >>  	}
> >> +	__highest_used_section_nr = section_nr;
> >>  }
> >>
> >>  #ifndef CONFIG_SPARSEMEM_VMEMMAP
> >> diff --git a/mm/sparse.h b/mm/sparse.h
> >> index 7c5d82ceb7142..a3af4967fd5c5 100644
> >> --- a/mm/sparse.h
> >> +++ b/mm/sparse.h
> >> @@ -97,6 +97,9 @@ static inline void sparse_init_one_section(struct mem_section *ms,
> >>
> >>  	BUILD_BUG_ON(SECTION_MAP_LAST_BIT > PFN_SECTION_SHIFT);
> >>
> >> +	if (section_nr > __highest_used_section_nr)
> >> +		__highest_used_section_nr = section_nr;
> >> +
> >
> > Could also be:
> >
> > 	section_nr = max(section_nr, __highest_used_section_nr);
>
> Ack!
>
> --
> Cheers,
>
> David

--
Cheers, Lorenzo

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

* Re: [PATCH 09/12] mm/sparse: remove SECTION_MARKED_PRESENT
  2026-09-10 14:32   ` Lorenzo Stoakes (ARM)
@ 2026-09-10 15:11     ` David Hildenbrand (Arm)
  0 siblings, 0 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-10 15:11 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel, Seongjun Hong

On 9/10/26 16:32, Lorenzo Stoakes (ARM) wrote:
> On Wed, Sep 09, 2026 at 03:33:02PM +0200, David Hildenbrand (Arm) wrote:
>> All present section iterators run before memory hotplug added any
>> further memory sections, Therefore, we can simply use the SECTION_IS_EARLY
>> flag by setting that flag earlier in sparse_prepare_early_sections().
> 
> Hmm? sparse_prepare_early_sections() doesn't seem to be a function that exists?
> 
> Do you mean sparse_sections_init()?

Rebase artifact, thanks! :)

> 
>>
>> Get rid of SECTION_MARKED_PRESENT entirely and rename
>> for_each_present_section_nr() to for_each_early_section_nr().
>>
>> Also update the gdb script to use the updated value for
>> SECTION_IS_EARLY.
> 
> The change seems fine.
> 
>>
>> No functional change intended.
>>
>> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> 
> With commit msg updated:
> 
> Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> 
> One small question type comment below.

Thanks!

[...]

>> +++ b/scripts/gdb/linux/mm.py
>> @@ -76,7 +76,7 @@ class x86_page_ops():
>>              self.SECTION_IS_EARLY = 1 << int(gdb.parse_and_eval('SECTION_IS_EARLY_BIT'))
>>          except:
>>              self.SECTION_HAS_MEM_MAP = 1 << 0
>> -            self.SECTION_IS_EARLY = 1 << 3
>> +            self.SECTION_IS_EARLY = 1 << 2
> 
> Seems a bit strage given the code is:
> 
>         try:
>             self.SECTION_HAS_MEM_MAP = 1 << int(gdb.parse_and_eval('SECTION_HAS_MEM_MAP_BIT'))
>             self.SECTION_IS_EARLY = 1 << int(gdb.parse_and_eval('SECTION_IS_EARLY_BIT'))
>         except:
>             self.SECTION_HAS_MEM_MAP = 1 << 0
>             self.SECTION_IS_EARLY = 1 << 2
> 
> Whereas other variables must be available with no try, e.g.:
> 
>         self.PAGE_OFFSET = int(gdb.parse_and_eval("page_offset_base"))
>         self.VMEMMAP_START = int(gdb.parse_and_eval("vmemmap_base"))
>         self.PHYS_BASE = int(gdb.parse_and_eval("(unsigned long) phys_base"))
> 
> etc.
> 
> Is there some weirdness with gdb? Or is it maybe because there are some configs
> without these symbols maybe?

TBH, I have absolutely no idea and I was asking myself the same thing (but
decided that I couldn't care less about a python gdb script).

This code was added in February:

commit 55f8b4518d14b7436f70defe27faba4eca0cd4e1
Author: Seongjun Hong <hsj0512@snu.ac.kr>
Date:   Mon Feb 2 12:42:41 2026 +0900

    scripts/gdb: implement x86_page_ops in mm.py

    Implement all member functions of x86_page_ops strictly following the
    logic of aarch64_page_ops.

    This includes full support for SPARSEMEM and standard page translation
    functions.

    This fixes compatibility with 'lx-' commands on x86_64, preventing
    AttributeErrors when using lx-pfn_to_page and others.

@Seongjun, why are these conditional and the others not? Trying to support older
kernels?


-- 
Cheers,

David

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

* Re: [PATCH 11/12] fs/proc/page: clarify comment in get_max_dump_pfn()
  2026-09-10 14:41   ` Lorenzo Stoakes (ARM)
@ 2026-09-10 15:14     ` David Hildenbrand (Arm)
  0 siblings, 0 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-10 15:14 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/10/26 16:41, Lorenzo Stoakes (ARM) wrote:
> On Wed, Sep 09, 2026 at 03:33:04PM +0200, David Hildenbrand (Arm) wrote:
>> pfn_to_online_page() will only succeed on some PFNs within the same
>> section, not necessarily all. Let's make that clearer.
>>
>> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> 
> Nit on comment below, but LGTM so:
> 
> Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> 
>> ---
>>  fs/proc/page.c | 7 +++----
>>  1 file changed, 3 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/proc/page.c b/fs/proc/page.c
>> index 260772b20bd99..6856ff3e3cf28 100644
>> --- a/fs/proc/page.c
>> +++ b/fs/proc/page.c
>> @@ -31,10 +31,9 @@ static inline unsigned long get_max_dump_pfn(void)
>>  {
>>  #ifdef CONFIG_SPARSEMEM
>>  	/*
>> -	 * The memmap of early sections is completely populated and marked
>> -	 * online even if max_pfn does not fall on a section boundary -
>> -	 * pfn_to_online_page() will succeed on all pages. Allow inspecting
>> -	 * these memmaps.
>> +	 * If max_pfn does not fall on a section boundary, pfn_to_online_page()
>> +	 * can succeed on PFNs beyond max_pfn within the same section. Allow
>> +	 * inspecting these memmaps.
> 
> 'Allow inspection of' these memmaps is clearer I think. But this odd turn of
> phrase existed before this change also :)

Done, thanks!

-- 
Cheers,

David

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

* Re: [PATCH 12/12] mm/memory_hotplug: drop CONFIG_HAVE_ARCH_PFN_VALID handling from pfn_to_online_page()
  2026-09-10 14:47   ` Lorenzo Stoakes (ARM)
@ 2026-09-10 15:15     ` David Hildenbrand (Arm)
  0 siblings, 0 replies; 51+ messages in thread
From: David Hildenbrand (Arm) @ 2026-09-10 15:15 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Jan Kiszka, Kieran Bingham, linux-kernel,
	linux-mm, linux-cxl, driver-core, linux-fsdevel

On 9/10/26 16:47, Lorenzo Stoakes (ARM) wrote:
> On Wed, Sep 09, 2026 at 03:33:05PM +0200, David Hildenbrand (Arm) wrote:
>> Drop CONFIG_HAVE_ARCH_PFN_VALID handling, as CONFIG_HAVE_ARCH_PFN_VALID
>> is never used with CONFIG_MEMORY_HOTPLUG, as the latter depends on
>> CONFIG_SPARSEMEM_VMEMMAP. Make sure it stays that way.
> 
> So argument is:
> 
> mm/Makefile:
> 
> memory-hotplug-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
> 
> Is memory_hotplug.c even compiled at all?
> 
> mm/Kconfig:
> 
> menuconfig MEMORY_HOTPLUG
> 	bool "Memory hotplug"
> 	select MEMORY_ISOLATION
> 	depends on SPARSEMEM_VMEMMAP
> 	depends on ARCH_ENABLE_MEMORY_HOTPLUG
> 	depends on 64BIT
> 	select NUMA_KEEP_MEMINFO if NUMA
> 
> $ cd arch
> $ rg HAVE_ARCH_PFN_VALID
> Kconfig
> 1762:config HAVE_ARCH_PFN_VALID
> 
> arm/Kconfig
> 94:	select HAVE_ARCH_PFN_VALID
> 
> arm/mm/init.c
> 121:#ifdef CONFIG_HAVE_ARCH_PFN_VALID
> 
> arm/include/asm/page.h
> 178:#ifdef CONFIG_HAVE_ARCH_PFN_VALID
> 
> m68k/Kconfig.cpu
> 23:	select HAVE_ARCH_PFN_VALID
> 40:	select HAVE_ARCH_PFN_VALID
> 
> arc/Kconfig
> 463:	select HAVE_ARCH_PFN_VALID
> 
> All of arm, m68k and arc are 32-bit arches so by definition MEMORY_HOTPLUG
> can't be selected.
> 
>>
>> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> 
> So LGTM and:
> 
> Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> 
>> ---
>>  mm/memory_hotplug.c | 9 ++-------
>>  1 file changed, 2 insertions(+), 7 deletions(-)
>>
>> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
>> index b428da66d279c..58ce35cb48f57 100644
>> --- a/mm/memory_hotplug.c
>> +++ b/mm/memory_hotplug.c
>> @@ -344,6 +344,8 @@ struct page *pfn_to_online_page(unsigned long pfn)
>>  	struct dev_pagemap *pgmap;
>>  	struct mem_section *ms;
>>
>> +	BUILD_BUG_ON(IS_ENABLED(CONFIG_HAVE_ARCH_PFN_VALID));
> 
> Haha nicest way of removing some later code I've seen. Just make it not compile
> if such a thing happens :)

Better be safe than sorry :)

Thanks!

-- 
Cheers,

David

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

end of thread, other threads:[~2026-09-10 15:15 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 13:32 [PATCH 00/12] mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups David Hildenbrand (Arm)
2026-09-09 13:32 ` [PATCH 01/12] mm/sparse: move mem_section init to sparse_extreme_init() David Hildenbrand (Arm)
2026-09-09 17:02   ` Oscar Salvador (SUSE)
2026-09-10 12:52   ` Lorenzo Stoakes (ARM)
2026-09-10 13:13     ` David Hildenbrand (Arm)
2026-09-10 13:33       ` Lorenzo Stoakes (ARM)
2026-09-09 13:32 ` [PATCH 02/12] mm/sparse: refactor sparse_sections_init() David Hildenbrand (Arm)
2026-09-09 17:09   ` Oscar Salvador (SUSE)
2026-09-09 17:18     ` David Hildenbrand (Arm)
2026-09-10 13:29   ` Lorenzo Stoakes (ARM)
2026-09-10 14:30     ` David Hildenbrand (Arm)
2026-09-10 14:38       ` Lorenzo Stoakes (ARM)
2026-09-09 13:32 ` [PATCH 03/12] mm/sparse: move initialization of section metadata to sparse_metadata_init() David Hildenbrand (Arm)
2026-09-09 17:22   ` Oscar Salvador (SUSE)
2026-09-10 13:43   ` Lorenzo Stoakes (ARM)
2026-09-09 13:32 ` [PATCH 04/12] mm/sparse: rename and cleanup sparse_init_nid() David Hildenbrand (Arm)
2026-09-10  7:41   ` Oscar Salvador (SUSE)
2026-09-10 13:46   ` Lorenzo Stoakes (ARM)
2026-09-10 14:29     ` David Hildenbrand (Arm)
2026-09-09 13:32 ` [PATCH 05/12] mm/sparse: cleanup sparse_init_one_section() David Hildenbrand (Arm)
2026-09-10  7:45   ` Oscar Salvador (SUSE)
2026-09-10 13:47   ` Lorenzo Stoakes (ARM)
2026-09-09 13:32 ` [PATCH 06/12] mm/sparse: rename __highest_present_section_nr to __highest_used_section_nr David Hildenbrand (Arm)
2026-09-10  7:56   ` Oscar Salvador (SUSE)
2026-09-10 13:49   ` Lorenzo Stoakes (ARM)
2026-09-09 13:33 ` [PATCH 07/12] mm/sparse: remove pfn_in_present_section() David Hildenbrand (Arm)
2026-09-10  7:59   ` Oscar Salvador (SUSE)
2026-09-10 13:50   ` Lorenzo Stoakes (ARM)
2026-09-09 13:33 ` [PATCH 08/12] mm/sparse: move __highest_used_section_nr handling David Hildenbrand (Arm)
2026-09-09 14:44   ` David Hildenbrand (Arm)
2026-09-10  8:33   ` Oscar Salvador (SUSE)
2026-09-10  9:13     ` David Hildenbrand (Arm)
2026-09-10 12:08       ` Oscar Salvador (SUSE)
2026-09-10 13:33         ` David Hildenbrand (Arm)
2026-09-10 14:16   ` Lorenzo Stoakes (ARM)
2026-09-10 14:29     ` David Hildenbrand (Arm)
2026-09-10 14:51       ` Lorenzo Stoakes (ARM)
2026-09-09 13:33 ` [PATCH 09/12] mm/sparse: remove SECTION_MARKED_PRESENT David Hildenbrand (Arm)
2026-09-10 12:15   ` Oscar Salvador (SUSE)
2026-09-10 14:32   ` Lorenzo Stoakes (ARM)
2026-09-10 15:11     ` David Hildenbrand (Arm)
2026-09-09 13:33 ` [PATCH 10/12] mm/sparse: remove flags parameter from sparse_init_one_section() David Hildenbrand (Arm)
2026-09-10 12:34   ` Oscar Salvador (SUSE)
2026-09-10 14:34   ` Lorenzo Stoakes (ARM)
2026-09-09 13:33 ` [PATCH 11/12] fs/proc/page: clarify comment in get_max_dump_pfn() David Hildenbrand (Arm)
2026-09-10 12:46   ` Oscar Salvador (SUSE)
2026-09-10 14:41   ` Lorenzo Stoakes (ARM)
2026-09-10 15:14     ` David Hildenbrand (Arm)
2026-09-09 13:33 ` [PATCH 12/12] mm/memory_hotplug: drop CONFIG_HAVE_ARCH_PFN_VALID handling from pfn_to_online_page() David Hildenbrand (Arm)
2026-09-10 14:47   ` Lorenzo Stoakes (ARM)
2026-09-10 15:15     ` David Hildenbrand (Arm)

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