Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4447

kernel-2.6.18-194.11.1.el5.src.rpm

From: Neil Horman <nhorman@redhat.com>
Date: Mon, 18 Aug 2008 10:59:30 -0400
Subject: [xen] HV: ability to use makedumpfile with vmcoreinfo
Message-id: 20080818145930.GD7052@hmsendeavour.rdu.redhat.com
O-Subject: [RHEL 5.3 PATCH] 1/2: xen: add ability for dom0 kernels to use makedumpfile with vmcoreinfo (bz 454498)
Bugzilla: 454498
RH-Acked-by: Bill Burns <bburns@redhat.com>
RH-Acked-by: Bill Burns <bburns@redhat.com>

Hey-
	This is the hypervisor portion of this patch

diff --git a/arch/ia64/xen/machine_kexec.c b/arch/ia64/xen/machine_kexec.c
index df7ad0c..cef8cab 100644
--- a/arch/ia64/xen/machine_kexec.c
+++ b/arch/ia64/xen/machine_kexec.c
@@ -1,6 +1,9 @@
 #include <xen/lib.h>       /* for printk() used in stubs */
 #include <xen/types.h>
 #include <public/kexec.h>
+#include <xen/mm.h>
+
+extern unsigned long frametable_pg_dir[];
 
 int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
 {
@@ -23,6 +26,14 @@ void machine_reboot_kexec(xen_kexec_image_t *image)
     printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
 }
 
+void arch_crash_save_vmcoreinfo(void)
+{
+    VMCOREINFO_SYMBOL(dom_xen);
+    VMCOREINFO_SYMBOL(dom_io);
+    VMCOREINFO_SYMBOL(xen_pstart);
+    VMCOREINFO_SYMBOL(frametable_pg_dir);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/arch/ia64/xen/mm.c b/arch/ia64/xen/mm.c
index 26601f1..de7e72e 100644
--- a/arch/ia64/xen/mm.c
+++ b/arch/ia64/xen/mm.c
@@ -187,7 +187,7 @@ static int efi_ucwb(unsigned long physaddr, unsigned long size);
 
 extern unsigned long ia64_iobase;
 
-static struct domain *dom_xen, *dom_io;
+struct domain *dom_xen, *dom_io;
 
 // followings are stolen from arch_init_memory() @ xen/arch/x86/mm.c
 void
diff --git a/arch/x86/machine_kexec.c b/arch/x86/machine_kexec.c
index e5033da..d9d9ee2 100644
--- a/arch/x86/machine_kexec.c
+++ b/arch/x86/machine_kexec.c
@@ -140,6 +140,20 @@ void machine_kexec(xen_kexec_image_t *image)
     }
 }
 
+void arch_crash_save_vmcoreinfo(void)
+{
+    VMCOREINFO_SYMBOL(dom_xen);
+    VMCOREINFO_SYMBOL(dom_io);
+
+#ifdef CONFIG_X86_PAE
+    VMCOREINFO_SYMBOL_ALIAS(pgd_l3, idle_pg_table);
+#endif
+#ifdef CONFIG_X86_64
+    VMCOREINFO_SYMBOL_ALIAS(pgd_l4, idle_pg_table);
+#endif
+}
+
+
 /*
  * Local variables:
  * mode: C
diff --git a/arch/x86/mm.c b/arch/x86/mm.c
index f7f9e04..fe71d1f 100644
--- a/arch/x86/mm.c
+++ b/arch/x86/mm.c
@@ -140,7 +140,7 @@ static DEFINE_PER_CPU(struct percpu_mm_info, percpu_mm_info);
 #define FOREIGNDOM (this_cpu(percpu_mm_info).foreign ?: current->domain)
 
 /* Private domain structs for DOMID_XEN and DOMID_IO. */
-static struct domain *dom_xen, *dom_io;
+struct domain *dom_xen, *dom_io;
 
 /* Frame table and its size in pages. */
 struct page_info *frame_table;
diff --git a/common/kexec.c b/common/kexec.c
index 2437799..99ffdb9 100644
--- a/common/kexec.c
+++ b/common/kexec.c
@@ -42,6 +42,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)
@@ -222,6 +225,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)(XEN_GUEST_HANDLE(void) uarg)
 {
     xen_kexec_range_t range;
@@ -241,6 +251,9 @@ static int kexec_get(range)(XEN_GUEST_HANDLE(void) uarg)
     case KEXEC_RANGE_MA_CPU:
         ret = kexec_get(cpu)(&range);
         break;
+    case KEXEC_RANGE_MA_VMCOREINFO:
+        ret = kexec_get(vmcoreinfo)(&range);
+        break;
     }
 
     if ( ret == 0 && unlikely(copy_to_guest(uarg, &range, 1)) )
@@ -269,6 +282,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
+}
+
 #endif
 
 static int kexec_load_unload(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
@@ -307,6 +370,9 @@ static int kexec_load_unload(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
             /* Make new image the active one */
             change_bit(bit, &kexec_flags);
         }
+#ifndef COMPAT
+        crash_save_vmcoreinfo();
+#endif
     }
 
     /* Unload the old image if present and load successful */
diff --git a/common/page_alloc.c b/common/page_alloc.c
index 834e09e..6c010fa 100644
--- a/common/page_alloc.c
+++ b/common/page_alloc.c
@@ -93,7 +93,7 @@ static unsigned long scrub_pages;
  *  One bit per page of memory. Bit set => page is allocated.
  */
 
-static unsigned long *alloc_bitmap;
+unsigned long *alloc_bitmap;
 #define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8)
 
 #define allocated_in_map(_pn)                       \
diff --git a/include/asm-ia64/config.h b/include/asm-ia64/config.h
index ee14018..12c9bf9 100644
--- a/include/asm-ia64/config.h
+++ b/include/asm-ia64/config.h
@@ -282,4 +282,6 @@ struct screen_info { };
 /* Define CONFIG_PRIVIFY to support privified OS (deprecated).  */
 #undef CONFIG_PRIVIFY
 
+#define ARCH_CRASH_SAVE_VMCOREINFO
+
 #endif	/* _IA64_CONFIG_H_ */
diff --git a/include/asm-ia64/mm.h b/include/asm-ia64/mm.h
index d5d4148..6e88fa9 100644
--- a/include/asm-ia64/mm.h
+++ b/include/asm-ia64/mm.h
@@ -508,4 +508,6 @@ int steal_page(
 
 #define domain_get_maximum_gpfn(d) (-ENOSYS)
 
+extern struct domain *dom_xen, *dom_io;	/* for vmcoreinfo */
+
 #endif /* __ASM_IA64_MM_H__ */
diff --git a/include/asm-x86/config.h b/include/asm-x86/config.h
index 83e118b..cbdccf7 100644
--- a/include/asm-x86/config.h
+++ b/include/asm-x86/config.h
@@ -390,4 +390,6 @@ extern unsigned long xen_phys_start, xenheap_phys_start, xenheap_phys_end;
 #define ELFSIZE 32
 #endif
 
+#define ARCH_CRASH_SAVE_VMCOREINFO
+
 #endif /* __X86_CONFIG_H__ */
diff --git a/include/asm-x86/mm.h b/include/asm-x86/mm.h
index 43d03ec..8c02a76 100644
--- a/include/asm-x86/mm.h
+++ b/include/asm-x86/mm.h
@@ -402,4 +402,6 @@ unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits);
 
 unsigned long domain_get_maximum_gpfn(struct domain *d);
 
+extern struct domain *dom_xen, *dom_io;	/* for vmcoreinfo */
+
 #endif /* __ASM_X86_MM_H__ */
diff --git a/include/public/kexec.h b/include/public/kexec.h
index ca6e85b..7af1d47 100644
--- a/include/public/kexec.h
+++ b/include/public/kexec.h
@@ -109,6 +109,7 @@ typedef struct xen_kexec_load {
 #define KEXEC_RANGE_MA_XEN   1   /* machine address and size of Xen itself */
 #define KEXEC_RANGE_MA_CPU   2   /* machine address and size of a CPU note */
 
+#define KEXEC_RANGE_MA_VMCOREINFO 6 /* machine address and size of vmcoreinfo */
 /*
  * Find the address and size of certain memory areas
  * range == KEXEC_RANGE_... [in]
@@ -124,6 +125,27 @@ typedef struct xen_kexec_range {
     unsigned long start;
 } xen_kexec_range_t;
 
+/* vmcoreinfo stuff */
+#define VMCOREINFO_BYTES           (4096)
+#define VMCOREINFO_NOTE_NAME       "VMCOREINFO_XEN"
+void arch_crash_save_vmcoreinfo(void);
+void vmcoreinfo_append_str(const char *fmt, ...)
+       __attribute__ ((format (printf, 1, 2)));
+#define VMCOREINFO_PAGESIZE(value) \
+       vmcoreinfo_append_str("PAGESIZE=%ld\n", value)
+#define VMCOREINFO_SYMBOL(name) \
+       vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
+#define VMCOREINFO_SYMBOL_ALIAS(alias, name) \
+       vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #alias, (unsigned long)&name)
+#define VMCOREINFO_STRUCT_SIZE(name) \
+       vmcoreinfo_append_str("SIZE(%s)=%zu\n", #name, sizeof(struct name))
+#define VMCOREINFO_OFFSET(name, field) \
+       vmcoreinfo_append_str("OFFSET(%s.%s)=%zu\n", #name, #field, \
+                             offsetof(struct name, field))
+#define VMCOREINFO_OFFSET_ALIAS(name, field, alias) \
+       vmcoreinfo_append_str("OFFSET(%s.%s)=%zu\n", #name, #alias, \
+                             offsetof(struct name, field))
+
 #endif /* _XEN_PUBLIC_KEXEC_H */
 
 /*
diff --git a/include/xen/mm.h b/include/xen/mm.h
index a5183fd..8a67fc7 100644
--- a/include/xen/mm.h
+++ b/include/xen/mm.h
@@ -108,4 +108,6 @@ int guest_remove_page(struct domain *d, unsigned long gmfn);
 /* Returns TRUE if the memory at address @p is ordinary RAM. */
 int memory_is_conventional_ram(paddr_t p);
 
+extern unsigned long *alloc_bitmap;	/* for vmcoreinfo */
+
 #endif /* __XEN_MM_H__ */