Commit b2be05273a1744d175bf4b67f6665637bb9ac7a8
Committed by
David Woodhouse
1 parent
8954da1f82
Exists in
master
and in
20 other branches
panic: Allow warnings to set different taint flags
WARN() is used in some places to report firmware or hardware bugs that are then worked-around. These bugs do not affect the stability of the kernel and should not set the flag for TAINT_WARN. To allow for this, add WARN_TAINT() and WARN_TAINT_ONCE() macros that take a taint number as argument. Architectures that implement warnings using trap instructions instead of calls to warn_slowpath_*() now implement __WARN_TAINT(taint) instead of __WARN(). Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Acked-by: Helge Deller <deller@gmx.de> Tested-by: Paul Mundt <lethal@linux-sh.org> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Showing 8 changed files with 67 additions and 20 deletions Side-by-side Diff
Documentation/oops-tracing.txt
arch/parisc/include/asm/bug.h
... | ... | @@ -44,7 +44,7 @@ |
44 | 44 | #endif |
45 | 45 | |
46 | 46 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
47 | -#define __WARN() \ | |
47 | +#define __WARN_TAINT(taint) \ | |
48 | 48 | do { \ |
49 | 49 | asm volatile("\n" \ |
50 | 50 | "1:\t" PARISC_BUG_BREAK_ASM "\n" \ |
51 | 51 | |
... | ... | @@ -54,11 +54,11 @@ |
54 | 54 | "\t.org 2b+%c3\n" \ |
55 | 55 | "\t.popsection" \ |
56 | 56 | : : "i" (__FILE__), "i" (__LINE__), \ |
57 | - "i" (BUGFLAG_WARNING), \ | |
57 | + "i" (BUGFLAG_TAINT(taint)), \ | |
58 | 58 | "i" (sizeof(struct bug_entry)) ); \ |
59 | 59 | } while(0) |
60 | 60 | #else |
61 | -#define __WARN() \ | |
61 | +#define __WARN_TAINT(taint) \ | |
62 | 62 | do { \ |
63 | 63 | asm volatile("\n" \ |
64 | 64 | "1:\t" PARISC_BUG_BREAK_ASM "\n" \ |
... | ... | @@ -67,7 +67,7 @@ |
67 | 67 | "\t.short %c0\n" \ |
68 | 68 | "\t.org 2b+%c1\n" \ |
69 | 69 | "\t.popsection" \ |
70 | - : : "i" (BUGFLAG_WARNING), \ | |
70 | + : : "i" (BUGFLAG_TAINT(taint)), \ | |
71 | 71 | "i" (sizeof(struct bug_entry)) ); \ |
72 | 72 | } while(0) |
73 | 73 | #endif |
arch/powerpc/include/asm/bug.h
... | ... | @@ -85,12 +85,12 @@ |
85 | 85 | } \ |
86 | 86 | } while (0) |
87 | 87 | |
88 | -#define __WARN() do { \ | |
88 | +#define __WARN_TAINT(taint) do { \ | |
89 | 89 | __asm__ __volatile__( \ |
90 | 90 | "1: twi 31,0,0\n" \ |
91 | 91 | _EMIT_BUG_ENTRY \ |
92 | 92 | : : "i" (__FILE__), "i" (__LINE__), \ |
93 | - "i" (BUGFLAG_WARNING), \ | |
93 | + "i" (BUGFLAG_TAINT(taint)), \ | |
94 | 94 | "i" (sizeof(struct bug_entry))); \ |
95 | 95 | } while (0) |
96 | 96 | |
... | ... | @@ -104,7 +104,7 @@ |
104 | 104 | "1: "PPC_TLNEI" %4,0\n" \ |
105 | 105 | _EMIT_BUG_ENTRY \ |
106 | 106 | : : "i" (__FILE__), "i" (__LINE__), \ |
107 | - "i" (BUGFLAG_WARNING), \ | |
107 | + "i" (BUGFLAG_TAINT(TAINT_WARN)), \ | |
108 | 108 | "i" (sizeof(struct bug_entry)), \ |
109 | 109 | "r" (__ret_warn_on)); \ |
110 | 110 | } \ |
arch/s390/include/asm/bug.h
... | ... | @@ -46,18 +46,18 @@ |
46 | 46 | unreachable(); \ |
47 | 47 | } while (0) |
48 | 48 | |
49 | -#define __WARN() do { \ | |
50 | - __EMIT_BUG(BUGFLAG_WARNING); \ | |
49 | +#define __WARN_TAINT(taint) do { \ | |
50 | + __EMIT_BUG(BUGFLAG_TAINT(taint)); \ | |
51 | 51 | } while (0) |
52 | 52 | |
53 | 53 | #define WARN_ON(x) ({ \ |
54 | 54 | int __ret_warn_on = !!(x); \ |
55 | 55 | if (__builtin_constant_p(__ret_warn_on)) { \ |
56 | 56 | if (__ret_warn_on) \ |
57 | - __EMIT_BUG(BUGFLAG_WARNING); \ | |
57 | + __WARN(); \ | |
58 | 58 | } else { \ |
59 | 59 | if (unlikely(__ret_warn_on)) \ |
60 | - __EMIT_BUG(BUGFLAG_WARNING); \ | |
60 | + __WARN(); \ | |
61 | 61 | } \ |
62 | 62 | unlikely(__ret_warn_on); \ |
63 | 63 | }) |
arch/sh/include/asm/bug.h
... | ... | @@ -48,7 +48,7 @@ |
48 | 48 | "i" (sizeof(struct bug_entry))); \ |
49 | 49 | } while (0) |
50 | 50 | |
51 | -#define __WARN() \ | |
51 | +#define __WARN_TAINT(taint) \ | |
52 | 52 | do { \ |
53 | 53 | __asm__ __volatile__ ( \ |
54 | 54 | "1:\t.short %O0\n" \ |
... | ... | @@ -57,7 +57,7 @@ |
57 | 57 | : "n" (TRAPA_BUG_OPCODE), \ |
58 | 58 | "i" (__FILE__), \ |
59 | 59 | "i" (__LINE__), \ |
60 | - "i" (BUGFLAG_WARNING), \ | |
60 | + "i" (BUGFLAG_TAINT(taint)), \ | |
61 | 61 | "i" (sizeof(struct bug_entry))); \ |
62 | 62 | } while (0) |
63 | 63 |
include/asm-generic/bug.h
... | ... | @@ -25,7 +25,10 @@ |
25 | 25 | }; |
26 | 26 | #endif /* __ASSEMBLY__ */ |
27 | 27 | |
28 | -#define BUGFLAG_WARNING (1<<0) | |
28 | +#define BUGFLAG_WARNING (1 << 0) | |
29 | +#define BUGFLAG_TAINT(taint) (BUGFLAG_WARNING | ((taint) << 8)) | |
30 | +#define BUG_GET_TAINT(bug) ((bug)->flags >> 8) | |
31 | + | |
29 | 32 | #endif /* CONFIG_GENERIC_BUG */ |
30 | 33 | |
31 | 34 | /* |
32 | 35 | |
33 | 36 | |
34 | 37 | |
35 | 38 | |
... | ... | @@ -56,17 +59,25 @@ |
56 | 59 | * appear at runtime. Use the versions with printk format strings |
57 | 60 | * to provide better diagnostics. |
58 | 61 | */ |
59 | -#ifndef __WARN | |
62 | +#ifndef __WARN_TAINT | |
60 | 63 | #ifndef __ASSEMBLY__ |
61 | 64 | extern void warn_slowpath_fmt(const char *file, const int line, |
62 | 65 | const char *fmt, ...) __attribute__((format(printf, 3, 4))); |
66 | +extern void warn_slowpath_fmt_taint(const char *file, const int line, | |
67 | + unsigned taint, const char *fmt, ...) | |
68 | + __attribute__((format(printf, 4, 5))); | |
63 | 69 | extern void warn_slowpath_null(const char *file, const int line); |
64 | 70 | #define WANT_WARN_ON_SLOWPATH |
65 | 71 | #endif |
66 | 72 | #define __WARN() warn_slowpath_null(__FILE__, __LINE__) |
67 | 73 | #define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg) |
74 | +#define __WARN_printf_taint(taint, arg...) \ | |
75 | + warn_slowpath_fmt_taint(__FILE__, __LINE__, taint, arg) | |
68 | 76 | #else |
77 | +#define __WARN() __WARN_TAINT(TAINT_WARN) | |
69 | 78 | #define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0) |
79 | +#define __WARN_printf_taint(taint, arg...) \ | |
80 | + do { printk(arg); __WARN_TAINT(taint); } while (0) | |
70 | 81 | #endif |
71 | 82 | |
72 | 83 | #ifndef WARN_ON |
... | ... | @@ -87,6 +98,13 @@ |
87 | 98 | }) |
88 | 99 | #endif |
89 | 100 | |
101 | +#define WARN_TAINT(condition, taint, format...) ({ \ | |
102 | + int __ret_warn_on = !!(condition); \ | |
103 | + if (unlikely(__ret_warn_on)) \ | |
104 | + __WARN_printf_taint(taint, format); \ | |
105 | + unlikely(__ret_warn_on); \ | |
106 | +}) | |
107 | + | |
90 | 108 | #else /* !CONFIG_BUG */ |
91 | 109 | #ifndef HAVE_ARCH_BUG |
92 | 110 | #define BUG() do {} while(0) |
... | ... | @@ -110,6 +128,8 @@ |
110 | 128 | }) |
111 | 129 | #endif |
112 | 130 | |
131 | +#define WARN_TAINT(condition, taint, format...) WARN_ON(condition) | |
132 | + | |
113 | 133 | #endif |
114 | 134 | |
115 | 135 | #define WARN_ON_ONCE(condition) ({ \ |
... | ... | @@ -128,6 +148,16 @@ |
128 | 148 | \ |
129 | 149 | if (unlikely(__ret_warn_once)) \ |
130 | 150 | if (WARN(!__warned, format)) \ |
151 | + __warned = true; \ | |
152 | + unlikely(__ret_warn_once); \ | |
153 | +}) | |
154 | + | |
155 | +#define WARN_TAINT_ONCE(condition, taint, format...) ({ \ | |
156 | + static bool __warned; \ | |
157 | + int __ret_warn_once = !!(condition); \ | |
158 | + \ | |
159 | + if (unlikely(__ret_warn_once)) \ | |
160 | + if (WARN_TAINT(!__warned, taint, format)) \ | |
131 | 161 | __warned = true; \ |
132 | 162 | unlikely(__ret_warn_once); \ |
133 | 163 | }) |
kernel/panic.c
... | ... | @@ -365,7 +365,8 @@ |
365 | 365 | va_list args; |
366 | 366 | }; |
367 | 367 | |
368 | -static void warn_slowpath_common(const char *file, int line, void *caller, struct slowpath_args *args) | |
368 | +static void warn_slowpath_common(const char *file, int line, void *caller, | |
369 | + unsigned taint, struct slowpath_args *args) | |
369 | 370 | { |
370 | 371 | const char *board; |
371 | 372 | |
... | ... | @@ -381,7 +382,7 @@ |
381 | 382 | print_modules(); |
382 | 383 | dump_stack(); |
383 | 384 | print_oops_end_marker(); |
384 | - add_taint(TAINT_WARN); | |
385 | + add_taint(taint); | |
385 | 386 | } |
386 | 387 | |
387 | 388 | void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...) |
388 | 389 | |
389 | 390 | |
... | ... | @@ -390,14 +391,29 @@ |
390 | 391 | |
391 | 392 | args.fmt = fmt; |
392 | 393 | va_start(args.args, fmt); |
393 | - warn_slowpath_common(file, line, __builtin_return_address(0), &args); | |
394 | + warn_slowpath_common(file, line, __builtin_return_address(0), | |
395 | + TAINT_WARN, &args); | |
394 | 396 | va_end(args.args); |
395 | 397 | } |
396 | 398 | EXPORT_SYMBOL(warn_slowpath_fmt); |
397 | 399 | |
400 | +void warn_slowpath_fmt_taint(const char *file, int line, | |
401 | + unsigned taint, const char *fmt, ...) | |
402 | +{ | |
403 | + struct slowpath_args args; | |
404 | + | |
405 | + args.fmt = fmt; | |
406 | + va_start(args.args, fmt); | |
407 | + warn_slowpath_common(file, line, __builtin_return_address(0), | |
408 | + taint, &args); | |
409 | + va_end(args.args); | |
410 | +} | |
411 | +EXPORT_SYMBOL(warn_slowpath_fmt_taint); | |
412 | + | |
398 | 413 | void warn_slowpath_null(const char *file, int line) |
399 | 414 | { |
400 | - warn_slowpath_common(file, line, __builtin_return_address(0), NULL); | |
415 | + warn_slowpath_common(file, line, __builtin_return_address(0), | |
416 | + TAINT_WARN, NULL); | |
401 | 417 | } |
402 | 418 | EXPORT_SYMBOL(warn_slowpath_null); |
403 | 419 | #endif |