diff options
Diffstat (limited to 'kernel/panic.c')
-rw-r--r-- | kernel/panic.c | 51 |
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 | ||
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 |
@@ -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 | ||
142 | EXPORT_SYMBOL(panic); | 160 | EXPORT_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 |