aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/crash.c
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@xensource.com>2006-11-30 12:38:51 +0000
committerIan Campbell <ian.campbell@xensource.com>2006-11-30 12:38:51 +0000
commit6dd60f6880df6d369385bdac2e41a5b6211423d9 (patch)
tree6d5b586741d303a0a4003648b1a8ed20d559173b /xen/arch/x86/crash.c
parenta173b7d011523df95259a206a5ff5d6ceeea336b (diff)
downloadxen-6dd60f6880df6d369385bdac2e41a5b6211423d9.tar.gz
xen-6dd60f6880df6d369385bdac2e41a5b6211423d9.tar.bz2
xen-6dd60f6880df6d369385bdac2e41a5b6211423d9.zip
[XEN] 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@valinux.co.jp> Signed-Off-By: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'xen/arch/x86/crash.c')
-rw-r--r--xen/arch/x86/crash.c115
1 files changed, 112 insertions, 3 deletions
diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c
index f1729786ea..73ed160021 100644
--- a/xen/arch/x86/crash.c
+++ b/xen/arch/x86/crash.c
@@ -1,10 +1,119 @@
-#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@verge.net.au>
+ * - Magnus Damm <magnus@valinux.co.jp>
+ */
+
+#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>
+
+#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)
+{
+ crash_xen_info_t *info;
+
+ info = machine_crash_save_info();
+
+ info->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();
}
/*