Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Ben Hutchings and committed by
David Woodhouse
b2be0527 8954da1f

+67 -20
+1
Documentation/oops-tracing.txt
··· 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
+4 -4
arch/parisc/include/asm/bug.h
··· 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" \ ··· 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 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
+3 -3
arch/powerpc/include/asm/bug.h
··· 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 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 } \
+4 -4
arch/s390/include/asm/bug.h
··· 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 })
+2 -2
arch/sh/include/asm/bug.h
··· 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 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
+32 -2
include/asm-generic/bug.h
··· 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 /* ··· 59 56 * appear at runtime. Use the versions with printk format strings 60 57 * to provide better diagnostics. 61 58 */ 62 - #ifndef __WARN 59 + #ifndef __WARN_TAINT 63 60 #ifndef __ASSEMBLY__ 64 61 extern void warn_slowpath_fmt(const char *file, const int line, 65 62 const char *fmt, ...) __attribute__((format(printf, 3, 4))); 63 + extern void warn_slowpath_fmt_taint(const char *file, const int line, 64 + unsigned taint, const char *fmt, ...) 65 + __attribute__((format(printf, 4, 5))); 66 66 extern void warn_slowpath_null(const char *file, const int line); 67 67 #define WANT_WARN_ON_SLOWPATH 68 68 #endif 69 69 #define __WARN() warn_slowpath_null(__FILE__, __LINE__) 70 70 #define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg) 71 + #define __WARN_printf_taint(taint, arg...) \ 72 + warn_slowpath_fmt_taint(__FILE__, __LINE__, taint, arg) 71 73 #else 74 + #define __WARN() __WARN_TAINT(TAINT_WARN) 72 75 #define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0) 76 + #define __WARN_printf_taint(taint, arg...) \ 77 + do { printk(arg); __WARN_TAINT(taint); } while (0) 73 78 #endif 74 79 75 80 #ifndef WARN_ON ··· 97 86 unlikely(__ret_warn_on); \ 98 87 }) 99 88 #endif 89 + 90 + #define WARN_TAINT(condition, taint, format...) ({ \ 91 + int __ret_warn_on = !!(condition); \ 92 + if (unlikely(__ret_warn_on)) \ 93 + __WARN_printf_taint(taint, format); \ 94 + unlikely(__ret_warn_on); \ 95 + }) 100 96 101 97 #else /* !CONFIG_BUG */ 102 98 #ifndef HAVE_ARCH_BUG ··· 128 110 }) 129 111 #endif 130 112 113 + #define WARN_TAINT(condition, taint, format...) WARN_ON(condition) 114 + 131 115 #endif 132 116 133 117 #define WARN_ON_ONCE(condition) ({ \ ··· 148 128 \ 149 129 if (unlikely(__ret_warn_once)) \ 150 130 if (WARN(!__warned, format)) \ 131 + __warned = true; \ 132 + unlikely(__ret_warn_once); \ 133 + }) 134 + 135 + #define WARN_TAINT_ONCE(condition, taint, format...) ({ \ 136 + static bool __warned; \ 137 + int __ret_warn_once = !!(condition); \ 138 + \ 139 + if (unlikely(__ret_warn_once)) \ 140 + if (WARN_TAINT(!__warned, taint, format)) \ 151 141 __warned = true; \ 152 142 unlikely(__ret_warn_once); \ 153 143 })
+20 -4
kernel/panic.c
··· 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 ··· 382 381 print_modules(); 383 382 dump_stack(); 384 383 print_oops_end_marker(); 385 - add_taint(TAINT_WARN); 384 + add_taint(taint); 386 385 } 387 386 388 387 void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...) ··· 391 390 392 391 args.fmt = fmt; 393 392 va_start(args.args, fmt); 394 - warn_slowpath_common(file, line, __builtin_return_address(0), &args); 393 + warn_slowpath_common(file, line, __builtin_return_address(0), 394 + TAINT_WARN, &args); 395 395 va_end(args.args); 396 396 } 397 397 EXPORT_SYMBOL(warn_slowpath_fmt); 398 398 399 + void warn_slowpath_fmt_taint(const char *file, int line, 400 + unsigned taint, const char *fmt, ...) 401 + { 402 + struct slowpath_args args; 403 + 404 + args.fmt = fmt; 405 + va_start(args.args, fmt); 406 + warn_slowpath_common(file, line, __builtin_return_address(0), 407 + taint, &args); 408 + va_end(args.args); 409 + } 410 + EXPORT_SYMBOL(warn_slowpath_fmt_taint); 411 + 399 412 void warn_slowpath_null(const char *file, int line) 400 413 { 401 - warn_slowpath_common(file, line, __builtin_return_address(0), NULL); 414 + warn_slowpath_common(file, line, __builtin_return_address(0), 415 + TAINT_WARN, NULL); 402 416 } 403 417 EXPORT_SYMBOL(warn_slowpath_null); 404 418 #endif
+1 -1
lib/bug.c
··· 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