[PATCH v2 0/2] x86/crash: fix kexec_file_load(2) -EINVAL on machines with many possible CPUs
From: Ionut Nechita (Wind River)
Date: Tue Aug 25 2026 - 03:58:57 EST
From: Ionut Nechita <ionut.nechita@xxxxxxxxxxxxx>
Hi,
On x86 with CONFIG_CRASH_HOTPLUG=y and CONFIG_MEMORY_HOTPLUG=n, the
crash elfcorehdr segment is reserved for
nr_mem_ranges + 2 + CONFIG_NR_CPUS_DEFAULT
program headers, while the header that crash_prepare_elf64_headers()
actually builds carries
nr_mem_ranges + 2 + num_possible_cpus()
of them. num_possible_cpus() is bounded by CONFIG_NR_CPUS, not by
CONFIG_NR_CPUS_DEFAULT, so on configs that raise CONFIG_NR_CPUS above
the arch default without MAXSMP the header outgrows its reservation once
the excess exceeds the page padding, and kexec_file_load(2) is rejected
by sanity_check_segment_list() with -EINVAL. The classic kexec_load(2)
path is unaffected because user space builds the elfcorehdr without the
hotplug over-allocation.
Patch 1 reserves the elfcorehdr for CONFIG_NR_CPUS, the compile-time
upper bound of num_possible_cpus(), so the reservation always covers the
header that is actually generated.
Patch 2 is a documentation-only follow-up requested during v1 review: it
updates the two remaining places that still name NR_CPUS_DEFAULT when
describing the elfcorehdr sizing (the comment above
crash_handle_hotplug_event() and the CRASH_MAX_MEMORY_RANGES help text).
Based on linux-next (next-20260824, base-commit 4b18edbd8e70f).
Verified on a single-socket Xeon 6776P running a PREEMPT_RT kernel with:
# CONFIG_MAXSMP is not set
# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_NR_CPUS_RANGE_BEGIN=2
CONFIG_NR_CPUS_RANGE_END=512
CONFIG_NR_CPUS_DEFAULT=64
CONFIG_NR_CPUS=256
CONFIG_CRASH_MAX_MEMORY_RANGES=8192
- 144 possible CPUs: excess is (144 - 64) * 56 = 4480 bytes, more than
the 4096 bytes of page padding, so 'kexec -p -s' fails with
"kexec_file_load failed: Invalid argument"
- 72 possible CPUs (reduced via firmware): excess is (72 - 64) * 56 =
448 bytes, still absorbed by the page rounding, and the load succeeds
Changes since v1:
- Patch 1/2: the changelog has been substantially rewritten. v1
described the reservation as "2 + CONFIG_NR_CPUS_DEFAULT" and did not
explain where the CPU term goes missing. The actual mechanism is that
the @pnum the reservation builds on is crash_prepare_headers()'s
@nr_mem_ranges out parameter - a memory range count, not a phdr count
- so the CONFIG_NR_CPUS_DEFAULT term is the entire CPU allowance, and
it is exceeded as soon as num_possible_cpus() > CONFIG_NR_CPUS_DEFAULT
(modulo the page rounding on both sides). The changelog now spells
this out, including why the CONFIG_MEMORY_HOTPLUG=y path does not fail
in practice with the default CONFIG_CRASH_MAX_MEMORY_RANGES=8192.
- Patch 1/2: the Fixes: tag was wrong in v1. The two lines being
changed were introduced by ea53ad9cf73b ("x86/crash: add x86 crash
hotplug support"), not by a72bbec70da2 ("crash: hotplug support for
kexec_load()") - which is the kexec_load(2) commit, i.e. the path this
patch does not touch. Corrected.
- Patch 1/2: added a paragraph on memory impact, and the reproducer now
states CONFIG_MEMORY_HOTPLUG and CONFIG_CRASH_MAX_MEMORY_RANGES, which
v1 omitted and which are needed to reproduce.
- Added patch 2/2 updating the stale NR_CPUS_DEFAULT references in the
crash_handle_hotplug_event() comment (Jinjie Ruan) and in the
CRASH_MAX_MEMORY_RANGES Kconfig help text (Bradley Morgan).
- Rebased from next-20260811 onto next-20260824.
Jinjie, Bradley: the code in patch 1/2 is byte-identical to v1, so I
carried your Reviewed-by tags, but given how much the changelog and the
Fixes: tag changed please re-check that you are still happy with them
and I will drop them if not.
On the num_possible_cpus() alternative raised by Jinjie in v1: it would
give a tighter reservation and powerpc's arch_crash_get_elfcorehdr_size()
already does exactly that. I kept CONFIG_NR_CPUS here because it is the
minimal, easy-to-backport fix - it just swaps the wrong compile-time
constant for the correct compile-time upper bound, and keeps both
branches of the expression homogeneous alongside the equally
compile-time CONFIG_CRASH_MAX_MEMORY_RANGES term. I am happy to respin
with num_possible_cpus() if maintainers prefer that.
v1: https://lore.kernel.org/lkml/20260812170433.533845-1-ionut.nechita@xxxxxxxxxxxxx/
Ionut Nechita (2):
x86/crash: reserve elfcorehdr for CONFIG_NR_CPUS, not
CONFIG_NR_CPUS_DEFAULT
crash: update stale NR_CPUS_DEFAULT references in elfcorehdr sizing
docs
arch/x86/kernel/crash.c | 6 +++---
kernel/Kconfig.kexec | 2 +-
kernel/crash_core.c | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
base-commit: 4b18edbd8e70f7e6860d56370f13244896d0f95c
--
2.55.0