aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/kexec.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-06-13 09:54:03 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-06-13 09:54:03 +0100
commit65ce603cc1ca8882b22e3bf689b1958eedd40c97 (patch)
tree9c04aad8a1b2992ee5f781d6ee4ed39fc3baeb27 /xen/common/kexec.c
parent95f9581198d7c591c13cb2fe6e447092f46d50de (diff)
downloadxen-65ce603cc1ca8882b22e3bf689b1958eedd40c97.tar.gz
xen-65ce603cc1ca8882b22e3bf689b1958eedd40c97.tar.bz2
xen-65ce603cc1ca8882b22e3bf689b1958eedd40c97.zip
extract vmcoreinfo from /proc/vmcore for Xen
- the machine address and the size of the vmcoreinfo area is returned via the kexec_op(get_range) hypercall - fill the vmcoreinfo data when the kexec_op(crash load) hypercall is called Signed-off-by: Itsuro Oda <oda@valinux.co.jp>
Diffstat (limited to 'xen/common/kexec.c')
-rw-r--r--xen/common/kexec.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index 02f633d660..2eb73e94b5 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -43,6 +43,9 @@ static unsigned long kexec_flags = 0; /* the lowest bits are for KEXEC_IMAGE...
static spinlock_t kexec_lock = SPIN_LOCK_UNLOCKED;
+static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
+static size_t vmcoreinfo_size = 0;
+
xen_kexec_reserve_t kexec_crash_area;
static void __init parse_crashkernel(const char *str)
@@ -208,6 +211,13 @@ static int kexec_get_cpu(xen_kexec_range_t *range)
return 0;
}
+static int kexec_get_vmcoreinfo(xen_kexec_range_t *range)
+{
+ range->start = __pa((unsigned long)vmcoreinfo_data);
+ range->size = VMCOREINFO_BYTES;
+ return 0;
+}
+
static int kexec_get_range_internal(xen_kexec_range_t *range)
{
int ret = -EINVAL;
@@ -220,6 +230,9 @@ static int kexec_get_range_internal(xen_kexec_range_t *range)
case KEXEC_RANGE_MA_CPU:
ret = kexec_get_cpu(range);
break;
+ case KEXEC_RANGE_MA_VMCOREINFO:
+ ret = kexec_get_vmcoreinfo(range);
+ break;
default:
ret = machine_kexec_get(range);
break;
@@ -288,6 +301,56 @@ static int kexec_load_get_bits(int type, int *base, int *bit)
return 0;
}
+void vmcoreinfo_append_str(const char *fmt, ...)
+{
+ va_list args;
+ char buf[0x50];
+ int r;
+ size_t note_size = sizeof(Elf_Note) + ELFNOTE_ALIGN(strlen(VMCOREINFO_NOTE_NAME) + 1);
+
+ if (vmcoreinfo_size + note_size + sizeof(buf) > VMCOREINFO_BYTES)
+ return;
+
+ va_start(args, fmt);
+ r = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ memcpy(&vmcoreinfo_data[note_size + vmcoreinfo_size], buf, r);
+
+ vmcoreinfo_size += r;
+}
+
+static void crash_save_vmcoreinfo(void)
+{
+ size_t data_size;
+
+ if (vmcoreinfo_size > 0) /* already saved */
+ return;
+
+ data_size = VMCOREINFO_BYTES - (sizeof(Elf_Note) + ELFNOTE_ALIGN(strlen(VMCOREINFO_NOTE_NAME) + 1));
+ setup_note((Elf_Note *)vmcoreinfo_data, VMCOREINFO_NOTE_NAME, 0, data_size);
+
+ VMCOREINFO_PAGESIZE(PAGE_SIZE);
+
+ VMCOREINFO_SYMBOL(domain_list);
+ VMCOREINFO_SYMBOL(frame_table);
+ VMCOREINFO_SYMBOL(alloc_bitmap);
+ VMCOREINFO_SYMBOL(max_page);
+ VMCOREINFO_SYMBOL(xenheap_phys_end);
+
+ VMCOREINFO_STRUCT_SIZE(page_info);
+ VMCOREINFO_STRUCT_SIZE(domain);
+
+ VMCOREINFO_OFFSET(page_info, count_info);
+ VMCOREINFO_OFFSET_ALIAS(page_info, u, _domain);
+ VMCOREINFO_OFFSET(domain, domain_id);
+ VMCOREINFO_OFFSET(domain, next_in_list);
+
+#ifdef ARCH_CRASH_SAVE_VMCOREINFO
+ arch_crash_save_vmcoreinfo();
+#endif
+}
+
static int kexec_load_unload_internal(unsigned long op, xen_kexec_load_t *load)
{
xen_kexec_image_t *image;
@@ -316,6 +379,8 @@ static int kexec_load_unload_internal(unsigned long op, xen_kexec_load_t *load)
/* Make new image the active one */
change_bit(bit, &kexec_flags);
}
+
+ crash_save_vmcoreinfo();
}
/* Unload the old image if present and load successful */