[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEN] Kexec / Kdump: Generic code



# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
# Node ID c988f781817daa646828262eb8ff02f60a3a4f2e
# Parent  d1b0a5adaeabffa3a1a68ae08bc974f5fb28d2c7
[XEN] Kexec / Kdump: Generic code

This patch implements the generic portion of the Kexec / Kdump port to Xen.

Signed-Off-By: Magnus Damm <magnus@xxxxxxxxxxxxx>
Signed-Off-By: Simon Horman <horms@xxxxxxxxxxxx>
---
 linux-2.6-xen-sparse/drivers/xen/core/Makefile        |    1 
 linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c |  170 ++++++++
 patches/linux-2.6.16.33/kexec-generic.patch           |  167 ++++++++
 patches/linux-2.6.16.33/series                        |    1 
 xen/arch/ia64/xen/Makefile                            |    2 
 xen/arch/ia64/xen/crash.c                             |   19 
 xen/arch/ia64/xen/machine_kexec.c                     |   34 +
 xen/arch/powerpc/Makefile                             |    2 
 xen/arch/powerpc/crash.c                              |   19 
 xen/arch/powerpc/machine_kexec.c                      |   34 +
 xen/arch/x86/Makefile                                 |    2 
 xen/arch/x86/crash.c                                  |   19 
 xen/arch/x86/machine_kexec.c                          |   34 +
 xen/common/Makefile                                   |    1 
 xen/common/kexec.c                                    |  370 ++++++++++++++++++
 xen/common/page_alloc.c                               |   37 +
 xen/drivers/char/console.c                            |    3 
 xen/include/asm-ia64/elf.h                            |   30 +
 xen/include/asm-ia64/kexec.h                          |   25 +
 xen/include/asm-powerpc/elf.h                         |   30 +
 xen/include/asm-powerpc/kexec.h                       |   25 +
 xen/include/asm-x86/elf.h                             |   30 +
 xen/include/asm-x86/kexec.h                           |   24 +
 xen/include/public/elfnote.h                          |   19 
 xen/include/public/kexec.h                            |  131 ++++++
 xen/include/xen/elf.h                                 |   20 
 xen/include/xen/elfcore.h                             |  137 ++++++
 xen/include/xen/hypercall.h                           |    6 
 xen/include/xen/kexec.h                               |   43 ++
 xen/include/xen/mm.h                                  |    1 
 30 files changed, 1409 insertions(+), 27 deletions(-)

diff -r d1b0a5adaeab -r c988f781817d 
linux-2.6-xen-sparse/drivers/xen/core/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile    Wed Nov 29 23:40:40 
2006 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile    Thu Nov 30 12:38:50 
2006 +0000
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SKBUFF)      += skbuff.o
 obj-$(CONFIG_XEN_SKBUFF)       += skbuff.o
 obj-$(CONFIG_XEN_REBOOT)       += reboot.o machine_reboot.o
 obj-$(CONFIG_XEN_SMPBOOT)      += smpboot.o
+obj-$(CONFIG_KEXEC)            += machine_kexec.o
diff -r d1b0a5adaeab -r c988f781817d patches/linux-2.6.16.33/series
--- a/patches/linux-2.6.16.33/series    Wed Nov 29 23:40:40 2006 +0000
+++ b/patches/linux-2.6.16.33/series    Thu Nov 30 12:38:50 2006 +0000
@@ -1,3 +1,4 @@ blktap-aio-16_03_06.patch
+kexec-generic.patch
 blktap-aio-16_03_06.patch
 device_bind.patch
 fix-hz-suspend.patch
diff -r d1b0a5adaeab -r c988f781817d xen/arch/ia64/xen/Makefile
--- a/xen/arch/ia64/xen/Makefile        Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/arch/ia64/xen/Makefile        Thu Nov 30 12:38:50 2006 +0000
@@ -1,3 +1,5 @@ obj-y += acpi.o
+obj-y += machine_kexec.o
+obj-y += crash.o
 obj-y += acpi.o
 obj-y += dom0_ops.o
 obj-y += domain.o
diff -r d1b0a5adaeab -r c988f781817d xen/arch/powerpc/Makefile
--- a/xen/arch/powerpc/Makefile Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/arch/powerpc/Makefile Thu Nov 30 12:38:50 2006 +0000
@@ -40,6 +40,8 @@ obj-y += sysctl.o
 obj-y += sysctl.o
 obj-y += time.o
 obj-y += usercopy.o
+obj-y += machine_kexec.o
+obj-y += crash.o
 
 obj-$(debug) += 0opt.o
 obj-$(crash_debug) += gdbstub.o
diff -r d1b0a5adaeab -r c988f781817d xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile     Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/arch/x86/Makefile     Thu Nov 30 12:38:50 2006 +0000
@@ -43,6 +43,8 @@ obj-y += traps.o
 obj-y += traps.o
 obj-y += usercopy.o
 obj-y += x86_emulate.o
+obj-y += machine_kexec.o
+obj-y += crash.o
 
 obj-$(crash_debug) += gdbstub.o
 
diff -r d1b0a5adaeab -r c988f781817d xen/common/Makefile
--- a/xen/common/Makefile       Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/common/Makefile       Thu Nov 30 12:38:50 2006 +0000
@@ -7,6 +7,7 @@ obj-y += grant_table.o
 obj-y += grant_table.o
 obj-y += kernel.o
 obj-y += keyhandler.o
+obj-y += kexec.o
 obj-y += lib.o
 obj-y += memory.o
 obj-y += multicall.o
diff -r d1b0a5adaeab -r c988f781817d xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/common/page_alloc.c   Thu Nov 30 12:38:50 2006 +0000
@@ -237,24 +237,35 @@ void init_boot_pages(paddr_t ps, paddr_t
     }
 }
 
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at)
+{
+    unsigned long i;
+
+    for ( i = 0; i < nr_pfns; i++ )
+        if ( allocated_in_map(pfn_at + i) )
+             break;
+
+    if ( i == nr_pfns )
+    {
+        map_alloc(pfn_at, nr_pfns);
+        return pfn_at;
+    }
+
+    return 0;
+}
+
 unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
 {
-    unsigned long pg, i;
+    unsigned long pg, i = 0;
 
     for ( pg = 0; (pg + nr_pfns) < max_page; pg += pfn_align )
     {
-        for ( i = 0; i < nr_pfns; i++ )
-            if ( allocated_in_map(pg + i) )
-                 break;
-
-        if ( i == nr_pfns )
-        {
-            map_alloc(pg, nr_pfns);
-            return pg;
-        }
-    }
-
-    return 0;
+        i = alloc_boot_pages_at(nr_pfns, pg);
+        if (i != 0)
+            break;
+    }
+
+    return i;
 }
 
 
diff -r d1b0a5adaeab -r c988f781817d xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/drivers/char/console.c        Thu Nov 30 12:38:50 2006 +0000
@@ -27,6 +27,7 @@
 #include <xen/guest_access.h>
 #include <xen/shutdown.h>
 #include <xen/vga.h>
+#include <xen/kexec.h>
 #include <asm/current.h>
 #include <asm/debugger.h>
 #include <asm/io.h>
@@ -865,6 +866,8 @@ void panic(const char *fmt, ...)
 
     debugger_trap_immediate();
 
+    machine_crash_kexec();
+
     if ( opt_noreboot )
     {
         machine_halt();
diff -r d1b0a5adaeab -r c988f781817d xen/include/public/elfnote.h
--- a/xen/include/public/elfnote.h      Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/include/public/elfnote.h      Thu Nov 30 12:38:50 2006 +0000
@@ -147,6 +147,25 @@
  */
 #define XEN_ELFNOTE_HV_START_LOW  12
 
+/*
+ * System information exported through crash notes.
+ *
+ * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_INFO 
+ * note in case of a system crash. This note will contain various
+ * information about the system, see xen/include/xen/elfcore.h.
+ */
+#define XEN_ELFNOTE_CRASH_INFO 0x1000001
+
+/*
+ * System registers exported through crash notes.
+ *
+ * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_REGS 
+ * note per cpu in case of a system crash. This note is architecture
+ * specific and will contain registers not saved in the "CORE" note.
+ * See xen/include/xen/elfcore.h for more information.
+ */
+#define XEN_ELFNOTE_CRASH_REGS 0x1000002
+
 #endif /* __XEN_PUBLIC_ELFNOTE_H__ */
 
 /*
diff -r d1b0a5adaeab -r c988f781817d xen/include/xen/elf.h
--- a/xen/include/xen/elf.h     Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/include/xen/elf.h     Thu Nov 30 12:38:50 2006 +0000
@@ -452,18 +452,12 @@ unsigned int elf_hash(const unsigned cha
 /*
  * Note Definitions
  */
-typedef struct {
-       Elf32_Word namesz;
-       Elf32_Word descsz;
-       Elf32_Word type;
-} Elf32_Note;
-
-typedef struct {
-       Elf64_Half namesz;
-       Elf64_Half descsz;
-       Elf64_Half type;
-} Elf64_Note;
-
+
+typedef struct {
+       u32 namesz;
+       u32 descsz;
+       u32 type;
+} Elf_Note; /* same format for both 32-bit and 64-bit ELF */
 
 #if defined(ELFSIZE)
 #define CONCAT(x,y)    __CONCAT(x,y)
@@ -486,7 +480,6 @@ typedef struct {
 #define Elf_Addr       Elf32_Addr
 #define Elf_Off                Elf32_Off
 #define Elf_Nhdr       Elf32_Nhdr
-#define Elf_Note       Elf32_Note
 
 #define ELF_R_SYM      ELF32_R_SYM
 #define ELF_R_TYPE     ELF32_R_TYPE
@@ -511,7 +504,6 @@ typedef struct {
 #define Elf_Addr       Elf64_Addr
 #define Elf_Off                Elf64_Off
 #define Elf_Nhdr       Elf64_Nhdr
-#define Elf_Note       Elf64_Note
 
 #define ELF_R_SYM      ELF64_R_SYM
 #define ELF_R_TYPE     ELF64_R_TYPE
diff -r d1b0a5adaeab -r c988f781817d xen/include/xen/hypercall.h
--- a/xen/include/xen/hypercall.h       Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/include/xen/hypercall.h       Thu Nov 30 12:38:50 2006 +0000
@@ -102,4 +102,10 @@ do_hvm_op(
     unsigned long op,
     XEN_GUEST_HANDLE(void) arg);
 
+extern long
+do_kexec_op(
+    unsigned long op,
+    int arg1,
+    XEN_GUEST_HANDLE(void) arg);
+
 #endif /* __XEN_HYPERCALL_H__ */
diff -r d1b0a5adaeab -r c988f781817d xen/include/xen/mm.h
--- a/xen/include/xen/mm.h      Wed Nov 29 23:40:40 2006 +0000
+++ b/xen/include/xen/mm.h      Thu Nov 30 12:38:50 2006 +0000
@@ -40,6 +40,7 @@ paddr_t init_boot_allocator(paddr_t bitm
 paddr_t init_boot_allocator(paddr_t bitmap_start);
 void init_boot_pages(paddr_t ps, paddr_t pe);
 unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at);
 void end_boot_allocator(void);
 
 /* Generic allocator. These functions are *not* interrupt-safe. */
diff -r d1b0a5adaeab -r c988f781817d 
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c     Thu Nov 30 
12:38:50 2006 +0000
@@ -0,0 +1,170 @@
+/*
+ * drivers/xen/core/machine_kexec.c 
+ * handle transition of Linux booting another kernel
+ */
+
+#include <linux/kexec.h>
+#include <xen/interface/kexec.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <asm/hypercall.h>
+
+extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, 
+                                        struct kimage *image);
+
+int xen_max_nr_phys_cpus;
+struct resource xen_hypervisor_res;
+struct resource *xen_phys_cpus;
+
+void xen_machine_kexec_setup_resources(void)
+{
+       xen_kexec_range_t range;
+       struct resource *res;
+       int k = 0;
+
+       /* determine maximum number of physical cpus */
+
+       while (1) {
+               memset(&range, 0, sizeof(range));
+               range.range = KEXEC_RANGE_MA_CPU;
+               range.nr = k;
+
+               if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
+                       break;
+
+               k++;
+       }
+
+       xen_max_nr_phys_cpus = k;
+
+       /* allocate xen_phys_cpus */
+
+       xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource));
+       BUG_ON(!xen_phys_cpus);
+
+       /* fill in xen_phys_cpus with per-cpu crash note information */
+
+       for (k = 0; k < xen_max_nr_phys_cpus; k++) {
+               memset(&range, 0, sizeof(range));
+               range.range = KEXEC_RANGE_MA_CPU;
+               range.nr = k;
+
+               BUG_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range));
+
+               res = xen_phys_cpus + k;
+
+               memset(res, 0, sizeof(*res));
+               res->name = "Crash note";
+               res->start = range.start;
+               res->end = range.start + range.size - 1;
+               res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+       }
+
+       /* fill in xen_hypervisor_res with hypervisor machine address range */
+
+       memset(&range, 0, sizeof(range));
+       range.range = KEXEC_RANGE_MA_XEN;
+
+       BUG_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range));
+
+       xen_hypervisor_res.name = "Hypervisor code and data";
+       xen_hypervisor_res.start = range.start;
+       xen_hypervisor_res.end = range.start + range.size - 1;
+       xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+
+       /* fill in crashk_res if range is reserved by hypervisor */
+
+       memset(&range, 0, sizeof(range));
+       range.range = KEXEC_RANGE_MA_CRASH;
+
+       BUG_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range));
+
+       if (range.size) {
+               crashk_res.start = range.start;
+               crashk_res.end = range.start + range.size - 1;
+       }
+}
+
+void xen_machine_kexec_register_resources(struct resource *res)
+{
+       int k;
+
+       request_resource(res, &xen_hypervisor_res);
+
+       for (k = 0; k < xen_max_nr_phys_cpus; k++)
+               request_resource(res, xen_phys_cpus + k);
+
+}
+
+static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
+{
+       machine_kexec_setup_load_arg(xki, image);
+
+       xki->indirection_page = image->head;
+       xki->start_address = image->start;
+}
+
+/*
+ * Load the image into xen so xen can kdump itself
+ * This might have been done in prepare, but prepare
+ * is currently called too early. It might make sense
+ * to move prepare, but for now, just add an extra hook.
+ */
+int xen_machine_kexec_load(struct kimage *image)
+{
+       xen_kexec_load_t xkl;
+
+       memset(&xkl, 0, sizeof(xkl));
+       xkl.type = image->type;
+       setup_load_arg(&xkl.image, image);
+       return HYPERVISOR_kexec_op(KEXEC_CMD_kexec_load, &xkl);
+}
+
+/*
+ * Unload the image that was stored by machine_kexec_load()
+ * This might have been done in machine_kexec_cleanup() but it
+ * is called too late, and its possible xen could try and kdump
+ * using resources that have been freed.
+ */
+void xen_machine_kexec_unload(struct kimage *image)
+{
+       xen_kexec_load_t xkl;
+
+       memset(&xkl, 0, sizeof(xkl));
+       xkl.type = image->type;
+       HYPERVISOR_kexec_op(KEXEC_CMD_kexec_unload, &xkl);
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ *
+ * This has the hypervisor move to the prefered reboot CPU, 
+ * stop all CPUs and kexec. That is it combines machine_shutdown()
+ * and machine_kexec() in Linux kexec terms.
+ */
+NORET_TYPE void xen_machine_kexec(struct kimage *image)
+{
+       xen_kexec_exec_t xke;
+
+       memset(&xke, 0, sizeof(xke));
+       xke.type = image->type;
+       HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke);
+       panic("KEXEC_CMD_kexec hypercall should not return\n");
+}
+
+void machine_shutdown(void)
+{
+       /* do nothing */
+}
+
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d patches/linux-2.6.16.33/kexec-generic.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/kexec-generic.patch       Thu Nov 30 12:38:50 
2006 +0000
@@ -0,0 +1,228 @@
+--- 0001/include/linux/kexec.h
++++ work/include/linux/kexec.h
+@@ -31,6 +31,13 @@
+ #error KEXEC_ARCH not defined
+ #endif
+ 
++#ifndef KEXEC_ARCH_HAS_PAGE_MACROS
++#define kexec_page_to_pfn(page)  page_to_pfn(page)
++#define kexec_pfn_to_page(pfn)   pfn_to_page(pfn)
++#define kexec_virt_to_phys(addr) virt_to_phys(addr)
++#define kexec_phys_to_virt(addr) phys_to_virt(addr)
++#endif
++
+ /*
+  * This structure is used to hold the arguments that are used when loading
+  * kernel binaries.
+@@ -91,6 +98,13 @@ struct kimage {
+ extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET;
+ extern int machine_kexec_prepare(struct kimage *image);
+ extern void machine_kexec_cleanup(struct kimage *image);
++#ifdef CONFIG_XEN
++extern int xen_machine_kexec_load(struct kimage *image);
++extern void xen_machine_kexec_unload(struct kimage *image);
++extern NORET_TYPE void xen_machine_kexec(struct kimage *image) ATTRIB_NORET;
++extern void xen_machine_kexec_setup_resources(void);
++extern void xen_machine_kexec_register_resources(struct resource *res);
++#endif
+ extern asmlinkage long sys_kexec_load(unsigned long entry,
+                                       unsigned long nr_segments,
+                                       struct kexec_segment __user *segments,
+--- 0001/kernel/kexec.c
++++ work/kernel/kexec.c
+@@ -403,7 +403,7 @@ static struct page *kimage_alloc_normal_
+               pages = kimage_alloc_pages(GFP_KERNEL, order);
+               if (!pages)
+                       break;
+-              pfn   = page_to_pfn(pages);
++              pfn   = kexec_page_to_pfn(pages);
+               epfn  = pfn + count;
+               addr  = pfn << PAGE_SHIFT;
+               eaddr = epfn << PAGE_SHIFT;
+@@ -437,6 +437,7 @@ static struct page *kimage_alloc_normal_
+       return pages;
+ }
+ 
++#ifndef CONFIG_XEN
+ static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
+                                                     unsigned int order)
+ {
+@@ -490,7 +491,7 @@ static struct page *kimage_alloc_crash_c
+               }
+               /* If I don't overlap any segments I have found my hole! */
+               if (i == image->nr_segments) {
+-                      pages = pfn_to_page(hole_start >> PAGE_SHIFT);
++                      pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
+                       break;
+               }
+       }
+@@ -517,6 +518,13 @@ struct page *kimage_alloc_control_pages(
+ 
+       return pages;
+ }
++#else /* !CONFIG_XEN */
++struct page *kimage_alloc_control_pages(struct kimage *image,
++                                       unsigned int order)
++{
++      return kimage_alloc_normal_control_pages(image, order);
++}
++#endif
+ 
+ static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
+ {
+@@ -532,7 +540,7 @@ static int kimage_add_entry(struct kimag
+                       return -ENOMEM;
+ 
+               ind_page = page_address(page);
+-              *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
++              *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
+               image->entry = ind_page;
+               image->last_entry = ind_page +
+                                     ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
+@@ -593,13 +601,13 @@ static int kimage_terminate(struct kimag
+ #define for_each_kimage_entry(image, ptr, entry) \
+       for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
+               ptr = (entry & IND_INDIRECTION)? \
+-                      phys_to_virt((entry & PAGE_MASK)): ptr +1)
++                      kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
+ 
+ static void kimage_free_entry(kimage_entry_t entry)
+ {
+       struct page *page;
+ 
+-      page = pfn_to_page(entry >> PAGE_SHIFT);
++      page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
+       kimage_free_pages(page);
+ }
+ 
+@@ -611,6 +619,10 @@ static void kimage_free(struct kimage *i
+       if (!image)
+               return;
+ 
++#ifdef CONFIG_XEN
++      xen_machine_kexec_unload(image);
++#endif
++
+       kimage_free_extra_pages(image);
+       for_each_kimage_entry(image, ptr, entry) {
+               if (entry & IND_INDIRECTION) {
+@@ -686,7 +698,7 @@ static struct page *kimage_alloc_page(st
+        * have a match.
+        */
+       list_for_each_entry(page, &image->dest_pages, lru) {
+-              addr = page_to_pfn(page) << PAGE_SHIFT;
++              addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+               if (addr == destination) {
+                       list_del(&page->lru);
+                       return page;
+@@ -701,12 +713,12 @@ static struct page *kimage_alloc_page(st
+               if (!page)
+                       return NULL;
+               /* If the page cannot be used file it away */
+-              if (page_to_pfn(page) >
++              if (kexec_page_to_pfn(page) >
+                               (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
+                       list_add(&page->lru, &image->unuseable_pages);
+                       continue;
+               }
+-              addr = page_to_pfn(page) << PAGE_SHIFT;
++              addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+ 
+               /* If it is the destination page we want use it */
+               if (addr == destination)
+@@ -729,7 +741,7 @@ static struct page *kimage_alloc_page(st
+                       struct page *old_page;
+ 
+                       old_addr = *old & PAGE_MASK;
+-                      old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
++                      old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
+                       copy_highpage(page, old_page);
+                       *old = addr | (*old & ~PAGE_MASK);
+ 
+@@ -779,7 +791,7 @@ static int kimage_load_normal_segment(st
+                       result  = -ENOMEM;
+                       goto out;
+               }
+-              result = kimage_add_page(image, page_to_pfn(page)
++              result = kimage_add_page(image, kexec_page_to_pfn(page)
+                                                               << PAGE_SHIFT);
+               if (result < 0)
+                       goto out;
+@@ -811,6 +823,7 @@ out:
+       return result;
+ }
+ 
++#ifndef CONFIG_XEN
+ static int kimage_load_crash_segment(struct kimage *image,
+                                       struct kexec_segment *segment)
+ {
+@@ -833,7 +846,7 @@ static int kimage_load_crash_segment(str
+               char *ptr;
+               size_t uchunk, mchunk;
+ 
+-              page = pfn_to_page(maddr >> PAGE_SHIFT);
++              page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
+               if (page == 0) {
+                       result  = -ENOMEM;
+                       goto out;
+@@ -881,6 +894,13 @@ static int kimage_load_segment(struct ki
+ 
+       return result;
+ }
++#else /* CONFIG_XEN */
++static int kimage_load_segment(struct kimage *image,
++                              struct kexec_segment *segment)
++{
++      return kimage_load_normal_segment(image, segment);
++}
++#endif
+ 
+ /*
+  * Exec Kernel system call: for obvious reasons only root may call it.
+@@ -991,6 +1011,11 @@ asmlinkage long sys_kexec_load(unsigned 
+               if (result)
+                       goto out;
+       }
++#ifdef CONFIG_XEN
++      result = xen_machine_kexec_load(image);
++      if (result)
++              goto out;
++#endif
+       /* Install the new kernel, and  Uninstall the old */
+       image = xchg(dest_image, image);
+ 
+@@ -1045,7 +1070,6 @@ void crash_kexec(struct pt_regs *regs)
+       struct kimage *image;
+       int locked;
+ 
+-
+       /* Take the kexec_lock here to prevent sys_kexec_load
+        * running on one cpu from replacing the crash kernel
+        * we are using after a panic on a different cpu.
+@@ -1061,7 +1085,11 @@ void crash_kexec(struct pt_regs *regs)
+                       struct pt_regs fixed_regs;
+                       crash_setup_regs(&fixed_regs, regs);
+                       machine_crash_shutdown(&fixed_regs);
++#ifdef CONFIG_XEN
++                      xen_machine_kexec(image);
++#else
+                       machine_kexec(image);
++#endif
+               }
+               xchg(&kexec_lock, 0);
+       }
+--- 0002/kernel/sys.c
++++ work/kernel/sys.c
+@@ -435,8 +435,12 @@ void kernel_kexec(void)
+       kernel_restart_prepare(NULL);
+       printk(KERN_EMERG "Starting new kernel\n");
+       machine_shutdown();
++#ifdef CONFIG_XEN
++      xen_machine_kexec(image);
++#else
+       machine_kexec(image);
+ #endif
++#endif
+ }
+ EXPORT_SYMBOL_GPL(kernel_kexec);
+ 
diff -r d1b0a5adaeab -r c988f781817d xen/arch/ia64/xen/crash.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ia64/xen/crash.c Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,19 @@
+#include <xen/lib.h>       /* for printk() used in stub */
+#include <xen/types.h>
+#include <public/kexec.h>
+
+void machine_crash_shutdown(void)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -r d1b0a5adaeab -r c988f781817d xen/arch/ia64/xen/machine_kexec.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ia64/xen/machine_kexec.c Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,34 @@
+#include <xen/lib.h>       /* for printk() used in stubs */
+#include <xen/types.h>
+#include <public/kexec.h>
+
+int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+    return -1;
+}
+
+void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+void machine_kexec(xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+void machine_shutdown(xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/arch/powerpc/crash.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/crash.c  Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,19 @@
+#include <xen/lib.h>       /* for printk() used in stub */
+#include <xen/types.h>
+#include <public/kexec.h>
+
+void machine_crash_shutdown(void)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -r d1b0a5adaeab -r c988f781817d xen/arch/powerpc/machine_kexec.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/machine_kexec.c  Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,34 @@
+#include <xen/lib.h>       /* for printk() used in stubs */
+#include <xen/types.h>
+#include <public/kexec.h>
+
+int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+    return -1;
+}
+
+void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+void machine_kexec(xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+void machine_shutdown(xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/arch/x86/crash.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/crash.c      Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,19 @@
+#include <xen/lib.h>       /* for printk() used in stub */
+#include <xen/types.h>
+#include <public/kexec.h>
+
+void machine_crash_shutdown(void)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -r d1b0a5adaeab -r c988f781817d xen/arch/x86/machine_kexec.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/machine_kexec.c      Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,34 @@
+#include <xen/lib.h>       /* for printk() used in stubs */
+#include <xen/types.h>
+#include <public/kexec.h>
+
+int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+    return -1;
+}
+
+void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+void machine_kexec(xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+void machine_shutdown(xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/common/kexec.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/common/kexec.c        Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,370 @@
+/******************************************************************************
+ * kexec.c - Achitecture independent kexec code for Xen
+ * 
+ * Xen port written by:
+ * - Simon 'Horms' Horman <horms@xxxxxxxxxxxx>
+ * - Magnus Damm <magnus@xxxxxxxxxxxxx>
+ */
+
+#include <asm/kexec.h>
+#include <xen/lib.h>
+#include <xen/ctype.h>
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/sched.h>
+#include <xen/types.h>
+#include <xen/kexec.h>
+#include <xen/keyhandler.h>
+#include <public/kexec.h>
+#include <xen/cpumask.h>
+#include <asm/atomic.h>
+#include <xen/spinlock.h>
+#include <xen/version.h>
+#include <public/elfnote.h>
+
+static char opt_crashkernel[32] = "";
+string_param("crashkernel", opt_crashkernel);
+
+DEFINE_PER_CPU (crash_note_t, crash_notes);
+cpumask_t crash_saved_cpus;
+int crashing_cpu;
+
+xen_kexec_image_t kexec_image[KEXEC_IMAGE_NR];
+
+#define KEXEC_FLAG_DEFAULT_POS   (KEXEC_IMAGE_NR + 0)
+#define KEXEC_FLAG_CRASH_POS     (KEXEC_IMAGE_NR + 1)
+#define KEXEC_FLAG_IN_PROGRESS   (KEXEC_IMAGE_NR + 2)
+
+unsigned long kexec_flags = 0; /* the lowest bits are for KEXEC_IMAGE... */
+
+spinlock_t kexec_lock = SPIN_LOCK_UNLOCKED;
+
+static void one_cpu_only(void)
+{
+   /* Only allow the first cpu to continue - force other cpus to spin */
+    if (test_and_set_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags))
+    {
+        while (1);
+    }
+}
+
+/* Save the registers in the per-cpu crash note buffer */
+
+void machine_crash_save_cpu(void)
+{
+    int cpu = smp_processor_id();
+    crash_note_t *cntp;
+
+    if (!cpu_test_and_set(cpu, crash_saved_cpus))
+    {
+        cntp = &per_cpu(crash_notes, cpu);
+        elf_core_save_regs(&cntp->core.desc.desc.pr_reg,
+                           &cntp->xen_regs.desc.desc);
+
+        /* setup crash "CORE" note */
+        setup_crash_note(cntp, core, CORE_STR, CORE_STR_LEN, NT_PRSTATUS);
+
+        /* setup crash note "Xen", XEN_ELFNOTE_CRASH_REGS */
+        setup_crash_note(cntp, xen_regs, XEN_STR, XEN_STR_LEN, 
+                         XEN_ELFNOTE_CRASH_REGS);
+    }
+}
+
+/* Setup the single Xen specific info crash note */
+
+crash_xen_info_t *machine_crash_save_info(void)
+{
+    int cpu = smp_processor_id();
+    crash_note_t *cntp;
+    crash_xen_info_t *info;
+
+    BUG_ON(!cpu_test_and_set(cpu, crash_saved_cpus));
+
+    cntp = &per_cpu(crash_notes, cpu);
+
+    /* setup crash note "Xen", XEN_ELFNOTE_CRASH_INFO */
+    setup_crash_note(cntp, xen_info, XEN_STR, XEN_STR_LEN, 
+                     XEN_ELFNOTE_CRASH_INFO);
+
+    info = &cntp->xen_info.desc.desc;
+
+    info->xen_major_version = xen_major_version();
+    info->xen_minor_version = xen_minor_version();
+    info->xen_extra_version = __pa(xen_extra_version());
+    info->xen_changeset = __pa(xen_changeset());
+    info->xen_compiler = __pa(xen_compiler());
+    info->xen_compile_date = __pa(xen_compile_date());
+    info->xen_compile_time = __pa(xen_compile_time());
+    info->tainted = tainted;
+
+    return info;
+}
+
+void machine_crash_kexec(void)
+{
+    int pos;
+    xen_kexec_image_t *image;
+
+    one_cpu_only();
+ 
+    machine_crash_save_cpu();
+    crashing_cpu = smp_processor_id();
+
+    machine_crash_shutdown();
+
+    pos = (test_bit(KEXEC_FLAG_CRASH_POS, &kexec_flags) != 0);
+
+    if (test_bit(KEXEC_IMAGE_CRASH_BASE + pos, &kexec_flags))
+    {
+        image = &kexec_image[KEXEC_IMAGE_CRASH_BASE + pos];
+        machine_kexec(image); /* Does not return */
+    }
+
+    while (1); /* No image available - just spin */
+}
+
+static void do_crashdump_trigger(unsigned char key)
+{
+       printk("triggering crashdump\n");
+       machine_crash_kexec();
+}
+
+static __init int register_crashdump_trigger(void)
+{
+       register_keyhandler('c', do_crashdump_trigger, "trigger a crashdump");
+       return 0;
+}
+__initcall(register_crashdump_trigger);
+
+void machine_kexec_reserved(xen_kexec_reserve_t *reservation)
+{
+    unsigned long val[2];
+    char *str = opt_crashkernel;
+    int k = 0; 
+
+    memset(reservation, 0, sizeof(*reservation));
+
+    while (k < ARRAY_SIZE(val)) {
+        if (*str == '\0') {
+            break;
+        }
+        val[k] = simple_strtoul(str, &str, 0);
+        switch (toupper(*str)) {
+        case 'G': val[k] <<= 10;
+        case 'M': val[k] <<= 10;
+        case 'K': val[k] <<= 10;
+            str++;
+        }
+        if (*str == '@') {
+            str++;
+        }
+        k++;
+    }
+
+    if (k == ARRAY_SIZE(val)) {
+        reservation->size = val[0];
+        reservation->start = val[1];
+    }
+}
+
+static int kexec_get_reserve(xen_kexec_range_t *range)
+{
+    xen_kexec_reserve_t reservation;
+    
+    machine_kexec_reserved(&reservation);
+
+    range->start = reservation.start;
+    range->size = reservation.size;
+    return 0;
+}
+
+extern unsigned long _text, _end;
+
+static int kexec_get_xen(xen_kexec_range_t *range, int get_ma)
+{
+    if (get_ma)
+        range->start = virt_to_maddr(&_text);
+    else
+        range->start = (unsigned long) &_text;
+
+    range->size = &_end - &_text;
+    return 0;
+}
+
+static int kexec_get_cpu(xen_kexec_range_t *range)
+{
+    if (range->nr < 0 || range->nr >= num_present_cpus())
+        return -EINVAL;
+
+    range->start = __pa((unsigned long)&per_cpu(crash_notes, range->nr));
+    range->size = sizeof(crash_note_t);
+    return 0;
+}
+
+static int kexec_get_range(XEN_GUEST_HANDLE(void) uarg)
+{
+    xen_kexec_range_t range;
+    int ret = -EINVAL;
+    
+    if (unlikely(copy_from_guest(&range, uarg, 1)))
+        return -EFAULT;
+
+    switch (range.range)
+    {
+    case KEXEC_RANGE_MA_CRASH:
+        ret = kexec_get_reserve(&range);
+        break;
+    case KEXEC_RANGE_MA_XEN:
+        ret = kexec_get_xen(&range, 1);
+        break;
+    case KEXEC_RANGE_VA_XEN:
+        ret = kexec_get_xen(&range, 0);
+        break;
+    case KEXEC_RANGE_MA_CPU:
+        ret = kexec_get_cpu(&range);
+        break;
+    }
+
+    if (ret == 0 && unlikely(copy_to_guest(uarg, &range, 1)))
+        return -EFAULT;
+    
+    return ret;
+}
+
+static int kexec_load_get_bits(int type, int *base, int *bit)
+{
+    switch (type)
+    {
+    case KEXEC_TYPE_DEFAULT:
+        *base = KEXEC_IMAGE_DEFAULT_BASE;
+        *bit = KEXEC_FLAG_DEFAULT_POS;
+        break;
+    case KEXEC_TYPE_CRASH:
+        *base = KEXEC_IMAGE_CRASH_BASE;
+        *bit = KEXEC_FLAG_CRASH_POS;
+        break;
+    default:
+        return -1;
+    }
+    return 0;
+}
+
+static int kexec_load_unload(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
+{
+    xen_kexec_load_t load;
+    xen_kexec_image_t *image;
+    int base, bit, pos;
+    int ret = 0;
+
+    if (unlikely(copy_from_guest(&load, uarg, 1)))
+        return -EFAULT;
+
+    if (kexec_load_get_bits(load.type, &base, &bit))
+        return -EINVAL;
+
+    pos = (test_bit(bit, &kexec_flags) != 0);
+
+    /* Load the user data into an unused image */
+    if (op == KEXEC_CMD_kexec_load)
+    {
+        image = &kexec_image[base + !pos];
+
+        BUG_ON(test_bit((base + !pos), &kexec_flags)); /* must be free */
+
+        memcpy(image, &load.image, sizeof(*image));
+            
+        if (!(ret = machine_kexec_load(load.type, base + !pos, image)))
+        {
+            /* Set image present bit */
+            set_bit((base + !pos), &kexec_flags);
+
+            /* Make new image the active one */
+            change_bit(bit, &kexec_flags);
+        }
+    }
+
+    /* Unload the old image if present and load successful */
+    if (ret == 0 && !test_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags))
+    {
+        if (test_and_clear_bit((base + pos), &kexec_flags))
+        {
+            image = &kexec_image[base + pos];
+            machine_kexec_unload(load.type, base + pos, image);
+        }
+    }
+
+    return ret;
+}
+
+static int kexec_exec(XEN_GUEST_HANDLE(void) uarg)
+{
+    xen_kexec_exec_t exec;
+    xen_kexec_image_t *image;
+    int base, bit, pos;
+
+    if (unlikely(copy_from_guest(&exec, uarg, 1)))
+        return -EFAULT;
+
+    if (kexec_load_get_bits(exec.type, &base, &bit))
+        return -EINVAL;
+
+    pos = (test_bit(bit, &kexec_flags) != 0);
+
+    /* Only allow kexec/kdump into loaded images */
+    if (!test_bit(base + pos, &kexec_flags))
+        return -ENOENT;
+
+    switch (exec.type)
+    {
+    case KEXEC_TYPE_DEFAULT:
+        image = &kexec_image[base + pos];
+        one_cpu_only();
+        machine_shutdown(image); /* Does not return */
+        break;
+    case KEXEC_TYPE_CRASH:
+        machine_crash_kexec(); /* Does not return */
+        break;
+    }
+
+    return -EINVAL; /* never reached */
+}
+
+long do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
+{
+    unsigned long flags;
+    int ret = -EINVAL;
+
+    if ( !IS_PRIV(current->domain) )  
+        return -EPERM;
+
+    switch (op)
+    {
+    case KEXEC_CMD_kexec_get_range:
+        ret = kexec_get_range(uarg);
+        break;
+    case KEXEC_CMD_kexec_load:
+    case KEXEC_CMD_kexec_unload:
+        spin_lock_irqsave(&kexec_lock, flags);
+        if (!test_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags))
+        {
+            ret = kexec_load_unload(op, uarg);
+        }
+        spin_unlock_irqrestore(&kexec_lock, flags);
+        break;
+    case KEXEC_CMD_kexec:
+        ret = kexec_exec(uarg);
+        break;
+    }
+
+    return ret;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/include/asm-ia64/elf.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-ia64/elf.h        Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,30 @@
+#ifndef __IA64_ELF_H__
+#define __IA64_ELF_H__
+
+#include <xen/lib.h>       /* for printk() used in stub */
+
+typedef struct {
+    unsigned long dummy;
+} ELF_Gregset;
+
+typedef struct {
+    unsigned long dummy;
+} crash_xen_core_t;
+
+extern inline void elf_core_save_regs(ELF_Gregset *core_regs, 
+                                      crash_xen_core_t *xen_core_regs)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+#endif /* __IA64_ELF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/include/asm-ia64/kexec.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-ia64/kexec.h      Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,25 @@
+#ifndef __IA64_KEXEC_H__
+#define __IA64_KEXEC_H__
+
+#include <xen/lib.h>       /* for printk() used in stub */
+#include <xen/types.h>
+#include <public/xen.h>
+#include <xen/kexec.h>
+
+static inline void machine_kexec(xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+#endif /* __IA64_KEXEC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -r d1b0a5adaeab -r c988f781817d xen/include/asm-powerpc/elf.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-powerpc/elf.h     Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,30 @@
+#ifndef _ASM_ELF_H__
+#define _ASM_ELF_H__
+
+#include <xen/lib.h>       /* for printk() used in stub */
+
+typedef struct {
+    unsigned long dummy;
+} ELF_Gregset;
+
+typedef struct {
+    unsigned long dummy;
+} crash_xen_core_t;
+
+extern inline void elf_core_save_regs(ELF_Gregset *core_regs, 
+                                      crash_xen_core_t *xen_core_regs)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+#endif /* _ASM_ELF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/include/asm-powerpc/kexec.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-powerpc/kexec.h   Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,25 @@
+#ifndef _ASM_KEXEC_H__
+#define _ASM_KEXEC_H__
+
+#include <xen/lib.h>       /* for printk() used in stub */
+#include <xen/types.h>
+#include <public/xen.h>
+#include <xen/kexec.h>
+
+static inline void machine_kexec(xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+#endif /* _ASM_KEXEC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -r d1b0a5adaeab -r c988f781817d xen/include/asm-x86/elf.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/elf.h Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,30 @@
+#ifndef __X86_ELF_H__
+#define __X86_ELF_H__
+
+#include <xen/lib.h>       /* for printk() used in stub */
+
+typedef struct {
+    unsigned long dummy;
+} ELF_Gregset;
+
+typedef struct {
+    unsigned long dummy;
+} crash_xen_core_t;
+
+extern inline void elf_core_save_regs(ELF_Gregset *core_regs, 
+                                      crash_xen_core_t *xen_core_regs)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+#endif /* __X86_ELF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/include/asm-x86/kexec.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/kexec.h       Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,24 @@
+#ifndef __X86_KEXEC_H__
+#define __X86_KEXEC_H__
+
+#include <xen/lib.h>       /* for printk() used in stub */
+#include <xen/types.h>
+#include <public/xen.h>
+#include <xen/kexec.h>
+
+static inline void machine_kexec(xen_kexec_image_t *image)
+{
+    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+#endif /* __X86_KEXEC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/include/public/kexec.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/public/kexec.h        Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,131 @@
+/******************************************************************************
+ * kexec.h - Public portion
+ * 
+ * Xen port written by:
+ * - Simon 'Horms' Horman <horms@xxxxxxxxxxxx>
+ * - Magnus Damm <magnus@xxxxxxxxxxxxx>
+ */
+
+#ifndef _XEN_PUBLIC_KEXEC_H
+#define _XEN_PUBLIC_KEXEC_H
+
+
+/* This file describes the Kexec / Kdump hypercall interface for Xen.
+ *
+ * Kexec under vanilla Linux allows a user to reboot the physical machine 
+ * into a new user-specified kernel. The Xen port extends this idea
+ * to allow rebooting of the machine from dom0. When kexec for dom0
+ * is used to reboot,  both the hypervisor and the domains get replaced
+ * with some other kernel. It is possible to kexec between vanilla
+ * Linux and Xen and back again. Xen to Xen works well too.
+ *
+ * The hypercall interface for kexec can be divided into three main
+ * types of hypercall operations:
+ *
+ * 1) Range information:
+ *    This is used by the dom0 kernel to ask the hypervisor about various 
+ *    address information. This information is needed to allow kexec-tools 
+ *    to fill in the ELF headers for /proc/vmcore properly.
+ *
+ * 2) Load and unload of images:
+ *    There are no big surprises here, the kexec binary from kexec-tools
+ *    runs in userspace in dom0. The tool loads/unloads data into the
+ *    dom0 kernel such as new kernel, initramfs and hypervisor. When
+ *    loaded the dom0 kernel performs a load hypercall operation, and
+ *    before releasing all page references the dom0 kernel calls unload.
+ *
+ * 3) Kexec operation:
+ *    This is used to start a previously loaded kernel.
+ */
+
+#include "xen.h"
+
+/*
+ * Prototype for this hypercall is:
+ *  int kexec_op(int cmd, void *args)
+ * @cmd  == KEXEC_CMD_... 
+ *          KEXEC operation to perform
+ * @args == Operation-specific extra arguments (NULL if none).
+ */
+
+/*
+ * Kexec supports two types of operation:
+ * - kexec into a regular kernel, very similar to a standard reboot
+ *   - KEXEC_TYPE_DEFAULT is used to specify this type
+ * - kexec into a special "crash kernel", aka kexec-on-panic
+ *   - KEXEC_TYPE_CRASH is used to specify this type
+ *   - parts of our system may be broken at kexec-on-panic time
+ *     - the code should be kept as simple and self-contained as possible
+ */
+
+#define KEXEC_TYPE_DEFAULT 0
+#define KEXEC_TYPE_CRASH   1
+
+
+/* The kexec implementation for Xen allows the user to load two
+ * types of kernels, KEXEC_TYPE_DEFAULT and KEXEC_TYPE_CRASH.
+ * All data needed for a kexec reboot is kept in one xen_kexec_image_t
+ * per "instance". The data mainly consists of machine address lists to pages
+ * together with destination addresses. The data in xen_kexec_image_t
+ * is passed to the "code page" which is one page of code that performs
+ * the final relocations before jumping to the new kernel.
+ */
+ 
+typedef struct xen_kexec_image {
+    unsigned long indirection_page;
+    unsigned long start_address;
+} xen_kexec_image_t;
+
+/*
+ * Perform kexec having previously loaded a kexec or kdump kernel
+ * as appropriate.
+ * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
+ */
+#define KEXEC_CMD_kexec                 0
+typedef struct xen_kexec_exec {
+    int type;
+} xen_kexec_exec_t;
+
+/*
+ * Load/Unload kernel image for kexec or kdump.
+ * type  == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
+ * image == relocation information for kexec (ignored for unload) [in]
+ */
+#define KEXEC_CMD_kexec_load            1
+#define KEXEC_CMD_kexec_unload          2
+typedef struct xen_kexec_load {
+    int type;
+    xen_kexec_image_t image;
+} xen_kexec_load_t;
+
+#define KEXEC_RANGE_MA_CRASH 0   /* machine address and size of crash area */
+#define KEXEC_RANGE_MA_XEN   1   /* machine address and size of Xen itself */
+#define KEXEC_RANGE_VA_XEN   2   /* virtual adrress and size of Xen itself */
+#define KEXEC_RANGE_MA_CPU   3   /* machine address and size of a CPU note */
+
+/*
+ * Find the address and size of certain memory areas
+ * range == KEXEC_RANGE_... [in]
+ * nr    == physical CPU number (starting from 0) if KEXEC_RANGE_MA_CPU [in]
+ * size  == number of bytes reserved in window [out]
+ * start == address of the first byte in the window [out]
+ */
+#define KEXEC_CMD_kexec_get_range       3
+typedef struct xen_kexec_range {
+    int range;
+    int nr;
+    unsigned long size;
+    unsigned long start;
+} xen_kexec_range_t;
+
+#endif /* _XEN_PUBLIC_KEXEC_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/include/xen/elfcore.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/xen/elfcore.h Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,137 @@
+/******************************************************************************
+ * elfcore.h
+ *
+ * Based heavily on include/linux/elfcore.h from Linux 2.6.16
+ * Naming scheeme based on include/xen/elf.h (not include/linux/elfcore.h)
+ *
+ */
+
+#ifndef __ELFCOREC_H__
+#define __ELFCOREC_H__
+
+#include <xen/types.h>
+#include <xen/elf.h>
+#include <asm/elf.h>
+#include <public/xen.h>
+
+#define NT_PRSTATUS     1
+
+typedef struct
+{
+    int signo;                       /* signal number */
+    int code;                        /* extra code */
+    int errno;                       /* errno */
+} ELF_Signifo;
+
+/* These seem to be the same length on all architectures on Linux */
+typedef int ELF_Pid;
+typedef struct {
+       long tv_sec;
+       long tv_usec;
+} ELF_Timeval;
+
+/*
+ * Definitions to generate Intel SVR4-like core files.
+ * These mostly have the same names as the SVR4 types with "elf_"
+ * tacked on the front to prevent clashes with linux definitions,
+ * and the typedef forms have been avoided.  This is mostly like
+ * the SVR4 structure, but more Linuxy, with things that Linux does
+ * not support and which gdb doesn't really use excluded.
+ */
+typedef struct
+{
+    ELF_Signifo pr_info;         /* Info associated with signal */
+    short pr_cursig;             /* Current signal */
+    unsigned long pr_sigpend;    /* Set of pending signals */
+    unsigned long pr_sighold;    /* Set of held signals */
+    ELF_Pid pr_pid;
+    ELF_Pid pr_ppid;
+    ELF_Pid pr_pgrp;
+    ELF_Pid pr_sid;
+    ELF_Timeval pr_utime;        /* User time */
+    ELF_Timeval pr_stime;        /* System time */
+    ELF_Timeval pr_cutime;       /* Cumulative user time */
+    ELF_Timeval pr_cstime;       /* Cumulative system time */
+    ELF_Gregset pr_reg;          /* GP registers - from asm header file */
+    int pr_fpvalid;              /* True if math co-processor being used.  */
+} ELF_Prstatus;
+
+/*
+ * The following data structures provide 64-bit ELF notes. In theory it should 
+ * be possible to support both 64-bit and 32-bit ELF files, but to keep it 
+ * simple we only do 64-bit.
+ *
+ * Please note that the current code aligns the 64-bit notes in the same
+ * way as Linux does. We are not following the 64-bit ELF spec, no one does.
+ *
+ * We are avoiding two problems by restricting us to 64-bit notes only:
+ * - Alignment of notes change with the word size. Ick.
+ * - We would need to tell kexec-tools which format we are using in the
+ *   hypervisor to make sure the right ELF format is generated.
+ *   That requires infrastructure. Let's not.
+ */
+
+#define ALIGN(x, n) ((x + ((1 << n) - 1)) / (1 << n))
+#define PAD32(x) u32 pad_data[ALIGN(x, 2)]
+
+#define TYPEDEF_NOTE(type, strlen, desctype)    \
+    typedef struct {                            \
+        union {                                 \
+            struct {                            \
+                Elf_Note note;                  \
+                unsigned char name[strlen];     \
+            } note;                             \
+            PAD32(sizeof(Elf_Note) + strlen);   \
+        } note;                                 \
+        union {                                 \
+            desctype desc;                      \
+            PAD32(sizeof(desctype));            \
+        } desc;                                 \
+    } __attribute__ ((packed)) type
+
+#define CORE_STR                "CORE"
+#define CORE_STR_LEN            5 /* including terminating zero */
+
+TYPEDEF_NOTE(crash_note_core_t, CORE_STR_LEN, ELF_Prstatus);
+
+#define XEN_STR                 "Xen"
+#define XEN_STR_LEN             4 /* including terminating zero */
+
+TYPEDEF_NOTE(crash_note_xen_core_t, XEN_STR_LEN, crash_xen_core_t);
+
+typedef struct {
+    unsigned long xen_major_version;
+    unsigned long xen_minor_version;
+    unsigned long xen_extra_version;
+    unsigned long xen_changeset;
+    unsigned long xen_compiler;
+    unsigned long xen_compile_date;
+    unsigned long xen_compile_time;
+    unsigned long tainted;
+} crash_xen_info_t;
+
+TYPEDEF_NOTE(crash_note_xen_info_t, XEN_STR_LEN, crash_xen_info_t);
+
+typedef struct {
+    crash_note_core_t core;
+    crash_note_xen_core_t xen_regs;
+    crash_note_xen_info_t xen_info;
+} __attribute__ ((packed)) crash_note_t;
+
+#define setup_crash_note(np, member, str, str_len, id) \
+  np->member.note.note.note.namesz = str_len; \
+  np->member.note.note.note.descsz = sizeof(np->member.desc.desc); \
+  np->member.note.note.note.type = id; \
+  memcpy(np->member.note.note.name, str, str_len)
+
+#endif /* __ELFCOREC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1b0a5adaeab -r c988f781817d xen/include/xen/kexec.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/xen/kexec.h   Thu Nov 30 12:38:50 2006 +0000
@@ -0,0 +1,43 @@
+#ifndef __XEN_KEXEC_H__
+#define __XEN_KEXEC_H__
+
+#include <public/kexec.h>
+#include <asm/percpu.h>
+#include <xen/elfcore.h>
+
+extern int crashing_cpu;
+
+typedef struct xen_kexec_reserve {
+    unsigned long size;
+    unsigned long start;
+} xen_kexec_reserve_t;
+
+/* We have space for 4 images to support atomic update
+ * of images. This is important for CRASH images since
+ * a panic can happen at any time...
+ */
+
+#define KEXEC_IMAGE_DEFAULT_BASE 0
+#define KEXEC_IMAGE_CRASH_BASE   2
+#define KEXEC_IMAGE_NR           4
+
+int machine_kexec_load(int type, int slot, xen_kexec_image_t *image);
+void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image);
+void machine_kexec_reserved(xen_kexec_reserve_t *reservation);
+void machine_shutdown(xen_kexec_image_t *image);
+void machine_crash_kexec(void);
+void machine_crash_save_cpu(void);
+crash_xen_info_t *machine_crash_save_info(void);
+void machine_crash_shutdown(void);
+
+#endif /* __XEN_KEXEC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.