Drivers: hv: restore hypervcall page cleanup before kexec
authorVitaly Kuznetsov <vkuznets@redhat.com>
Sat, 28 Jan 2017 19:37:14 +0000 (12:37 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 31 Jan 2017 10:05:58 +0000 (11:05 +0100)
We need to cleanup the hypercall page before doing kexec/kdump or the new
kernel may crash if it tries to use it. Reuse the now-empty hv_cleanup
function renaming it to hyperv_cleanup and moving to the arch specific
code.

Fixes: 8730046c1498 ("Drivers: hv vmbus: Move Hypercall page setup out of common code")
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/hyperv/hv_init.c
arch/x86/include/asm/mshyperv.h
drivers/hv/hv.c
drivers/hv/hyperv_vmbus.h
drivers/hv/vmbus_drv.c

index d289bc29d2822eb9453efe78ea5d3b459ed1e98f..d6b018b86c424cfd6d54806e7f2d2592f649306f 100644 (file)
@@ -165,6 +165,22 @@ void hyperv_init(void)
                clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
 }
 
+/*
+ * This routine is called before kexec/kdump, it does the required cleanup.
+ */
+void hyperv_cleanup(void)
+{
+       union hv_x64_msr_hypercall_contents hypercall_msr;
+
+       /* Reset our OS id */
+       wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
+
+       /* Reset the hypercall page */
+       hypercall_msr.as_uint64 = 0;
+       wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+}
+EXPORT_SYMBOL_GPL(hyperv_cleanup);
+
 /*
  * hv_do_hypercall- Invoke the specified hypercall
  */
index 42505d1158d6fcf71a9ba30eb98b682a1ed16aa3..f8dc3700de6786fb289be5c23e6b0cade00f8f77 100644 (file)
@@ -171,5 +171,6 @@ void hv_remove_crash_handler(void);
 void hyperv_init(void);
 void hyperv_report_panic(struct pt_regs *regs);
 bool hv_is_hypercall_page_setup(void);
+void hyperv_cleanup(void);
 #endif
 #endif
index 60594fa3250d5fcf3e5e60d6ffd91b9c4c47172a..0f73237bed0a5f1fe78b76bb67d6b801ed4e8f5a 100644 (file)
@@ -70,16 +70,6 @@ int hv_init(void)
        return 0;
 }
 
-/*
- * hv_cleanup - Cleanup routine.
- *
- * This routine is called normally during driver unloading or exiting.
- */
-void hv_cleanup(bool crash)
-{
-
-}
-
 /*
  * hv_post_message - Post a message using the hypervisor message IPC.
  *
index 2463ef93c1f6c9584aadb8fd41c3a0a199eb15d2..86b56b677dc39ba071da220bbe4d81baa098c91b 100644 (file)
@@ -255,8 +255,6 @@ struct hv_ring_buffer_debug_info {
 
 extern int hv_init(void);
 
-extern void hv_cleanup(bool crash);
-
 extern int hv_post_message(union hv_connection_id connection_id,
                         enum hv_message_type message_type,
                         void *payload, size_t payload_size);
index 8e81346114d41b9d17f0959a7e202352291fbb01..f8ebe13cf25101f0362806315311237b3572cc38 100644 (file)
@@ -962,7 +962,7 @@ static int vmbus_bus_init(void)
 
        ret = bus_register(&hv_bus);
        if (ret)
-               goto err_cleanup;
+               return ret;
 
        hv_setup_vmbus_irq(vmbus_isr);
 
@@ -1004,9 +1004,6 @@ err_alloc:
 
        bus_unregister(&hv_bus);
 
-err_cleanup:
-       hv_cleanup(false);
-
        return ret;
 }
 
@@ -1462,7 +1459,7 @@ static void hv_kexec_handler(void)
        /* Make sure conn_state is set as hv_synic_cleanup checks for it */
        mb();
        cpuhp_remove_state(hyperv_cpuhp_online);
-       hv_cleanup(false);
+       hyperv_cleanup();
 };
 
 static void hv_crash_handler(struct pt_regs *regs)
@@ -1475,7 +1472,7 @@ static void hv_crash_handler(struct pt_regs *regs)
         */
        vmbus_connection.conn_state = DISCONNECTED;
        hv_synic_cleanup(smp_processor_id());
-       hv_cleanup(true);
+       hyperv_cleanup();
 };
 
 static int __init hv_acpi_init(void)
@@ -1535,7 +1532,6 @@ static void __exit vmbus_exit(void)
                                                 &hyperv_panic_block);
        }
        bus_unregister(&hv_bus);
-       hv_cleanup(false);
        for_each_online_cpu(cpu) {
                tasklet_kill(hv_context.event_dpc[cpu]);
        }