diff options
Diffstat (limited to 'kernel/panic.c')
-rw-r--r-- | kernel/panic.c | 117 |
1 files changed, 65 insertions, 52 deletions
diff --git a/kernel/panic.c b/kernel/panic.c index e0a87bb025c0..3a0b0898690a 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
@@ -21,9 +21,10 @@ | |||
21 | #include <linux/debug_locks.h> | 21 | #include <linux/debug_locks.h> |
22 | #include <linux/random.h> | 22 | #include <linux/random.h> |
23 | #include <linux/kallsyms.h> | 23 | #include <linux/kallsyms.h> |
24 | #include <linux/dmi.h> | ||
24 | 25 | ||
25 | int panic_on_oops; | 26 | int panic_on_oops; |
26 | int tainted; | 27 | static unsigned long tainted_mask; |
27 | static int pause_on_oops; | 28 | static int pause_on_oops; |
28 | static int pause_on_oops_flag; | 29 | static int pause_on_oops_flag; |
29 | static DEFINE_SPINLOCK(pause_on_oops_lock); | 30 | static DEFINE_SPINLOCK(pause_on_oops_lock); |
@@ -34,13 +35,6 @@ ATOMIC_NOTIFIER_HEAD(panic_notifier_list); | |||
34 | 35 | ||
35 | EXPORT_SYMBOL(panic_notifier_list); | 36 | EXPORT_SYMBOL(panic_notifier_list); |
36 | 37 | ||
37 | static int __init panic_setup(char *str) | ||
38 | { | ||
39 | panic_timeout = simple_strtoul(str, NULL, 0); | ||
40 | return 1; | ||
41 | } | ||
42 | __setup("panic=", panic_setup); | ||
43 | |||
44 | static long no_blink(long time) | 38 | static long no_blink(long time) |
45 | { | 39 | { |
46 | return 0; | 40 | return 0; |
@@ -146,6 +140,27 @@ NORET_TYPE void panic(const char * fmt, ...) | |||
146 | 140 | ||
147 | EXPORT_SYMBOL(panic); | 141 | EXPORT_SYMBOL(panic); |
148 | 142 | ||
143 | |||
144 | struct tnt { | ||
145 | u8 bit; | ||
146 | char true; | ||
147 | char false; | ||
148 | }; | ||
149 | |||
150 | static const struct tnt tnts[] = { | ||
151 | { TAINT_PROPRIETARY_MODULE, 'P', 'G' }, | ||
152 | { TAINT_FORCED_MODULE, 'F', ' ' }, | ||
153 | { TAINT_UNSAFE_SMP, 'S', ' ' }, | ||
154 | { TAINT_FORCED_RMMOD, 'R', ' ' }, | ||
155 | { TAINT_MACHINE_CHECK, 'M', ' ' }, | ||
156 | { TAINT_BAD_PAGE, 'B', ' ' }, | ||
157 | { TAINT_USER, 'U', ' ' }, | ||
158 | { TAINT_DIE, 'D', ' ' }, | ||
159 | { TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' }, | ||
160 | { TAINT_WARN, 'W', ' ' }, | ||
161 | { TAINT_CRAP, 'C', ' ' }, | ||
162 | }; | ||
163 | |||
149 | /** | 164 | /** |
150 | * print_tainted - return a string to represent the kernel taint state. | 165 | * print_tainted - return a string to represent the kernel taint state. |
151 | * | 166 | * |
@@ -156,46 +171,50 @@ EXPORT_SYMBOL(panic); | |||
156 | * 'M' - System experienced a machine check exception. | 171 | * 'M' - System experienced a machine check exception. |
157 | * 'B' - System has hit bad_page. | 172 | * 'B' - System has hit bad_page. |
158 | * 'U' - Userspace-defined naughtiness. | 173 | * 'U' - Userspace-defined naughtiness. |
174 | * 'D' - Kernel has oopsed before | ||
159 | * 'A' - ACPI table overridden. | 175 | * 'A' - ACPI table overridden. |
160 | * 'W' - Taint on warning. | 176 | * 'W' - Taint on warning. |
177 | * 'C' - modules from drivers/staging are loaded. | ||
161 | * | 178 | * |
162 | * The string is overwritten by the next call to print_taint(). | 179 | * The string is overwritten by the next call to print_taint(). |
163 | */ | 180 | */ |
164 | |||
165 | const char *print_tainted(void) | 181 | const char *print_tainted(void) |
166 | { | 182 | { |
167 | static char buf[20]; | 183 | static char buf[ARRAY_SIZE(tnts) + sizeof("Tainted: ") + 1]; |
168 | if (tainted) { | 184 | |
169 | snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c%c%c", | 185 | if (tainted_mask) { |
170 | tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G', | 186 | char *s; |
171 | tainted & TAINT_FORCED_MODULE ? 'F' : ' ', | 187 | int i; |
172 | tainted & TAINT_UNSAFE_SMP ? 'S' : ' ', | 188 | |
173 | tainted & TAINT_FORCED_RMMOD ? 'R' : ' ', | 189 | s = buf + sprintf(buf, "Tainted: "); |
174 | tainted & TAINT_MACHINE_CHECK ? 'M' : ' ', | 190 | for (i = 0; i < ARRAY_SIZE(tnts); i++) { |
175 | tainted & TAINT_BAD_PAGE ? 'B' : ' ', | 191 | const struct tnt *t = &tnts[i]; |
176 | tainted & TAINT_USER ? 'U' : ' ', | 192 | *s++ = test_bit(t->bit, &tainted_mask) ? |
177 | tainted & TAINT_DIE ? 'D' : ' ', | 193 | t->true : t->false; |
178 | tainted & TAINT_OVERRIDDEN_ACPI_TABLE ? 'A' : ' ', | 194 | } |
179 | tainted & TAINT_WARN ? 'W' : ' '); | 195 | *s = 0; |
180 | } | 196 | } else |
181 | else | ||
182 | snprintf(buf, sizeof(buf), "Not tainted"); | 197 | snprintf(buf, sizeof(buf), "Not tainted"); |
183 | return(buf); | 198 | return(buf); |
184 | } | 199 | } |
185 | 200 | ||
186 | void add_taint(unsigned flag) | 201 | int test_taint(unsigned flag) |
187 | { | 202 | { |
188 | debug_locks = 0; /* can't trust the integrity of the kernel anymore */ | 203 | return test_bit(flag, &tainted_mask); |
189 | tainted |= flag; | 204 | } |
205 | EXPORT_SYMBOL(test_taint); | ||
206 | |||
207 | unsigned long get_taint(void) | ||
208 | { | ||
209 | return tainted_mask; | ||
190 | } | 210 | } |
191 | EXPORT_SYMBOL(add_taint); | ||
192 | 211 | ||
193 | static int __init pause_on_oops_setup(char *str) | 212 | void add_taint(unsigned flag) |
194 | { | 213 | { |
195 | pause_on_oops = simple_strtoul(str, NULL, 0); | 214 | debug_locks = 0; /* can't trust the integrity of the kernel anymore */ |
196 | return 1; | 215 | set_bit(flag, &tainted_mask); |
197 | } | 216 | } |
198 | __setup("pause_on_oops=", pause_on_oops_setup); | 217 | EXPORT_SYMBOL(add_taint); |
199 | 218 | ||
200 | static void spin_msec(int msecs) | 219 | static void spin_msec(int msecs) |
201 | { | 220 | { |
@@ -306,36 +325,27 @@ void oops_exit(void) | |||
306 | } | 325 | } |
307 | 326 | ||
308 | #ifdef WANT_WARN_ON_SLOWPATH | 327 | #ifdef WANT_WARN_ON_SLOWPATH |
309 | void warn_on_slowpath(const char *file, int line) | ||
310 | { | ||
311 | char function[KSYM_SYMBOL_LEN]; | ||
312 | unsigned long caller = (unsigned long) __builtin_return_address(0); | ||
313 | sprint_symbol(function, caller); | ||
314 | |||
315 | printk(KERN_WARNING "------------[ cut here ]------------\n"); | ||
316 | printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file, | ||
317 | line, function); | ||
318 | print_modules(); | ||
319 | dump_stack(); | ||
320 | print_oops_end_marker(); | ||
321 | add_taint(TAINT_WARN); | ||
322 | } | ||
323 | EXPORT_SYMBOL(warn_on_slowpath); | ||
324 | |||
325 | |||
326 | void warn_slowpath(const char *file, int line, const char *fmt, ...) | 328 | void warn_slowpath(const char *file, int line, const char *fmt, ...) |
327 | { | 329 | { |
328 | va_list args; | 330 | va_list args; |
329 | char function[KSYM_SYMBOL_LEN]; | 331 | char function[KSYM_SYMBOL_LEN]; |
330 | unsigned long caller = (unsigned long)__builtin_return_address(0); | 332 | unsigned long caller = (unsigned long)__builtin_return_address(0); |
333 | const char *board; | ||
334 | |||
331 | sprint_symbol(function, caller); | 335 | sprint_symbol(function, caller); |
332 | 336 | ||
333 | printk(KERN_WARNING "------------[ cut here ]------------\n"); | 337 | printk(KERN_WARNING "------------[ cut here ]------------\n"); |
334 | printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file, | 338 | printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file, |
335 | line, function); | 339 | line, function); |
336 | va_start(args, fmt); | 340 | board = dmi_get_system_info(DMI_PRODUCT_NAME); |
337 | vprintk(fmt, args); | 341 | if (board) |
338 | va_end(args); | 342 | printk(KERN_WARNING "Hardware name: %s\n", board); |
343 | |||
344 | if (fmt) { | ||
345 | va_start(args, fmt); | ||
346 | vprintk(fmt, args); | ||
347 | va_end(args); | ||
348 | } | ||
339 | 349 | ||
340 | print_modules(); | 350 | print_modules(); |
341 | dump_stack(); | 351 | dump_stack(); |
@@ -363,3 +373,6 @@ void __stack_chk_fail(void) | |||
363 | EXPORT_SYMBOL(__stack_chk_fail); | 373 | EXPORT_SYMBOL(__stack_chk_fail); |
364 | 374 | ||
365 | #endif | 375 | #endif |
376 | |||
377 | core_param(panic, panic_timeout, int, 0644); | ||
378 | core_param(pause_on_oops, pause_on_oops, int, 0644); | ||