#include <asm/mshyperv.h>
 #include <linux/notifier.h>
 #include <linux/ptrace.h>
+#include <linux/kdebug.h>
 #include "hyperv_vmbus.h"
 
 static struct acpi_device  *hv_acpi_dev;
 static int irq;
 
 
-static int hyperv_panic_event(struct notifier_block *nb,
-                       unsigned long event, void *ptr)
+static void hyperv_report_panic(struct pt_regs *regs)
 {
-       struct pt_regs *regs;
+       static bool panic_reported;
 
-       regs = current_pt_regs();
+       /*
+        * We prefer to report panic on 'die' chain as we have proper
+        * registers to report, but if we miss it (e.g. on BUG()) we need
+        * to report it on 'panic'.
+        */
+       if (panic_reported)
+               return;
+       panic_reported = true;
 
        wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip);
        wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax);
         * Let Hyper-V know there is crash data available
         */
        wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
+}
+
+static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
+                             void *args)
+{
+       struct pt_regs *regs;
+
+       regs = current_pt_regs();
+
+       hyperv_report_panic(regs);
        return NOTIFY_DONE;
 }
 
+static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
+                           void *args)
+{
+       struct die_args *die = (struct die_args *)args;
+       struct pt_regs *regs = die->regs;
+
+       hyperv_report_panic(regs);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block hyperv_die_block = {
+       .notifier_call = hyperv_die_event,
+};
 static struct notifier_block hyperv_panic_block = {
        .notifier_call = hyperv_panic_event,
 };
         * Only register if the crash MSRs are available
         */
        if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+               register_die_notifier(&hyperv_die_block);
                atomic_notifier_chain_register(&panic_notifier_list,
                                               &hyperv_panic_block);
        }
        tasklet_kill(&msg_dpc);
        vmbus_free_channels();
        if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+               unregister_die_notifier(&hyperv_die_block);
                atomic_notifier_chain_unregister(&panic_notifier_list,
                                                 &hyperv_panic_block);
        }