aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/panic.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/panic.c')
-rw-r--r--kernel/panic.c87
1 files changed, 50 insertions, 37 deletions
diff --git a/kernel/panic.c b/kernel/panic.c
index 13d966b4c14a..4c13b1a88ebb 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -24,6 +24,9 @@
24#include <linux/nmi.h> 24#include <linux/nmi.h>
25#include <linux/dmi.h> 25#include <linux/dmi.h>
26 26
27#define PANIC_TIMER_STEP 100
28#define PANIC_BLINK_SPD 18
29
27int panic_on_oops; 30int panic_on_oops;
28static unsigned long tainted_mask; 31static unsigned long tainted_mask;
29static int pause_on_oops; 32static int pause_on_oops;
@@ -36,36 +39,15 @@ ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
36 39
37EXPORT_SYMBOL(panic_notifier_list); 40EXPORT_SYMBOL(panic_notifier_list);
38 41
39/* Returns how long it waited in ms */ 42static long no_blink(int state)
40long (*panic_blink)(long time);
41EXPORT_SYMBOL(panic_blink);
42
43static void panic_blink_one_second(void)
44{ 43{
45 static long i = 0, end; 44 return 0;
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} 45}
68 46
47/* Returns how long it waited in ms */
48long (*panic_blink)(int state);
49EXPORT_SYMBOL(panic_blink);
50
69/** 51/**
70 * panic - halt the system 52 * panic - halt the system
71 * @fmt: The text string to print 53 * @fmt: The text string to print
@@ -78,7 +60,8 @@ NORET_TYPE void panic(const char * fmt, ...)
78{ 60{
79 static char buf[1024]; 61 static char buf[1024];
80 va_list args; 62 va_list args;
81 long i; 63 long i, i_next = 0;
64 int state = 0;
82 65
83 /* 66 /*
84 * It's possible to come here directly from a panic-assertion and 67 * It's possible to come here directly from a panic-assertion and
@@ -87,6 +70,7 @@ NORET_TYPE void panic(const char * fmt, ...)
87 */ 70 */
88 preempt_disable(); 71 preempt_disable();
89 72
73 console_verbose();
90 bust_spinlocks(1); 74 bust_spinlocks(1);
91 va_start(args, fmt); 75 va_start(args, fmt);
92 vsnprintf(buf, sizeof(buf), fmt, args); 76 vsnprintf(buf, sizeof(buf), fmt, args);
@@ -116,6 +100,9 @@ NORET_TYPE void panic(const char * fmt, ...)
116 100
117 bust_spinlocks(0); 101 bust_spinlocks(0);
118 102
103 if (!panic_blink)
104 panic_blink = no_blink;
105
119 if (panic_timeout > 0) { 106 if (panic_timeout > 0) {
120 /* 107 /*
121 * Delay timeout seconds before rebooting the machine. 108 * Delay timeout seconds before rebooting the machine.
@@ -123,9 +110,13 @@ NORET_TYPE void panic(const char * fmt, ...)
123 */ 110 */
124 printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout); 111 printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout);
125 112
126 for (i = 0; i < panic_timeout; i++) { 113 for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) {
127 touch_nmi_watchdog(); 114 touch_nmi_watchdog();
128 panic_blink_one_second(); 115 if (i >= i_next) {
116 i += panic_blink(state ^= 1);
117 i_next = i + 3600 / PANIC_BLINK_SPD;
118 }
119 mdelay(PANIC_TIMER_STEP);
129 } 120 }
130 /* 121 /*
131 * This will not be a clean reboot, with everything 122 * This will not be a clean reboot, with everything
@@ -151,9 +142,13 @@ NORET_TYPE void panic(const char * fmt, ...)
151 } 142 }
152#endif 143#endif
153 local_irq_enable(); 144 local_irq_enable();
154 while (1) { 145 for (i = 0; ; i += PANIC_TIMER_STEP) {
155 touch_softlockup_watchdog(); 146 touch_softlockup_watchdog();
156 panic_blink_one_second(); 147 if (i >= i_next) {
148 i += panic_blink(state ^= 1);
149 i_next = i + 3600 / PANIC_BLINK_SPD;
150 }
151 mdelay(PANIC_TIMER_STEP);
157 } 152 }
158} 153}
159 154
@@ -178,6 +173,7 @@ static const struct tnt tnts[] = {
178 { TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' }, 173 { TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' },
179 { TAINT_WARN, 'W', ' ' }, 174 { TAINT_WARN, 'W', ' ' },
180 { TAINT_CRAP, 'C', ' ' }, 175 { TAINT_CRAP, 'C', ' ' },
176 { TAINT_FIRMWARE_WORKAROUND, 'I', ' ' },
181}; 177};
182 178
183/** 179/**
@@ -194,6 +190,7 @@ static const struct tnt tnts[] = {
194 * 'A' - ACPI table overridden. 190 * 'A' - ACPI table overridden.
195 * 'W' - Taint on warning. 191 * 'W' - Taint on warning.
196 * 'C' - modules from drivers/staging are loaded. 192 * 'C' - modules from drivers/staging are loaded.
193 * 'I' - Working around severe firmware bug.
197 * 194 *
198 * The string is overwritten by the next call to print_tainted(). 195 * The string is overwritten by the next call to print_tainted().
199 */ 196 */
@@ -341,7 +338,7 @@ static int init_oops_id(void)
341} 338}
342late_initcall(init_oops_id); 339late_initcall(init_oops_id);
343 340
344static void print_oops_end_marker(void) 341void print_oops_end_marker(void)
345{ 342{
346 init_oops_id(); 343 init_oops_id();
347 printk(KERN_WARNING "---[ end trace %016llx ]---\n", 344 printk(KERN_WARNING "---[ end trace %016llx ]---\n",
@@ -365,7 +362,8 @@ struct slowpath_args {
365 va_list args; 362 va_list args;
366}; 363};
367 364
368static void warn_slowpath_common(const char *file, int line, void *caller, struct slowpath_args *args) 365static void warn_slowpath_common(const char *file, int line, void *caller,
366 unsigned taint, struct slowpath_args *args)
369{ 367{
370 const char *board; 368 const char *board;
371 369
@@ -381,7 +379,7 @@ static void warn_slowpath_common(const char *file, int line, void *caller, struc
381 print_modules(); 379 print_modules();
382 dump_stack(); 380 dump_stack();
383 print_oops_end_marker(); 381 print_oops_end_marker();
384 add_taint(TAINT_WARN); 382 add_taint(taint);
385} 383}
386 384
387void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...) 385void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
@@ -390,14 +388,29 @@ void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
390 388
391 args.fmt = fmt; 389 args.fmt = fmt;
392 va_start(args.args, fmt); 390 va_start(args.args, fmt);
393 warn_slowpath_common(file, line, __builtin_return_address(0), &args); 391 warn_slowpath_common(file, line, __builtin_return_address(0),
392 TAINT_WARN, &args);
394 va_end(args.args); 393 va_end(args.args);
395} 394}
396EXPORT_SYMBOL(warn_slowpath_fmt); 395EXPORT_SYMBOL(warn_slowpath_fmt);
397 396
397void warn_slowpath_fmt_taint(const char *file, int line,
398 unsigned taint, const char *fmt, ...)
399{
400 struct slowpath_args args;
401
402 args.fmt = fmt;
403 va_start(args.args, fmt);
404 warn_slowpath_common(file, line, __builtin_return_address(0),
405 taint, &args);
406 va_end(args.args);
407}
408EXPORT_SYMBOL(warn_slowpath_fmt_taint);
409
398void warn_slowpath_null(const char *file, int line) 410void warn_slowpath_null(const char *file, int line)
399{ 411{
400 warn_slowpath_common(file, line, __builtin_return_address(0), NULL); 412 warn_slowpath_common(file, line, __builtin_return_address(0),
413 TAINT_WARN, NULL);
401} 414}
402EXPORT_SYMBOL(warn_slowpath_null); 415EXPORT_SYMBOL(warn_slowpath_null);
403#endif 416#endif