summaryrefslogtreecommitdiff
path: root/kexec/arch/s390/crashdump-s390.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexec/arch/s390/crashdump-s390.c')
-rw-r--r--kexec/arch/s390/crashdump-s390.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/kexec/arch/s390/crashdump-s390.c b/kexec/arch/s390/crashdump-s390.c
new file mode 100644
index 0000000..86a30a8
--- /dev/null
+++ b/kexec/arch/s390/crashdump-s390.c
@@ -0,0 +1,74 @@
+/*
+ * kexec/arch/s390/crashdump-s390.c
+ *
+ * Copyright IBM Corp. 2011
+ *
+ * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#ifdef __s390x__
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <elf.h>
+#include <limits.h>
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "../../kexec/crashdump.h"
+#include "kexec-s390.h"
+
+/*
+ * Load additional segments for kdump kernel
+ */
+int load_crashdump_segments(struct kexec_info *info, unsigned long crash_base,
+ unsigned long crash_end)
+{
+ static struct memory_range crash_memory_range[MAX_MEMORY_RANGES];
+ unsigned long bufsz, elfcorehdr, elfcorehdr_size, crash_size;
+ 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;
+ elf_info.machine = EM_S390;
+ elf_info.class = ELFCLASS64;
+ elf_info.get_note_info = get_crash_notes_per_cpu;
+
+ if (get_memory_ranges_s390(crash_memory_range, &ranges, 0))
+ return -1;
+
+ if (crash_create_elf64_headers(info, &elf_info, crash_memory_range,
+ ranges, &tmp, &bufsz,
+ ELF_CORE_HEADER_ALIGN))
+ return -1;
+
+ elfcorehdr = add_buffer(info, tmp, bufsz, bufsz, 1024,
+ crash_base, crash_end, -1);
+ elfcorehdr_size = bufsz;
+ elf_rel_build_load(info, &info->rhdr, (const char *) purgatory,
+ purgatory_size, crash_base + 0x2000,
+ crash_base + 0x10000, -1, 0);
+ elf_rel_set_symbol(&info->rhdr, "crash_base", &crash_base,
+ sizeof(crash_base));
+ 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
+/*
+ * kdump is not available for s390
+ */
+int load_crashdump_segments(struct kexec_info *info, unsigned long crash_base,
+ unsigned long crash_end)
+{
+ return -1;
+}
+#endif