Drivers: hv: avoid vfree() on crash
authorVitaly Kuznetsov <vkuznets@redhat.com>
Sat, 4 Jun 2016 00:09:22 +0000 (17:09 -0700)
committerWilly Tarreau <w@1wt.eu>
Wed, 7 Jun 2017 22:47:10 +0000 (00:47 +0200)
commit a9f61ca793becabdefab03b77568d6c6f8c1bc79 upstream.

When we crash from NMI context (e.g. after NMI injection from host when
'sysctl -w kernel.unknown_nmi_panic=1' is set) we hit

    kernel BUG at mm/vmalloc.c:1530!

as vfree() is denied. While the issue could be solved with in_nmi() check
instead I opted for skipping vfree on all sorts of crashes to reduce the
amount of work which can cause consequent crashes. We don't really need to
free anything on crash.

[js] no tsc and kexec in 3.12 yet

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Willy Tarreau <w@1wt.eu>
drivers/hv/hv.c
drivers/hv/hyperv_vmbus.h
drivers/hv/vmbus_drv.c

index ae4923756d98788490166af3393fecba5a84b6a0..b1039552b623d474b19904723184015724a5e051 100644 (file)
@@ -193,7 +193,7 @@ cleanup:
  *
  * This routine is called normally during driver unloading or exiting.
  */
-void hv_cleanup(void)
+void hv_cleanup(bool crash)
 {
        union hv_x64_msr_hypercall_contents hypercall_msr;
 
@@ -203,7 +203,8 @@ void hv_cleanup(void)
        if (hv_context.hypercall_page) {
                hypercall_msr.as_uint64 = 0;
                wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
-               vfree(hv_context.hypercall_page);
+               if (!crash)
+                       vfree(hv_context.hypercall_page);
                hv_context.hypercall_page = NULL;
        }
 }
index 12f2f9e989f73be86d6fbf7da7b928cab13aa0cf..11d4e6222f52939394aa9f63df3b240dafb0b2ed 100644 (file)
@@ -519,7 +519,7 @@ extern struct hv_context hv_context;
 
 extern int hv_init(void);
 
-extern void hv_cleanup(void);
+extern void hv_cleanup(bool crash);
 
 extern int hv_post_message(union hv_connection_id connection_id,
                         enum hv_message_type message_type,
index 80754e2d80869e7d5e5cbb0e15606ff9341ed9cd..3190a1fc7bc83570314f1a0016e20d8d72486e2a 100644 (file)
@@ -618,7 +618,7 @@ err_unregister:
        bus_unregister(&hv_bus);
 
 err_cleanup:
-       hv_cleanup();
+       hv_cleanup(false);
 
        return ret;
 }
@@ -841,7 +841,7 @@ static void __exit vmbus_exit(void)
        free_irq(irq, hv_acpi_dev);
        vmbus_free_channels();
        bus_unregister(&hv_bus);
-       hv_cleanup();
+       hv_cleanup(false);
        acpi_bus_unregister_driver(&vmbus_acpi_driver);
        hv_cpu_hotplug_quirk(false);
 }