diff options
author | Vivek Goyal <vgoyal@in.ibm.com> | 2005-11-17 19:10:42 +0530 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2006-07-27 10:36:17 -0600 |
commit | 4023a9d123263a1de3bde0c42e1257d068d33a31 (patch) | |
tree | 356929601d369bc922ce901fb34686bef9719704 | |
parent | 4e2f70e3c75f2b81878c34c4f8b3c298ec1b1cd2 (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.c | 75 | ||||
-rw-r--r-- | kexec/arch/x86_64/kexec-elf-x86_64.c | 14 |
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), |