Hello Simon, From: Michael Holzheu <holzheu@xxxxxxxxxxxxxxxxxx> For s390 we have two modes for kdump: For the first mode, as on all other architectures, the kexec tool creates the ELF header and the 2nd kernel processes it for /proc/vmcore setup. This mode has the disadvantage that for memory and CPU hotplug the kdump kernel has to be reloaded by the kexec tool. For s390 this is a real problem because we have a cpuplugd daemon that sets CPUs online and offline according to the current workload. So CPU online/offline events occur very often. For the second mode on s390, the ELF header is created by the kdump kernel. This is done automatically when the kernel is booted in kdump mode and no "elfcorehdr" kernel parameter is specified. On s390 the kdump kernel can get all necessary information to build the ELF header. We can get the memory map, all CPU registers, and vmcoreinfo With this patch a compile switch WITH_ELF_HEADER is introduced. When the macro is defined, kexec will create the ELF header and add the "elfcorehdr" kernel parameter. If it is not specified (default), no header is created. For s390 we want to have the 2nd mode as default because it has only advantages for us. Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com> -- kexec/arch/s390/crashdump-s390.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) --- a/kexec/arch/s390/crashdump-s390.c +++ b/kexec/arch/s390/crashdump-s390.c @@ -12,25 +12,26 @@ #include <stdio.h> #include <elf.h> #include <limits.h> +#include <string.h> #include "../../kexec.h" #include "../../kexec-syscall.h" #include "../../kexec/crashdump.h" #include "kexec-s390.h" /* - * Load additional segments for kdump kernel + * Create ELF core header */ -int load_crashdump_segments(struct kexec_info *info, unsigned long crash_base, - unsigned long crash_end) +static int create_elf_header(struct kexec_info *info, unsigned long crash_base, + unsigned long crash_end) { +#ifdef WITH_ELF_HEADER static struct memory_range crash_memory_range[MAX_MEMORY_RANGES]; - unsigned long bufsz, elfcorehdr, elfcorehdr_size, crash_size; + unsigned long elfcorehdr, elfcorehdr_size, bufsz; struct crash_elf_info elf_info; char str[COMMAND_LINESIZE]; int ranges; void *tmp; - crash_size = crash_end - crash_base + 1; memset(&elf_info, 0, sizeof(elf_info)); elf_info.data = ELFDATA2MSB; @@ -49,6 +50,23 @@ int load_crashdump_segments(struct kexec elfcorehdr = add_buffer(info, tmp, bufsz, bufsz, 1024, crash_base, crash_end, -1); elfcorehdr_size = bufsz; + snprintf(str, sizeof(str), " elfcorehdr=%ld@%ldK\n", + elfcorehdr_size, elfcorehdr / 1024); + command_line_add(str); +#endif + return 0; +} + +/* + * Load additional segments for kdump kernel + */ +int load_crashdump_segments(struct kexec_info *info, unsigned long crash_base, + unsigned long crash_end) +{ + unsigned long crash_size = crash_size = crash_end - crash_base + 1; + + if (create_elf_header(info, crash_base, crash_end)) + return -1; elf_rel_build_load(info, &info->rhdr, (const char *) purgatory, purgatory_size, crash_base + 0x2000, crash_base + 0x10000, -1, 0); @@ -57,9 +75,6 @@ int load_crashdump_segments(struct kexec elf_rel_set_symbol(&info->rhdr, "crash_size", &crash_size, sizeof(crash_size)); info->entry = (void *) elf_rel_get_addr(&info->rhdr, "purgatory_start"); - snprintf(str, sizeof(str), " elfcorehdr=%ld@%ldK\n", - elfcorehdr_size, elfcorehdr / 1024); - command_line_add(str); return 0; } #else