Re: [PATCH 1/1] x86/crash: reserve elfcorehdr for CONFIG_NR_CPUS, not CONFIG_NR_CPUS_DEFAULT

Bradley Morgan include at grrlz.net
Mon Aug 17 16:16:18 PDT 2026


On 17 August 2026 02:18:59 BST, Jinjie Ruan <ruanjinjie at huawei.com> wrote:
>
>
>在 2026/8/13 1:04, Ionut Nechita (Wind River) 写道:
>> From: Ionut Nechita <ionut.nechita at windriver.com>
>> 
>> kexec_file_load(2) fails with -EINVAL when loading a crash kernel on a
>> machine whose number of possible CPUs exceeds CONFIG_NR_CPUS_DEFAULT,
>> even though the classic kexec_load(2) path succeeds on the same machine.
>> 
>> With CONFIG_CRASH_HOTPLUG=y the elfcorehdr segment is over-allocated so
>> it can be updated in place on CPU/memory hotplug. crash_load_segments()
>> and arch_crash_get_elfcorehdr_size() compute that reservation from
>> CONFIG_NR_CPUS_DEFAULT:
>> 
>> 	if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
>> 		pnum = 2 + CONFIG_NR_CPUS_DEFAULT + CONFIG_CRASH_MAX_MEMORY_RANGES;
>> 	else
>> 		pnum += 2 + CONFIG_NR_CPUS_DEFAULT;
>> 
>> However the actual header produced by crash_prepare_elf64_headers()
>> contains one PT_NOTE per *possible* CPU, i.e. num_possible_cpus(), which
>> is bounded by CONFIG_NR_CPUS, not by CONFIG_NR_CPUS_DEFAULT.  On configs
>> that raise CONFIG_NR_CPUS above the arch default while leaving
>> CONFIG_NR_CPUS_DEFAULT untouched (e.g. CONFIG_NR_CPUS=256,
>> CONFIG_NR_CPUS_DEFAULT=64 on x86_64 without MAXSMP), a system with more
>> than ~CONFIG_NR_CPUS_DEFAULT possible CPUs builds a header whose bufsz
>> exceeds the reserved, page-aligned memsz.  sanity_check_segment_list()
>> then rejects the image:
>> 
>> 	if (image->segment[i].bufsz > image->segment[i].memsz)
>> 		return -EINVAL;
>> 
>> kexec_load(2) is unaffected because user space builds the elfcorehdr
>> without the hotplug over-allocation.
>> 
>> Observed on a single-socket Xeon 6776P (144 possible CPUs) running a
>> PREEMPT_RT kernel with:
>> 
>> 	# CONFIG_MAXSMP is not set
>> 	CONFIG_NR_CPUS_RANGE_BEGIN=2
>> 	CONFIG_NR_CPUS_RANGE_END=512
>> 	CONFIG_NR_CPUS_DEFAULT=64
>> 	CONFIG_NR_CPUS=256
>> 
>> kexec -p -s fails with "kexec_file_load failed: Invalid argument".
>> Reducing the possible CPU count below the page-rounding threshold
>> (e.g. 72 via firmware) makes it succeed, confirming the reservation is
>> the limiting factor.
>> 
>> Reserve 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.
>> 
>> Fixes: a72bbec70da2 ("crash: hotplug support for kexec_load()")
>> Signed-off-by: Ionut Nechita <ionut.nechita at windriver.com>
>> ---
>>  arch/x86/kernel/crash.c | 6 +++---
>
>We should also update the comment in crash_handle_hotplug_event() to
>avoid misleading people.
>
>diff --git a/kernel/crash_core.c b/kernel/crash_core.c
>index 4f21fc3b108b..b046c1682aad 100644
>--- a/kernel/crash_core.c
>+++ b/kernel/crash_core.c
>@@ -565,7 +565,7 @@ int crash_check_hotplug_support(void)
>  * new list of CPUs and memory. To make changes to the elfcorehdr, it
>  * should be large enough to permit a growing number of CPU and Memory
>  * resources. One can estimate the elfcorehdr memory size based on
>- * NR_CPUS_DEFAULT and CRASH_MAX_MEMORY_RANGES. The elfcorehdr is
>+ * NR_CPUS and CRASH_MAX_MEMORY_RANGES. The elfcorehdr is

One more spot carries the same stale name though:

kernel/Kconfig.kexec: "This value is combined with NR_CPUS_DEFAULT
and multiplied by sizeof(Elf64_Phdr) to determine the final
elfcorehdr memory buffer/segment size."

The CRASH_MAX_MEMORY_RANGES help text needs the same
s/NR_CPUS_DEFAULT/NR_CPUS/, either here or in Ionut's v2.



Reviewed-by: Bradley Morgan <include at grrlz.net>


>  * excluded from SHA verification by default if the architecture
>  * supports crash hotplug.
>  */
>
>
>>  1 file changed, 3 insertions(+), 3 deletions(-)
>> 
>> diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
>> index e681ec9cf1dc8..e6f23933a6df2 100644
>> --- a/arch/x86/kernel/crash.c
>> +++ b/arch/x86/kernel/crash.c
>> @@ -369,9 +369,9 @@ int crash_load_segments(struct kimage *image)
>>  	 * maximum CPUs and maximum memory ranges.
>>  	 */
>>  	if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
>> -		pnum = 2 + CONFIG_NR_CPUS_DEFAULT + CONFIG_CRASH_MAX_MEMORY_RANGES;
>> +		pnum = 2 + CONFIG_NR_CPUS + CONFIG_CRASH_MAX_MEMORY_RANGES;
>>  	else
>> -		pnum += 2 + CONFIG_NR_CPUS_DEFAULT;
>> +		pnum += 2 + CONFIG_NR_CPUS;
>>  
>>  	if (pnum < (unsigned long)PN_XNUM) {
>>  		kbuf.memsz = pnum * sizeof(Elf64_Phdr);
>> @@ -430,7 +430,7 @@ unsigned int arch_crash_get_elfcorehdr_size(void)
>>  	unsigned int sz;
>>  
>>  	/* kernel_map, VMCOREINFO and maximum CPUs */
>> -	sz = 2 + CONFIG_NR_CPUS_DEFAULT;
>> +	sz = 2 + CONFIG_NR_CPUS;
>>  	if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
>>  		sz += CONFIG_CRASH_MAX_MEMORY_RANGES;
>>  	sz *= sizeof(Elf64_Phdr);
>
>
>

Thanks!



More information about the kexec mailing list