All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] x86/crash: fix kexec_file_load(2) -EINVAL on machines with many possible CPUs
@ 2026-08-26  7:35 Ionut Nechita (Wind River)
  2026-08-26  7:35 ` [PATCH v3 1/2] x86/crash: reserve elfcorehdr for CONFIG_NR_CPUS, not CONFIG_NR_CPUS_DEFAULT Ionut Nechita (Wind River)
  2026-08-26  7:35 ` [PATCH v3 2/2] crash: update stale NR_CPUS_DEFAULT references in elfcorehdr sizing docs Ionut Nechita (Wind River)
  0 siblings, 2 replies; 4+ messages in thread
From: Ionut Nechita (Wind River) @ 2026-08-26  7:35 UTC (permalink / raw)
  To: x86, kexec
  Cc: tglx, mingo, bp, dave.hansen, hpa, akpm, baoquan.he, rppt,
	pasha.tatashin, pratyush, ruirui.yang, eric.devolder, hbathini,
	sourabhjain, ruanjinjie, include, linux-kernel

From: Ionut Nechita <ionut.nechita@windriver.com>

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.

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.  It also fixes the same shortfall in
arch_crash_get_elfcorehdr_size(), which feeds
/sys/kernel/crash_elfcorehdr_size and therefore the kexec_load(2) path.

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-20260825, base-commit a8406e6c0b79b).

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 v2:
- No code changes.  The diff is byte-identical to v2; only the patch 1/2
  changelog and the collected tags differ.
- Patch 1/2: corrected the claim that kexec_load(2) is "unaffected".
  As Sourabh Jain pointed out, with crash hotplug enabled kexec-tools
  sizes the elfcorehdr segment from /sys/kernel/crash_elfcorehdr_size in
  load_crashdump_segments(), i.e. from arch_crash_get_elfcorehdr_size(),
  which uses the same CONFIG_NR_CPUS_DEFAULT; add_segment_phys_virt()
  then clamps bufsz to memsz.  So that path does not fail the load, it
  silently truncates the elfcorehdr, which shows up later as a bad dump.
  Switching arch_crash_get_elfcorehdr_size() to CONFIG_NR_CPUS - which
  this patch already did - fixes that path as well.  The changelog now
  says so instead of claiming immunity.
- Patch 1/2: picked up Reviewed-by from Sourabh Jain and Acked-by from
  Baoquan He.
- Patch 2/2: picked up Reviewed-by from Bradley Morgan.
- Both patches: added an Assisted-by: LLM trailer, per
  Documentation/process/coding-assistants.rst.  An LLM was used for the
  root cause analysis and the changelog wording; the bug itself was
  found and reproduced on real hardware, the fix was reviewed by me, and
  the Signed-off-by is mine.  This should have been present in v1 and
  v2, and was not - my oversight.
- Rebased from next-20260824 onto next-20260825.

The two further issues Sourabh raised on the v2 thread - the
add_segment_phys_virt() bufsz truncation in kexec-tools, and having
crash_load_segments() skip the kbuf.memsz update when the prepared
buffer is already larger than the statically computed size - are
deliberately left out of this series and are worth handling separately,
as he suggested.

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.  I am happy to respin
with num_possible_cpus() if maintainers prefer that.

v1: https://lore.kernel.org/lkml/20260812170433.533845-1-ionut.nechita@windriver.com/
v2: https://lore.kernel.org/lkml/20260825075043.42041-1-ionut.nechita@windriver.com/

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: a8406e6c0b793ce0788019683837c40855b55995
--
2.55.0



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-26 13:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-26  7:35 [PATCH v3 0/2] x86/crash: fix kexec_file_load(2) -EINVAL on machines with many possible CPUs Ionut Nechita (Wind River)
2026-08-26  7:35 ` [PATCH v3 1/2] x86/crash: reserve elfcorehdr for CONFIG_NR_CPUS, not CONFIG_NR_CPUS_DEFAULT Ionut Nechita (Wind River)
2026-08-26 13:33   ` Dave Hansen
2026-08-26  7:35 ` [PATCH v3 2/2] crash: update stale NR_CPUS_DEFAULT references in elfcorehdr sizing docs Ionut Nechita (Wind River)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.