summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@in.ibm.com>2006-11-01 16:12:04 -0500
committerSimon Horman <horms@verge.net.au>2006-11-08 12:58:09 +0900
commitb7d1e7aab0da6904986a12f2851dd6010c5f503f (patch)
treed9c2e2dc26966ca434260bff99e1e1f498d793fc
parent1ac7cb4dd95229495ba7d2d5f490565d843b2e58 (diff)
kexec-tools: Enable use of relocatable bzImage to capture crash kernel core dumps
o Modify bzImage loader to also load kernel core elf headers so that relocatable bzImage can be used for dump capturing purposes. Signed-off-by: Vivek Goyal <vgoyal@in.ibm.com> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--kexec/arch/i386/crashdump-x86.c7
-rw-r--r--kexec/arch/i386/kexec-bzImage.c54
2 files changed, 58 insertions, 3 deletions
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 59dd3cd..d8fa091 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -676,7 +676,9 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
tmp = xmalloc(sz);
memset(tmp, 0, sz);
info->backup_start = add_buffer(info, tmp, sz, sz, align,
- 0, max_addr, 1);
+ 0, max_addr, -1);
+ dfprintf(stdout, "Created backup segment at 0x%lx\n",
+ info->backup_start);
if (delete_memmap(memmap_p, info->backup_start, sz) < 0)
return -1;
@@ -715,7 +717,8 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
* 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);
+ max_addr, -1);
+ dfprintf(stdout, "Created elf header segment at 0x%lx\n", elfcorehdr);
if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
return -1;
cmdline_add_memmap(mod_cmdline, memmap_p);
diff --git a/kexec/arch/i386/kexec-bzImage.c b/kexec/arch/i386/kexec-bzImage.c
index 77ccfa3..3d35297 100644
--- a/kexec/arch/i386/kexec-bzImage.c
+++ b/kexec/arch/i386/kexec-bzImage.c
@@ -34,8 +34,10 @@
#include <x86/x86-linux.h>
#include "../../kexec.h"
#include "../../kexec-elf.h"
+#include "../../kexec-syscall.h"
#include "kexec-x86.h"
#include "x86-linux-setup.h"
+#include "crashdump-x86.h"
#include <arch/options.h>
static const int probe_debug = 0;
@@ -111,6 +113,7 @@ int do_bzImage_load(struct kexec_info *info,
struct entry16_regs regs16;
unsigned int relocatable_kernel = 0;
unsigned long kernel32_load_addr;
+ char *modified_cmdline;
/*
* Find out about the file I am about to load.
@@ -136,6 +139,45 @@ int do_bzImage_load(struct kexec_info *info,
dfprintf(stdout, "bzImage is relocatable\n");
}
+ /* Can't use bzImage for crash dump purposes with real mode entry */
+ if((info->kexec_flags & KEXEC_ON_CRASH) && real_mode_entry) {
+ fprintf(stderr, "Can't use bzImage for crash dump purposes"
+ " with real mode entry\n");
+ return -1;
+ }
+
+ if((info->kexec_flags & KEXEC_ON_CRASH) && !relocatable_kernel) {
+ fprintf(stderr, "BzImage is not relocatable. Can't be used"
+ " as capture kernel.\n");
+ return -1;
+ }
+
+ /* Need to append some command line parameters internally in case of
+ * taking crash dumps.
+ */
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
+ memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE);
+ if (command_line) {
+ strncpy(modified_cmdline, command_line,
+ COMMAND_LINE_SIZE);
+ modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
+ }
+
+ /* If panic kernel is being loaded, additional segments need
+ * to be created. load_crashdump_segments will take care of
+ * loading the segments as high in memory as possible, hence
+ * in turn as away as possible from kernel to avoid being
+ * stomped by the kernel.
+ */
+ if (load_crashdump_segments(info, modified_cmdline, -1, 0) < 0)
+ return -1;
+
+ /* Use new command line buffer */
+ command_line = modified_cmdline;
+ command_line_len = strlen(command_line) +1;
+ }
+
/* Load the trampoline. This must load at a higher address
* the the argument/parameter segment or the kernel will stomp
* it's gdt.
@@ -152,7 +194,16 @@ int do_bzImage_load(struct kexec_info *info,
setup_size = kern16_size + command_line_len;
real_mode = xmalloc(setup_size);
memcpy(real_mode, kernel, kern16_size);
- if (real_mode->protocol_version >= 0x0200) {
+
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ /* 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.
+ */
+ setup_base = add_buffer(info, real_mode, setup_size, setup_size,
+ 16, 0x3000, -1, 1);
+ }
+ else if (real_mode->protocol_version >= 0x0200) {
/* Careful setup_base must be greater than 8K */
setup_base = add_buffer(info, real_mode, setup_size, setup_size,
16, 0x3000, 640*1024, 1);
@@ -162,6 +213,7 @@ int do_bzImage_load(struct kexec_info *info,
}
dfprintf(stdout, "Loaded real-mode code and command line at 0x%lx\n",
setup_base);
+
/* Verify purgatory loads higher than the parameters */
if (info->rhdr.rel_addr < setup_base) {
die("Could not put setup code above the kernel parameters\n");