WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 02/04] Kexec / Kdump: Code shared between x86_32 and

To: Keir Fraser <Keir.Fraser@xxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 02/04] Kexec / Kdump: Code shared between x86_32 and x86_64
From: Magnus Damm <magnus@xxxxxxxxxxxxx>
Date: Wed, 22 Nov 2006 16:11:07 +0900
Cc: Ian Pratt <m+Ian.Pratt@xxxxxxxxxxxx>, Kazuo Moriwaka <moriwaka@xxxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx, Akio Takebe <takebe_akio@xxxxxxxxxxxxxx>, magnus.damm@xxxxxxxxx, Isaku Yamahata <yamahata@xxxxxxxxxxxxx>, Magnus Damm <magnus@xxxxxxxxxxxxx>, Horms <horms@xxxxxxxxxxxx>
Delivery-date: Tue, 21 Nov 2006 23:12:49 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <20061122071050.24010.92547.sendpatchset@localhost>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <20061122071050.24010.92547.sendpatchset@localhost>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
[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-12502.

 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                      | 130 +++++++++-
 xen/arch/x86/machine_kexec.c              | 83 +++++-
 xen/arch/x86/setup.c                      | 73 ++++-
 xen/arch/x86/traps.c                      |  2
 xen/include/asm-x86/elf.h                 | 15 -
 xen/include/asm-x86/fixmap.h              |  4
 xen/include/asm-x86/hypercall.h           |  5
 xen/include/asm-x86/kexec.h               | 14 -
 xen/include/asm-x86/x86_32/elf.h          | 25 +
 xen/include/asm-x86/x86_32/kexec.h        | 24 +
 xen/include/asm-x86/x86_64/elf.h          | 25 +
 xen/include/asm-x86/x86_64/kexec.h        | 24 +
 xen/include/public/kexec.h                |  7
 xen/include/xen/elfcore.h                 |  3
 17 files changed, 550 insertions(+), 41 deletions(-)

--- /dev/null
+++ 
work/patches/linux-2.6.16.29/git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch
@@ -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
@@ -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
@@ -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
@@ -1,10 +1,134 @@
-#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 <xen/version.h>
+#include <public/xen.h>
+#include <asm/hvm/hvm.h>
+
+#ifdef CONFIG_SMP
+static atomic_t waiting_for_crash_ipi;
+
+static int crash_nmi_callback(struct cpu_user_regs *regs, int cpu)
+{
+       /* 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();
+
+    machine_crash_save_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
+
+static void crash_save_xen_notes(void)
+{
+    int cpu = smp_processor_id();
+    crash_note_t *cntp = &per_cpu(crash_notes, cpu);
+
+    /* this code assumes that the first note has been written already */
+
+    cntp->xen.note.note.note.namesz = XEN_STR_LEN;
+    cntp->xen.note.note.note.descsz = sizeof(xen_crash_xen_regs_t);
+    cntp->xen.note.note.note.type = 0x10000001; /* NT_XEN_DOM0_CR3 */
+    memcpy(cntp->xen.note.note.name, XEN_STR, XEN_STR_LEN);
+
+    cntp->xen.desc.desc.xen_major_version = xen_major_version();
+    cntp->xen.desc.desc.xen_minor_version = xen_minor_version();
+    cntp->xen.desc.desc.xen_extra_version = __pa(xen_extra_version());
+    cntp->xen.desc.desc.xen_changeset = __pa(xen_changeset());
+    cntp->xen.desc.desc.xen_compiler = __pa(xen_compiler());
+    cntp->xen.desc.desc.xen_compile_date = __pa(xen_compile_date());
+    cntp->xen.desc.desc.xen_compile_time = __pa(xen_compile_time());
+    
+    cntp->xen.desc.desc.dom0_pfn_to_mfn_frame_list_list = \
+        dom0->shared_info->arch.pfn_to_mfn_frame_list_list;
+}
 
 void machine_crash_shutdown(void)
 {
-    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+       printk("machine_crash_shutdown: %d\n", smp_processor_id());
+       local_irq_disable();
+
+#ifdef CONFIG_SMP
+       nmi_shootdown_cpus();
+#endif
+
+#ifdef CONFIG_X86_IO_APIC
+    disable_IO_APIC();
+#endif
+    hvm_disable();
+
+    crash_save_xen_notes();
 }
 
 /*
--- 0003/xen/arch/x86/machine_kexec.c
+++ work/xen/arch/x86/machine_kexec.c
@@ -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
@@ -27,6 +27,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);
@@ -273,6 +274,20 @@ static void srat_detect_node(int cpu)
         printk(KERN_INFO "CPU %d APIC %d -> Node %d\n", cpu, apicid, node);
 }
 
+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;
@@ -284,6 +299,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',
@@ -415,15 +431,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));
@@ -471,6 +480,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
@@ -45,6 +45,7 @@
 #include <xen/iocap.h>
 #include <xen/nmi.h>
 #include <xen/version.h>
+#include <xen/kexec.h>
 #include <asm/shadow.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -1633,6 +1634,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");
+        machine_crash_kexec();
     }
 }
 
--- 0003/xen/include/asm-x86/elf.h
+++ work/xen/include/asm-x86/elf.h
@@ -1,16 +1,11 @@
 #ifndef __X86_ELF_H__
 #define __X86_ELF_H__
 
-#include <xen/lib.h>       /* for printk() used in stub */
-
-typedef struct {
-    unsigned long dummy;
-} ELF_Gregset;
-
-extern inline void elf_core_save_regs(ELF_Gregset *dst)
-{
-    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
@@ -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
@@ -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
@@ -1,15 +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 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
@@ -0,0 +1,25 @@
+#ifndef __X86_32_ELF_H__
+#define __X86_32_ELF_H__
+
+#include <xen/lib.h>       /* for printk() used in stub */
+
+typedef struct {
+    unsigned long dummy;
+} ELF_Gregset;
+
+extern inline void elf_core_save_regs(ELF_Gregset *dst)
+{
+    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
@@ -0,0 +1,24 @@
+#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 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
@@ -0,0 +1,25 @@
+#ifndef __X86_64_ELF_H__
+#define __X86_64_ELF_H__
+
+#include <xen/lib.h>       /* for printk() used in stub */
+
+typedef struct {
+    unsigned long dummy;
+} ELF_Gregset;
+
+extern inline void elf_core_save_regs(ELF_Gregset *dst)
+{
+    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
@@ -0,0 +1,24 @@
+#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 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
@@ -40,6 +40,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)
@@ -72,6 +76,9 @@
  */
  
 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;
--- 0003/xen/include/xen/elfcore.h
+++ work/xen/include/xen/elfcore.h
@@ -105,6 +105,9 @@ typedef struct {
     unsigned long xen_compiler;
     unsigned long xen_compile_date;
     unsigned long xen_compile_time;
+#ifdef CONFIG_X86
+    unsigned long dom0_pfn_to_mfn_frame_list_list;
+#endif
 } xen_crash_xen_regs_t;
 
 TYPEDEF_NOTE(crash_note_xen_t, XEN_STR_LEN, xen_crash_xen_regs_t);

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