[PATCH 01/04] Kexec / Kdump: Generic code
This patch implements the generic portion of the Kexec / Kdump port to Xen.
Signed-Off-By: Magnus Damm <magnus@xxxxxxxxxxxxx>
---
Applies on top of xen-unstable-11856.
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1
linux-2.6-xen-sparse/drivers/xen/core/crash.c | 44 ++
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 80 ++++
linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4
patches/linux-2.6.16.29/kexec-generic.patch | 281 ++++++++++++++++
patches/linux-2.6.16.29/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 | 288 +++++++++++++++++
xen/common/page_alloc.c | 33 +
xen/drivers/char/console.c | 3
xen/include/asm-ia64/elf.h | 23 +
xen/include/asm-ia64/kexec.h | 31 +
xen/include/asm-powerpc/elf.h | 23 +
xen/include/asm-powerpc/kexec.h | 31 +
xen/include/asm-x86/elf.h | 23 +
xen/include/asm-x86/kexec.h | 30 +
xen/include/public/kexec.h | 88 +++++
xen/include/xen/elfcore.h | 71 ++++
xen/include/xen/hypercall.h | 6
xen/include/xen/kexec.h | 37 ++
xen/include/xen/mm.h | 1
30 files changed, 1254 insertions(+), 11 deletions(-)
--- 0001/linux-2.6-xen-sparse/drivers/xen/core/Makefile
+++ work/linux-2.6-xen-sparse/drivers/xen/core/Makefile 2006-10-23
11:36:13.000000000 +0900
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
obj-$(CONFIG_XEN_SKBUFF) += skbuff.o
obj-$(CONFIG_XEN_REBOOT) += reboot.o
obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
--- /dev/null
+++ work/linux-2.6-xen-sparse/drivers/xen/core/crash.c 2006-10-23
11:36:14.000000000 +0900
@@ -0,0 +1,44 @@
+#include <asm/ptrace.h>
+#include <linux/types.h>
+#include <asm/kexec-xen.h>
+#include <asm/hypervisor.h>
+#include <asm/system.h>
+#include <linux/preempt.h>
+#include <linux/smp.h>
+#include <asm/hw_irq.h>
+#include <xen/interface/kexec.h>
+
+/*
+ * This passes the registers's down to the hypervisor and has it kexec()
+ * This is a bit different to the linux implementation which
+ * has this call save registers and stop CPUs and then goes into
+ * machine_kexec() later. But for Xen it makes more sense to
+ * have the kexec hypercall do everything, and this call
+ * has the registers parameter that is needed.
+ * to the hypervisor to allow the hypervisor to kdump itself
+ * on an internal panic
+ */
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ xen_kexec_exec_t xke;
+
+ printk("machine_crash_shutdown: %d\n", smp_processor_id());
+
+ local_irq_disable();
+ memset(&xke, 0, sizeof(xke));
+ xke.type = KEXEC_TYPE_CRASH;
+ crash_translate_regs(regs, &xke.regs);
+
+ HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke);
+ panic("KEXEC_CMD_kexec hypercall should not return\n");
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- /dev/null
+++ work/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c 2006-10-23
11:36:14.000000000 +0900
@@ -0,0 +1,80 @@
+/*
+ * 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 <asm/hypercall.h>
+#include <asm/kexec-xen.h>
+
+extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki,
+ struct kimage *image);
+
+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");
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- 0001/linux-2.6-xen-sparse/drivers/xen/core/reboot.c
+++ work/linux-2.6-xen-sparse/drivers/xen/core/reboot.c 2006-10-23
11:36:13.000000000 +0900
@@ -65,6 +65,10 @@ void machine_power_off(void)
HYPERVISOR_shutdown(SHUTDOWN_poweroff);
}
+#ifdef CONFIG_KEXEC
+void machine_shutdown(void) { }
+#endif
+
int reboot_thru_bios = 0; /* for dmi_scan.c */
EXPORT_SYMBOL(machine_restart);
EXPORT_SYMBOL(machine_halt);
--- /dev/null
+++ work/patches/linux-2.6.16.29/kexec-generic.patch 2006-10-23
11:36:14.000000000 +0900
@@ -0,0 +1,281 @@
+--- 0002/drivers/base/cpu.c
++++ work/drivers/base/cpu.c
+@@ -11,6 +11,10 @@
+
+ #include "base.h"
+
++#ifdef CONFIG_XEN
++#include <xen/interface/kexec.h>
++#endif
++
+ struct sysdev_class cpu_sysdev_class = {
+ set_kset_name("cpu"),
+ };
+@@ -86,6 +90,22 @@ static inline void register_cpu_control(
+ #ifdef CONFIG_KEXEC
+ #include <linux/kexec.h>
+
++#ifdef CONFIG_XEN
++static unsigned long get_crash_notes(int cpu)
++{
++ xen_kexec_note_t note;
++
++ memset(¬e, 0, sizeof(note));
++ note.vcpu = cpu;
++
++ if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_crash_note, ¬e) < 0)
++ return 0UL;
++
++ return note.address;
++}
++#endif
++
++/* XXX: This only finds dom0's CPU's */
+ static ssize_t show_crash_notes(struct sys_device *dev, char *buf)
+ {
+ struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+@@ -101,7 +121,11 @@ static ssize_t show_crash_notes(struct s
+ * boot up and this data does not change there after. Hence this
+ * operation should be safe. No locking required.
+ */
++#ifndef CONFIG_XEN
+ addr = __pa(per_cpu_ptr(crash_notes, cpunum));
++#else
++ addr = (unsigned long long)get_crash_notes(cpunum);
++#endif
+ rc = sprintf(buf, "%Lx\n", addr);
+ return rc;
+ }
+--- 0001/include/linux/kexec.h
++++ work/include/linux/kexec.h
+@@ -91,6 +91,11 @@ 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;
++#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
+@@ -26,6 +26,9 @@
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/semaphore.h>
++#ifdef CONFIG_XEN
++#include <asm/kexec-xen.h>
++#endif
+
+ /* Per cpu memory for storing cpu states in case of system crash. */
+ note_buf_t* crash_notes;
+@@ -403,7 +406,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 +440,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 +494,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 +521,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 +543,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 +604,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 +622,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 +701,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 +716,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 +744,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 +794,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 +826,7 @@ out:
+ return result;
+ }
+
++#ifndef CONFIG_XEN
+ static int kimage_load_crash_segment(struct kimage *image,
+ struct kexec_segment *segment)
+ {
+@@ -833,7 +849,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 +897,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 +1014,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 +1073,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,12 +1088,17 @@ 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);
+ }
+ }
+
++#ifndef CONFIG_XEN
+ static int __init crash_notes_memory_init(void)
+ {
+ /* Allocate memory for saving cpu registers. */
+@@ -1079,3 +1111,4 @@ static int __init crash_notes_memory_ini
+ return 0;
+ }
+ module_init(crash_notes_memory_init)
++#endif
+--- 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);
+
--- 0001/patches/linux-2.6.16.29/series
+++ work/patches/linux-2.6.16.29/series 2006-10-23 11:36:13.000000000 +0900
@@ -1,3 +1,4 @@
+kexec-generic.patch
blktap-aio-16_03_06.patch
device_bind.patch
fix-hz-suspend.patch
--- 0001/xen/arch/ia64/xen/Makefile
+++ work/xen/arch/ia64/xen/Makefile 2006-10-23 11:36:13.000000000 +0900
@@ -1,3 +1,5 @@
+obj-y += machine_kexec.o
+obj-y += crash.o
obj-y += acpi.o
obj-y += dom0_ops.o
obj-y += domain.o
--- /dev/null
+++ work/xen/arch/ia64/xen/crash.c 2006-10-23 11:36:14.000000000 +0900
@@ -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(struct cpu_user_regs *regs)
+{
+ 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:
+ */
+
--- /dev/null
+++ work/xen/arch/ia64/xen/machine_kexec.c 2006-10-23 11:36:14.000000000
+0900
@@ -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:
+ */
--- 0001/xen/arch/powerpc/Makefile
+++ work/xen/arch/powerpc/Makefile 2006-10-23 11:36:13.000000000 +0900
@@ -40,6 +40,8 @@ obj-y += smp-tbsync.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
--- /dev/null
+++ work/xen/arch/powerpc/crash.c 2006-10-23 11:36:14.000000000 +0900
@@ -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(struct cpu_user_regs *regs)
+{
+ 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:
+ */
+
--- /dev/null
+++ work/xen/arch/powerpc/machine_kexec.c 2006-10-23 11:36:14.000000000
+0900
@@ -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:
+ */
--- 0001/xen/arch/x86/Makefile
+++ work/xen/arch/x86/Makefile 2006-10-23 11:36:13.000000000 +0900
@@ -41,6 +41,8 @@ obj-y += trampoline.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
--- /dev/null
+++ work/xen/arch/x86/crash.c 2006-10-23 11:36:14.000000000 +0900
@@ -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(struct cpu_user_regs *regs)
+{
+ 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:
+ */
+
--- /dev/null
+++ work/xen/arch/x86/machine_kexec.c 2006-10-23 11:36:14.000000000 +0900
@@ -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:
+ */
--- 0001/xen/common/Makefile
+++ work/xen/common/Makefile 2006-10-23 11:36:13.000000000 +0900
@@ -7,6 +7,7 @@ obj-y += event_channel.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
--- /dev/null
+++ work/xen/common/kexec.c 2006-10-23 11:36:14.000000000 +0900
@@ -0,0 +1,288 @@
+/******************************************************************************
+ * 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 <asm/atomic.h>
+#include <xen/spinlock.h>
+
+static char opt_crashkernel[32] = "";
+string_param("crashkernel", opt_crashkernel);
+
+DEFINE_PER_CPU (note_buf_t, crash_notes);
+
+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);
+ }
+}
+
+void crash_kexec(struct cpu_user_regs *regs)
+{
+ int pos;
+ xen_kexec_image_t *image;
+ struct cpu_user_regs fixed_regs;
+
+ one_cpu_only();
+
+ crash_setup_regs(&fixed_regs, regs);
+ machine_crash_shutdown(&fixed_regs);
+
+ 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");
+ crash_kexec(NULL);
+}
+
+static __init int register_crashdump_trigger(void)
+{
+ register_keyhandler('c', do_crashdump_trigger, "trigger a crashdump");
+ return 0;
+}
+__initcall(register_crashdump_trigger);
+
+static int kexec_get_crash_note(XEN_GUEST_HANDLE(void) uarg)
+{
+ xen_kexec_note_t note;
+ struct domain *domain = current->domain;
+ struct vcpu *vcpu;
+
+ if (unlikely(copy_from_guest(¬e, uarg, 1)))
+ return -EFAULT;
+
+ if (note.vcpu < 0 || note.vcpu >= MAX_VIRT_CPUS)
+ return -EINVAL;
+
+ if (!(vcpu = domain->vcpu[note.vcpu]))
+ return -EINVAL;
+
+ note.address = __pa((unsigned long)per_cpu(crash_notes, vcpu->processor));
+
+ if (unlikely(copy_to_guest(uarg, ¬e, 1)))
+ return -EFAULT;
+
+ return 0;
+}
+
+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_GUEST_HANDLE(void) uarg)
+{
+ xen_kexec_reserve_t reservation;
+
+ machine_kexec_reserved(&reservation);
+
+ if (unlikely(copy_to_guest(uarg, &reservation, 1)))
+ return -EFAULT;
+
+ return 0;
+}
+
+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:
+ crash_kexec(&exec.regs); /* 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_crash_note:
+ spin_lock_irqsave(&kexec_lock, flags);
+ ret = kexec_get_crash_note(uarg);
+ spin_unlock_irqrestore(&kexec_lock, flags);
+ break;
+ case KEXEC_CMD_kexec_reserve:
+ ret = kexec_get_reserve(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:
+ */
--- 0001/xen/common/page_alloc.c
+++ work/xen/common/page_alloc.c 2006-10-23 11:36:13.000000000 +0900
@@ -213,24 +213,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;
- }
+ i = alloc_boot_pages_at(nr_pfns, pg);
+ if (i != 0)
+ break;
}
- return 0;
+ return i;
}
--- 0001/xen/drivers/char/console.c
+++ work/xen/drivers/char/console.c 2006-10-23 11:36:13.000000000 +0900
@@ -613,6 +613,7 @@ void panic(const char *fmt, ...)
char buf[128];
unsigned long flags;
static DEFINE_SPINLOCK(lock);
+ extern void crash_kexec(struct cpu_user_regs *regs);
debugtrace_dump();
@@ -635,6 +636,8 @@ void panic(const char *fmt, ...)
debugger_trap_immediate();
+ crash_kexec(NULL);
+
if ( opt_noreboot )
{
machine_halt();
--- /dev/null
+++ work/xen/include/asm-ia64/elf.h 2006-10-23 11:36:14.000000000 +0900
@@ -0,0 +1,23 @@
+#ifndef __IA64_ELF_H__
+#define __IA64_ELF_H__
+
+#include <xen/lib.h> /* for printk() used in stub */
+
+#define ELF_NGREG 1 /* XXX: Define to be at least as large as
+ however many register slots are needed when
+ crash notes are written during crash dump */
+
+#define ELF_CORE_COPY_REGS(pr_reg, 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:
+ */
--- /dev/null
+++ work/xen/include/asm-ia64/kexec.h 2006-10-23 11:36:14.000000000 +0900
@@ -0,0 +1,31 @@
+#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 void crash_setup_regs(struct cpu_user_regs *newregs,
+ struct cpu_user_regs *oldregs)
+{
+ printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+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:
+ */
+
--- /dev/null
+++ work/xen/include/asm-powerpc/elf.h 2006-10-23 11:36:14.000000000 +0900
@@ -0,0 +1,23 @@
+#ifndef _ASM_ELF_H__
+#define _ASM_ELF_H__
+
+#include <xen/lib.h> /* for printk() used in stub */
+
+#define ELF_NGREG 1 /* XXX: Define to be at least as large as
+ however many register slots are needed when
+ crash notes are written during crash dump */
+
+#define ELF_CORE_COPY_REGS(pr_reg, 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:
+ */
--- /dev/null
+++ work/xen/include/asm-powerpc/kexec.h 2006-10-23 11:36:14.000000000
+0900
@@ -0,0 +1,31 @@
+#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 void crash_setup_regs(struct cpu_user_regs *newregs,
+ struct cpu_user_regs *oldregs)
+{
+ printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+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:
+ */
+
--- /dev/null
+++ work/xen/include/asm-x86/elf.h 2006-10-23 11:36:14.000000000 +0900
@@ -0,0 +1,23 @@
+#ifndef __X86_ELF_H__
+#define __X86_ELF_H__
+
+#include <xen/lib.h> /* for printk() used in stub */
+
+#define ELF_NGREG 1 /* XXX: Define to be at least as large as
+ however many register slots are needed when
+ crash notes are written during crash dump */
+
+#define ELF_CORE_COPY_REGS(pr_reg, 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:
+ */
--- /dev/null
+++ work/xen/include/asm-x86/kexec.h 2006-10-23 11:36:14.000000000 +0900
@@ -0,0 +1,30 @@
+#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 void crash_setup_regs(struct cpu_user_regs *newregs,
+ struct cpu_user_regs *oldregs)
+{
+ printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+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:
+ */
--- /dev/null
+++ work/xen/include/public/kexec.h 2006-10-23 11:36:14.000000000 +0900
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * 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
+
+#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).
+ */
+
+#define KEXEC_TYPE_DEFAULT 0
+#define KEXEC_TYPE_CRASH 1
+
+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]
+ * regs == pointer to cpu_user_regs_t structure (ignored for default) [in]
+ */
+#define KEXEC_CMD_kexec 0
+typedef struct xen_kexec_exec {
+ int type;
+ cpu_user_regs_t regs;
+} 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;
+
+/*
+ * Find the base pointer and size of the area that xen has
+ * reserved for use by the crash kernel.
+ * size == number of bytes reserved in window [out]
+ * start == machine address of the first byte in the window [out]
+ */
+#define KEXEC_CMD_kexec_reserve 3
+typedef struct xen_kexec_reserve {
+ unsigned long size;
+ unsigned long start;
+} xen_kexec_reserve_t;
+
+/*
+ * Find the base pointer of the area that xen has
+ * reserved for use by a crash note for a given VCPU
+ * vcpu == VCPU number to look up [in]
+ * address == VCPU crash note machine address [out]
+ */
+#define KEXEC_CMD_kexec_crash_note 4
+typedef struct xen_kexec_note {
+ int vcpu;
+ unsigned long address;
+} xen_kexec_note_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:
+ */
--- /dev/null
+++ work/xen/include/xen/elfcore.h 2006-10-23 11:36:14.000000000 +0900
@@ -0,0 +1,71 @@
+/******************************************************************************
+ * 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;
+typedef unsigned long ELF_Greg;
+typedef ELF_Greg ELF_Gregset[ELF_NGREG];
+
+/*
+ * 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 */
+ int pr_fpvalid; /* True if math co-processor being used. */
+} ELF_Prstatus;
+
+#endif /* __ELFCOREC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- 0001/xen/include/xen/hypercall.h
+++ work/xen/include/xen/hypercall.h 2006-10-23 11:36:13.000000000 +0900
@@ -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__ */
--- /dev/null
+++ work/xen/include/xen/kexec.h 2006-10-23 11:36:14.000000000 +0900
@@ -0,0 +1,37 @@
+#ifndef __XEN_KEXEC_H__
+#define __XEN_KEXEC_H__
+
+#include <public/kexec.h>
+#include <asm/percpu.h>
+
+#define MAX_NOTE_BYTES 1024
+
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+DECLARE_PER_CPU (note_buf_t, crash_notes);
+
+/* 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_shutdown(cpu_user_regs_t *regs);
+
+#endif /* __XEN_KEXEC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- 0001/xen/include/xen/mm.h
+++ work/xen/include/xen/mm.h 2006-10-23 11:36:13.000000000 +0900
@@ -40,6 +40,7 @@ struct page_info;
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. */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|