liveupdate: a fix for v7.2-rc7

* fix a regression caused by allowing coexistence of KHO with deferred
   initialization of the memory map.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEeOVYVaWZL5900a/pOQOGJssO/ZEFAmpweGsACgkQOQOGJssO
 /ZHe4gf/b06J+YW9GO7FGQclCf3s30DbL8nNeEkb74lpWU8CAfk2vbo9QyrlYH8+
 5wtISj9+SdBwMfY4XFdDWOur1EHD47N52xbT5zL3yp1UEPpXYbggiiKuzwCXK1MZ
 lVhyc3XfPmF4eRP5V0Nr7AsN1pAujH83uRrTgg//ZJziOaOtLi7ZWJZa0Oae3UY1
 z+/bRIM21DzkL2wD2fitlYxYBmrooYRS6FVr+wv/khBnLxAtcWGM+nfHGI4/i4bK
 5oz/9D3+nD/rQBqOT6F+Vf6Dz3zPtJPLe7+B459x24f2yPzJplIt6cDq9nxZKbY2
 L7q3npvcsts7iLXVsKSeaHeEfn2l7g==
 =xzQP
 -----END PGP SIGNATURE-----

Merge tag 'liveupdate-fixes-2026-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux

Pull liveupdate fix from Mike Rapoport:

 - fix a regression caused by allowing coexistence of KHO with deferred
   initialization of the memory map

* tag 'liveupdate-fixes-2026-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux:
  kho: align kho_scratch to MAX_ORDER_NR_PAGES pages
This commit is contained in:
Linus Torvalds 2026-08-03 09:21:45 -07:00
commit c8e0d43058

View File

@ -38,6 +38,16 @@
#include "../kexec_internal.h"
#include "kexec_handover_internal.h"
/*
* This is the minimal alignment required by deferred struct page init.
* deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
* at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
* If KHO scratch is not aligned to that value, buddy can access uninitialized
* struct pages, which can cause a crash.
*/
#define SCRATCH_ALIGNMENT_BYTES (PAGE_SIZE * MAX_ORDER_NR_PAGES)
static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
/* The magic token for preserved pages */
#define KHO_PAGE_MAGIC 0x4b484f50U /* ASCII for 'KHOP' */
@ -640,8 +650,8 @@ static void __init scratch_size_update(void)
* Scratch areas are released as MIGRATE_CMA. Round them up to the right
* size.
*/
scratch_size_lowmem = round_up(scratch_size_lowmem, CMA_MIN_ALIGNMENT_BYTES);
scratch_size_global = round_up(scratch_size_global, CMA_MIN_ALIGNMENT_BYTES);
scratch_size_lowmem = round_up(scratch_size_lowmem, SCRATCH_ALIGNMENT_BYTES);
scratch_size_global = round_up(scratch_size_global, SCRATCH_ALIGNMENT_BYTES);
}
static phys_addr_t __init scratch_size_node(int nid)
@ -656,7 +666,7 @@ static phys_addr_t __init scratch_size_node(int nid)
size = scratch_size_pernode;
}
return round_up(size, CMA_MIN_ALIGNMENT_BYTES);
return round_up(size, SCRATCH_ALIGNMENT_BYTES);
}
/**
@ -692,7 +702,7 @@ static void __init kho_reserve_scratch(void)
* next kernel
*/
size = scratch_size_lowmem;
addr = memblock_phys_alloc_range(size, CMA_MIN_ALIGNMENT_BYTES, 0,
addr = memblock_phys_alloc_range(size, SCRATCH_ALIGNMENT_BYTES, 0,
ARCH_LOW_ADDRESS_LIMIT);
if (!addr) {
pr_err("Failed to reserve lowmem scratch buffer\n");
@ -705,7 +715,7 @@ static void __init kho_reserve_scratch(void)
/* reserve large contiguous area for allocations without nid */
size = scratch_size_global;
addr = memblock_phys_alloc(size, CMA_MIN_ALIGNMENT_BYTES);
addr = memblock_phys_alloc(size, SCRATCH_ALIGNMENT_BYTES);
if (!addr) {
pr_err("Failed to reserve global scratch buffer\n");
goto err_free_scratch_areas;
@ -721,7 +731,7 @@ static void __init kho_reserve_scratch(void)
*/
for_each_node_state(nid, N_MEMORY) {
size = scratch_size_node(nid);
addr = memblock_alloc_range_nid(size, CMA_MIN_ALIGNMENT_BYTES,
addr = memblock_alloc_range_nid(size, SCRATCH_ALIGNMENT_BYTES,
0, MEMBLOCK_ALLOC_ACCESSIBLE,
nid, true);
if (!addr) {