diff options
author | Ian Campbell <ian.campbell@xensource.com> | 2006-11-30 12:38:51 +0000 |
---|---|---|
committer | Ian Campbell <ian.campbell@xensource.com> | 2006-11-30 12:38:51 +0000 |
commit | 6dd60f6880df6d369385bdac2e41a5b6211423d9 (patch) | |
tree | 6d5b586741d303a0a4003648b1a8ed20d559173b /xen/arch/x86/crash.c | |
parent | a173b7d011523df95259a206a5ff5d6ceeea336b (diff) | |
download | xen-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.c | 115 |
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(); } /* |