summaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-21 09:46:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-21 09:46:14 -0700
commitd639d9fa162aadec1ae9980c4dcf6e50bd2f8290 (patch)
treef9bc42aecac73a391e96e08d944a8fe962821356 /mm
parent1e762b53a86d7ed19016c66cc1883e4b9f8b2c1b (diff)
parente98a9c61721c14bcd29f11f4802e52e908701f7a (diff)
Merge tag 'liveupdate-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux
Pull liveupdate updates from Mike Rapoport: "Kexec Handover (KHO): - make memory preservation compatible with deferred initialization of the memory map Live Update Orchestrator (LUO): - add LIVEUPDATE_SESSION_GET_NAME ioctl and parameter verification for LIVEUPDATE_IOCTL_CREATE_SESSION ioctl - documentation updates for liveupdate=on command line option, systemd support and the current compatibility status - remove the fixed limits on the number of files that can be preserved within a single session, and the total number of sessions managed by the LUO Misc fixes: - reference count incoming File-Lifecycle-Bound (FLB) data so it cannot be freed while a subsystem is still using it - fixes for a TOCTOU race in luo_session_retrieve(), a use- after-free in the file finish and unpreserve paths, concurrent session mutations during reboot and serialization on preserve_context kexec - make sure ioctls for incoming LUO sessions are blocked for outgoing sessions and vice versa - make sure KHO scratch size is always aligned by CMA_MIN_ALIGNMENT_BYTES - fix memblock tests build issue introduced by KHO changes" * tag 'liveupdate-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux: (36 commits) liveupdate: Document that retrieve failure is permanent docs: memfd_preservation: fix rendering of ABI documentation selftests/liveupdate: Add stress-files kexec test selftests/liveupdate: Add stress-sessions kexec test selftests/liveupdate: Test session and file limit removal liveupdate: Remove limit on the number of files per session liveupdate: Remove limit on the number of sessions liveupdate: defer session block allocation and physical address setting kho: add support for linked-block serialization liveupdate: Extract luo_session_deserialize_one helper liveupdate: Extract luo_file_deserialize_one helper liveupdate: register luo_ser as KHO subtree liveupdate: centralize state management into struct luo_ser liveupdate: avoid mixing cleanup guards with goto in luo_session_retrieve_fd liveupdate: change file_set->count type to u64 for type safety liveupdate: Remove unused ser field from struct luo_session liveupdate: fix u-a-f in luo_file_unpreserve_files() and luo_file_finish() liveupdate: block session mutations during reboot liveupdate: fix TOCTOU race in luo_session_retrieve() liveupdate: skip serialization for context-preserving kexec ...
Diffstat (limited to 'mm')
-rw-r--r--mm/memblock.c56
-rw-r--r--mm/mm_init.c30
2 files changed, 39 insertions, 47 deletions
diff --git a/mm/memblock.c b/mm/memblock.c
index ccd43f3abb82..6349c48154f4 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1028,40 +1028,6 @@ int __init_memblock memblock_physmem_add(phys_addr_t base, phys_addr_t size)
}
#endif
-#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH
-__init void memblock_set_kho_scratch_only(void)
-{
- kho_scratch_only = true;
-}
-
-__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
-
/**
* memblock_setclr_flag - set or clear flag for a memory region
* @type: memblock type to set/clear flag for
@@ -2535,6 +2501,28 @@ int reserve_mem_release_by_name(const char *name)
return 1;
}
+#ifdef CONFIG_MEMBLOCK_KHO_SCRATCH
+__init void memblock_set_kho_scratch_only(void)
+{
+ kho_scratch_only = true;
+}
+
+__init void memblock_clear_kho_scratch_only(void)
+{
+ kho_scratch_only = false;
+}
+
+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
+
#ifdef CONFIG_KEXEC_HANDOVER
static int __init reserved_mem_preserve(void)
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 65623f95bec3..0f64909e8d20 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -706,9 +706,11 @@ void __meminit __init_page_from_nid(unsigned long pfn, int nid)
}
__init_single_page(pfn_to_page(pfn), pfn, zid, nid);
- if (pageblock_aligned(pfn))
- init_pageblock_migratetype(pfn_to_page(pfn), MIGRATE_MOVABLE,
- false);
+ if (pageblock_aligned(pfn)) {
+ enum migratetype mt =
+ kho_scratch_migratetype(pfn, MIGRATE_MOVABLE);
+ init_pageblock_migratetype(pfn_to_page(pfn), mt, false);
+ }
}
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
@@ -941,7 +943,8 @@ void __meminit memmap_init_range(unsigned long size, int nid, unsigned long zone
static void __init memmap_init_zone_range(struct zone *zone,
unsigned long start_pfn,
unsigned long end_pfn,
- unsigned long *hole_pfn)
+ unsigned long *hole_pfn,
+ enum migratetype mt)
{
unsigned long zone_start_pfn = zone->zone_start_pfn;
unsigned long zone_end_pfn = zone_start_pfn + zone->spanned_pages;
@@ -954,8 +957,7 @@ static void __init memmap_init_zone_range(struct zone *zone,
return;
memmap_init_range(end_pfn - start_pfn, nid, zone_id, start_pfn,
- zone_end_pfn, MEMINIT_EARLY, NULL, MIGRATE_MOVABLE,
- false);
+ zone_end_pfn, MEMINIT_EARLY, NULL, mt, false);
if (*hole_pfn < start_pfn)
init_unavailable_range(*hole_pfn, start_pfn, zone_id, nid);
@@ -971,6 +973,8 @@ static void __init memmap_init(void)
for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
struct pglist_data *node = NODE_DATA(nid);
+ enum migratetype mt =
+ kho_scratch_migratetype(start_pfn, MIGRATE_MOVABLE);
for (j = 0; j < MAX_NR_ZONES; j++) {
struct zone *zone = node->node_zones + j;
@@ -979,7 +983,7 @@ static void __init memmap_init(void)
continue;
memmap_init_zone_range(zone, start_pfn, end_pfn,
- &hole_pfn);
+ &hole_pfn, mt);
zone_id = j;
}
}
@@ -1969,7 +1973,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;
@@ -1982,8 +1986,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;
}
@@ -1993,8 +1996,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);
}
}
@@ -2052,6 +2054,8 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn,
for_each_free_mem_range(i, nid, 0, &start, &end, NULL) {
unsigned long spfn = PFN_UP(start);
unsigned long epfn = PFN_DOWN(end);
+ enum migratetype mt =
+ kho_scratch_migratetype(spfn, MIGRATE_MOVABLE);
if (spfn >= end_pfn)
break;
@@ -2064,7 +2068,7 @@ deferred_init_memmap_chunk(unsigned long start_pfn, unsigned long end_pfn,
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;