* [PATCH v1 1/7] crashdump: introduce the --hotplug option
2022-10-20 17:03 [PATCH v1 0/7] crashdump: Kernel handling of CPU and memory hot un/plug Eric DeVolder
@ 2022-10-20 17:03 ` Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 2/7] crashdump: exclude elfcorehdr segment from digest for hotplug Eric DeVolder
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Eric DeVolder @ 2022-10-20 17:03 UTC (permalink / raw)
To: kexec; +Cc: boris.ostrovsky, eric.devolder
This change introduces the --hotplug option which is to indicate
that kernel changes to the elfcorehdr, in response to hot un/plug
events, can occur.
Beginning with Linux kernel v6.x (FIX!), the kernel can modify
the elfcorehdr in response to hotplug changes to cpus and memory.
As such, the buffer containing the elfcorehdr must be excluded
from the purgatory checksum/digest; otherwise kernel changes to
the elfcorehdr as a result of hotplug would result in the checksum
failing at panic kernel boot time, and kdump fail.
This option excludes the elfcorehdr buffer from the purgatory
checksum/digest so that kernel changes to the elfcorehdr can occur.
This option is only meaningful for kexec_load syscall. For the
kexec_file_load syscall, this option is a no-op as the kernel
handles all the kexec memory segments appropriately.
Signed-off-by: Eric DeVolder <eric.devolder@oracle.com>
---
kexec/kexec.c | 6 ++++++
kexec/kexec.h | 7 ++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/kexec/kexec.c b/kexec/kexec.c
index 0e92d96..1276726 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -62,6 +62,7 @@ static unsigned long kexec_flags = 0;
/* Flags for kexec file (fd) based syscall */
static unsigned long kexec_file_flags = 0;
int kexec_debug = 0;
+int do_hotplug = 0;
void dbgprint_mem_range(const char *prefix, struct memory_range *mr, int nr_mr)
{
@@ -1057,6 +1058,8 @@ void usage(void)
" -d, --debug Enable debugging to help spot a failure.\n"
" -S, --status Return 1 if the type (by default crash) is loaded,\n"
" 0 if not.\n"
+ " --hotplug Enable kernel modification of the elfcorehdr, in\n"
+ " response to hot un/plug changes to CPUs and memory\n"
"\n"
"Supported kernel file types and options: \n");
for (i = 0; i < file_types; i++) {
@@ -1565,6 +1568,9 @@ int main(int argc, char *argv[])
case OPT_PRINT_CKR_SIZE:
print_crashkernel_region_size();
return 0;
+ case OPT_HOTPLUG:
+ do_hotplug = 1;
+ break;
default:
break;
}
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 0d820ad..7f7936d 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -231,7 +231,8 @@ extern int file_types;
#define OPT_PRINT_CKR_SIZE 262
#define OPT_LOAD_LIVE_UPDATE 263
#define OPT_EXEC_LIVE_UPDATE 264
-#define OPT_MAX 265
+#define OPT_HOTPLUG 265
+#define OPT_MAX 266
#define KEXEC_OPTIONS \
{ "help", 0, 0, OPT_HELP }, \
{ "version", 0, 0, OPT_VERSION }, \
@@ -258,6 +259,8 @@ extern int file_types;
{ "debug", 0, 0, OPT_DEBUG }, \
{ "status", 0, 0, OPT_STATUS }, \
{ "print-ckr-size", 0, 0, OPT_PRINT_CKR_SIZE }, \
+ { "hotplug", 0, 0, OPT_HOTPLUG }, \
+
#define KEXEC_OPT_STR "h?vdfixyluet:pscaS"
@@ -292,6 +295,8 @@ extern void arch_reuse_initrd(void);
extern int ifdown(void);
+extern int do_hotplug;
+
extern char purgatory[];
extern size_t purgatory_size;
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v1 2/7] crashdump: exclude elfcorehdr segment from digest for hotplug
2022-10-20 17:03 [PATCH v1 0/7] crashdump: Kernel handling of CPU and memory hot un/plug Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 1/7] crashdump: introduce the --hotplug option Eric DeVolder
@ 2022-10-20 17:03 ` Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 3/7] crashdump/x86: identify elfcorehdr segment " Eric DeVolder
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Eric DeVolder @ 2022-10-20 17:03 UTC (permalink / raw)
To: kexec; +Cc: boris.ostrovsky, eric.devolder
To allow modification of the elfcorehdr by the kernel, in
response to hot un/plug events, the buffer containing the
elfcorehdr must be excluded from the purgatory checksum/digest.
To do so, the address of the elfcorehdr is stored in info->elfcorehdr,
and the buffer is excluded from the checksum if the --hotplug option
is in effect.
Signed-off-by: Eric DeVolder <eric.devolder@oracle.com>
---
kexec/kexec.c | 9 +++++++++
kexec/kexec.h | 1 +
2 files changed, 10 insertions(+)
diff --git a/kexec/kexec.c b/kexec/kexec.c
index 1276726..90f2e71 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -673,6 +673,15 @@ static void update_purgatory(struct kexec_info *info)
if (info->segment[i].mem == (void *)info->rhdr.rel_addr) {
continue;
}
+
+ /* Do not include the elfcorehdr in the checksum, if hotplug
+ * support is enabled. The elfcorehdr is modified upon
+ * hotplug changes, and would fail checksum at crash time.
+ */
+ if (do_hotplug && (info->segment[i].mem == (void *)info->elfcorehdr)) {
+ continue;
+ }
+
sha256_update(&ctx, info->segment[i].buf,
info->segment[i].bufsz);
nullsz = info->segment[i].memsz - info->segment[i].bufsz;
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 7f7936d..9a26065 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -169,6 +169,7 @@ struct kexec_info {
int command_line_len;
int skip_checks;
+ unsigned long elfcorehdr;
};
struct arch_map_entry {
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v1 3/7] crashdump/x86: identify elfcorehdr segment for hotplug
2022-10-20 17:03 [PATCH v1 0/7] crashdump: Kernel handling of CPU and memory hot un/plug Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 1/7] crashdump: introduce the --hotplug option Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 2/7] crashdump: exclude elfcorehdr segment from digest for hotplug Eric DeVolder
@ 2022-10-20 17:03 ` Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 4/7] kexec: create get_nr_cpus() Eric DeVolder
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Eric DeVolder @ 2022-10-20 17:03 UTC (permalink / raw)
To: kexec; +Cc: boris.ostrovsky, eric.devolder
Identify and record the elfcorehdr buffer so that it can be
excluded from the purgatory checksum/digest if --hotplug is
in effect.
Signed-off-by: Eric DeVolder <eric.devolder@oracle.com>
---
kexec/arch/i386/crashdump-x86.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index df1f24c..cb86ca7 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -956,6 +956,9 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
} else {
memsz = bufsz;
}
+
+ /* Record the location of the elfcorehdr for hotplug handling */
+ info->elfcorehdr =
elfcorehdr = add_buffer(info, tmp, bufsz, memsz, align, min_base,
max_addr, -1);
dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v1 4/7] kexec: create get_nr_cpus()
2022-10-20 17:03 [PATCH v1 0/7] crashdump: Kernel handling of CPU and memory hot un/plug Eric DeVolder
` (2 preceding siblings ...)
2022-10-20 17:03 ` [PATCH v1 3/7] crashdump/x86: identify elfcorehdr segment " Eric DeVolder
@ 2022-10-20 17:03 ` Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 5/7] crashdump: introduce --elfcorehdrsz option Eric DeVolder
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Eric DeVolder @ 2022-10-20 17:03 UTC (permalink / raw)
To: kexec; +Cc: boris.ostrovsky, eric.devolder
From existing code, create function get_nr_cpus(). This function,
will be referenced from multiple locations.
No functional changes.
Signed-off-by: Eric DeVolder <eric.devolder@oracle.com>
---
kexec/crashdump-elf.c | 6 +-----
kexec/crashdump.h | 1 -
kexec/kexec-xen.h | 1 +
kexec/kexec.c | 11 +++++++++++
kexec/kexec.h | 2 ++
5 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/kexec/crashdump-elf.c b/kexec/crashdump-elf.c
index b8bb686..5e29f7a 100644
--- a/kexec/crashdump-elf.c
+++ b/kexec/crashdump-elf.c
@@ -43,11 +43,7 @@ int FUNC(struct kexec_info *info,
int (*get_note_info)(int cpu, uint64_t *addr, uint64_t *len);
long int count_cpu;
- if (xen_present())
- nr_cpus = xen_get_nr_phys_cpus();
- else
- nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
-
+ nr_cpus = get_nr_cpus();
if (nr_cpus < 0) {
return -1;
}
diff --git a/kexec/crashdump.h b/kexec/crashdump.h
index 18bd691..28d3278 100644
--- a/kexec/crashdump.h
+++ b/kexec/crashdump.h
@@ -57,7 +57,6 @@ unsigned long phys_to_virt(struct crash_elf_info *elf_info,
unsigned long long paddr);
unsigned long xen_architecture(struct crash_elf_info *elf_info);
-int xen_get_nr_phys_cpus(void);
int xen_get_note(int cpu, uint64_t *addr, uint64_t *len);
int xen_get_crashkernel_region(uint64_t *start, uint64_t *end);
diff --git a/kexec/kexec-xen.h b/kexec/kexec-xen.h
index 70fb576..f54a2dd 100644
--- a/kexec/kexec-xen.h
+++ b/kexec/kexec-xen.h
@@ -83,5 +83,6 @@ extern int __xc_interface_close(xc_interface *xch);
#endif
int xen_get_kexec_range(int range, uint64_t *start, uint64_t *end);
+int xen_get_nr_phys_cpus(void);
#endif /* KEXEC_XEN_H */
diff --git a/kexec/kexec.c b/kexec/kexec.c
index 90f2e71..d2379cb 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -490,6 +490,17 @@ static int add_backup_segments(struct kexec_info *info,
return 0;
}
+long int get_nr_cpus(void)
+{
+ long int nr_cpus;
+
+ if (xen_present())
+ nr_cpus = xen_get_nr_phys_cpus();
+ else
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ return nr_cpus;
+}
+
static char *slurp_fd(int fd, const char *filename, off_t size, off_t *nread)
{
char *buf;
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 9a26065..9675e79 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -294,6 +294,8 @@ extern unsigned long add_buffer_phys_virt(struct kexec_info *info,
int buf_end, int phys);
extern void arch_reuse_initrd(void);
+extern long int get_nr_cpus(void);
+
extern int ifdown(void);
extern int do_hotplug;
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v1 5/7] crashdump: introduce --elfcorehdrsz option
2022-10-20 17:03 [PATCH v1 0/7] crashdump: Kernel handling of CPU and memory hot un/plug Eric DeVolder
` (3 preceding siblings ...)
2022-10-20 17:03 ` [PATCH v1 4/7] kexec: create get_nr_cpus() Eric DeVolder
@ 2022-10-20 17:03 ` Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 6/7] crashdump: create get_elfcorehdrsz() Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 7/7] crashdump/x86: utilize get_elfcorehdrsz() Eric DeVolder
6 siblings, 0 replies; 8+ messages in thread
From: Eric DeVolder @ 2022-10-20 17:03 UTC (permalink / raw)
To: kexec; +Cc: boris.ostrovsky, eric.devolder
This option provides a means for tuning the size of the elfcorehdr
buffer segment.
The motivation for this option is that a maximum-sized elfcorehdr
can be several MiB, whereas a typical just-large-enough tends to be
several KiB. This order of magnitude difference may be unpalatable
for some users, and so this option allows the size to be dialed in.
See patch "crashdump: create get_elfcorehdrsz()" for more info.
Signed-off-by: Eric DeVolder <eric.devolder@oracle.com>
---
kexec/kexec.c | 11 +++++++++++
kexec/kexec.h | 5 ++++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/kexec/kexec.c b/kexec/kexec.c
index d2379cb..5a54c07 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -63,6 +63,7 @@ static unsigned long kexec_flags = 0;
static unsigned long kexec_file_flags = 0;
int kexec_debug = 0;
int do_hotplug = 0;
+unsigned long long elfcorehdrsz = 0;
void dbgprint_mem_range(const char *prefix, struct memory_range *mr, int nr_mr)
{
@@ -1080,6 +1081,7 @@ void usage(void)
" 0 if not.\n"
" --hotplug Enable kernel modification of the elfcorehdr, in\n"
" response to hot un/plug changes to CPUs and memory\n"
+ " --elfcorehdrsz Specify the size of the elfcorehdr buffer segment\n"
"\n"
"Supported kernel file types and options: \n");
for (i = 0; i < file_types; i++) {
@@ -1591,6 +1593,15 @@ int main(int argc, char *argv[])
case OPT_HOTPLUG:
do_hotplug = 1;
break;
+ case OPT_ELFCOREHDRSZ:
+ elfcorehdrsz = strtoul(optarg, &endptr, 0);
+ if (*endptr) {
+ fprintf(stderr,
+ "Bad option value in --elfcorehdrsz=%s\n", optarg);
+ usage();
+ return 1;
+ }
+ break;
default:
break;
}
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 9675e79..ae55d2d 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -233,7 +233,8 @@ extern int file_types;
#define OPT_LOAD_LIVE_UPDATE 263
#define OPT_EXEC_LIVE_UPDATE 264
#define OPT_HOTPLUG 265
-#define OPT_MAX 266
+#define OPT_ELFCOREHDRSZ 266
+#define OPT_MAX 267
#define KEXEC_OPTIONS \
{ "help", 0, 0, OPT_HELP }, \
{ "version", 0, 0, OPT_VERSION }, \
@@ -261,6 +262,7 @@ extern int file_types;
{ "status", 0, 0, OPT_STATUS }, \
{ "print-ckr-size", 0, 0, OPT_PRINT_CKR_SIZE }, \
{ "hotplug", 0, 0, OPT_HOTPLUG }, \
+ { "elfcorehdrsz", 1, 0, OPT_ELFCOREHDRSZ }, \
#define KEXEC_OPT_STR "h?vdfixyluet:pscaS"
@@ -299,6 +301,7 @@ extern long int get_nr_cpus(void);
extern int ifdown(void);
extern int do_hotplug;
+extern unsigned long long elfcorehdrsz;
extern char purgatory[];
extern size_t purgatory_size;
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v1 6/7] crashdump: create get_elfcorehdrsz()
2022-10-20 17:03 [PATCH v1 0/7] crashdump: Kernel handling of CPU and memory hot un/plug Eric DeVolder
` (4 preceding siblings ...)
2022-10-20 17:03 ` [PATCH v1 5/7] crashdump: introduce --elfcorehdrsz option Eric DeVolder
@ 2022-10-20 17:03 ` Eric DeVolder
2022-10-20 17:03 ` [PATCH v1 7/7] crashdump/x86: utilize get_elfcorehdrsz() Eric DeVolder
6 siblings, 0 replies; 8+ messages in thread
From: Eric DeVolder @ 2022-10-20 17:03 UTC (permalink / raw)
To: kexec; +Cc: boris.ostrovsky, eric.devolder
This routine provides a means to tune the size of the elfcorehdr
buffer segment, taking into account the --hotplug and
--elfcorehdrsz options. The possibilities are:
no --elfcorehdrsz w/ --elfcorehdrsz
no --hotplug just-large-enough user-specified
w/ --hotplug maximum-size user-specified
Where just-large-enough is the min_size parameter, computed based
upon the existing CPUs and memory regions in the system.
Where maximum-size is computed based upon the maximum number of
CPUs and memory regions possible in the system.
Signed-off-by: Eric DeVolder <eric.devolder@oracle.com>
---
include/elf.h | 2 ++
kexec/crashdump.c | 33 +++++++++++++++++++++++++++++++++
kexec/crashdump.h | 4 ++++
3 files changed, 39 insertions(+)
diff --git a/include/elf.h b/include/elf.h
index 1c8d2cc..2c5884d 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -163,6 +163,8 @@ typedef struct
#define EI_PAD 9 /* Byte index of padding bytes */
+#define PN_XNUM 0xffff /* Maximum number of headers in e_phnum */
+
/* Legal values for e_type (object file type). */
#define ET_NONE 0 /* No file type */
diff --git a/kexec/crashdump.c b/kexec/crashdump.c
index 0b363c5..4210c53 100644
--- a/kexec/crashdump.c
+++ b/kexec/crashdump.c
@@ -53,6 +53,9 @@
#undef EHDR
#undef FUNC
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
unsigned long crash_architecture(struct crash_elf_info *elf_info)
{
if (xen_present())
@@ -157,3 +160,33 @@ int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len)
{
return get_vmcoreinfo("/sys/kernel/vmcoreinfo", addr, len);
}
+
+unsigned long get_elfcorehdrsz(struct crash_elf_info *elf_info,
+ unsigned long min_size,
+ unsigned long nr_memory_ranges)
+{
+ /* Size elfcorehdr appropriately */
+ unsigned long sz = min_size;
+
+ if (elfcorehdrsz) {
+ /* Utilize option value */
+ sz = elfcorehdrsz;
+ } else {
+ /* Compute maximum for hotplug */
+ if (do_hotplug) {
+ long int nr_cpus = get_nr_cpus();
+ sz = nr_cpus + nr_memory_ranges;
+ sz = MIN(sz, PN_XNUM);
+ if (elf_info->class == ELFCLASS32) {
+ sz *= sizeof(Elf32_Phdr);
+ sz += sizeof(Elf32_Ehdr);
+ } else {
+ sz *= sizeof(Elf64_Phdr);
+ sz += sizeof(Elf64_Ehdr);
+ }
+ }
+ /* else default is min_size */
+ }
+ sz = MAX(min_size, sz);
+ return sz;
+}
diff --git a/kexec/crashdump.h b/kexec/crashdump.h
index 28d3278..e4cedce 100644
--- a/kexec/crashdump.h
+++ b/kexec/crashdump.h
@@ -53,6 +53,10 @@ int crash_create_elf64_headers(struct kexec_info *info,
unsigned long crash_architecture(struct crash_elf_info *elf_info);
+unsigned long get_elfcorehdrsz(struct crash_elf_info *elf_info,
+ unsigned long min_size,
+ unsigned long nr_memory_ranges);
+
unsigned long phys_to_virt(struct crash_elf_info *elf_info,
unsigned long long paddr);
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v1 7/7] crashdump/x86: utilize get_elfcorehdrsz()
2022-10-20 17:03 [PATCH v1 0/7] crashdump: Kernel handling of CPU and memory hot un/plug Eric DeVolder
` (5 preceding siblings ...)
2022-10-20 17:03 ` [PATCH v1 6/7] crashdump: create get_elfcorehdrsz() Eric DeVolder
@ 2022-10-20 17:03 ` Eric DeVolder
6 siblings, 0 replies; 8+ messages in thread
From: Eric DeVolder @ 2022-10-20 17:03 UTC (permalink / raw)
To: kexec; +Cc: boris.ostrovsky, eric.devolder
Call get_elfcorehdrsz() to obtain the size of the elfcorehdr
buffer.
Signed-off-by: Eric DeVolder <eric.devolder@oracle.com>
---
kexec/arch/i386/crashdump-x86.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index cb86ca7..29d4ba5 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -957,6 +957,12 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
memsz = bufsz;
}
+ /* Adjust size of buffer according to hotplug and user */
+ sz = get_elfcorehdrsz(&elf_info, bufsz, CRASH_MAX_MEMORY_RANGES);
+ if (sz > memsz)
+ memsz = sz;
+ memsz = _ALIGN(memsz, align);
+
/* Record the location of the elfcorehdr for hotplug handling */
info->elfcorehdr =
elfcorehdr = add_buffer(info, tmp, bufsz, memsz, align, min_base,
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 8+ messages in thread