diff options
Diffstat (limited to 'kernel/panic.c')
-rw-r--r-- | kernel/panic.c | 50 |
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 | ||
36 | EXPORT_SYMBOL(panic_notifier_list); | 37 | EXPORT_SYMBOL(panic_notifier_list); |
37 | 38 | ||
38 | static 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 */ |
44 | long (*panic_blink)(long time); | 40 | long (*panic_blink)(long time); |
45 | EXPORT_SYMBOL(panic_blink); | 41 | EXPORT_SYMBOL(panic_blink); |
46 | 42 | ||
43 | static 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 |