[PATCH 02/04] Kexec / Kdump: Code shared between x86_32 and x86_64
This patch contains Kexec / Kdump code shared between x86_32 and x86_64.
Signed-Off-By: Magnus Damm <magnus@xxxxxxxxxxxxx>
---
Applies on top of xen-unstable-11856.
patches/linux-2.6.16.29/git-2a...f7.patch | 62 ++
patches/linux-2.6.16.29/git-2e...11.patch | 93 ++++
patches/linux-2.6.16.29/series | 2
xen/arch/x86/crash.c | 227 +++++++++-
xen/arch/x86/machine_kexec.c | 83 +++
xen/arch/x86/setup.c | 73 ++-
xen/arch/x86/traps.c | 3
xen/include/asm-x86/elf.h | 13
xen/include/asm-x86/fixmap.h | 4
xen/include/asm-x86/hypercall.h | 5
xen/include/asm-x86/kexec.h | 20
xen/include/asm-x86/x86_32/elf.h | 23 +
xen/include/asm-x86/x86_32/kexec.h | 43 +
xen/include/asm-x86/x86_64/elf.h | 23 +
xen/include/asm-x86/x86_64/kexec.h | 30 +
xen/include/public/kexec.h | 7
16 files changed, 666 insertions(+), 45 deletions(-)
--- /dev/null
+++
work/patches/linux-2.6.16.29/git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch
2006-10-23 11:36:15.000000000 +0900
@@ -0,0 +1,62 @@
+From: Eric W. Biederman <ebiederm@xxxxxxxxxxxx>
+Date: Sun, 30 Jul 2006 10:03:20 +0000 (-0700)
+Subject: [PATCH] machine_kexec.c: Fix the description of segment handling
+X-Git-Tag: v2.6.18-rc4
+X-Git-Url:
http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=2a8a3d5b65e86ec1dfef7d268c64a909eab94af7
+
+[PATCH] machine_kexec.c: Fix the description of segment handling
+
+One of my original comments in machine_kexec was unclear
+and this should fix it.
+
+Signed-off-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxx>
+Cc: Andi Kleen <ak@xxxxxx>
+Acked-by: Horms <horms@xxxxxxxxxxxx>
+Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
+Signed-off-by: Linus Torvalds <torvalds@xxxxxxxx>
+---
+
+--- a/arch/i386/kernel/machine_kexec.c
++++ b/arch/i386/kernel/machine_kexec.c
+@@ -189,14 +189,11 @@ NORET_TYPE void machine_kexec(struct kim
+ memcpy((void *)reboot_code_buffer, relocate_new_kernel,
+ relocate_new_kernel_size);
+
+- /* The segment registers are funny things, they are
+- * automatically loaded from a table, in memory wherever you
+- * set them to a specific selector, but this table is never
+- * accessed again you set the segment to a different selector.
+- *
+- * The more common model is are caches where the behide
+- * the scenes work is done, but is also dropped at arbitrary
+- * times.
++ /* The segment registers are funny things, they have both a
++ * visible and an invisible part. Whenever the visible part is
++ * set to a specific selector, the invisible part is loaded
++ * with from a table in memory. At no other time is the
++ * descriptor table in memory accessed.
+ *
+ * I take advantage of this here by force loading the
+ * segments, before I zap the gdt with an invalid value.
+--- a/arch/x86_64/kernel/machine_kexec.c
++++ b/arch/x86_64/kernel/machine_kexec.c
+@@ -207,14 +207,11 @@ NORET_TYPE void machine_kexec(struct kim
+ __flush_tlb();
+
+
+- /* The segment registers are funny things, they are
+- * automatically loaded from a table, in memory wherever you
+- * set them to a specific selector, but this table is never
+- * accessed again unless you set the segment to a different selector.
+- *
+- * The more common model are caches where the behide
+- * the scenes work is done, but is also dropped at arbitrary
+- * times.
++ /* The segment registers are funny things, they have both a
++ * visible and an invisible part. Whenever the visible part is
++ * set to a specific selector, the invisible part is loaded
++ * with from a table in memory. At no other time is the
++ * descriptor table in memory accessed.
+ *
+ * I take advantage of this here by force loading the
+ * segments, before I zap the gdt with an invalid value.
--- /dev/null
+++
work/patches/linux-2.6.16.29/git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch
2006-10-23 11:36:15.000000000 +0900
@@ -0,0 +1,93 @@
+From: Tobias Klauser <tklauser@xxxxxxxxxxx>
+Date: Mon, 26 Jun 2006 16:57:34 +0000 (+0200)
+Subject: Storage class should be first
+X-Git-Tag: v2.6.18-rc1
+X-Git-Url:
http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=2efe55a9cec8418f0e0cde3dc3787a42fddc4411
+
+Storage class should be first
+
+Storage class should be before const
+
+Signed-off-by: Tobias Klauser <tklauser@xxxxxxxxxxx>
+Signed-off-by: Adrian Bunk <bunk@xxxxxxxxx>
+---
+
+--- a/arch/i386/kernel/machine_kexec.c
++++ b/arch/i386/kernel/machine_kexec.c
+@@ -133,9 +133,9 @@ typedef asmlinkage NORET_TYPE void (*rel
+ unsigned long start_address,
+ unsigned int has_pae) ATTRIB_NORET;
+
+-const extern unsigned char relocate_new_kernel[];
++extern const unsigned char relocate_new_kernel[];
+ extern void relocate_new_kernel_end(void);
+-const extern unsigned int relocate_new_kernel_size;
++extern const unsigned int relocate_new_kernel_size;
+
+ /*
+ * A architecture hook called to validate the
+--- a/arch/powerpc/kernel/machine_kexec_32.c
++++ b/arch/powerpc/kernel/machine_kexec_32.c
+@@ -30,8 +30,8 @@ typedef NORET_TYPE void (*relocate_new_k
+ */
+ void default_machine_kexec(struct kimage *image)
+ {
+- const extern unsigned char relocate_new_kernel[];
+- const extern unsigned int relocate_new_kernel_size;
++ extern const unsigned char relocate_new_kernel[];
++ extern const unsigned int relocate_new_kernel_size;
+ unsigned long page_list;
+ unsigned long reboot_code_buffer, reboot_code_buffer_phys;
+ relocate_new_kernel_t rnk;
+--- a/arch/ppc/kernel/machine_kexec.c
++++ b/arch/ppc/kernel/machine_kexec.c
+@@ -25,8 +25,8 @@ typedef NORET_TYPE void (*relocate_new_k
+ unsigned long reboot_code_buffer,
+ unsigned long start_address) ATTRIB_NORET;
+
+-const extern unsigned char relocate_new_kernel[];
+-const extern unsigned int relocate_new_kernel_size;
++extern const unsigned char relocate_new_kernel[];
++extern const unsigned int relocate_new_kernel_size;
+
+ void machine_shutdown(void)
+ {
+--- a/arch/s390/kernel/machine_kexec.c
++++ b/arch/s390/kernel/machine_kexec.c
+@@ -27,8 +27,8 @@ static void kexec_halt_all_cpus(void *);
+
+ typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long);
+
+-const extern unsigned char relocate_kernel[];
+-const extern unsigned long long relocate_kernel_len;
++extern const unsigned char relocate_kernel[];
++extern const unsigned long long relocate_kernel_len;
+
+ int
+ machine_kexec_prepare(struct kimage *image)
+--- a/arch/sh/kernel/machine_kexec.c
++++ b/arch/sh/kernel/machine_kexec.c
+@@ -25,8 +25,8 @@ typedef NORET_TYPE void (*relocate_new_k
+ unsigned long start_address,
+ unsigned long vbr_reg) ATTRIB_NORET;
+
+-const extern unsigned char relocate_new_kernel[];
+-const extern unsigned int relocate_new_kernel_size;
++extern const unsigned char relocate_new_kernel[];
++extern const unsigned int relocate_new_kernel_size;
+ extern void *gdb_vbr_vector;
+
+ /*
+--- a/arch/x86_64/kernel/machine_kexec.c
++++ b/arch/x86_64/kernel/machine_kexec.c
+@@ -149,8 +149,8 @@ typedef NORET_TYPE void (*relocate_new_k
+ unsigned long start_address,
+ unsigned long pgtable) ATTRIB_NORET;
+
+-const extern unsigned char relocate_new_kernel[];
+-const extern unsigned long relocate_new_kernel_size;
++extern const unsigned char relocate_new_kernel[];
++extern const unsigned long relocate_new_kernel_size;
+
+ int machine_kexec_prepare(struct kimage *image)
+ {
--- 0003/patches/linux-2.6.16.29/series
+++ work/patches/linux-2.6.16.29/series 2006-10-23 11:36:14.000000000 +0900
@@ -1,4 +1,6 @@
kexec-generic.patch
+git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch
+git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch
blktap-aio-16_03_06.patch
device_bind.patch
fix-hz-suspend.patch
--- 0003/xen/arch/x86/crash.c
+++ work/xen/arch/x86/crash.c 2006-10-23 11:36:16.000000000 +0900
@@ -1,10 +1,231 @@
-#include <xen/lib.h> /* for printk() used in stub */
+/******************************************************************************
+ * crash.c
+ *
+ * Based heavily on arch/i386/kernel/crash.c from Linux 2.6.16
+ *
+ * Xen port written by:
+ * - Simon 'Horms' Horman <horms@xxxxxxxxxxxx>
+ * - Magnus Damm <magnus@xxxxxxxxxxxxx>
+ */
+
+
+#include <asm/atomic.h>
+#include <asm/elf.h>
+#include <asm/percpu.h>
+#include <asm/kexec.h>
#include <xen/types.h>
-#include <public/kexec.h>
+#include <xen/irq.h>
+#include <asm/ipi.h>
+#include <asm/nmi.h>
+#include <xen/string.h>
+#include <xen/elf.h>
+#include <xen/elfcore.h>
+#include <xen/smp.h>
+#include <xen/delay.h>
+#include <xen/perfc.h>
+#include <xen/kexec.h>
+#include <xen/sched.h>
+#include <public/xen.h>
+#include <asm/hvm/hvm.h>
+
+static int crashing_cpu;
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+ size_t data_len)
+{
+ Elf_Note note;
+
+ note.namesz = strlen(name) + 1;
+ note.descsz = data_len;
+ note.type = type;
+ memcpy(buf, ¬e, sizeof(note));
+ buf += (sizeof(note) +3)/4;
+ memcpy(buf, name, note.namesz);
+ buf += (note.namesz + 3)/4;
+ memcpy(buf, data, note.descsz);
+ buf += (note.descsz + 3)/4;
+
+ return buf;
+}
+
+static void final_note(u32 *buf)
+{
+ Elf_Note note;
+
+ note.namesz = 0;
+ note.descsz = 0;
+ note.type = 0;
+ memcpy(buf, ¬e, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct cpu_user_regs *regs, int cpu)
+{
+ ELF_Prstatus prstatus;
+ uint32_t *buf;
+
+ printk("crash_save_this_cpu: %d\n", cpu);
+
+ if ((cpu < 0) || (cpu >= NR_CPUS))
+ return;
+
+ /* Using ELF notes here is opportunistic.
+ * A well defined structure format with tags is needed
+ * ELF notes happen to provide this and there is infastructure
+ * in the Linux kernel to supprot them. In order to make
+ * crash dumps produced by xen the same, the same
+ * technique is used here.
+ */
+
+ /* It should be safe to use per_cpu() here instead of per_cpu_ptr()
+ * (which does not exist in xen) as kexecing_lock must be held in
+ * order to get anywhere near here */
+ buf = (uint32_t *)per_cpu(crash_notes, cpu);
+ if (!buf) /* XXX: Can this ever occur? */
+ return;
+ memset(&prstatus, 0, sizeof(prstatus));
+ /* XXX: Xen does not have processes. For the crashing CPU on a dom0
+ * crash this could be pased down from dom0, but is this
+ * neccessary?
+ * prstatus.pr_pid = current->pid; */
+ ELF_CORE_COPY_REGS(prstatus.pr_reg, regs);
+ buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+ sizeof(prstatus));
+ final_note(buf);
+}
+
+#ifdef CONFIG_SMP
+static atomic_t waiting_for_crash_ipi;
+
+static int crash_nmi_callback(struct cpu_user_regs *regs, int cpu)
+{
+#ifdef CONFIG_X86_32
+ struct cpu_user_regs fixed_regs;
+#endif
+
+ /* Don't do anything if this handler is invoked on crashing cpu.
+ * Otherwise, system will completely hang. Crashing cpu can get
+ * an NMI if system was initially booted with nmi_watchdog parameter.
+ */
+ if (cpu == crashing_cpu)
+ return 1;
+ local_irq_disable();
+
+#ifdef CONFIG_X86_32
+ if (!user_mode(regs)) {
+ crash_fixup_ss_esp(&fixed_regs, regs);
+ regs = &fixed_regs;
+ }
+#endif
+ crash_save_this_cpu(regs, cpu);
+ disable_local_APIC();
+ atomic_dec(&waiting_for_crash_ipi);
+ hvm_disable();
+
+ for ( ; ; )
+ __asm__ __volatile__ ( "hlt" );
+
+ return 1;
+}
+
+/*
+ * By using the NMI code instead of a vector we just sneak thru the
+ * word generator coming out with just what we want. AND it does
+ * not matter if clustered_apic_mode is set or not.
+ */
+static void smp_send_nmi_allbutself(void)
+{
+ cpumask_t allbutself = cpu_online_map;
+
+ cpu_clear(smp_processor_id(), allbutself);
+ send_IPI_mask(allbutself, APIC_DM_NMI);
+}
+
+static void nmi_shootdown_cpus(void)
+{
+ unsigned long msecs;
+
+ atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+ /* Would it be better to replace the trap vector here? */
+ set_nmi_callback(crash_nmi_callback);
+ /* Ensure the new callback function is set before sending
+ * out the NMI
+ */
+ wmb();
+
+ smp_send_nmi_allbutself();
+
+ msecs = 1000; /* Wait at most a second for the other cpus to stop */
+ while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+ mdelay(1);
+ msecs--;
+ }
+
+ /* Leave the nmi callback set */
+ disable_local_APIC();
+}
+#endif
+
+/* The cr3 for dom0 on each of its vcpus
+ * This code runs after all cpus except the crashing one have
+ * been shutdown so as to avoid having to hold domlist_lock,
+ * as locking after a crash is playing with fire */
+void find_dom0_cr3(void)
+{
+ struct domain *d;
+ struct vcpu *v;
+ uint32_t *buf;
+ uint32_t cr3;
+ Elf_Note note;
+
+ /* Don't need to grab domlist_lock as we are the only thing running */
+
+ /* No need to traverse domain_list, as dom0 is always first */
+ d = domain_list;
+ BUG_ON(d->domain_id);
+
+ for_each_vcpu ( d, v ) {
+ if ( test_bit(_VCPUF_down, &v->vcpu_flags) )
+ continue;
+ buf = (uint32_t *)per_cpu(crash_notes, v->processor);
+ if (!buf) /* XXX: Can this ever occur? */
+ continue;
+
+ memcpy(¬e, buf, sizeof(Elf_Note));
+ buf += (sizeof(Elf_Note) +3)/4 + (note.namesz + 3)/4 +
+ (note.descsz + 3)/4;
+
+ /* XXX: This probably doesn't take into account shadow mode,
+ * but that might not be a problem */
+ cr3 = pagetable_get_pfn(v->arch.guest_table);
+
+ /* create a hackish note with id 0x10000001 (NT_XEN_DOM0_CR3) */
+ buf = append_elf_note(buf, "Xen Domain-0 CR3",
+ 0x10000001, &cr3, 4);
+ final_note(buf);
+
+ printk("domain:%i vcpu:%u processor:%u cr3:%08x\n",
+ d->domain_id, v->vcpu_id, v->processor, cr3);
+ }
+}
void machine_crash_shutdown(struct cpu_user_regs *regs)
{
- printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+ printk("machine_crash_shutdown: %d\n", smp_processor_id());
+ local_irq_disable();
+
+ crashing_cpu = smp_processor_id();
+#ifdef CONFIG_SMP
+ nmi_shootdown_cpus();
+#endif
+
+#ifdef CONFIG_X86_IO_APIC
+ disable_IO_APIC();
+#endif
+ hvm_disable();
+
+ find_dom0_cr3();
+
+ crash_save_this_cpu(regs, smp_processor_id());
}
/*
--- 0003/xen/arch/x86/machine_kexec.c
+++ work/xen/arch/x86/machine_kexec.c 2006-10-23 11:36:16.000000000 +0900
@@ -1,26 +1,89 @@
-#include <xen/lib.h> /* for printk() used in stubs */
+/******************************************************************************
+ * machine_kexec.c
+ *
+ * Xen port written by:
+ * - Simon 'Horms' Horman <horms@xxxxxxxxxxxx>
+ * - Magnus Damm <magnus@xxxxxxxxxxxxx>
+ */
+
+#include <xen/lib.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/flushtlb.h>
+#include <xen/smp.h>
+#include <xen/nmi.h>
#include <xen/types.h>
-#include <public/kexec.h>
+#include <xen/console.h>
+#include <xen/kexec.h>
+#include <asm/kexec.h>
+#include <xen/domain_page.h>
+#include <asm/fixmap.h>
+#include <asm/hvm/hvm.h>
int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
{
- printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
- return -1;
+ unsigned long prev_ma = 0;
+ int fix_base = FIX_KEXEC_BASE_0 + (slot * (KEXEC_XEN_NO_PAGES >> 1));
+ int k;
+
+ /* setup fixmap to point to our pages and record the virtual address
+ * in every odd index in page_list[].
+ */
+
+ for (k = 0; k < KEXEC_XEN_NO_PAGES; k++) {
+ if ((k & 1) == 0) { /* even pages: machine address */
+ prev_ma = image->page_list[k];
+ }
+ else { /* odd pages: va for previous ma */
+ set_fixmap(fix_base + (k >> 1), prev_ma);
+ image->page_list[k] = fix_to_virt(fix_base + (k >> 1));
+ }
+ }
+
+ return 0;
}
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)
+
+static void __machine_shutdown(void *data)
{
- printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
-}
+ xen_kexec_image_t *image = (xen_kexec_image_t *)data;
+ watchdog_disable();
+ console_start_sync();
+
+ smp_send_stop();
+
+#ifdef CONFIG_X86_IO_APIC
+ disable_IO_APIC();
+#endif
+ hvm_disable();
+
+ machine_kexec(image);
+}
+
void machine_shutdown(xen_kexec_image_t *image)
{
- printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+ int reboot_cpu_id;
+ cpumask_t reboot_cpu;
+
+ reboot_cpu_id = 0;
+
+ if (!cpu_isset(reboot_cpu_id, cpu_online_map))
+ reboot_cpu_id = smp_processor_id();
+
+ if (reboot_cpu_id != smp_processor_id()) {
+ cpus_clear(reboot_cpu);
+ cpu_set(reboot_cpu_id, reboot_cpu);
+ on_selected_cpus(reboot_cpu, __machine_shutdown, image, 1, 0);
+ for (;;)
+ ; /* nothing */
+ }
+ else
+ __machine_shutdown(image);
+ BUG();
}
/*
--- 0001/xen/arch/x86/setup.c
+++ work/xen/arch/x86/setup.c 2006-10-23 11:36:14.000000000 +0900
@@ -26,6 +26,7 @@
#include <asm/shadow.h>
#include <asm/e820.h>
#include <acm/acm_hooks.h>
+#include <xen/kexec.h>
extern void dmi_scan_machine(void);
extern void generic_apic_probe(void);
@@ -257,6 +258,20 @@ static void __init init_idle_domain(void
setup_idle_pagetable();
}
+void __init move_memory(unsigned long dst,
+ unsigned long src_start, unsigned long src_end)
+{
+#if defined(CONFIG_X86_32)
+ memmove((void *)dst, /* use low mapping */
+ (void *)src_start, /* use low mapping */
+ src_end - src_start);
+#elif defined(CONFIG_X86_64)
+ memmove(__va(dst),
+ __va(src_start),
+ src_end - src_start);
+#endif
+}
+
void __init __start_xen(multiboot_info_t *mbi)
{
char __cmdline[] = "", *cmdline = __cmdline;
@@ -268,6 +283,7 @@ void __init __start_xen(multiboot_info_t
unsigned long nr_pages, modules_length;
paddr_t s, e;
int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0;
+ xen_kexec_reserve_t crash_area;
struct ns16550_defaults ns16550 = {
.data_bits = 8,
.parity = 'n',
@@ -399,15 +415,8 @@ void __init __start_xen(multiboot_info_t
initial_images_start = xenheap_phys_end;
initial_images_end = initial_images_start + modules_length;
-#if defined(CONFIG_X86_32)
- memmove((void *)initial_images_start, /* use low mapping */
- (void *)mod[0].mod_start, /* use low mapping */
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#elif defined(CONFIG_X86_64)
- memmove(__va(initial_images_start),
- __va(mod[0].mod_start),
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#endif
+ move_memory(initial_images_start,
+ mod[0].mod_start, mod[mbi->mods_count-1].mod_end);
/* Initialise boot-time allocator with all RAM situated after modules. */
xenheap_phys_start = init_boot_allocator(__pa(&_end));
@@ -455,6 +464,52 @@ void __init __start_xen(multiboot_info_t
#endif
}
+ machine_kexec_reserved(&crash_area);
+ if (crash_area.size > 0) {
+ unsigned long kdump_start, kdump_size, k;
+
+ /* mark images pages as free for now */
+
+ init_boot_pages(initial_images_start, initial_images_end);
+
+ kdump_start = crash_area.start;
+ kdump_size = crash_area.size;
+
+ printk("Kdump: %luMB (%lukB) at 0x%lx\n",
+ kdump_size >> 20,
+ kdump_size >> 10,
+ kdump_start);
+
+ if ((kdump_start & ~PAGE_MASK) || (kdump_size & ~PAGE_MASK))
+ panic("Kdump parameters not page aligned\n");
+
+ kdump_start >>= PAGE_SHIFT;
+ kdump_size >>= PAGE_SHIFT;
+
+ /* allocate pages for Kdump memory area */
+
+ k = alloc_boot_pages_at(kdump_size, kdump_start);
+
+ if (k != kdump_start)
+ panic("Unable to reserve Kdump memory\n");
+
+ /* allocate pages for relocated initial images */
+
+ k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
+ k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
+
+ k = alloc_boot_pages(k, 1);
+
+ if (!k)
+ panic("Unable to allocate initial images memory\n");
+
+ move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end);
+
+ initial_images_end -= initial_images_start;
+ initial_images_start = k << PAGE_SHIFT;
+ initial_images_end += initial_images_start;
+ }
+
memguard_init();
percpu_guard_areas();
--- 0001/xen/arch/x86/traps.c
+++ work/xen/arch/x86/traps.c 2006-10-23 11:36:14.000000000 +0900
@@ -105,6 +105,8 @@ unsigned long do_get_debugreg(int reg);
static int debug_stack_lines = 20;
integer_param("debug_stack_lines", debug_stack_lines);
+extern void crash_kexec(struct cpu_user_regs *regs);
+
#ifdef CONFIG_X86_32
#define stack_words_per_line 8
#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp)
@@ -1595,6 +1597,7 @@ static void unknown_nmi_error(unsigned c
printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
printk("Dazed and confused, but trying to continue\n");
printk("Do you have a strange power saving mode enabled?\n");
+ crash_kexec(NULL);
}
}
--- 0003/xen/include/asm-x86/elf.h
+++ work/xen/include/asm-x86/elf.h 2006-10-23 11:36:16.000000000 +0900
@@ -1,14 +1,11 @@
#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__);
+#ifdef __x86_64__
+#include <asm/x86_64/elf.h>
+#else
+#include <asm/x86_32/elf.h>
+#endif
#endif /* __X86_ELF_H__ */
--- 0001/xen/include/asm-x86/fixmap.h
+++ work/xen/include/asm-x86/fixmap.h 2006-10-23 11:36:14.000000000 +0900
@@ -16,6 +16,7 @@
#include <asm/apicdef.h>
#include <asm/acpi.h>
#include <asm/page.h>
+#include <xen/kexec.h>
/*
* Here we define all the compile-time 'special' virtual
@@ -36,6 +37,9 @@ enum fixed_addresses {
FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
FIX_HPET_BASE,
FIX_CYCLONE_TIMER,
+ FIX_KEXEC_BASE_0,
+ FIX_KEXEC_BASE_END = FIX_KEXEC_BASE_0 \
+ + ((KEXEC_XEN_NO_PAGES >> 1) * KEXEC_IMAGE_NR) - 1,
__end_of_fixed_addresses
};
--- 0001/xen/include/asm-x86/hypercall.h
+++ work/xen/include/asm-x86/hypercall.h 2006-10-23 11:36:14.000000000
+0900
@@ -6,6 +6,7 @@
#define __ASM_X86_HYPERCALL_H__
#include <public/physdev.h>
+#include <xen/types.h>
extern long
do_event_channel_op_compat(
@@ -87,6 +88,10 @@ extern long
arch_do_vcpu_op(
int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg);
+extern int
+do_kexec(
+ unsigned long op, unsigned arg1, XEN_GUEST_HANDLE(void) uarg);
+
#ifdef __x86_64__
extern long
--- 0003/xen/include/asm-x86/kexec.h
+++ work/xen/include/asm-x86/kexec.h 2006-10-23 11:36:16.000000000 +0900
@@ -1,21 +1,11 @@
#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__);
-}
+#ifdef __x86_64__
+#include <asm/x86_64/kexec.h>
+#else
+#include <asm/x86_32/kexec.h>
+#endif
#endif /* __X86_KEXEC_H__ */
--- /dev/null
+++ work/xen/include/asm-x86/x86_32/elf.h 2006-10-23 11:36:16.000000000
+0900
@@ -0,0 +1,23 @@
+#ifndef __X86_32_ELF_H__
+#define __X86_32_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_32_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/x86_32/kexec.h 2006-10-23 11:36:16.000000000
+0900
@@ -0,0 +1,43 @@
+#ifndef __X86_32_KEXEC_H__
+#define __X86_32_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 crash_fixup_ss_esp(struct cpu_user_regs *newregs,
+ struct cpu_user_regs *oldregs)
+{
+ printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+ return;
+}
+
+static inline void crash_setup_regs(struct cpu_user_regs *newregs,
+ struct cpu_user_regs *oldregs)
+{
+ printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+static inline int user_mode(struct cpu_user_regs *regs)
+{
+ printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+ return -1;
+}
+
+static inline void machine_kexec(xen_kexec_image_t *image)
+{
+ printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+#endif /* __X86_32_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/x86_64/elf.h 2006-10-23 11:36:16.000000000
+0900
@@ -0,0 +1,23 @@
+#ifndef __X86_64_ELF_H__
+#define __X86_64_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_64_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/x86_64/kexec.h 2006-10-23 11:36:16.000000000
+0900
@@ -0,0 +1,30 @@
+#ifndef __X86_64_KEXEC_H__
+#define __X86_64_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 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_64_KEXEC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- 0003/xen/include/public/kexec.h
+++ work/xen/include/public/kexec.h 2006-10-23 11:36:16.000000000 +0900
@@ -11,6 +11,10 @@
#include "xen.h"
+#if defined(__i386__) || defined(__x86_64__)
+#define KEXEC_XEN_NO_PAGES 17
+#endif
+
/*
* Prototype for this hypercall is:
* int kexec_op(int cmd, void *args)
@@ -23,6 +27,9 @@
#define KEXEC_TYPE_CRASH 1
typedef struct xen_kexec_image {
+#if defined(__i386__) || defined(__x86_64__)
+ unsigned long page_list[KEXEC_XEN_NO_PAGES];
+#endif
unsigned long indirection_page;
unsigned long start_address;
} xen_kexec_image_t;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|