Commit b2be05273a1744d175bf4b67f6665637bb9ac7a8

Authored by Ben Hutchings
Committed by David Woodhouse
1 parent 8954da1f82

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
... ... @@ -256,6 +256,7 @@
256 256 9: 'A' if the ACPI table has been overridden.
257 257  
258 258 10: 'W' if a warning has previously been issued by the kernel.
  259 + (Though some warnings may set more specific taint flags.)
259 260  
260 261 11: 'C' if a staging driver has been loaded.
261 262  
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 })
... ... @@ -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
... ... @@ -165,7 +165,7 @@
165 165 (void *)bugaddr);
166 166  
167 167 show_regs(regs);
168   - add_taint(TAINT_WARN);
  168 + add_taint(BUG_GET_TAINT(bug));
169 169 return BUG_TRAP_TYPE_WARN;
170 170 }
171 171