aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/panic.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/panic.c')
-rw-r--r--kernel/panic.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/kernel/panic.c b/kernel/panic.c
index bcdef26e3332..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
@@ -90,8 +114,7 @@ NORET_TYPE void panic(const char * fmt, ...)
90 114
91 atomic_notifier_call_chain(&panic_notifier_list, 0, buf); 115 atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
92 116
93 if (!panic_blink) 117 bust_spinlocks(0);
94 panic_blink = no_blink;
95 118
96 if (panic_timeout > 0) { 119 if (panic_timeout > 0) {
97 /* 120 /*
@@ -100,11 +123,9 @@ NORET_TYPE void panic(const char * fmt, ...)
100 */ 123 */
101 printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout); 124 printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout);
102 125
103 for (i = 0; i < panic_timeout*1000; ) { 126 for (i = 0; i < panic_timeout; i++) {
104 touch_nmi_watchdog(); 127 touch_nmi_watchdog();
105 i += panic_blink(i); 128 panic_blink_one_second();
106 mdelay(1);
107 i++;
108 } 129 }
109 /* 130 /*
110 * This will not be a clean reboot, with everything 131 * This will not be a clean reboot, with everything
@@ -130,13 +151,10 @@ NORET_TYPE void panic(const char * fmt, ...)
130 } 151 }
131#endif 152#endif
132 local_irq_enable(); 153 local_irq_enable();
133 for (i = 0; ; ) { 154 while (1) {
134 touch_softlockup_watchdog(); 155 touch_softlockup_watchdog();
135 i += panic_blink(i); 156 panic_blink_one_second();
136 mdelay(1);
137 i++;
138 } 157 }
139 bust_spinlocks(0);
140} 158}
141 159
142EXPORT_SYMBOL(panic); 160EXPORT_SYMBOL(panic);
@@ -338,6 +356,7 @@ void oops_exit(void)
338{ 356{
339 do_oops_enter_exit(); 357 do_oops_enter_exit();
340 print_oops_end_marker(); 358 print_oops_end_marker();
359 kmsg_dump(KMSG_DUMP_OOPS);
341} 360}
342 361
343#ifdef WANT_WARN_ON_SLOWPATH 362#ifdef WANT_WARN_ON_SLOWPATH