diff options
Diffstat (limited to 'kexec/arch')
-rw-r--r-- | kexec/arch/i386/crashdump-x86.c | 51 | ||||
-rw-r--r-- | kexec/arch/i386/kexec-bzImage.c | 10 | ||||
-rw-r--r-- | kexec/arch/i386/kexec-elf-x86.c | 4 | ||||
-rw-r--r-- | kexec/arch/i386/kexec-x86-common.c | 3 | ||||
-rw-r--r-- | kexec/arch/i386/x86-linux-setup.h | 3 |
5 files changed, 51 insertions, 20 deletions
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c index 7717219..478d6be 100644 --- a/kexec/arch/i386/crashdump-x86.c +++ b/kexec/arch/i386/crashdump-x86.c @@ -57,7 +57,8 @@ static struct memory_range crash_reserved_mem; * to look into down the line. May be something like /proc/kernelmem or may * be zone data structures exported from kernel. */ -static int get_crash_memory_ranges(struct memory_range **range, int *ranges) +static int get_crash_memory_ranges(struct memory_range **range, int *ranges, + int kexec_flags) { const char *iomem = proc_iomem(); int memory_ranges = 0; @@ -74,10 +75,12 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges) /* First entry is for first 640K region. Different bios report first * 640K in different manner hence hardcoding it */ - crash_memory_range[0].start = 0x00000000; - crash_memory_range[0].end = 0x0009ffff; - crash_memory_range[0].type = RANGE_RAM; - memory_ranges++; + if (!(kexec_flags & KEXEC_PRESERVE_CONTEXT)) { + crash_memory_range[0].start = 0x00000000; + crash_memory_range[0].end = 0x0009ffff; + crash_memory_range[0].type = RANGE_RAM; + memory_ranges++; + } while(fgets(line, sizeof(line), fp) != 0) { char *str; @@ -128,6 +131,22 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges) } } fclose(fp); + if (kexec_flags & KEXEC_PRESERVE_CONTEXT) { + int i; + for (i = 0; i < memory_ranges; i++) { + if (crash_memory_range[i].end > 0x0009ffff) { + crash_reserved_mem.start = \ + crash_memory_range[i].start; + break; + } + } + if (crash_reserved_mem.start >= mem_max) { + fprintf("Too small mem_max: 0x%lx.\n", mem_max); + return -1; + } + crash_reserved_mem.end = mem_max; + crash_reserved_mem.type = RANGE_RAM; + } if (exclude_crash_reserve_region(&memory_ranges) < 0) return -1; *range = crash_memory_range; @@ -514,7 +533,8 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, int nr_ranges, align = 1024; struct memory_range *mem_range, *memmap_p; - if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0) + if (get_crash_memory_ranges(&mem_range, &nr_ranges, + info->kexec_flags) < 0) return -1; /* @@ -535,14 +555,17 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, add_memmap(memmap_p, crash_reserved_mem.start, sz); /* Create a backup region segment to store backup data*/ - sz = (BACKUP_SRC_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); - dbgprintf("Created backup segment at 0x%lx\n", info->backup_start); - if (delete_memmap(memmap_p, info->backup_start, sz) < 0) - return -1; + if (!(info->kexec_flags & KEXEC_PRESERVE_CONTEXT)) { + sz = (BACKUP_SRC_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); + dbgprintf("Created backup segment at 0x%lx\n", + info->backup_start); + if (delete_memmap(memmap_p, info->backup_start, sz) < 0) + return -1; + } /* Create elf header segment and store crash image data. */ if (arch_options.core_header_type == CORE_TYPE_ELF64) { diff --git a/kexec/arch/i386/kexec-bzImage.c b/kexec/arch/i386/kexec-bzImage.c index 1f40076..be88a3f 100644 --- a/kexec/arch/i386/kexec-bzImage.c +++ b/kexec/arch/i386/kexec-bzImage.c @@ -114,6 +114,7 @@ int do_bzImage_load(struct kexec_info *info, unsigned int relocatable_kernel = 0; unsigned long kernel32_load_addr; char *modified_cmdline; + unsigned long cmdline_end; /* * Find out about the file I am about to load. @@ -166,7 +167,7 @@ int do_bzImage_load(struct kexec_info *info, /* Need to append some command line parameters internally in case of * taking crash dumps. */ - if (info->kexec_flags & KEXEC_ON_CRASH) { + if (info->kexec_flags & (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT)) { modified_cmdline = xmalloc(COMMAND_LINE_SIZE); memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE); if (command_line) { @@ -205,11 +206,11 @@ int do_bzImage_load(struct kexec_info *info, 0x3000, 640*1024, -1, 0); dbgprintf("Loaded purgatory at addr 0x%lx\n", info->rhdr.rel_addr); /* The argument/parameter segment */ - setup_size = kern16_size + command_line_len; + setup_size = kern16_size + command_line_len + PURGATORY_CMDLINE_SIZE; real_mode = xmalloc(setup_size); memcpy(real_mode, kernel, kern16_size); - if (info->kexec_flags & KEXEC_ON_CRASH) { + if (info->kexec_flags & (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT)) { /* If using bzImage for capture kernel, then we will not be * executing real mode code. setup segment can be loaded * anywhere as we will be just reading command line. @@ -316,6 +317,9 @@ int do_bzImage_load(struct kexec_info *info, elf_rel_set_symbol(&info->rhdr, "entry16_regs", ®s16, sizeof(regs16)); elf_rel_set_symbol(&info->rhdr, "entry16_debug_regs", ®s16, sizeof(regs16)); elf_rel_set_symbol(&info->rhdr, "entry32_regs", ®s32, sizeof(regs32)); + cmdline_end = setup_base + kern16_size + command_line_len - 1; + elf_rel_set_symbol(&info->rhdr, "cmdline_end", &cmdline_end, + sizeof(unsigned long)); /* Fill in the information BIOS calls would normally provide. */ if (!real_mode_entry) { diff --git a/kexec/arch/i386/kexec-elf-x86.c b/kexec/arch/i386/kexec-elf-x86.c index ddd4a10..5a763bd 100644 --- a/kexec/arch/i386/kexec-elf-x86.c +++ b/kexec/arch/i386/kexec-elf-x86.c @@ -170,7 +170,7 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len, /* Need to append some command line parameters internally in case of * taking crash dumps. */ - if (info->kexec_flags & KEXEC_ON_CRASH) { + if (info->kexec_flags & (KEXEC_ON_CRASH|KEXEC_PRESERVE_CONTEXT)) { modified_cmdline = xmalloc(COMMAND_LINE_SIZE); memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE); if (command_line) { @@ -257,7 +257,7 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len, /* If panic kernel is being loaded, additional segments need * to be created. */ - if (info->kexec_flags & KEXEC_ON_CRASH) { + if (info->kexec_flags & (KEXEC_ON_CRASH|KEXEC_PRESERVE_CONTEXT)) { rc = load_crashdump_segments(info, modified_cmdline, max_addr, 0); if (rc < 0) diff --git a/kexec/arch/i386/kexec-x86-common.c b/kexec/arch/i386/kexec-x86-common.c index 4533425..00c2be3 100644 --- a/kexec/arch/i386/kexec-x86-common.c +++ b/kexec/arch/i386/kexec-x86-common.c @@ -174,7 +174,8 @@ int get_memory_ranges(struct memory_range **range, int *ranges, * Override user values only if kernel exported values are * subset of user defined values. */ - if (kexec_flags & KEXEC_ON_CRASH) { + if ((kexec_flags & KEXEC_ON_CRASH) && + !(kexec_flags & KEXEC_PRESERVE_CONTEXT)) { unsigned long long start, end; ret = parse_iomem_single("Crash kernel\n", &start, &end); diff --git a/kexec/arch/i386/x86-linux-setup.h b/kexec/arch/i386/x86-linux-setup.h index 13784cf..c16b41a 100644 --- a/kexec/arch/i386/x86-linux-setup.h +++ b/kexec/arch/i386/x86-linux-setup.h @@ -15,4 +15,7 @@ void setup_linux_system_parameters(struct x86_linux_param_header *real_mode, #define KERN32_BASE 0x100000 /* 1MB */ #define INITRD_BASE 0x1000000 /* 16MB */ +/* command line parameter may be appended by purgatory */ +#define PURGATORY_CMDLINE_SIZE 64 + #endif /* X86_LINUX_SETUP_H */ |