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

Jinjie Ruan <[email protected]>
Newsgroups org.infradead.lists.kexec,org.kernel.vger.linux-kernel
Message-ID <[email protected]>

在 2026/8/13 1:04, Ionut Nechita (Wind River) 写道:
> From: Ionut Nechita <[email protected]>
> 
> 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 <[email protected]>
> ---
>  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
  * 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);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.