Re: [PATCH v14 7/7] x86/crash: add x86 crash hotplug support

2022-12-08 Thread Eric DeVolder




On 12/7/22 04:19, Borislav Petkov wrote:

On Wed, Nov 16, 2022 at 04:46:43PM -0500, Eric DeVolder wrote:

When CPU or memory is hot un/plugged, the crash elfcorehdr, which
describes the CPUs and memory in the system, must also be updated.

A new elfcorehdr is generated from the available CPUs and memory
into a buffer, and then installed over the top of the existing
elfcorehdr. The segment containing the elfcorehdr is identified
at run time in crash_core:handle_hotplug_event(), which works for
both the kexec_load() and kexec_file_load() syscalls.

In the patch 'kexec: exclude elfcorehdr from the segment digest'
the need to update purgatory due to the change in elfcorehdr was
eliminated.  As a result, no changes to purgatory or boot_params
(as the elfcorehdr= kernel command line parameter pointer
remains unchanged and correct) are needed, just elfcorehdr.

To accommodate a growing number of resources via hotplug, the
elfcorehdr segment must be sufficiently large enough to accommodate
changes, see the CRASH_MAX_MEMORY_RANGES description.

Signed-off-by: Eric DeVolder 
---
  arch/x86/Kconfig |   9 +++
  arch/x86/include/asm/kexec.h |  15 +
  arch/x86/kernel/crash.c  | 106 ++-
  3 files changed, 127 insertions(+), 3 deletions(-)


Some quick cleanups ontop, there's potential for more:

---
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ffee99046942..486509030d3a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2091,13 +2091,16 @@ config CRASH_DUMP
  For more details see Documentation/admin-guide/kdump/kdump.rst
  
  config CRASH_HOTPLUG

-   bool "kernel updates of crash elfcorehdr"
+   bool "Update the crash elfcorehdr on system configuration changes"
default n
depends on CRASH_DUMP && (HOTPLUG_CPU || MEMORY_HOTPLUG)
help
- Enable the kernel to directly update the crash elfcorehdr (which
- contains the list of CPUs and memory regions to be dumped upon
- a crash) in response to hot plug/unplug of CPUs or memory.
+ Enable direct updates to the crash elfcorehdr (which contains
+ the list of CPUs and memory regions to be dumped upon a crash)
+ in response to hot plug/unplug of CPUs or memory. This is a much
+ more advanced approach than userspace attempting that.
+
+ If unsure, say Y.

Done!

  
  config KEXEC_JUMP

bool "kexec jump"
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index d2238bcf8106..d26f208e582e 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -413,25 +413,32 @@ int crash_load_segments(struct kimage *image)
image->elf_headers_sz= kbuf.bufsz;
kbuf.memsz  = kbuf.bufsz;
  
-#ifdef CONFIG_CRASH_HOTPLUG

-   /* Ensure elfcorehdr segment large enough for hotplug changes */
-   unsigned long pnum = 2; /* VMCOREINFO and kernel_map */
-
-   if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
-   pnum += CONFIG_NR_CPUS_DEFAULT;
-   if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
-   pnum += CRASH_MAX_MEMORY_RANGES;
-   if (pnum < (unsigned long)PN_XNUM) {
-   kbuf.memsz = pnum * sizeof(Elf64_Phdr);
-   kbuf.memsz += sizeof(Elf64_Ehdr);
-   image->elfcorehdr_index = image->nr_segments;
-   image->elfcorehdr_index_valid = true;
-   /* Mark as usable to crash kernel, else crash kernel fails on 
boot */
-   image->elf_headers_sz = kbuf.memsz;
-   } else {
-   pr_err("number of Phdrs %lu exceeds max\n", pnum);
+   if (IS_ENABLED(CONFIG_CRASH_HOTPLUG)) {
+   /*
+* Ensure the elfcorehdr segment large enough for hotplug 
changes.
+* Start with VMCOREINFO and kernel_map:
+*/
+   unsigned long pnum = 2;
+
+   if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
+   pnum += CONFIG_NR_CPUS_DEFAULT;
+
+   if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+   pnum += CRASH_MAX_MEMORY_RANGES;
+
+   if (pnum < (unsigned long)PN_XNUM) {
+   kbuf.memsz = pnum * sizeof(Elf64_Phdr);
+   kbuf.memsz += sizeof(Elf64_Ehdr);
+
+   image->elfcorehdr_index = image->nr_segments;
+   image->elfcorehdr_index_valid = true;
+
+   /* Mark as usable to crash kernel, else crash kernel 
fails on boot */
+   image->elf_headers_sz = kbuf.memsz;
+   } else {
+   pr_err("number of Phdrs %lu exceeds max\n", pnum);
+   }

Done, converted this block to an IS_ENABLED(CONFIG_CRASH_HOTPLUG).


}
-#endif
  
  	kbuf.buf_align = ELF_CORE_HEADER_ALIGN;

kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
@@ -463,10 +470,9 @@ int crash_load_segments(struct kimage *image)
   */
  void 

Re: [PATCH v14 7/7] x86/crash: add x86 crash hotplug support

2022-12-07 Thread Borislav Petkov
On Wed, Nov 16, 2022 at 04:46:43PM -0500, Eric DeVolder wrote:
> When CPU or memory is hot un/plugged, the crash elfcorehdr, which
> describes the CPUs and memory in the system, must also be updated.
> 
> A new elfcorehdr is generated from the available CPUs and memory
> into a buffer, and then installed over the top of the existing
> elfcorehdr. The segment containing the elfcorehdr is identified
> at run time in crash_core:handle_hotplug_event(), which works for
> both the kexec_load() and kexec_file_load() syscalls.
> 
> In the patch 'kexec: exclude elfcorehdr from the segment digest'
> the need to update purgatory due to the change in elfcorehdr was
> eliminated.  As a result, no changes to purgatory or boot_params
> (as the elfcorehdr= kernel command line parameter pointer
> remains unchanged and correct) are needed, just elfcorehdr.
> 
> To accommodate a growing number of resources via hotplug, the
> elfcorehdr segment must be sufficiently large enough to accommodate
> changes, see the CRASH_MAX_MEMORY_RANGES description.
> 
> Signed-off-by: Eric DeVolder 
> ---
>  arch/x86/Kconfig |   9 +++
>  arch/x86/include/asm/kexec.h |  15 +
>  arch/x86/kernel/crash.c  | 106 ++-
>  3 files changed, 127 insertions(+), 3 deletions(-)

Some quick cleanups ontop, there's potential for more:

---
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ffee99046942..486509030d3a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2091,13 +2091,16 @@ config CRASH_DUMP
  For more details see Documentation/admin-guide/kdump/kdump.rst
 
 config CRASH_HOTPLUG
-   bool "kernel updates of crash elfcorehdr"
+   bool "Update the crash elfcorehdr on system configuration changes"
default n
depends on CRASH_DUMP && (HOTPLUG_CPU || MEMORY_HOTPLUG)
help
- Enable the kernel to directly update the crash elfcorehdr (which
- contains the list of CPUs and memory regions to be dumped upon
- a crash) in response to hot plug/unplug of CPUs or memory.
+ Enable direct updates to the crash elfcorehdr (which contains
+ the list of CPUs and memory regions to be dumped upon a crash)
+ in response to hot plug/unplug of CPUs or memory. This is a much
+ more advanced approach than userspace attempting that.
+
+ If unsure, say Y.
 
 config KEXEC_JUMP
bool "kexec jump"
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index d2238bcf8106..d26f208e582e 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -413,25 +413,32 @@ int crash_load_segments(struct kimage *image)
image->elf_headers_sz   = kbuf.bufsz;
kbuf.memsz  = kbuf.bufsz;
 
-#ifdef CONFIG_CRASH_HOTPLUG
-   /* Ensure elfcorehdr segment large enough for hotplug changes */
-   unsigned long pnum = 2; /* VMCOREINFO and kernel_map */
-
-   if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
-   pnum += CONFIG_NR_CPUS_DEFAULT;
-   if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
-   pnum += CRASH_MAX_MEMORY_RANGES;
-   if (pnum < (unsigned long)PN_XNUM) {
-   kbuf.memsz = pnum * sizeof(Elf64_Phdr);
-   kbuf.memsz += sizeof(Elf64_Ehdr);
-   image->elfcorehdr_index = image->nr_segments;
-   image->elfcorehdr_index_valid = true;
-   /* Mark as usable to crash kernel, else crash kernel fails on 
boot */
-   image->elf_headers_sz = kbuf.memsz;
-   } else {
-   pr_err("number of Phdrs %lu exceeds max\n", pnum);
+   if (IS_ENABLED(CONFIG_CRASH_HOTPLUG)) {
+   /*
+* Ensure the elfcorehdr segment large enough for hotplug 
changes.
+* Start with VMCOREINFO and kernel_map:
+*/
+   unsigned long pnum = 2;
+
+   if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
+   pnum += CONFIG_NR_CPUS_DEFAULT;
+
+   if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+   pnum += CRASH_MAX_MEMORY_RANGES;
+
+   if (pnum < (unsigned long)PN_XNUM) {
+   kbuf.memsz = pnum * sizeof(Elf64_Phdr);
+   kbuf.memsz += sizeof(Elf64_Ehdr);
+
+   image->elfcorehdr_index = image->nr_segments;
+   image->elfcorehdr_index_valid = true;
+
+   /* Mark as usable to crash kernel, else crash kernel 
fails on boot */
+   image->elf_headers_sz = kbuf.memsz;
+   } else {
+   pr_err("number of Phdrs %lu exceeds max\n", pnum);
+   }
}
-#endif
 
kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
@@ -463,10 +470,9 @@ int crash_load_segments(struct kimage *image)
  */
 void arch_crash_handle_hotplug_event(struct kimage *image)
 {
+   void *elfbuf, *old_elfcorehdr;
unsigned long 

[PATCH v14 7/7] x86/crash: add x86 crash hotplug support

2022-11-16 Thread Eric DeVolder
When CPU or memory is hot un/plugged, the crash elfcorehdr, which
describes the CPUs and memory in the system, must also be updated.

A new elfcorehdr is generated from the available CPUs and memory
into a buffer, and then installed over the top of the existing
elfcorehdr. The segment containing the elfcorehdr is identified
at run time in crash_core:handle_hotplug_event(), which works for
both the kexec_load() and kexec_file_load() syscalls.

In the patch 'kexec: exclude elfcorehdr from the segment digest'
the need to update purgatory due to the change in elfcorehdr was
eliminated.  As a result, no changes to purgatory or boot_params
(as the elfcorehdr= kernel command line parameter pointer
remains unchanged and correct) are needed, just elfcorehdr.

To accommodate a growing number of resources via hotplug, the
elfcorehdr segment must be sufficiently large enough to accommodate
changes, see the CRASH_MAX_MEMORY_RANGES description.

Signed-off-by: Eric DeVolder 
---
 arch/x86/Kconfig |   9 +++
 arch/x86/include/asm/kexec.h |  15 +
 arch/x86/kernel/crash.c  | 106 ++-
 3 files changed, 127 insertions(+), 3 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 67745ceab0db..fc7b6457a0b4 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2072,6 +2072,15 @@ config CRASH_DUMP
  (CONFIG_RELOCATABLE=y).
  For more details see Documentation/admin-guide/kdump/kdump.rst
 
+config CRASH_HOTPLUG
+   bool "kernel updates of crash elfcorehdr"
+   default n
+   depends on CRASH_DUMP && (HOTPLUG_CPU || MEMORY_HOTPLUG)
+   help
+ Enable the kernel to directly update the crash elfcorehdr (which
+ contains the list of CPUs and memory regions to be dumped upon
+ a crash) in response to hot plug/unplug of CPUs or memory.
+
 config KEXEC_JUMP
bool "kexec jump"
depends on KEXEC && HIBERNATION
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index a3760ca796aa..1bc852ce347d 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -212,6 +212,21 @@ typedef void crash_vmclear_fn(void);
 extern crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss;
 extern void kdump_nmi_shootdown_cpus(void);
 
+#ifdef CONFIG_CRASH_HOTPLUG
+void arch_crash_handle_hotplug_event(struct kimage *image);
+#define arch_crash_handle_hotplug_event arch_crash_handle_hotplug_event
+
+#ifdef CONFIG_HOTPLUG_CPU
+static inline int crash_hotplug_cpu_support(void) { return 1; }
+#define crash_hotplug_cpu_support crash_hotplug_cpu_support
+#endif
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+static inline int crash_hotplug_memory_support(void) { return 1; }
+#define crash_hotplug_memory_support crash_hotplug_memory_support
+#endif
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_KEXEC_H */
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 9ceb93c176a6..d2238bcf8106 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -42,6 +42,21 @@
 #include 
 #include 
 
+/*
+ * For the kexec_file_load() syscall path, specify the maximum number of
+ * memory regions that the elfcorehdr buffer/segment can accommodate.
+ * These regions are obtained via walk_system_ram_res(); eg. the
+ * 'System RAM' entries in /proc/iomem.
+ * This value is combined with NR_CPUS_DEFAULT and multiplied by
+ * sizeof(Elf64_Phdr) to determine the final elfcorehdr memory buffer/
+ * segment size.
+ * The value 8192, for example, covers a (sparsely populated) 1TiB system
+ * consisting of 128MiB memblocks, while resulting in an elfcorehdr
+ * memory buffer/segment size under 1MiB. This represents a sane choice
+ * to accommodate both baremetal and virtual machine configurations.
+ */
+#define CRASH_MAX_MEMORY_RANGES 8192
+
 /* Used while preparing memory map entries for second kernel */
 struct crash_memmap_data {
struct boot_params *params;
@@ -394,10 +409,30 @@ int crash_load_segments(struct kimage *image)
if (ret)
return ret;
 
-   image->elf_headers = kbuf.buffer;
-   image->elf_headers_sz = kbuf.bufsz;
+   image->elf_headers  = kbuf.buffer;
+   image->elf_headers_sz   = kbuf.bufsz;
+   kbuf.memsz  = kbuf.bufsz;
+
+#ifdef CONFIG_CRASH_HOTPLUG
+   /* Ensure elfcorehdr segment large enough for hotplug changes */
+   unsigned long pnum = 2; /* VMCOREINFO and kernel_map */
+
+   if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
+   pnum += CONFIG_NR_CPUS_DEFAULT;
+   if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+   pnum += CRASH_MAX_MEMORY_RANGES;
+   if (pnum < (unsigned long)PN_XNUM) {
+   kbuf.memsz = pnum * sizeof(Elf64_Phdr);
+   kbuf.memsz += sizeof(Elf64_Ehdr);
+   image->elfcorehdr_index = image->nr_segments;
+   image->elfcorehdr_index_valid = true;
+   /* Mark as usable to crash kernel, else crash kernel fails on 
boot */
+