summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@in.ibm.com>2005-11-17 19:10:42 +0530
committerEric W. Biederman <ebiederm@xmission.com>2006-07-27 10:36:17 -0600
commit4023a9d123263a1de3bde0c42e1257d068d33a31 (patch)
tree356929601d369bc922ce901fb34686bef9719704
parent4e2f70e3c75f2b81878c34c4f8b3c298ec1b1cd2 (diff)
kexec-tools: x86_64 load crashdump segments
o Calls prepare_crash_memory_elf64_headers to create elfcore headers for each memory chunck. o Creates a segment for storing elf headers. o Create a backup region segment to store backup data. Signed-off-by:Murali M Chakravarthy <muralim@in.ibm.com> Signed-off-by: Vivek Goyal <vgoyal@in.ibm.com> Signed-off-by: Maneesh Soni <maneesh@in.ibm.com>
-rw-r--r--kexec/arch/x86_64/crashdump-x86_64.c75
-rw-r--r--kexec/arch/x86_64/kexec-elf-x86_64.c14
2 files changed, 89 insertions, 0 deletions
diff --git a/kexec/arch/x86_64/crashdump-x86_64.c b/kexec/arch/x86_64/crashdump-x86_64.c
index 8f06eee..d4f5135 100644
--- a/kexec/arch/x86_64/crashdump-x86_64.c
+++ b/kexec/arch/x86_64/crashdump-x86_64.c
@@ -676,3 +676,78 @@ static int prepare_crash_memory_elf32_headers(struct kexec_info *info,
return 0;
}
+/* Loads additional segments in case of a panic kernel is being loaded.
+ * One segment for backup region, another segment for storing elf headers
+ * for crash memory image.
+ */
+int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
+ unsigned long max_addr, unsigned long min_base)
+{
+ void *tmp;
+ unsigned long sz, elfcorehdr;
+ int nr_ranges, align = 1024;
+ long int nr_cpus = 0;
+ struct memory_range *mem_range, *memmap_p;
+
+ if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
+ return -1;
+
+ /* Memory regions which panic kernel can safely use to boot into */
+ sz = (sizeof(struct memory_range) * (KEXEC_MAX_SEGMENTS + 1));
+ memmap_p = xmalloc(sz);
+ memset(memmap_p, 0, sz);
+ add_memmap(memmap_p, BACKUP_START, BACKUP_SIZE);
+ sz = crash_reserved_mem.end - crash_reserved_mem.start +1;
+ add_memmap(memmap_p, crash_reserved_mem.start, sz);
+
+ /* Create a backup region segment to store backup data*/
+ sz = (BACKUP_SIZE + align - 1) & ~(align - 1);
+ tmp = xmalloc(sz);
+ memset(tmp, 0, sz);
+ info->backup_start = add_buffer(info, tmp, sz, sz, align,
+ 0, max_addr, 1);
+ if (delete_memmap(memmap_p, info->backup_start, sz) < 0)
+ return -1;
+
+ /* Create elf header segment and store crash image data. */
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ if (nr_cpus < 0) {
+ fprintf(stderr,"kexec_load (elf header segment)"
+ " failed: %s\n", strerror(errno));
+ return -1;
+ }
+ if (arch_options.core_header_type == CORE_TYPE_ELF64) {
+ sz = sizeof(Elf64_Ehdr) +
+ nr_cpus * sizeof(Elf64_Phdr) +
+ nr_ranges * sizeof(Elf64_Phdr);
+ } else {
+ sz = sizeof(Elf32_Ehdr) +
+ nr_cpus * sizeof(Elf32_Phdr) +
+ nr_ranges * sizeof(Elf32_Phdr);
+ }
+ sz = (sz + align - 1) & ~(align -1);
+ tmp = xmalloc(sz);
+ memset(tmp, 0, sz);
+ if (arch_options.core_header_type == CORE_TYPE_ELF64) {
+ if (prepare_crash_memory_elf64_headers(info, tmp, sz) < 0)
+ return -1;
+ } else {
+ if (prepare_crash_memory_elf32_headers(info, tmp, sz) < 0)
+ return -1;
+ }
+
+ /* Hack: With some ld versions (GNU ld version 2.14.90.0.4 20030523),
+ * vmlinux program headers show a gap of two pages between bss segment
+ * and data segment but effectively kernel considers it as bss segment
+ * and overwrites the any data placed there. Hence bloat the memsz of
+ * elf core header segment to 16K to avoid being placed in such gaps.
+ * This is a makeshift solution until it is fixed in kernel.
+ */
+ elfcorehdr = add_buffer(info, tmp, sz, 16*1024, align, min_base,
+ max_addr, 1);
+ if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
+ return -1;
+ cmdline_add_memmap(mod_cmdline, memmap_p);
+ cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
+ return 0;
+}
diff --git a/kexec/arch/x86_64/kexec-elf-x86_64.c b/kexec/arch/x86_64/kexec-elf-x86_64.c
index 1f3c54d..e7272af 100644
--- a/kexec/arch/x86_64/kexec-elf-x86_64.c
+++ b/kexec/arch/x86_64/kexec-elf-x86_64.c
@@ -37,6 +37,7 @@
#include "../../kexec-elf-boot.h"
#include "../i386/x86-linux-setup.h"
#include "kexec-x86_64.h"
+#include "crashdump-x86_64.h"
#include <arch/options.h>
static const int probe_debug = 0;
@@ -216,6 +217,7 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
const unsigned char *ramdisk_buf;
off_t ramdisk_length;
struct entry64_regs regs;
+ int rc=0;
/* Get the linux parameter header */
hdr = xmalloc(sizeof(*hdr));
@@ -233,6 +235,18 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
ramdisk_buf = slurp_file(ramdisk, &ramdisk_length);
}
+ /* If panic kernel is being loaded, additional segments need
+ * to be created. */
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ rc = load_crashdump_segments(info, modified_cmdline,
+ max_addr, 0);
+ if (rc < 0)
+ return -1;
+ /* Use new command line. */
+ command_line = modified_cmdline;
+ command_line_len = strlen(modified_cmdline) + 1;
+ }
+
/* Tell the kernel what is going on */
setup_linux_bootloader_parameters(info, &hdr->hdr, param_base,
offsetof(struct x86_linux_faked_param_header, command_line),