xref: /openbmc/linux/arch/x86/kernel/crash.c (revision f23d1f4a)
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>
19f23d1f4aSZhang Yanfei #include <linux/module.h>
2062a31a03SHiroshi Shimamoto 
2162a31a03SHiroshi Shimamoto #include <asm/processor.h>
2262a31a03SHiroshi Shimamoto #include <asm/hardirq.h>
2362a31a03SHiroshi Shimamoto #include <asm/nmi.h>
2462a31a03SHiroshi Shimamoto #include <asm/hw_irq.h>
2562a31a03SHiroshi Shimamoto #include <asm/apic.h>
260c1b2724SOGAWA Hirofumi #include <asm/hpet.h>
2762a31a03SHiroshi Shimamoto #include <linux/kdebug.h>
2896b89dc6SJaswinder Singh Rajput #include <asm/cpu.h>
29ed23dc6fSGlauber Costa #include <asm/reboot.h>
302340b62fSEduardo Habkost #include <asm/virtext.h>
318e294786SEduardo Habkost 
325edd19afSCliff Wickman int in_crash_kexec;
335edd19afSCliff Wickman 
34f23d1f4aSZhang Yanfei /*
35f23d1f4aSZhang Yanfei  * This is used to VMCLEAR all VMCSs loaded on the
36f23d1f4aSZhang Yanfei  * processor. And when loading kvm_intel module, the
37f23d1f4aSZhang Yanfei  * callback function pointer will be assigned.
38f23d1f4aSZhang Yanfei  *
39f23d1f4aSZhang Yanfei  * protected by rcu.
40f23d1f4aSZhang Yanfei  */
41f23d1f4aSZhang Yanfei void (*crash_vmclear_loaded_vmcss)(void) = NULL;
42f23d1f4aSZhang Yanfei EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss);
43f23d1f4aSZhang Yanfei 
44f23d1f4aSZhang Yanfei static inline void cpu_crash_vmclear_loaded_vmcss(void)
45f23d1f4aSZhang Yanfei {
46f23d1f4aSZhang Yanfei 	void (*do_vmclear_operation)(void) = NULL;
47f23d1f4aSZhang Yanfei 
48f23d1f4aSZhang Yanfei 	rcu_read_lock();
49f23d1f4aSZhang Yanfei 	do_vmclear_operation = rcu_dereference(crash_vmclear_loaded_vmcss);
50f23d1f4aSZhang Yanfei 	if (do_vmclear_operation)
51f23d1f4aSZhang Yanfei 		do_vmclear_operation();
52f23d1f4aSZhang Yanfei 	rcu_read_unlock();
53f23d1f4aSZhang Yanfei }
54f23d1f4aSZhang Yanfei 
55b2bbe71bSEduardo Habkost #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
56b2bbe71bSEduardo Habkost 
579c48f1c6SDon Zickus static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
5862a31a03SHiroshi Shimamoto {
591fb473d8SMike Galbraith #ifdef CONFIG_X86_32
6062a31a03SHiroshi Shimamoto 	struct pt_regs fixed_regs;
6162a31a03SHiroshi Shimamoto #endif
62a7d41820SEduardo Habkost 
63a7d41820SEduardo Habkost #ifdef CONFIG_X86_32
64a7d41820SEduardo Habkost 	if (!user_mode_vm(regs)) {
65a7d41820SEduardo Habkost 		crash_fixup_ss_esp(&fixed_regs, regs);
66a7d41820SEduardo Habkost 		regs = &fixed_regs;
67a7d41820SEduardo Habkost 	}
68a7d41820SEduardo Habkost #endif
69a7d41820SEduardo Habkost 	crash_save_cpu(regs, cpu);
70a7d41820SEduardo Habkost 
71f23d1f4aSZhang Yanfei 	/*
72f23d1f4aSZhang Yanfei 	 * VMCLEAR VMCSs loaded on all cpus if needed.
73f23d1f4aSZhang Yanfei 	 */
74f23d1f4aSZhang Yanfei 	cpu_crash_vmclear_loaded_vmcss();
75f23d1f4aSZhang Yanfei 
762340b62fSEduardo Habkost 	/* Disable VMX or SVM if needed.
772340b62fSEduardo Habkost 	 *
782340b62fSEduardo Habkost 	 * We need to disable virtualization on all CPUs.
792340b62fSEduardo Habkost 	 * Having VMX or SVM enabled on any CPU may break rebooting
802340b62fSEduardo Habkost 	 * after the kdump kernel has finished its task.
812340b62fSEduardo Habkost 	 */
822340b62fSEduardo Habkost 	cpu_emergency_vmxoff();
832340b62fSEduardo Habkost 	cpu_emergency_svm_disable();
842340b62fSEduardo Habkost 
85a7d41820SEduardo Habkost 	disable_local_APIC();
86a7d41820SEduardo Habkost }
87a7d41820SEduardo Habkost 
88d1e7b91cSEduardo Habkost static void kdump_nmi_shootdown_cpus(void)
89d1e7b91cSEduardo Habkost {
905edd19afSCliff Wickman 	in_crash_kexec = 1;
918e294786SEduardo Habkost 	nmi_shootdown_cpus(kdump_nmi_callback);
92d1e7b91cSEduardo Habkost 
9362a31a03SHiroshi Shimamoto 	disable_local_APIC();
9462a31a03SHiroshi Shimamoto }
95d1e7b91cSEduardo Habkost 
9662a31a03SHiroshi Shimamoto #else
97d1e7b91cSEduardo Habkost static void kdump_nmi_shootdown_cpus(void)
9862a31a03SHiroshi Shimamoto {
9962a31a03SHiroshi Shimamoto 	/* There are no cpus to shootdown */
10062a31a03SHiroshi Shimamoto }
10162a31a03SHiroshi Shimamoto #endif
10262a31a03SHiroshi Shimamoto 
103ed23dc6fSGlauber Costa void native_machine_crash_shutdown(struct pt_regs *regs)
10462a31a03SHiroshi Shimamoto {
10562a31a03SHiroshi Shimamoto 	/* This function is only called after the system
10662a31a03SHiroshi Shimamoto 	 * has panicked or is otherwise in a critical state.
10762a31a03SHiroshi Shimamoto 	 * The minimum amount of code to allow a kexec'd kernel
10862a31a03SHiroshi Shimamoto 	 * to run successfully needs to happen here.
10962a31a03SHiroshi Shimamoto 	 *
11062a31a03SHiroshi Shimamoto 	 * In practice this means shooting down the other cpus in
11162a31a03SHiroshi Shimamoto 	 * an SMP system.
11262a31a03SHiroshi Shimamoto 	 */
11362a31a03SHiroshi Shimamoto 	/* The kernel is broken so disable interrupts */
11462a31a03SHiroshi Shimamoto 	local_irq_disable();
11562a31a03SHiroshi Shimamoto 
116d1e7b91cSEduardo Habkost 	kdump_nmi_shootdown_cpus();
1172340b62fSEduardo Habkost 
118f23d1f4aSZhang Yanfei 	/*
119f23d1f4aSZhang Yanfei 	 * VMCLEAR VMCSs loaded on this cpu if needed.
120f23d1f4aSZhang Yanfei 	 */
121f23d1f4aSZhang Yanfei 	cpu_crash_vmclear_loaded_vmcss();
122f23d1f4aSZhang Yanfei 
1232340b62fSEduardo Habkost 	/* Booting kdump kernel with VMX or SVM enabled won't work,
1242340b62fSEduardo Habkost 	 * because (among other limitations) we can't disable paging
1252340b62fSEduardo Habkost 	 * with the virt flags.
1262340b62fSEduardo Habkost 	 */
1272340b62fSEduardo Habkost 	cpu_emergency_vmxoff();
1282340b62fSEduardo Habkost 	cpu_emergency_svm_disable();
1292340b62fSEduardo Habkost 
13062a31a03SHiroshi Shimamoto 	lapic_shutdown();
13162a31a03SHiroshi Shimamoto #if defined(CONFIG_X86_IO_APIC)
13262a31a03SHiroshi Shimamoto 	disable_IO_APIC();
13362a31a03SHiroshi Shimamoto #endif
1340c1b2724SOGAWA Hirofumi #ifdef CONFIG_HPET_TIMER
1350c1b2724SOGAWA Hirofumi 	hpet_disable();
1360c1b2724SOGAWA Hirofumi #endif
13762a31a03SHiroshi Shimamoto 	crash_save_cpu(regs, safe_smp_processor_id());
13862a31a03SHiroshi Shimamoto }
139