aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/panic.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/panic.c')
-rw-r--r--kernel/panic.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/kernel/panic.c b/kernel/panic.c
index 96b45d0b4ba5..13d966b4c14a 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -10,6 +10,7 @@
10 */ 10 */
11#include <linux/debug_locks.h> 11#include <linux/debug_locks.h>
12#include <linux/interrupt.h> 12#include <linux/interrupt.h>
13#include <linux/kmsg_dump.h>
13#include <linux/kallsyms.h> 14#include <linux/kallsyms.h>
14#include <linux/notifier.h> 15#include <linux/notifier.h>
15#include <linux/module.h> 16#include <linux/module.h>
@@ -35,15 +36,36 @@ ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
35 36
36EXPORT_SYMBOL(panic_notifier_list); 37EXPORT_SYMBOL(panic_notifier_list);
37 38
38static long no_blink(long time)
39{
40 return 0;
41}
42
43/* Returns how long it waited in ms */ 39/* Returns how long it waited in ms */
44long (*panic_blink)(long time); 40long (*panic_blink)(long time);
45EXPORT_SYMBOL(panic_blink); 41EXPORT_SYMBOL(panic_blink);
46 42
43static void panic_blink_one_second(void)
44{
45 static long i = 0, end;
46
47 if (panic_blink) {
48 end = i + MSEC_PER_SEC;
49
50 while (i < end) {
51 i += panic_blink(i);
52 mdelay(1);
53 i++;
54 }
55 } else {
56 /*
57 * When running under a hypervisor a small mdelay may get
58 * rounded up to the hypervisor timeslice. For example, with
59 * a 1ms in 10ms hypervisor timeslice we might inflate a
60 * mdelay(1) loop by 10x.
61 *
62 * If we have nothing to blink, spin on 1 second calls to
63 * mdelay to avoid this.
64 */
65 mdelay(MSEC_PER_SEC);
66 }
67}
68
47/** 69/**
48 * panic - halt the system 70 * panic - halt the system
49 * @fmt: The text string to print 71 * @fmt: The text string to print
@@ -81,6 +103,8 @@ NORET_TYPE void panic(const char * fmt, ...)
81 */ 103 */
82 crash_kexec(NULL); 104 crash_kexec(NULL);
83 105
106 kmsg_dump(KMSG_DUMP_PANIC);
107
84 /* 108 /*
85 * Note smp_send_stop is the usual smp shutdown function, which 109 * Note smp_send_stop is the usual smp shutdown function, which
86 * unfortunately means it may not be hardened to work in a panic 110 * unfortunately means it may not be hardened to work in a panic
@@ -92,9 +116,6 @@ NORET_TYPE void panic(const char * fmt, ...)
92 116
93 bust_spinlocks(0); 117 bust_spinlocks(0);
94 118
95 if (!panic_blink)
96 panic_blink = no_blink;
97
98 if (panic_timeout > 0) { 119 if (panic_timeout > 0) {
99 /* 120 /*
100 * Delay timeout seconds before rebooting the machine. 121 * Delay timeout seconds before rebooting the machine.
@@ -102,11 +123,9 @@ NORET_TYPE void panic(const char * fmt, ...)
102 */ 123 */
103 printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout); 124 printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout);
104 125
105 for (i = 0; i < panic_timeout*1000; ) { 126 for (i = 0; i < panic_timeout; i++) {
106 touch_nmi_watchdog(); 127 touch_nmi_watchdog();
107 i += panic_blink(i); 128 panic_blink_one_second();
108 mdelay(1);
109 i++;
110 } 129 }
111 /* 130 /*
112 * This will not be a clean reboot, with everything 131 * This will not be a clean reboot, with everything
@@ -132,11 +151,9 @@ NORET_TYPE void panic(const char * fmt, ...)
132 } 151 }
133#endif 152#endif
134 local_irq_enable(); 153 local_irq_enable();
135 for (i = 0; ; ) { 154 while (1) {
136 touch_softlockup_watchdog(); 155 touch_softlockup_watchdog();
137 i += panic_blink(i); 156 panic_blink_one_second();
138 mdelay(1);
139 i++;
140 } 157 }
141} 158}
142 159
@@ -339,6 +356,7 @@ void oops_exit(void)
339{ 356{
340 do_oops_enter_exit(); 357 do_oops_enter_exit();
341 print_oops_end_marker(); 358 print_oops_end_marker();
359 kmsg_dump(KMSG_DUMP_OOPS);
342} 360}
343 361
344#ifdef WANT_WARN_ON_SLOWPATH 362#ifdef WANT_WARN_ON_SLOWPATH