diff options
Diffstat (limited to 'arch/x86/kernel/crash.c')
| -rw-r--r-- | arch/x86/kernel/crash.c | 46 | 
1 files changed, 37 insertions, 9 deletions
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 764c7c2b181..507de806659 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -7,7 +7,6 @@   *   */ -#include <linux/init.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/smp.h> @@ -16,6 +15,7 @@  #include <linux/delay.h>  #include <linux/elf.h>  #include <linux/elfcore.h> +#include <linux/module.h>  #include <asm/processor.h>  #include <asm/hardirq.h> @@ -30,18 +30,34 @@  int in_crash_kexec; +/* + * This is used to VMCLEAR all VMCSs loaded on the + * processor. And when loading kvm_intel module, the + * callback function pointer will be assigned. + * + * protected by rcu. + */ +crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss = NULL; +EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss); + +static inline void cpu_crash_vmclear_loaded_vmcss(void) +{ +	crash_vmclear_fn *do_vmclear_operation = NULL; + +	rcu_read_lock(); +	do_vmclear_operation = rcu_dereference(crash_vmclear_loaded_vmcss); +	if (do_vmclear_operation) +		do_vmclear_operation(); +	rcu_read_unlock(); +} +  #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) -static void kdump_nmi_callback(int cpu, struct die_args *args) +static void kdump_nmi_callback(int cpu, struct pt_regs *regs)  { -	struct pt_regs *regs;  #ifdef CONFIG_X86_32  	struct pt_regs fixed_regs; -#endif -	regs = args->regs; - -#ifdef CONFIG_X86_32  	if (!user_mode_vm(regs)) {  		crash_fixup_ss_esp(&fixed_regs, regs);  		regs = &fixed_regs; @@ -49,6 +65,11 @@ static void kdump_nmi_callback(int cpu, struct die_args *args)  #endif  	crash_save_cpu(regs, cpu); +	/* +	 * VMCLEAR VMCSs loaded on all cpus if needed. +	 */ +	cpu_crash_vmclear_loaded_vmcss(); +  	/* Disable VMX or SVM if needed.  	 *  	 * We need to disable virtualization on all CPUs. @@ -91,6 +112,11 @@ void native_machine_crash_shutdown(struct pt_regs *regs)  	kdump_nmi_shootdown_cpus(); +	/* +	 * VMCLEAR VMCSs loaded on this cpu if needed. +	 */ +	cpu_crash_vmclear_loaded_vmcss(); +  	/* Booting kdump kernel with VMX or SVM enabled won't work,  	 * because (among other limitations) we can't disable paging  	 * with the virt flags. @@ -98,10 +124,12 @@ void native_machine_crash_shutdown(struct pt_regs *regs)  	cpu_emergency_vmxoff();  	cpu_emergency_svm_disable(); -	lapic_shutdown(); -#if defined(CONFIG_X86_IO_APIC) +#ifdef CONFIG_X86_IO_APIC +	/* Prevent crash_kexec() from deadlocking on ioapic_lock. */ +	ioapic_zap_locks();  	disable_IO_APIC();  #endif +	lapic_shutdown();  #ifdef CONFIG_HPET_TIMER  	hpet_disable();  #endif  | 
