]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
kho: make sure scratch size is always aligned by CMA_MIN_ALIGNMENT_BYTES
authorPratyush Yadav (Google) <pratyush@kernel.org>
Tue, 19 May 2026 16:05:49 +0000 (18:05 +0200)
committerMike Rapoport (Microsoft) <rppt@kernel.org>
Mon, 1 Jun 2026 06:19:38 +0000 (09:19 +0300)
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: 3dc92c311498 ("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>
kernel/liveupdate/kexec_handover.c

index eb8abd04e7ffdbde0ddcf4c0438dde1a7c173628..4834a809985ab7abbcb6d2e9dd6f4a01cf71a711 100644 (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)