|
@@ -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,13 @@
|
|
|
#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);
|
|
|
+
|
|
|
#if IS_ENABLED(CONFIG_HYPERV)
|
|
|
static void (*vmbus_handler)(void);
|
|
|
|
|
@@ -67,8 +71,27 @@ 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);
|
|
|
#endif
|
|
|
|
|
|
+static void hv_machine_shutdown(void)
|
|
|
+{
|
|
|
+ if (kexec_in_progress && hv_kexec_handler)
|
|
|
+ hv_kexec_handler();
|
|
|
+ native_machine_shutdown();
|
|
|
+}
|
|
|
+
|
|
|
static uint32_t __init ms_hyperv_platform(void)
|
|
|
{
|
|
|
u32 eax;
|
|
@@ -141,6 +164,7 @@ static void __init ms_hyperv_init_platform(void)
|
|
|
no_timer_check = 1;
|
|
|
#endif
|
|
|
|
|
|
+ machine_ops.shutdown = hv_machine_shutdown;
|
|
|
}
|
|
|
|
|
|
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
|