Commit b2be05273a1744d175bf4b67f6665637bb9ac7a8
Committed by
David Woodhouse
1 parent
8954da1f82
Exists in
master
and in
4 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 |