Skip to content

Commit

Permalink
panic: Allow warnings to set different taint flags
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bwhacks authored and David Woodhouse committed May 19, 2010
1 parent 8954da1 commit b2be052
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 20 deletions.
1 change: 1 addition & 0 deletions Documentation/oops-tracing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ characters, each representing a particular tainted value.
9: 'A' if the ACPI table has been overridden.

10: 'W' if a warning has previously been issued by the kernel.
(Though some warnings may set more specific taint flags.)

11: 'C' if a staging driver has been loaded.

Expand Down
8 changes: 4 additions & 4 deletions arch/parisc/include/asm/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#endif

#ifdef CONFIG_DEBUG_BUGVERBOSE
#define __WARN() \
#define __WARN_TAINT(taint) \
do { \
asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \
Expand All @@ -54,11 +54,11 @@
"\t.org 2b+%c3\n" \
"\t.popsection" \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING), \
"i" (BUGFLAG_TAINT(taint)), \
"i" (sizeof(struct bug_entry)) ); \
} while(0)
#else
#define __WARN() \
#define __WARN_TAINT(taint) \
do { \
asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \
Expand All @@ -67,7 +67,7 @@
"\t.short %c0\n" \
"\t.org 2b+%c1\n" \
"\t.popsection" \
: : "i" (BUGFLAG_WARNING), \
: : "i" (BUGFLAG_TAINT(taint)), \
"i" (sizeof(struct bug_entry)) ); \
} while(0)
#endif
Expand Down
6 changes: 3 additions & 3 deletions arch/powerpc/include/asm/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@
} \
} while (0)

#define __WARN() do { \
#define __WARN_TAINT(taint) do { \
__asm__ __volatile__( \
"1: twi 31,0,0\n" \
_EMIT_BUG_ENTRY \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING), \
"i" (BUGFLAG_TAINT(taint)), \
"i" (sizeof(struct bug_entry))); \
} while (0)

Expand All @@ -104,7 +104,7 @@
"1: "PPC_TLNEI" %4,0\n" \
_EMIT_BUG_ENTRY \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING), \
"i" (BUGFLAG_TAINT(TAINT_WARN)), \
"i" (sizeof(struct bug_entry)), \
"r" (__ret_warn_on)); \
} \
Expand Down
8 changes: 4 additions & 4 deletions arch/s390/include/asm/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,18 @@
unreachable(); \
} while (0)

#define __WARN() do { \
__EMIT_BUG(BUGFLAG_WARNING); \
#define __WARN_TAINT(taint) do { \
__EMIT_BUG(BUGFLAG_TAINT(taint)); \
} while (0)

#define WARN_ON(x) ({ \
int __ret_warn_on = !!(x); \
if (__builtin_constant_p(__ret_warn_on)) { \
if (__ret_warn_on) \
__EMIT_BUG(BUGFLAG_WARNING); \
__WARN(); \
} else { \
if (unlikely(__ret_warn_on)) \
__EMIT_BUG(BUGFLAG_WARNING); \
__WARN(); \
} \
unlikely(__ret_warn_on); \
})
Expand Down
4 changes: 2 additions & 2 deletions arch/sh/include/asm/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ do { \
"i" (sizeof(struct bug_entry))); \
} while (0)

#define __WARN() \
#define __WARN_TAINT(taint) \
do { \
__asm__ __volatile__ ( \
"1:\t.short %O0\n" \
Expand All @@ -57,7 +57,7 @@ do { \
: "n" (TRAPA_BUG_OPCODE), \
"i" (__FILE__), \
"i" (__LINE__), \
"i" (BUGFLAG_WARNING), \
"i" (BUGFLAG_TAINT(taint)), \
"i" (sizeof(struct bug_entry))); \
} while (0)

Expand Down
34 changes: 32 additions & 2 deletions include/asm-generic/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ struct bug_entry {
};
#endif /* __ASSEMBLY__ */

#define BUGFLAG_WARNING (1<<0)
#define BUGFLAG_WARNING (1 << 0)
#define BUGFLAG_TAINT(taint) (BUGFLAG_WARNING | ((taint) << 8))
#define BUG_GET_TAINT(bug) ((bug)->flags >> 8)

#endif /* CONFIG_GENERIC_BUG */

/*
Expand Down Expand Up @@ -56,17 +59,25 @@ struct bug_entry {
* appear at runtime. Use the versions with printk format strings
* to provide better diagnostics.
*/
#ifndef __WARN
#ifndef __WARN_TAINT
#ifndef __ASSEMBLY__
extern void warn_slowpath_fmt(const char *file, const int line,
const char *fmt, ...) __attribute__((format(printf, 3, 4)));
extern void warn_slowpath_fmt_taint(const char *file, const int line,
unsigned taint, const char *fmt, ...)
__attribute__((format(printf, 4, 5)));
extern void warn_slowpath_null(const char *file, const int line);
#define WANT_WARN_ON_SLOWPATH
#endif
#define __WARN() warn_slowpath_null(__FILE__, __LINE__)
#define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg)
#define __WARN_printf_taint(taint, arg...) \
warn_slowpath_fmt_taint(__FILE__, __LINE__, taint, arg)
#else
#define __WARN() __WARN_TAINT(TAINT_WARN)
#define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0)
#define __WARN_printf_taint(taint, arg...) \
do { printk(arg); __WARN_TAINT(taint); } while (0)
#endif

#ifndef WARN_ON
Expand All @@ -87,6 +98,13 @@ extern void warn_slowpath_null(const char *file, const int line);
})
#endif

#define WARN_TAINT(condition, taint, format...) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_printf_taint(taint, format); \
unlikely(__ret_warn_on); \
})

#else /* !CONFIG_BUG */
#ifndef HAVE_ARCH_BUG
#define BUG() do {} while(0)
Expand All @@ -110,6 +128,8 @@ extern void warn_slowpath_null(const char *file, const int line);
})
#endif

#define WARN_TAINT(condition, taint, format...) WARN_ON(condition)

#endif

#define WARN_ON_ONCE(condition) ({ \
Expand All @@ -132,6 +152,16 @@ extern void warn_slowpath_null(const char *file, const int line);
unlikely(__ret_warn_once); \
})

#define WARN_TAINT_ONCE(condition, taint, format...) ({ \
static bool __warned; \
int __ret_warn_once = !!(condition); \
\
if (unlikely(__ret_warn_once)) \
if (WARN_TAINT(!__warned, taint, format)) \
__warned = true; \
unlikely(__ret_warn_once); \
})

#define WARN_ON_RATELIMIT(condition, state) \
WARN_ON((condition) && __ratelimit(state))

Expand Down
24 changes: 20 additions & 4 deletions kernel/panic.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,8 @@ struct slowpath_args {
va_list args;
};

static void warn_slowpath_common(const char *file, int line, void *caller, struct slowpath_args *args)
static void warn_slowpath_common(const char *file, int line, void *caller,
unsigned taint, struct slowpath_args *args)
{
const char *board;

Expand All @@ -381,7 +382,7 @@ static void warn_slowpath_common(const char *file, int line, void *caller, struc
print_modules();
dump_stack();
print_oops_end_marker();
add_taint(TAINT_WARN);
add_taint(taint);
}

void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
Expand All @@ -390,14 +391,29 @@ void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)

args.fmt = fmt;
va_start(args.args, fmt);
warn_slowpath_common(file, line, __builtin_return_address(0), &args);
warn_slowpath_common(file, line, __builtin_return_address(0),
TAINT_WARN, &args);
va_end(args.args);
}
EXPORT_SYMBOL(warn_slowpath_fmt);

void warn_slowpath_fmt_taint(const char *file, int line,
unsigned taint, const char *fmt, ...)
{
struct slowpath_args args;

args.fmt = fmt;
va_start(args.args, fmt);
warn_slowpath_common(file, line, __builtin_return_address(0),
taint, &args);
va_end(args.args);
}
EXPORT_SYMBOL(warn_slowpath_fmt_taint);

void warn_slowpath_null(const char *file, int line)
{
warn_slowpath_common(file, line, __builtin_return_address(0), NULL);
warn_slowpath_common(file, line, __builtin_return_address(0),
TAINT_WARN, NULL);
}
EXPORT_SYMBOL(warn_slowpath_null);
#endif
Expand Down
2 changes: 1 addition & 1 deletion lib/bug.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
(void *)bugaddr);

show_regs(regs);
add_taint(TAINT_WARN);
add_taint(BUG_GET_TAINT(bug));
return BUG_TRAP_TYPE_WARN;
}

Expand Down

0 comments on commit b2be052

Please sign in to comment.