162a31a03SHiroshi Shimamoto /* 262a31a03SHiroshi Shimamoto * Architecture specific (i386/x86_64) functions for kexec based crash dumps. 362a31a03SHiroshi Shimamoto * 462a31a03SHiroshi Shimamoto * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) 562a31a03SHiroshi Shimamoto * 662a31a03SHiroshi Shimamoto * Copyright (C) IBM Corporation, 2004. All rights reserved. 762a31a03SHiroshi Shimamoto * 862a31a03SHiroshi Shimamoto */ 962a31a03SHiroshi Shimamoto 1062a31a03SHiroshi Shimamoto #include <linux/init.h> 1162a31a03SHiroshi Shimamoto #include <linux/types.h> 1262a31a03SHiroshi Shimamoto #include <linux/kernel.h> 1362a31a03SHiroshi Shimamoto #include <linux/smp.h> 1462a31a03SHiroshi Shimamoto #include <linux/reboot.h> 1562a31a03SHiroshi Shimamoto #include <linux/kexec.h> 1662a31a03SHiroshi Shimamoto #include <linux/delay.h> 1762a31a03SHiroshi Shimamoto #include <linux/elf.h> 1862a31a03SHiroshi Shimamoto #include <linux/elfcore.h> 1962a31a03SHiroshi Shimamoto 2062a31a03SHiroshi Shimamoto #include <asm/processor.h> 2162a31a03SHiroshi Shimamoto #include <asm/hardirq.h> 2262a31a03SHiroshi Shimamoto #include <asm/nmi.h> 2362a31a03SHiroshi Shimamoto #include <asm/hw_irq.h> 2462a31a03SHiroshi Shimamoto #include <asm/apic.h> 250c1b2724SOGAWA Hirofumi #include <asm/hpet.h> 2662a31a03SHiroshi Shimamoto #include <linux/kdebug.h> 2762a31a03SHiroshi Shimamoto #include <asm/smp.h> 2862a31a03SHiroshi Shimamoto 291fb473d8SMike Galbraith #ifdef CONFIG_X86_32 3062a31a03SHiroshi Shimamoto #include <mach_ipi.h> 3162a31a03SHiroshi Shimamoto #else 3262a31a03SHiroshi Shimamoto #include <asm/mach_apic.h> 3362a31a03SHiroshi Shimamoto #endif 3462a31a03SHiroshi Shimamoto 3562a31a03SHiroshi Shimamoto /* This keeps a track of which one is crashing cpu. */ 3662a31a03SHiroshi Shimamoto static int crashing_cpu; 3762a31a03SHiroshi Shimamoto 3862a31a03SHiroshi Shimamoto #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) 3962a31a03SHiroshi Shimamoto static atomic_t waiting_for_crash_ipi; 4062a31a03SHiroshi Shimamoto 4162a31a03SHiroshi Shimamoto static int crash_nmi_callback(struct notifier_block *self, 4262a31a03SHiroshi Shimamoto unsigned long val, void *data) 4362a31a03SHiroshi Shimamoto { 4462a31a03SHiroshi Shimamoto struct pt_regs *regs; 451fb473d8SMike Galbraith #ifdef CONFIG_X86_32 4662a31a03SHiroshi Shimamoto struct pt_regs fixed_regs; 4762a31a03SHiroshi Shimamoto #endif 4862a31a03SHiroshi Shimamoto int cpu; 4962a31a03SHiroshi Shimamoto 5062a31a03SHiroshi Shimamoto if (val != DIE_NMI_IPI) 5162a31a03SHiroshi Shimamoto return NOTIFY_OK; 5262a31a03SHiroshi Shimamoto 5362a31a03SHiroshi Shimamoto regs = ((struct die_args *)data)->regs; 5462a31a03SHiroshi Shimamoto cpu = raw_smp_processor_id(); 5562a31a03SHiroshi Shimamoto 5662a31a03SHiroshi Shimamoto /* Don't do anything if this handler is invoked on crashing cpu. 5762a31a03SHiroshi Shimamoto * Otherwise, system will completely hang. Crashing cpu can get 5862a31a03SHiroshi Shimamoto * an NMI if system was initially booted with nmi_watchdog parameter. 5962a31a03SHiroshi Shimamoto */ 6062a31a03SHiroshi Shimamoto if (cpu == crashing_cpu) 6162a31a03SHiroshi Shimamoto return NOTIFY_STOP; 6262a31a03SHiroshi Shimamoto local_irq_disable(); 6362a31a03SHiroshi Shimamoto 641fb473d8SMike Galbraith #ifdef CONFIG_X86_32 6562a31a03SHiroshi Shimamoto if (!user_mode_vm(regs)) { 6662a31a03SHiroshi Shimamoto crash_fixup_ss_esp(&fixed_regs, regs); 6762a31a03SHiroshi Shimamoto regs = &fixed_regs; 6862a31a03SHiroshi Shimamoto } 6962a31a03SHiroshi Shimamoto #endif 7062a31a03SHiroshi Shimamoto crash_save_cpu(regs, cpu); 7162a31a03SHiroshi Shimamoto disable_local_APIC(); 7262a31a03SHiroshi Shimamoto atomic_dec(&waiting_for_crash_ipi); 7362a31a03SHiroshi Shimamoto /* Assume hlt works */ 7462a31a03SHiroshi Shimamoto halt(); 7562a31a03SHiroshi Shimamoto for (;;) 7662a31a03SHiroshi Shimamoto cpu_relax(); 7762a31a03SHiroshi Shimamoto 7862a31a03SHiroshi Shimamoto return 1; 7962a31a03SHiroshi Shimamoto } 8062a31a03SHiroshi Shimamoto 8162a31a03SHiroshi Shimamoto static void smp_send_nmi_allbutself(void) 8262a31a03SHiroshi Shimamoto { 8362a31a03SHiroshi Shimamoto cpumask_t mask = cpu_online_map; 8462a31a03SHiroshi Shimamoto cpu_clear(safe_smp_processor_id(), mask); 8562a31a03SHiroshi Shimamoto if (!cpus_empty(mask)) 8662a31a03SHiroshi Shimamoto send_IPI_mask(mask, NMI_VECTOR); 8762a31a03SHiroshi Shimamoto } 8862a31a03SHiroshi Shimamoto 8962a31a03SHiroshi Shimamoto static struct notifier_block crash_nmi_nb = { 9062a31a03SHiroshi Shimamoto .notifier_call = crash_nmi_callback, 9162a31a03SHiroshi Shimamoto }; 9262a31a03SHiroshi Shimamoto 9362a31a03SHiroshi Shimamoto static void nmi_shootdown_cpus(void) 9462a31a03SHiroshi Shimamoto { 9562a31a03SHiroshi Shimamoto unsigned long msecs; 9662a31a03SHiroshi Shimamoto 9762a31a03SHiroshi Shimamoto atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); 9862a31a03SHiroshi Shimamoto /* Would it be better to replace the trap vector here? */ 9962a31a03SHiroshi Shimamoto if (register_die_notifier(&crash_nmi_nb)) 10062a31a03SHiroshi Shimamoto return; /* return what? */ 10162a31a03SHiroshi Shimamoto /* Ensure the new callback function is set before sending 10262a31a03SHiroshi Shimamoto * out the NMI 10362a31a03SHiroshi Shimamoto */ 10462a31a03SHiroshi Shimamoto wmb(); 10562a31a03SHiroshi Shimamoto 10662a31a03SHiroshi Shimamoto smp_send_nmi_allbutself(); 10762a31a03SHiroshi Shimamoto 10862a31a03SHiroshi Shimamoto msecs = 1000; /* Wait at most a second for the other cpus to stop */ 10962a31a03SHiroshi Shimamoto while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { 11062a31a03SHiroshi Shimamoto mdelay(1); 11162a31a03SHiroshi Shimamoto msecs--; 11262a31a03SHiroshi Shimamoto } 11362a31a03SHiroshi Shimamoto 11462a31a03SHiroshi Shimamoto /* Leave the nmi callback set */ 11562a31a03SHiroshi Shimamoto disable_local_APIC(); 11662a31a03SHiroshi Shimamoto } 11762a31a03SHiroshi Shimamoto #else 11862a31a03SHiroshi Shimamoto static void nmi_shootdown_cpus(void) 11962a31a03SHiroshi Shimamoto { 12062a31a03SHiroshi Shimamoto /* There are no cpus to shootdown */ 12162a31a03SHiroshi Shimamoto } 12262a31a03SHiroshi Shimamoto #endif 12362a31a03SHiroshi Shimamoto 12462a31a03SHiroshi Shimamoto void machine_crash_shutdown(struct pt_regs *regs) 12562a31a03SHiroshi Shimamoto { 12662a31a03SHiroshi Shimamoto /* This function is only called after the system 12762a31a03SHiroshi Shimamoto * has panicked or is otherwise in a critical state. 12862a31a03SHiroshi Shimamoto * The minimum amount of code to allow a kexec'd kernel 12962a31a03SHiroshi Shimamoto * to run successfully needs to happen here. 13062a31a03SHiroshi Shimamoto * 13162a31a03SHiroshi Shimamoto * In practice this means shooting down the other cpus in 13262a31a03SHiroshi Shimamoto * an SMP system. 13362a31a03SHiroshi Shimamoto */ 13462a31a03SHiroshi Shimamoto /* The kernel is broken so disable interrupts */ 13562a31a03SHiroshi Shimamoto local_irq_disable(); 13662a31a03SHiroshi Shimamoto 13762a31a03SHiroshi Shimamoto /* Make a note of crashing cpu. Will be used in NMI callback.*/ 13862a31a03SHiroshi Shimamoto crashing_cpu = safe_smp_processor_id(); 13962a31a03SHiroshi Shimamoto nmi_shootdown_cpus(); 14062a31a03SHiroshi Shimamoto lapic_shutdown(); 14162a31a03SHiroshi Shimamoto #if defined(CONFIG_X86_IO_APIC) 14262a31a03SHiroshi Shimamoto disable_IO_APIC(); 14362a31a03SHiroshi Shimamoto #endif 1440c1b2724SOGAWA Hirofumi #ifdef CONFIG_HPET_TIMER 1450c1b2724SOGAWA Hirofumi hpet_disable(); 1460c1b2724SOGAWA Hirofumi #endif 14762a31a03SHiroshi Shimamoto crash_save_cpu(regs, safe_smp_processor_id()); 14862a31a03SHiroshi Shimamoto } 149