diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mshyperv.c')
| -rw-r--r-- | arch/x86/kernel/cpu/mshyperv.c | 48 | 
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index aad4bd84b475..381c8b9b3a33 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -18,6 +18,7 @@  #include <linux/efi.h>  #include <linux/interrupt.h>  #include <linux/irq.h> +#include <linux/kexec.h>  #include <asm/processor.h>  #include <asm/hypervisor.h>  #include <asm/hyperv.h> @@ -28,10 +29,14 @@  #include <asm/i8259.h>  #include <asm/apic.h>  #include <asm/timer.h> +#include <asm/reboot.h>  struct ms_hyperv_info ms_hyperv;  EXPORT_SYMBOL_GPL(ms_hyperv); +static void (*hv_kexec_handler)(void); +static void (*hv_crash_handler)(struct pt_regs *regs); +  #if IS_ENABLED(CONFIG_HYPERV)  static void (*vmbus_handler)(void); @@ -67,8 +72,47 @@ void hv_remove_vmbus_irq(void)  }  EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq);  EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq); + +void hv_setup_kexec_handler(void (*handler)(void)) +{ +	hv_kexec_handler = handler; +} +EXPORT_SYMBOL_GPL(hv_setup_kexec_handler); + +void hv_remove_kexec_handler(void) +{ +	hv_kexec_handler = NULL; +} +EXPORT_SYMBOL_GPL(hv_remove_kexec_handler); + +void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)) +{ +	hv_crash_handler = handler; +} +EXPORT_SYMBOL_GPL(hv_setup_crash_handler); + +void hv_remove_crash_handler(void) +{ +	hv_crash_handler = NULL; +} +EXPORT_SYMBOL_GPL(hv_remove_crash_handler);  #endif +static void hv_machine_shutdown(void) +{ +	if (kexec_in_progress && hv_kexec_handler) +		hv_kexec_handler(); +	native_machine_shutdown(); +} + +static void hv_machine_crash_shutdown(struct pt_regs *regs) +{ +	if (hv_crash_handler) +		hv_crash_handler(regs); +	native_machine_crash_shutdown(regs); +} + +  static uint32_t  __init ms_hyperv_platform(void)  {  	u32 eax; @@ -114,6 +158,7 @@ static void __init ms_hyperv_init_platform(void)  	 * Extract the features and hints  	 */  	ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES); +	ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);  	ms_hyperv.hints    = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);  	printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", @@ -141,6 +186,9 @@ static void __init ms_hyperv_init_platform(void)  	no_timer_check = 1;  #endif +	machine_ops.shutdown = hv_machine_shutdown; +	machine_ops.crash_shutdown = hv_machine_crash_shutdown; +	mark_tsc_unstable("running on Hyper-V");  }  const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {  |