kho: make sure scratch size is always aligned by CMA_MIN_ALIGNMENT_BYTES

When using scratch_scale, the scratch sizes are rounded up to
CMA_MIN_ALIGNMENT_BYTES since they will be released as MIGRATE_CMA. This
is not done when using fixed scratch sizes via command line. This can
result in user specifying a size which is not aligned, and thus kernel
releasing a pageblock that is only partially scratch.

Do the rounding up for both cases in scratch_size_update().

Fixes: 3dc92c3114 ("kexec: add Kexec HandOver (KHO) generation helpers")
Cc: stable@kernel.org
Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
Link: https://patch.msgid.link/20260519160554.2713361-1-pratyush@kernel.org
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
This commit is contained in:
Pratyush Yadav (Google) 2026-05-19 18:05:49 +02:00 committed by Mike Rapoport (Microsoft)
parent 6bd280c7fe
commit 0e39380a73

View File

@ -618,20 +618,30 @@ early_param("kho_scratch", kho_parse_scratch_size);
static void __init scratch_size_update(void)
{
phys_addr_t size;
/*
* If fixed sizes are not provided via command line, calculate them
* now.
*/
if (scratch_scale) {
phys_addr_t size;
if (!scratch_scale)
return;
size = memblock_reserved_kern_size(ARCH_LOW_ADDRESS_LIMIT,
NUMA_NO_NODE);
size = size * scratch_scale / 100;
scratch_size_lowmem = size;
size = memblock_reserved_kern_size(ARCH_LOW_ADDRESS_LIMIT,
NUMA_NO_NODE);
size = size * scratch_scale / 100;
scratch_size_lowmem = round_up(size, CMA_MIN_ALIGNMENT_BYTES);
size = memblock_reserved_kern_size(MEMBLOCK_ALLOC_ANYWHERE,
NUMA_NO_NODE);
size = size * scratch_scale / 100 - scratch_size_lowmem;
scratch_size_global = size;
}
size = memblock_reserved_kern_size(MEMBLOCK_ALLOC_ANYWHERE,
NUMA_NO_NODE);
size = size * scratch_scale / 100 - scratch_size_lowmem;
scratch_size_global = round_up(size, CMA_MIN_ALIGNMENT_BYTES);
/*
* 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);
}
static phys_addr_t __init scratch_size_node(int nid)