Skip to content

Commit bf480c6

Browse files
mclapinskirppt
authored andcommitted
kho: fix deferred initialization of scratch areas
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 __init_page_from_nid() recognize KHO scratch regions and set migratetype of pageblocks in those regions to MIGRATE_CMA. Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Signed-off-by: Michal Clapinski <mclapinski@google.com> Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com> Reviewed-by: Pratyush Yadav (Google) <pratyush@kernel.org> Link: https://patch.msgid.link/20260423122538.140993-2-mclapinski@google.com Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
1 parent e43ffb6 commit bf480c6

4 files changed

Lines changed: 58 additions & 74 deletions

File tree

include/linux/memblock.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,11 +613,28 @@ static inline void memtest_report_meminfo(struct seq_file *m) { }
613613
#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH
614614
void memblock_set_kho_scratch_only(void);
615615
void memblock_clear_kho_scratch_only(void);
616-
void memmap_init_kho_scratch_pages(void);
616+
bool memblock_is_kho_scratch_memory(phys_addr_t addr);
617+
618+
static inline enum migratetype kho_scratch_migratetype(unsigned long pfn,
619+
enum migratetype mt)
620+
{
621+
if (memblock_is_kho_scratch_memory(PFN_PHYS(pfn)))
622+
return MIGRATE_CMA;
623+
return mt;
624+
}
617625
#else
618626
static inline void memblock_set_kho_scratch_only(void) { }
619627
static inline void memblock_clear_kho_scratch_only(void) { }
620-
static inline void memmap_init_kho_scratch_pages(void) {}
628+
static inline bool memblock_is_kho_scratch_memory(phys_addr_t addr)
629+
{
630+
return false;
631+
}
632+
633+
static inline enum migratetype kho_scratch_migratetype(unsigned long pfn,
634+
enum migratetype mt)
635+
{
636+
return mt;
637+
}
621638
#endif
622639

623640
#endif /* _LINUX_MEMBLOCK_H */

kernel/liveupdate/kexec_handover.c

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,35 +1584,10 @@ static __init int kho_init(void)
15841584
}
15851585
fs_initcall(kho_init);
15861586

1587-
static void __init kho_release_scratch(void)
1588-
{
1589-
phys_addr_t start, end;
1590-
u64 i;
1591-
1592-
memmap_init_kho_scratch_pages();
1593-
1594-
/*
1595-
* Mark scratch mem as CMA before we return it. That way we
1596-
* ensure that no kernel allocations happen on it. That means
1597-
* we can reuse it as scratch memory again later.
1598-
*/
1599-
__for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE,
1600-
MEMBLOCK_KHO_SCRATCH, &start, &end, NULL) {
1601-
ulong start_pfn = pageblock_start_pfn(PFN_DOWN(start));
1602-
ulong end_pfn = pageblock_align(PFN_UP(end));
1603-
ulong pfn;
1604-
1605-
for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages)
1606-
init_pageblock_migratetype(pfn_to_page(pfn),
1607-
MIGRATE_CMA, false);
1608-
}
1609-
}
1610-
16111587
void __init kho_memory_init(void)
16121588
{
16131589
if (kho_in.scratch_phys) {
16141590
kho_scratch = phys_to_virt(kho_in.scratch_phys);
1615-
kho_release_scratch();
16161591

16171592
if (kho_mem_retrieve(kho_get_fdt()))
16181593
kho_in.fdt_phys = 0;

mm/memblock.c

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,40 +1028,6 @@ int __init_memblock memblock_physmem_add(phys_addr_t base, phys_addr_t size)
10281028
}
10291029
#endif
10301030

1031-
#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH
1032-
__init void memblock_set_kho_scratch_only(void)
1033-
{
1034-
kho_scratch_only = true;
1035-
}
1036-
1037-
__init void memblock_clear_kho_scratch_only(void)
1038-
{
1039-
kho_scratch_only = false;
1040-
}
1041-
1042-
__init void memmap_init_kho_scratch_pages(void)
1043-
{
1044-
phys_addr_t start, end;
1045-
unsigned long pfn;
1046-
int nid;
1047-
u64 i;
1048-
1049-
if (!IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT))
1050-
return;
1051-
1052-
/*
1053-
* Initialize struct pages for free scratch memory.
1054-
* The struct pages for reserved scratch memory will be set up in
1055-
* memmap_init_reserved_pages()
1056-
*/
1057-
__for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE,
1058-
MEMBLOCK_KHO_SCRATCH, &start, &end, &nid) {
1059-
for (pfn = PFN_UP(start); pfn < PFN_DOWN(end); pfn++)
1060-
init_deferred_page(pfn, nid);
1061-
}
1062-
}
1063-
#endif
1064-
10651031
/**
10661032
* memblock_setclr_flag - set or clear flag for a memory region
10671033
* @type: memblock type to set/clear flag for
@@ -2535,6 +2501,28 @@ int reserve_mem_release_by_name(const char *name)
25352501
return 1;
25362502
}
25372503

2504+
#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH
2505+
__init void memblock_set_kho_scratch_only(void)
2506+
{
2507+
kho_scratch_only = true;
2508+
}
2509+
2510+
__init void memblock_clear_kho_scratch_only(void)
2511+
{
2512+
kho_scratch_only = false;
2513+
}
2514+
2515+
bool __init_memblock memblock_is_kho_scratch_memory(phys_addr_t addr)
2516+
{
2517+
int i = memblock_search(&memblock.memory, addr);
2518+
2519+
if (i == -1)
2520+
return false;
2521+
2522+
return memblock_is_kho_scratch(&memblock.memory.regions[i]);
2523+
}
2524+
#endif
2525+
25382526
#ifdef CONFIG_KEXEC_HANDOVER
25392527

25402528
static int __init reserved_mem_preserve(void)

mm/mm_init.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -692,9 +692,11 @@ void __meminit __init_page_from_nid(unsigned long pfn, int nid)
692692
}
693693
__init_single_page(pfn_to_page(pfn), pfn, zid, nid);
694694

695-
if (pageblock_aligned(pfn))
696-
init_pageblock_migratetype(pfn_to_page(pfn), MIGRATE_MOVABLE,
697-
false);
695+
if (pageblock_aligned(pfn)) {
696+
enum migratetype mt =
697+
kho_scratch_migratetype(pfn, MIGRATE_MOVABLE);
698+
init_pageblock_migratetype(pfn_to_page(pfn), mt, false);
699+
}
698700
}
699701

700702
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
@@ -927,7 +929,8 @@ void __meminit memmap_init_range(unsigned long size, int nid, unsigned long zone
927929
static void __init memmap_init_zone_range(struct zone *zone,
928930
unsigned long start_pfn,
929931
unsigned long end_pfn,
930-
unsigned long *hole_pfn)
932+
unsigned long *hole_pfn,
933+
enum migratetype mt)
931934
{
932935
unsigned long zone_start_pfn = zone->zone_start_pfn;
933936
unsigned long zone_end_pfn = zone_start_pfn + zone->spanned_pages;
@@ -940,8 +943,7 @@ static void __init memmap_init_zone_range(struct zone *zone,
940943
return;
941944

942945
memmap_init_range(end_pfn - start_pfn, nid, zone_id, start_pfn,
943-
zone_end_pfn, MEMINIT_EARLY, NULL, MIGRATE_MOVABLE,
944-
false);
946+
zone_end_pfn, MEMINIT_EARLY, NULL, mt, false);
945947

946948
if (*hole_pfn < start_pfn)
947949
init_unavailable_range(*hole_pfn, start_pfn, zone_id, nid);
@@ -957,6 +959,8 @@ static void __init memmap_init(void)
957959

958960
for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
959961
struct pglist_data *node = NODE_DATA(nid);
962+
enum migratetype mt =
963+
kho_scratch_migratetype(start_pfn, MIGRATE_MOVABLE);
960964

961965
for (j = 0; j < MAX_NR_ZONES; j++) {
962966
struct zone *zone = node->node_zones + j;
@@ -965,7 +969,7 @@ static void __init memmap_init(void)
965969
continue;
966970

967971
memmap_init_zone_range(zone, start_pfn, end_pfn,
968-
&hole_pfn);
972+
&hole_pfn, mt);
969973
zone_id = j;
970974
}
971975
}
@@ -1970,7 +1974,7 @@ unsigned long __init node_map_pfn_alignment(void)
19701974

19711975
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
19721976
static void __init deferred_free_pages(unsigned long pfn,
1973-
unsigned long nr_pages)
1977+
unsigned long nr_pages, enum migratetype mt)
19741978
{
19751979
struct page *page;
19761980
unsigned long i;
@@ -1983,8 +1987,7 @@ static void __init deferred_free_pages(unsigned long pfn,
19831987
/* Free a large naturally-aligned chunk if possible */
19841988
if (nr_pages == MAX_ORDER_NR_PAGES && IS_MAX_ORDER_ALIGNED(pfn)) {
19851989
for (i = 0; i < nr_pages; i += pageblock_nr_pages)
1986-
init_pageblock_migratetype(page + i, MIGRATE_MOVABLE,
1987-
false);
1990+
init_pageblock_migratetype(page + i, mt, false);
19881991
__free_pages_core(page, MAX_PAGE_ORDER, MEMINIT_EARLY);
19891992
return;
19901993
}
@@ -1994,8 +1997,7 @@ static void __init deferred_free_pages(unsigned long pfn,
19941997

19951998
for (i = 0; i < nr_pages; i++, page++, pfn++) {
19961999
if (pageblock_aligned(pfn))
1997-
init_pageblock_migratetype(page, MIGRATE_MOVABLE,
1998-
false);
2000+
init_pageblock_migratetype(page, mt, false);
19992001
__free_pages_core(page, 0, MEMINIT_EARLY);
20002002
}
20012003
}
@@ -2053,6 +2055,8 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn,
20532055
for_each_free_mem_range(i, nid, 0, &start, &end, NULL) {
20542056
unsigned long spfn = PFN_UP(start);
20552057
unsigned long epfn = PFN_DOWN(end);
2058+
enum migratetype mt =
2059+
kho_scratch_migratetype(spfn, MIGRATE_MOVABLE);
20562060

20572061
if (spfn >= end_pfn)
20582062
break;
@@ -2065,7 +2069,7 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn,
20652069
unsigned long chunk_end = min(mo_pfn, epfn);
20662070

20672071
nr_pages += deferred_init_pages(zone, spfn, chunk_end);
2068-
deferred_free_pages(spfn, chunk_end - spfn);
2072+
deferred_free_pages(spfn, chunk_end - spfn, mt);
20692073

20702074
spfn = chunk_end;
20712075

0 commit comments

Comments
 (0)