* [PATCH v8 0/2] kho: add support for deferred struct page init
@ 2026-04-16 11:06 Michal Clapinski
2026-04-16 11:06 ` [PATCH v8 1/2] kho: fix deferred initialization of scratch areas Michal Clapinski
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Michal Clapinski @ 2026-04-16 11:06 UTC (permalink / raw)
To: Evangelos Petrongonas, Pasha Tatashin, Mike Rapoport,
Pratyush Yadav, Alexander Graf, Samiullah Khawaja, kexec,
linux-mm
Cc: linux-kernel, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan,
Michal Hocko, Brendan Jackman, Johannes Weiner, Zi Yan,
Michal Clapinski
When CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, struct page
initialization is deferred to parallel kthreads that run later in
the boot process.
Currently, KHO is incompatible with DEFERRED.
This series fixes that incompatibility.
---
v8:
- moved overriding the migratetype from init_pageblock_migratetype
to callsites
v7:
- reimplemented the initialization of kho scratch again
v6:
- reimplemented the initialization of kho scratch
v5:
- rebased
v4:
- added a new commit to fix deferred init of kho scratch
- switched to ulong when refering to pfn
v3:
- changed commit msg
- don't invoke early_pfn_to_nid if CONFIG_DEFERRED_STRUCT_PAGE_INIT=n
v2:
- updated a comment
I took Evangelos's test code:
https://git.infradead.org/?p=users/vpetrog/linux.git;a=shortlog;h=refs/heads/kho-deferred-struct-page-init
and then modified it to this monster test that does 2 allocations:
at core_initcall (early) and at module_init (late). Then kexec, then
2 more allocations at these points, then restore the original 2, then
kexec, then restore the other 2. Basically I test preservation of early
and late allocation both on cold and on warm boot.
Tested it both with and without DEFERRED.
This patch probably doesn't apply onto anything currently.
It's based on mm-new with
"memblock: move reserve_bootmem_range() to memblock.c and make it static"
cherrypicked from rppt/memblock.
Evangelos Petrongonas (1):
kho: make preserved pages compatible with deferred struct page init
Michal Clapinski (1):
kho: fix deferred initialization of scratch areas
include/linux/memblock.h | 7 ++--
kernel/liveupdate/Kconfig | 2 --
kernel/liveupdate/kexec_handover.c | 52 +++++++++++++++---------------
mm/memblock.c | 41 +++++++++++------------
mm/mm_init.c | 27 +++++++++++-----
5 files changed, 69 insertions(+), 60 deletions(-)
--
2.54.0.rc1.555.g9c883467ad-goog
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v8 1/2] kho: fix deferred initialization of scratch areas 2026-04-16 11:06 [PATCH v8 0/2] kho: add support for deferred struct page init Michal Clapinski @ 2026-04-16 11:06 ` Michal Clapinski 2026-04-16 14:45 ` Mike Rapoport 2026-04-16 11:06 ` [PATCH v8 2/2] kho: make preserved pages compatible with deferred struct page init Michal Clapinski 2026-04-16 15:00 ` [PATCH v8 0/2] kho: add support for " Mike Rapoport 2 siblings, 1 reply; 9+ messages in thread From: Michal Clapinski @ 2026-04-16 11:06 UTC (permalink / raw) To: Evangelos Petrongonas, Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf, Samiullah Khawaja, kexec, linux-mm Cc: linux-kernel, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko, Brendan Jackman, Johannes Weiner, Zi Yan, Michal Clapinski Currently, if CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, kho_release_scratch() will initialize the struct pages and set migratetype of KHO scratch. Unless the whole scratch fits below first_deferred_pfn, some of that will be overwritten either by deferred_init_pages() or memmap_init_reserved_range(). To fix it, make memmap_init_range(), deferred_init_memmap_chunk() and memmap_init_reserved_range() recognize KHO scratch regions and set migratetype of pageblocks in those regions to MIGRATE_CMA. Signed-off-by: Michal Clapinski <mclapinski@google.com> Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org> --- include/linux/memblock.h | 7 +++-- kernel/liveupdate/kexec_handover.c | 25 ------------------ mm/memblock.c | 41 ++++++++++++++---------------- mm/mm_init.c | 27 ++++++++++++++------ 4 files changed, 43 insertions(+), 57 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 6ec5e9ac0699..410f2a399691 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -614,11 +614,14 @@ static inline void memtest_report_meminfo(struct seq_file *m) { } #ifdef CONFIG_MEMBLOCK_KHO_SCRATCH void memblock_set_kho_scratch_only(void); void memblock_clear_kho_scratch_only(void); -void memmap_init_kho_scratch_pages(void); +bool memblock_is_kho_scratch_memory(phys_addr_t addr); #else static inline void memblock_set_kho_scratch_only(void) { } static inline void memblock_clear_kho_scratch_only(void) { } -static inline void memmap_init_kho_scratch_pages(void) {} +static inline bool memblock_is_kho_scratch_memory(phys_addr_t addr) +{ + return false; +} #endif #endif /* _LINUX_MEMBLOCK_H */ diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c index 18509d8082ea..a507366a2cf9 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -1576,35 +1576,10 @@ static __init int kho_init(void) } fs_initcall(kho_init); -static void __init kho_release_scratch(void) -{ - phys_addr_t start, end; - u64 i; - - memmap_init_kho_scratch_pages(); - - /* - * Mark scratch mem as CMA before we return it. That way we - * ensure that no kernel allocations happen on it. That means - * we can reuse it as scratch memory again later. - */ - __for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, - MEMBLOCK_KHO_SCRATCH, &start, &end, NULL) { - ulong start_pfn = pageblock_start_pfn(PFN_DOWN(start)); - ulong end_pfn = pageblock_align(PFN_UP(end)); - ulong pfn; - - for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) - init_pageblock_migratetype(pfn_to_page(pfn), - MIGRATE_CMA, false); - } -} - void __init kho_memory_init(void) { if (kho_in.scratch_phys) { kho_scratch = phys_to_virt(kho_in.scratch_phys); - kho_release_scratch(); if (kho_mem_retrieve(kho_get_fdt())) kho_in.fdt_phys = 0; diff --git a/mm/memblock.c b/mm/memblock.c index 4224fdaa8918..fab234f732c3 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -17,6 +17,7 @@ #include <linux/seq_file.h> #include <linux/memblock.h> #include <linux/mutex.h> +#include <linux/page-isolation.h> #ifdef CONFIG_KEXEC_HANDOVER #include <linux/libfdt.h> @@ -959,28 +960,6 @@ __init void memblock_clear_kho_scratch_only(void) { kho_scratch_only = false; } - -__init void memmap_init_kho_scratch_pages(void) -{ - phys_addr_t start, end; - unsigned long pfn; - int nid; - u64 i; - - if (!IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT)) - return; - - /* - * Initialize struct pages for free scratch memory. - * The struct pages for reserved scratch memory will be set up in - * memmap_init_reserved_pages() - */ - __for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, - MEMBLOCK_KHO_SCRATCH, &start, &end, &nid) { - for (pfn = PFN_UP(start); pfn < PFN_DOWN(end); pfn++) - init_deferred_page(pfn, nid); - } -} #endif /** @@ -1971,6 +1950,18 @@ bool __init_memblock memblock_is_map_memory(phys_addr_t addr) return !memblock_is_nomap(&memblock.memory.regions[i]); } +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH +bool __init_memblock memblock_is_kho_scratch_memory(phys_addr_t addr) +{ + int i = memblock_search(&memblock.memory, addr); + + if (i == -1) + return false; + + return memblock_is_kho_scratch(&memblock.memory.regions[i]); +} +#endif + int __init_memblock memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn, unsigned long *end_pfn) { @@ -2262,6 +2253,12 @@ static void __init memmap_init_reserved_range(phys_addr_t start, * access it yet. */ __SetPageReserved(page); + +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH + if (memblock_is_kho_scratch_memory(PFN_PHYS(pfn)) && + pageblock_aligned(pfn)) + init_pageblock_migratetype(page, MIGRATE_CMA, false); +#endif } } diff --git a/mm/mm_init.c b/mm/mm_init.c index f9f8e1af921c..890c3ae21ba0 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -916,8 +916,15 @@ void __meminit memmap_init_range(unsigned long size, int nid, unsigned long zone * over the place during system boot. */ if (pageblock_aligned(pfn)) { - init_pageblock_migratetype(page, migratetype, - isolate_pageblock); + int mt = migratetype; + +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH + if (memblock_is_kho_scratch_memory(page_to_phys(page))) + mt = MIGRATE_CMA; +#endif + + init_pageblock_migratetype(page, mt, + isolate_pageblock); cond_resched(); } pfn++; @@ -1970,7 +1977,7 @@ unsigned long __init node_map_pfn_alignment(void) #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT static void __init deferred_free_pages(unsigned long pfn, - unsigned long nr_pages) + unsigned long nr_pages, enum migratetype mt) { struct page *page; unsigned long i; @@ -1983,8 +1990,7 @@ static void __init deferred_free_pages(unsigned long pfn, /* Free a large naturally-aligned chunk if possible */ if (nr_pages == MAX_ORDER_NR_PAGES && IS_MAX_ORDER_ALIGNED(pfn)) { for (i = 0; i < nr_pages; i += pageblock_nr_pages) - init_pageblock_migratetype(page + i, MIGRATE_MOVABLE, - false); + init_pageblock_migratetype(page + i, mt, false); __free_pages_core(page, MAX_PAGE_ORDER, MEMINIT_EARLY); return; } @@ -1994,8 +2000,7 @@ static void __init deferred_free_pages(unsigned long pfn, for (i = 0; i < nr_pages; i++, page++, pfn++) { if (pageblock_aligned(pfn)) - init_pageblock_migratetype(page, MIGRATE_MOVABLE, - false); + init_pageblock_migratetype(page, mt, false); __free_pages_core(page, 0, MEMINIT_EARLY); } } @@ -2051,6 +2056,7 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn, u64 i = 0; for_each_free_mem_range(i, nid, 0, &start, &end, NULL) { + enum migratetype mt = MIGRATE_MOVABLE; unsigned long spfn = PFN_UP(start); unsigned long epfn = PFN_DOWN(end); @@ -2060,12 +2066,17 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn, spfn = max(spfn, start_pfn); epfn = min(epfn, end_pfn); +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH + if (memblock_is_kho_scratch_memory(PFN_PHYS(spfn))) + mt = MIGRATE_CMA; +#endif + while (spfn < epfn) { unsigned long mo_pfn = ALIGN(spfn + 1, MAX_ORDER_NR_PAGES); unsigned long chunk_end = min(mo_pfn, epfn); nr_pages += deferred_init_pages(zone, spfn, chunk_end); - deferred_free_pages(spfn, chunk_end - spfn); + deferred_free_pages(spfn, chunk_end - spfn, mt); spfn = chunk_end; -- 2.54.0.rc1.555.g9c883467ad-goog ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v8 1/2] kho: fix deferred initialization of scratch areas 2026-04-16 11:06 ` [PATCH v8 1/2] kho: fix deferred initialization of scratch areas Michal Clapinski @ 2026-04-16 14:45 ` Mike Rapoport 2026-04-16 15:06 ` Michał Cłapiński 0 siblings, 1 reply; 9+ messages in thread From: Mike Rapoport @ 2026-04-16 14:45 UTC (permalink / raw) To: Michal Clapinski Cc: Evangelos Petrongonas, Pasha Tatashin, Pratyush Yadav, Alexander Graf, Samiullah Khawaja, kexec, linux-mm, linux-kernel, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko, Brendan Jackman, Johannes Weiner, Zi Yan Hi Michal, On Thu, Apr 16, 2026 at 01:06:53PM +0200, Michal Clapinski wrote: > Currently, if CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, > kho_release_scratch() will initialize the struct pages and set migratetype > of KHO scratch. Unless the whole scratch fits below first_deferred_pfn, > some of that will be overwritten either by deferred_init_pages() or > memmap_init_reserved_range(). > > To fix it, make memmap_init_range(), deferred_init_memmap_chunk() and > memmap_init_reserved_range() recognize KHO scratch regions and set > migratetype of pageblocks in those regions to MIGRATE_CMA. > > Signed-off-by: Michal Clapinski <mclapinski@google.com> > Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> > Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Your signed-off should be last here :) https://docs.kernel.org/process/submitting-patches.html#when-to-use-acked-by-cc-and-co-developed-by > --- > include/linux/memblock.h | 7 +++-- > kernel/liveupdate/kexec_handover.c | 25 ------------------ > mm/memblock.c | 41 ++++++++++++++---------------- > mm/mm_init.c | 27 ++++++++++++++------ > 4 files changed, 43 insertions(+), 57 deletions(-) > > diff --git a/include/linux/memblock.h b/include/linux/memblock.h > index 6ec5e9ac0699..410f2a399691 100644 > --- a/include/linux/memblock.h > +++ b/include/linux/memblock.h > @@ -614,11 +614,14 @@ static inline void memtest_report_meminfo(struct seq_file *m) { } > #ifdef CONFIG_MEMBLOCK_KHO_SCRATCH > void memblock_set_kho_scratch_only(void); > void memblock_clear_kho_scratch_only(void); > -void memmap_init_kho_scratch_pages(void); > +bool memblock_is_kho_scratch_memory(phys_addr_t addr); > #else > static inline void memblock_set_kho_scratch_only(void) { } > static inline void memblock_clear_kho_scratch_only(void) { } > -static inline void memmap_init_kho_scratch_pages(void) {} > +static inline bool memblock_is_kho_scratch_memory(phys_addr_t addr) > +{ > + return false; > +} > #endif > > #endif /* _LINUX_MEMBLOCK_H */ > diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c > index 18509d8082ea..a507366a2cf9 100644 > --- a/kernel/liveupdate/kexec_handover.c > +++ b/kernel/liveupdate/kexec_handover.c > @@ -1576,35 +1576,10 @@ static __init int kho_init(void) > } > fs_initcall(kho_init); > > -static void __init kho_release_scratch(void) > -{ > - phys_addr_t start, end; > - u64 i; > - > - memmap_init_kho_scratch_pages(); > - > - /* > - * Mark scratch mem as CMA before we return it. That way we > - * ensure that no kernel allocations happen on it. That means > - * we can reuse it as scratch memory again later. > - */ > - __for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, > - MEMBLOCK_KHO_SCRATCH, &start, &end, NULL) { > - ulong start_pfn = pageblock_start_pfn(PFN_DOWN(start)); > - ulong end_pfn = pageblock_align(PFN_UP(end)); > - ulong pfn; > - > - for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) > - init_pageblock_migratetype(pfn_to_page(pfn), > - MIGRATE_CMA, false); > - } > -} > - > void __init kho_memory_init(void) > { > if (kho_in.scratch_phys) { > kho_scratch = phys_to_virt(kho_in.scratch_phys); > - kho_release_scratch(); > > if (kho_mem_retrieve(kho_get_fdt())) > kho_in.fdt_phys = 0; > diff --git a/mm/memblock.c b/mm/memblock.c > index 4224fdaa8918..fab234f732c3 100644 > --- a/mm/memblock.c > +++ b/mm/memblock.c > @@ -17,6 +17,7 @@ > #include <linux/seq_file.h> > #include <linux/memblock.h> > #include <linux/mutex.h> > +#include <linux/page-isolation.h> > > #ifdef CONFIG_KEXEC_HANDOVER > #include <linux/libfdt.h> > @@ -959,28 +960,6 @@ __init void memblock_clear_kho_scratch_only(void) > { > kho_scratch_only = false; > } > - > -__init void memmap_init_kho_scratch_pages(void) > -{ > - phys_addr_t start, end; > - unsigned long pfn; > - int nid; > - u64 i; > - > - if (!IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT)) > - return; > - > - /* > - * Initialize struct pages for free scratch memory. > - * The struct pages for reserved scratch memory will be set up in > - * memmap_init_reserved_pages() > - */ > - __for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, > - MEMBLOCK_KHO_SCRATCH, &start, &end, &nid) { > - for (pfn = PFN_UP(start); pfn < PFN_DOWN(end); pfn++) > - init_deferred_page(pfn, nid); > - } > -} > #endif > > /** > @@ -1971,6 +1950,18 @@ bool __init_memblock memblock_is_map_memory(phys_addr_t addr) > return !memblock_is_nomap(&memblock.memory.regions[i]); > } > > +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH > +bool __init_memblock memblock_is_kho_scratch_memory(phys_addr_t addr) We already have a block under #ifdef CONFIG_MEMBLOCK_KHO_SCRATCH, please add this function to that block. > +{ > + int i = memblock_search(&memblock.memory, addr); > + > + if (i == -1) > + return false; > + > + return memblock_is_kho_scratch(&memblock.memory.regions[i]); > +} > +#endif > + > int __init_memblock memblock_search_pfn_nid(unsigned long pfn, > unsigned long *start_pfn, unsigned long *end_pfn) > { > @@ -2262,6 +2253,12 @@ static void __init memmap_init_reserved_range(phys_addr_t start, > * access it yet. > */ > __SetPageReserved(page); > + > +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH No need for #ifdef here, there's a stub returning false for CONFIG_MEMBLOCK_KHO_SCRATCH=n case. > + if (memblock_is_kho_scratch_memory(PFN_PHYS(pfn)) && > + pageblock_aligned(pfn)) > + init_pageblock_migratetype(page, MIGRATE_CMA, false); > +#endif > } > } > > diff --git a/mm/mm_init.c b/mm/mm_init.c > index f9f8e1af921c..890c3ae21ba0 100644 > --- a/mm/mm_init.c > +++ b/mm/mm_init.c > @@ -916,8 +916,15 @@ void __meminit memmap_init_range(unsigned long size, int nid, unsigned long zone > * over the place during system boot. > */ > if (pageblock_aligned(pfn)) { > - init_pageblock_migratetype(page, migratetype, > - isolate_pageblock); > + int mt = migratetype; > + > +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH Ditto. > + if (memblock_is_kho_scratch_memory(page_to_phys(page))) > + mt = MIGRATE_CMA; > +#endif memmap_init_zone_range() is called each time for a region in memblock.memory. This means either entire range will be KHO_SCRATHC or not and we can check for memblock_is_kho_scratch_memory() once for every region in memmap_init_zone_range(). > + > + init_pageblock_migratetype(page, mt, > + isolate_pageblock); > cond_resched(); > } > pfn++; > @@ -1970,7 +1977,7 @@ unsigned long __init node_map_pfn_alignment(void) > > #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT > static void __init deferred_free_pages(unsigned long pfn, > - unsigned long nr_pages) > + unsigned long nr_pages, enum migratetype mt) > { > struct page *page; > unsigned long i; > @@ -1983,8 +1990,7 @@ static void __init deferred_free_pages(unsigned long pfn, > /* Free a large naturally-aligned chunk if possible */ > if (nr_pages == MAX_ORDER_NR_PAGES && IS_MAX_ORDER_ALIGNED(pfn)) { > for (i = 0; i < nr_pages; i += pageblock_nr_pages) > - init_pageblock_migratetype(page + i, MIGRATE_MOVABLE, > - false); > + init_pageblock_migratetype(page + i, mt, false); > __free_pages_core(page, MAX_PAGE_ORDER, MEMINIT_EARLY); > return; > } > @@ -1994,8 +2000,7 @@ static void __init deferred_free_pages(unsigned long pfn, > > for (i = 0; i < nr_pages; i++, page++, pfn++) { > if (pageblock_aligned(pfn)) > - init_pageblock_migratetype(page, MIGRATE_MOVABLE, > - false); > + init_pageblock_migratetype(page, mt, false); > __free_pages_core(page, 0, MEMINIT_EARLY); > } > } > @@ -2051,6 +2056,7 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn, > u64 i = 0; > > for_each_free_mem_range(i, nid, 0, &start, &end, NULL) { > + enum migratetype mt = MIGRATE_MOVABLE; > unsigned long spfn = PFN_UP(start); > unsigned long epfn = PFN_DOWN(end); > > @@ -2060,12 +2066,17 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn, > spfn = max(spfn, start_pfn); > epfn = min(epfn, end_pfn); > > +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH No need for #ifdef here as well. > + if (memblock_is_kho_scratch_memory(PFN_PHYS(spfn))) > + mt = MIGRATE_CMA; > +#endif > + > while (spfn < epfn) { > unsigned long mo_pfn = ALIGN(spfn + 1, MAX_ORDER_NR_PAGES); > unsigned long chunk_end = min(mo_pfn, epfn); > > nr_pages += deferred_init_pages(zone, spfn, chunk_end); > - deferred_free_pages(spfn, chunk_end - spfn); > + deferred_free_pages(spfn, chunk_end - spfn, mt); > > spfn = chunk_end; > > -- > 2.54.0.rc1.555.g9c883467ad-goog > -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v8 1/2] kho: fix deferred initialization of scratch areas 2026-04-16 14:45 ` Mike Rapoport @ 2026-04-16 15:06 ` Michał Cłapiński 2026-04-16 16:13 ` Mike Rapoport 0 siblings, 1 reply; 9+ messages in thread From: Michał Cłapiński @ 2026-04-16 15:06 UTC (permalink / raw) To: Mike Rapoport Cc: Evangelos Petrongonas, Pasha Tatashin, Pratyush Yadav, Alexander Graf, Samiullah Khawaja, kexec, linux-mm, linux-kernel, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko, Brendan Jackman, Johannes Weiner, Zi Yan On Thu, Apr 16, 2026 at 4:45 PM Mike Rapoport <rppt@kernel.org> wrote: > > Hi Michal, > > On Thu, Apr 16, 2026 at 01:06:53PM +0200, Michal Clapinski wrote: > > Currently, if CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, > > kho_release_scratch() will initialize the struct pages and set migratetype > > of KHO scratch. Unless the whole scratch fits below first_deferred_pfn, > > some of that will be overwritten either by deferred_init_pages() or > > memmap_init_reserved_range(). > > > > To fix it, make memmap_init_range(), deferred_init_memmap_chunk() and > > memmap_init_reserved_range() recognize KHO scratch regions and set > > migratetype of pageblocks in those regions to MIGRATE_CMA. > > > > Signed-off-by: Michal Clapinski <mclapinski@google.com> > > Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> > > Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org> > > Your signed-off should be last here :) > https://docs.kernel.org/process/submitting-patches.html#when-to-use-acked-by-cc-and-co-developed-by > > > --- > > include/linux/memblock.h | 7 +++-- > > kernel/liveupdate/kexec_handover.c | 25 ------------------ > > mm/memblock.c | 41 ++++++++++++++---------------- > > mm/mm_init.c | 27 ++++++++++++++------ > > 4 files changed, 43 insertions(+), 57 deletions(-) > > > > diff --git a/include/linux/memblock.h b/include/linux/memblock.h > > index 6ec5e9ac0699..410f2a399691 100644 > > --- a/include/linux/memblock.h > > +++ b/include/linux/memblock.h > > @@ -614,11 +614,14 @@ static inline void memtest_report_meminfo(struct seq_file *m) { } > > #ifdef CONFIG_MEMBLOCK_KHO_SCRATCH > > void memblock_set_kho_scratch_only(void); > > void memblock_clear_kho_scratch_only(void); > > -void memmap_init_kho_scratch_pages(void); > > +bool memblock_is_kho_scratch_memory(phys_addr_t addr); > > #else > > static inline void memblock_set_kho_scratch_only(void) { } > > static inline void memblock_clear_kho_scratch_only(void) { } > > -static inline void memmap_init_kho_scratch_pages(void) {} > > +static inline bool memblock_is_kho_scratch_memory(phys_addr_t addr) > > +{ > > + return false; > > +} > > #endif > > > > #endif /* _LINUX_MEMBLOCK_H */ > > diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c > > index 18509d8082ea..a507366a2cf9 100644 > > --- a/kernel/liveupdate/kexec_handover.c > > +++ b/kernel/liveupdate/kexec_handover.c > > @@ -1576,35 +1576,10 @@ static __init int kho_init(void) > > } > > fs_initcall(kho_init); > > > > -static void __init kho_release_scratch(void) > > -{ > > - phys_addr_t start, end; > > - u64 i; > > - > > - memmap_init_kho_scratch_pages(); > > - > > - /* > > - * Mark scratch mem as CMA before we return it. That way we > > - * ensure that no kernel allocations happen on it. That means > > - * we can reuse it as scratch memory again later. > > - */ > > - __for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, > > - MEMBLOCK_KHO_SCRATCH, &start, &end, NULL) { > > - ulong start_pfn = pageblock_start_pfn(PFN_DOWN(start)); > > - ulong end_pfn = pageblock_align(PFN_UP(end)); > > - ulong pfn; > > - > > - for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) > > - init_pageblock_migratetype(pfn_to_page(pfn), > > - MIGRATE_CMA, false); > > - } > > -} > > - > > void __init kho_memory_init(void) > > { > > if (kho_in.scratch_phys) { > > kho_scratch = phys_to_virt(kho_in.scratch_phys); > > - kho_release_scratch(); > > > > if (kho_mem_retrieve(kho_get_fdt())) > > kho_in.fdt_phys = 0; > > diff --git a/mm/memblock.c b/mm/memblock.c > > index 4224fdaa8918..fab234f732c3 100644 > > --- a/mm/memblock.c > > +++ b/mm/memblock.c > > @@ -17,6 +17,7 @@ > > #include <linux/seq_file.h> > > #include <linux/memblock.h> > > #include <linux/mutex.h> > > +#include <linux/page-isolation.h> > > > > #ifdef CONFIG_KEXEC_HANDOVER > > #include <linux/libfdt.h> > > @@ -959,28 +960,6 @@ __init void memblock_clear_kho_scratch_only(void) > > { > > kho_scratch_only = false; > > } > > - > > -__init void memmap_init_kho_scratch_pages(void) > > -{ > > - phys_addr_t start, end; > > - unsigned long pfn; > > - int nid; > > - u64 i; > > - > > - if (!IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT)) > > - return; > > - > > - /* > > - * Initialize struct pages for free scratch memory. > > - * The struct pages for reserved scratch memory will be set up in > > - * memmap_init_reserved_pages() > > - */ > > - __for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, > > - MEMBLOCK_KHO_SCRATCH, &start, &end, &nid) { > > - for (pfn = PFN_UP(start); pfn < PFN_DOWN(end); pfn++) > > - init_deferred_page(pfn, nid); > > - } > > -} > > #endif > > > > /** > > @@ -1971,6 +1950,18 @@ bool __init_memblock memblock_is_map_memory(phys_addr_t addr) > > return !memblock_is_nomap(&memblock.memory.regions[i]); > > } > > > > +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH > > +bool __init_memblock memblock_is_kho_scratch_memory(phys_addr_t addr) > > We already have a block under #ifdef CONFIG_MEMBLOCK_KHO_SCRATCH, please > add this function to that block. > > > +{ > > + int i = memblock_search(&memblock.memory, addr); > > + > > + if (i == -1) > > + return false; > > + > > + return memblock_is_kho_scratch(&memblock.memory.regions[i]); > > +} > > +#endif > > + > > int __init_memblock memblock_search_pfn_nid(unsigned long pfn, > > unsigned long *start_pfn, unsigned long *end_pfn) > > { > > @@ -2262,6 +2253,12 @@ static void __init memmap_init_reserved_range(phys_addr_t start, > > * access it yet. > > */ > > __SetPageReserved(page); > > + > > +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH > > No need for #ifdef here, there's a stub returning false for > CONFIG_MEMBLOCK_KHO_SCRATCH=n case. In all 3 places the #ifdef is there because MIGRATE_CMA might be undefined. I already broke mm-new branch in the past because of that. > > + if (memblock_is_kho_scratch_memory(PFN_PHYS(pfn)) && > > + pageblock_aligned(pfn)) > > + init_pageblock_migratetype(page, MIGRATE_CMA, false); > > +#endif > > } > > } > > > > diff --git a/mm/mm_init.c b/mm/mm_init.c > > index f9f8e1af921c..890c3ae21ba0 100644 > > --- a/mm/mm_init.c > > +++ b/mm/mm_init.c > > @@ -916,8 +916,15 @@ void __meminit memmap_init_range(unsigned long size, int nid, unsigned long zone > > * over the place during system boot. > > */ > > if (pageblock_aligned(pfn)) { > > - init_pageblock_migratetype(page, migratetype, > > - isolate_pageblock); > > + int mt = migratetype; > > + > > +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH > > Ditto. > > > + if (memblock_is_kho_scratch_memory(page_to_phys(page))) > > + mt = MIGRATE_CMA; > > +#endif > > memmap_init_zone_range() is called each time for a region in > memblock.memory. This means either entire range will be KHO_SCRATHC or not > and we can check for memblock_is_kho_scratch_memory() once for every region > in memmap_init_zone_range(). Thanks, I didn't notice for_each_mem_pfn_range iterates over regions. Will do. > > + > > + init_pageblock_migratetype(page, mt, > > + isolate_pageblock); > > cond_resched(); > > } > > pfn++; > > @@ -1970,7 +1977,7 @@ unsigned long __init node_map_pfn_alignment(void) > > > > #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT > > static void __init deferred_free_pages(unsigned long pfn, > > - unsigned long nr_pages) > > + unsigned long nr_pages, enum migratetype mt) > > { > > struct page *page; > > unsigned long i; > > @@ -1983,8 +1990,7 @@ static void __init deferred_free_pages(unsigned long pfn, > > /* Free a large naturally-aligned chunk if possible */ > > if (nr_pages == MAX_ORDER_NR_PAGES && IS_MAX_ORDER_ALIGNED(pfn)) { > > for (i = 0; i < nr_pages; i += pageblock_nr_pages) > > - init_pageblock_migratetype(page + i, MIGRATE_MOVABLE, > > - false); > > + init_pageblock_migratetype(page + i, mt, false); > > __free_pages_core(page, MAX_PAGE_ORDER, MEMINIT_EARLY); > > return; > > } > > @@ -1994,8 +2000,7 @@ static void __init deferred_free_pages(unsigned long pfn, > > > > for (i = 0; i < nr_pages; i++, page++, pfn++) { > > if (pageblock_aligned(pfn)) > > - init_pageblock_migratetype(page, MIGRATE_MOVABLE, > > - false); > > + init_pageblock_migratetype(page, mt, false); > > __free_pages_core(page, 0, MEMINIT_EARLY); > > } > > } > > @@ -2051,6 +2056,7 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn, > > u64 i = 0; > > > > for_each_free_mem_range(i, nid, 0, &start, &end, NULL) { > > + enum migratetype mt = MIGRATE_MOVABLE; > > unsigned long spfn = PFN_UP(start); > > unsigned long epfn = PFN_DOWN(end); > > > > @@ -2060,12 +2066,17 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn, > > spfn = max(spfn, start_pfn); > > epfn = min(epfn, end_pfn); > > > > +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH > > No need for #ifdef here as well. > > > + if (memblock_is_kho_scratch_memory(PFN_PHYS(spfn))) > > + mt = MIGRATE_CMA; > > +#endif > > + > > while (spfn < epfn) { > > unsigned long mo_pfn = ALIGN(spfn + 1, MAX_ORDER_NR_PAGES); > > unsigned long chunk_end = min(mo_pfn, epfn); > > > > nr_pages += deferred_init_pages(zone, spfn, chunk_end); > > - deferred_free_pages(spfn, chunk_end - spfn); > > + deferred_free_pages(spfn, chunk_end - spfn, mt); > > > > spfn = chunk_end; > > > > -- > > 2.54.0.rc1.555.g9c883467ad-goog > > > > -- > Sincerely yours, > Mike. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v8 1/2] kho: fix deferred initialization of scratch areas 2026-04-16 15:06 ` Michał Cłapiński @ 2026-04-16 16:13 ` Mike Rapoport 0 siblings, 0 replies; 9+ messages in thread From: Mike Rapoport @ 2026-04-16 16:13 UTC (permalink / raw) To: Michał Cłapiński Cc: Evangelos Petrongonas, Pasha Tatashin, Pratyush Yadav, Alexander Graf, Samiullah Khawaja, kexec, linux-mm, linux-kernel, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko, Brendan Jackman, Johannes Weiner, Zi Yan On Thu, Apr 16, 2026 at 05:06:10PM +0200, Michał Cłapiński wrote: > On Thu, Apr 16, 2026 at 4:45 PM Mike Rapoport <rppt@kernel.org> wrote: > > > > Hi Michal, > > > > On Thu, Apr 16, 2026 at 01:06:53PM +0200, Michal Clapinski wrote: > > > @@ -2262,6 +2253,12 @@ static void __init memmap_init_reserved_range(phys_addr_t start, > > > * access it yet. > > > */ > > > __SetPageReserved(page); > > > + > > > +#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH > > > > No need for #ifdef here, there's a stub returning false for > > CONFIG_MEMBLOCK_KHO_SCRATCH=n case. > > In all 3 places the #ifdef is there because MIGRATE_CMA might be > undefined. I already broke mm-new branch in the past because of that. Hmm, that hurts :/ The best I can think of is to add a static inline in memblock.h and ifdefs around it. > > > + if (memblock_is_kho_scratch_memory(PFN_PHYS(pfn)) && > > > + pageblock_aligned(pfn)) > > > + init_pageblock_migratetype(page, MIGRATE_CMA, false); > > > +#endif > > > } > > > } -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v8 2/2] kho: make preserved pages compatible with deferred struct page init 2026-04-16 11:06 [PATCH v8 0/2] kho: add support for deferred struct page init Michal Clapinski 2026-04-16 11:06 ` [PATCH v8 1/2] kho: fix deferred initialization of scratch areas Michal Clapinski @ 2026-04-16 11:06 ` Michal Clapinski 2026-04-16 15:00 ` [PATCH v8 0/2] kho: add support for " Mike Rapoport 2 siblings, 0 replies; 9+ messages in thread From: Michal Clapinski @ 2026-04-16 11:06 UTC (permalink / raw) To: Evangelos Petrongonas, Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf, Samiullah Khawaja, kexec, linux-mm Cc: linux-kernel, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko, Brendan Jackman, Johannes Weiner, Zi Yan, Michal Clapinski From: Evangelos Petrongonas <epetron@amazon.de> When CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, struct page initialization is deferred to parallel kthreads that run later in the boot process. During KHO restoration, kho_preserved_memory_reserve() writes metadata for each preserved memory region. However, if the struct page has not been initialized, this write targets uninitialized memory, potentially leading to errors like: BUG: unable to handle page fault for address: ... Fix this by introducing kho_get_preserved_page(), which ensures all struct pages in a preserved region are initialized by calling init_deferred_page() which is a no-op when the struct page is already initialized. Signed-off-by: Evangelos Petrongonas <epetron@amazon.de> Co-developed-by: Michal Clapinski <mclapinski@google.com> Signed-off-by: Michal Clapinski <mclapinski@google.com> Reviewed-by: Pratyush Yadav (Google) <pratyush@kernel.org> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com> Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> --- kernel/liveupdate/Kconfig | 2 -- kernel/liveupdate/kexec_handover.c | 27 ++++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/kernel/liveupdate/Kconfig b/kernel/liveupdate/Kconfig index 1a8513f16ef7..c13af38ba23a 100644 --- a/kernel/liveupdate/Kconfig +++ b/kernel/liveupdate/Kconfig @@ -1,12 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only menu "Live Update and Kexec HandOver" - depends on !DEFERRED_STRUCT_PAGE_INIT config KEXEC_HANDOVER bool "kexec handover" depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE - depends on !DEFERRED_STRUCT_PAGE_INIT select MEMBLOCK_KHO_SCRATCH select KEXEC_FILE select LIBFDT diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c index a507366a2cf9..d5718bef6d4d 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -473,6 +473,31 @@ struct page *kho_restore_pages(phys_addr_t phys, unsigned long nr_pages) } EXPORT_SYMBOL_GPL(kho_restore_pages); +/* + * With CONFIG_DEFERRED_STRUCT_PAGE_INIT, struct pages in higher memory regions + * may not be initialized yet at the time KHO deserializes preserved memory. + * KHO uses the struct page to store metadata and a later initialization would + * overwrite it. + * Ensure all the struct pages in the preservation are + * initialized. kho_preserved_memory_reserve() marks the reservation as noinit + * to make sure they don't get re-initialized later. + */ +static struct page *__init kho_get_preserved_page(phys_addr_t phys, + unsigned int order) +{ + unsigned long pfn = PHYS_PFN(phys); + int nid; + + if (!IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT)) + return pfn_to_page(pfn); + + nid = early_pfn_to_nid(pfn); + for (unsigned long i = 0; i < (1UL << order); i++) + init_deferred_page(pfn + i, nid); + + return pfn_to_page(pfn); +} + static int __init kho_preserved_memory_reserve(phys_addr_t phys, unsigned int order) { @@ -481,7 +506,7 @@ static int __init kho_preserved_memory_reserve(phys_addr_t phys, u64 sz; sz = 1 << (order + PAGE_SHIFT); - page = phys_to_page(phys); + page = kho_get_preserved_page(phys, order); /* Reserve the memory preserved in KHO in memblock */ memblock_reserve(phys, sz); -- 2.54.0.rc1.555.g9c883467ad-goog ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v8 0/2] kho: add support for deferred struct page init 2026-04-16 11:06 [PATCH v8 0/2] kho: add support for deferred struct page init Michal Clapinski 2026-04-16 11:06 ` [PATCH v8 1/2] kho: fix deferred initialization of scratch areas Michal Clapinski 2026-04-16 11:06 ` [PATCH v8 2/2] kho: make preserved pages compatible with deferred struct page init Michal Clapinski @ 2026-04-16 15:00 ` Mike Rapoport 2026-04-16 15:23 ` Michał Cłapiński 2 siblings, 1 reply; 9+ messages in thread From: Mike Rapoport @ 2026-04-16 15:00 UTC (permalink / raw) To: Michal Clapinski Cc: Evangelos Petrongonas, Pasha Tatashin, Pratyush Yadav, Alexander Graf, Samiullah Khawaja, kexec, linux-mm, linux-kernel, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko, Brendan Jackman, Johannes Weiner, Zi Yan On Thu, Apr 16, 2026 at 01:06:52PM +0200, Michal Clapinski wrote: > When CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, struct page > initialization is deferred to parallel kthreads that run later in > the boot process. > > Currently, KHO is incompatible with DEFERRED. > This series fixes that incompatibility. > --- > v8: > - moved overriding the migratetype from init_pageblock_migratetype > to callsites > v7: > - reimplemented the initialization of kho scratch again > v6: > - reimplemented the initialization of kho scratch > v5: > - rebased > v4: > - added a new commit to fix deferred init of kho scratch > - switched to ulong when refering to pfn > v3: > - changed commit msg > - don't invoke early_pfn_to_nid if CONFIG_DEFERRED_STRUCT_PAGE_INIT=n > v2: > - updated a comment > > I took Evangelos's test code: > https://git.infradead.org/?p=users/vpetrog/linux.git;a=shortlog;h=refs/heads/kho-deferred-struct-page-init > and then modified it to this monster test that does 2 allocations: > at core_initcall (early) and at module_init (late). Then kexec, then > 2 more allocations at these points, then restore the original 2, then > kexec, then restore the other 2. Basically I test preservation of early > and late allocation both on cold and on warm boot. > Tested it both with and without DEFERRED. Any chance you can clean that monster and send it as patch 3? There's no real difference between core_initcall() and module_init() with respect to that deferred page initialization, they both run after the memory map is fully initialized. > This patch probably doesn't apply onto anything currently. > It's based on mm-new with > "memblock: move reserve_bootmem_range() to memblock.c and make it static" > cherrypicked from rppt/memblock. You can base on for-next in the memblock tree: https://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock > Evangelos Petrongonas (1): > kho: make preserved pages compatible with deferred struct page init > > Michal Clapinski (1): > kho: fix deferred initialization of scratch areas > > include/linux/memblock.h | 7 ++-- > kernel/liveupdate/Kconfig | 2 -- > kernel/liveupdate/kexec_handover.c | 52 +++++++++++++++--------------- > mm/memblock.c | 41 +++++++++++------------ > mm/mm_init.c | 27 +++++++++++----- > 5 files changed, 69 insertions(+), 60 deletions(-) > > -- > 2.54.0.rc1.555.g9c883467ad-goog > -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v8 0/2] kho: add support for deferred struct page init 2026-04-16 15:00 ` [PATCH v8 0/2] kho: add support for " Mike Rapoport @ 2026-04-16 15:23 ` Michał Cłapiński 2026-04-16 15:43 ` Mike Rapoport 0 siblings, 1 reply; 9+ messages in thread From: Michał Cłapiński @ 2026-04-16 15:23 UTC (permalink / raw) To: Mike Rapoport Cc: Evangelos Petrongonas, Pasha Tatashin, Pratyush Yadav, Alexander Graf, Samiullah Khawaja, kexec, linux-mm, linux-kernel, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko, Brendan Jackman, Johannes Weiner, Zi Yan On Thu, Apr 16, 2026 at 5:00 PM Mike Rapoport <rppt@kernel.org> wrote: > > On Thu, Apr 16, 2026 at 01:06:52PM +0200, Michal Clapinski wrote: > > When CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, struct page > > initialization is deferred to parallel kthreads that run later in > > the boot process. > > > > Currently, KHO is incompatible with DEFERRED. > > This series fixes that incompatibility. > > --- > > v8: > > - moved overriding the migratetype from init_pageblock_migratetype > > to callsites > > v7: > > - reimplemented the initialization of kho scratch again > > v6: > > - reimplemented the initialization of kho scratch > > v5: > > - rebased > > v4: > > - added a new commit to fix deferred init of kho scratch > > - switched to ulong when refering to pfn > > v3: > > - changed commit msg > > - don't invoke early_pfn_to_nid if CONFIG_DEFERRED_STRUCT_PAGE_INIT=n > > v2: > > - updated a comment > > > > I took Evangelos's test code: > > https://git.infradead.org/?p=users/vpetrog/linux.git;a=shortlog;h=refs/heads/kho-deferred-struct-page-init > > and then modified it to this monster test that does 2 allocations: > > at core_initcall (early) and at module_init (late). Then kexec, then > > 2 more allocations at these points, then restore the original 2, then > > kexec, then restore the other 2. Basically I test preservation of early > > and late allocation both on cold and on warm boot. > > Tested it both with and without DEFERRED. > > Any chance you can clean that monster and send it as patch 3? I fear that would delay this series somewhere into v15, which I would like to avoid. Can I clean it up and send it separately? > There's no real difference between core_initcall() and module_init() with > respect to that deferred page initialization, they both run after the > memory map is fully initialized. One of them runs before kho_init() and the other after. So it allowed me to expose the bug that I introduced in v4. > > This patch probably doesn't apply onto anything currently. > > It's based on mm-new with > > "memblock: move reserve_bootmem_range() to memblock.c and make it static" > > cherrypicked from rppt/memblock. > > You can base on for-next in the memblock tree: > https://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock I tried that but that branch is missing other commits from mm-new. So I would have to modify my code, which would then conflict with mm-new. > > Evangelos Petrongonas (1): > > kho: make preserved pages compatible with deferred struct page init > > > > Michal Clapinski (1): > > kho: fix deferred initialization of scratch areas > > > > include/linux/memblock.h | 7 ++-- > > kernel/liveupdate/Kconfig | 2 -- > > kernel/liveupdate/kexec_handover.c | 52 +++++++++++++++--------------- > > mm/memblock.c | 41 +++++++++++------------ > > mm/mm_init.c | 27 +++++++++++----- > > 5 files changed, 69 insertions(+), 60 deletions(-) > > > > -- > > 2.54.0.rc1.555.g9c883467ad-goog > > > > -- > Sincerely yours, > Mike. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v8 0/2] kho: add support for deferred struct page init 2026-04-16 15:23 ` Michał Cłapiński @ 2026-04-16 15:43 ` Mike Rapoport 0 siblings, 0 replies; 9+ messages in thread From: Mike Rapoport @ 2026-04-16 15:43 UTC (permalink / raw) To: Michał Cłapiński Cc: Evangelos Petrongonas, Pasha Tatashin, Pratyush Yadav, Alexander Graf, Samiullah Khawaja, kexec, linux-mm, linux-kernel, Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko, Brendan Jackman, Johannes Weiner, Zi Yan On Thu, Apr 16, 2026 at 05:23:32PM +0200, Michał Cłapiński wrote: > On Thu, Apr 16, 2026 at 5:00 PM Mike Rapoport <rppt@kernel.org> wrote: > > > > On Thu, Apr 16, 2026 at 01:06:52PM +0200, Michal Clapinski wrote: > > > When CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, struct page > > > initialization is deferred to parallel kthreads that run later in > > > the boot process. > > > > > > Currently, KHO is incompatible with DEFERRED. > > > This series fixes that incompatibility. > > > --- > > > v8: > > > - moved overriding the migratetype from init_pageblock_migratetype > > > to callsites > > > v7: > > > - reimplemented the initialization of kho scratch again > > > v6: > > > - reimplemented the initialization of kho scratch > > > v5: > > > - rebased > > > v4: > > > - added a new commit to fix deferred init of kho scratch > > > - switched to ulong when refering to pfn > > > v3: > > > - changed commit msg > > > - don't invoke early_pfn_to_nid if CONFIG_DEFERRED_STRUCT_PAGE_INIT=n > > > v2: > > > - updated a comment > > > > > > I took Evangelos's test code: > > > https://git.infradead.org/?p=users/vpetrog/linux.git;a=shortlog;h=refs/heads/kho-deferred-struct-page-init > > > and then modified it to this monster test that does 2 allocations: > > > at core_initcall (early) and at module_init (late). Then kexec, then > > > 2 more allocations at these points, then restore the original 2, then > > > kexec, then restore the other 2. Basically I test preservation of early > > > and late allocation both on cold and on warm boot. > > > Tested it both with and without DEFERRED. > > > > Any chance you can clean that monster and send it as patch 3? > > I fear that would delay this series somewhere into v15, which I would > like to avoid. Can I clean it up and send it separately? I don't mind. For this series can we add a build with deferred pages to selftests/kho/vmtest.sh? Shouldn't be as controversial :) > > There's no real difference between core_initcall() and module_init() with > > respect to that deferred page initialization, they both run after the > > memory map is fully initialized. > > One of them runs before kho_init() and the other after. So it allowed > me to expose the bug that I introduced in v4. Ah, nice. > > > This patch probably doesn't apply onto anything currently. > > > It's based on mm-new with > > > "memblock: move reserve_bootmem_range() to memblock.c and make it static" > > > cherrypicked from rppt/memblock. > > > > You can base on for-next in the memblock tree: > > https://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock > > I tried that but that branch is missing other commits from mm-new. So > I would have to modify my code, which would then conflict with mm-new. Let's continue with mm-new and a cherrypicked memblock patch, it all should be sorted out after -rc1 I hope. > > > Evangelos Petrongonas (1): > > > kho: make preserved pages compatible with deferred struct page init > > > > > > Michal Clapinski (1): > > > kho: fix deferred initialization of scratch areas > > > > > > include/linux/memblock.h | 7 ++-- > > > kernel/liveupdate/Kconfig | 2 -- > > > kernel/liveupdate/kexec_handover.c | 52 +++++++++++++++--------------- > > > mm/memblock.c | 41 +++++++++++------------ > > > mm/mm_init.c | 27 +++++++++++----- > > > 5 files changed, 69 insertions(+), 60 deletions(-) > > > > > > -- > > > 2.54.0.rc1.555.g9c883467ad-goog > > > > > > > -- > > Sincerely yours, > > Mike. -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-04-16 16:13 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-04-16 11:06 [PATCH v8 0/2] kho: add support for deferred struct page init Michal Clapinski 2026-04-16 11:06 ` [PATCH v8 1/2] kho: fix deferred initialization of scratch areas Michal Clapinski 2026-04-16 14:45 ` Mike Rapoport 2026-04-16 15:06 ` Michał Cłapiński 2026-04-16 16:13 ` Mike Rapoport 2026-04-16 11:06 ` [PATCH v8 2/2] kho: make preserved pages compatible with deferred struct page init Michal Clapinski 2026-04-16 15:00 ` [PATCH v8 0/2] kho: add support for " Mike Rapoport 2026-04-16 15:23 ` Michał Cłapiński 2026-04-16 15:43 ` Mike Rapoport
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox