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>
This commit is contained in:
Ben Hutchings 2010-04-03 19:34:56 +01:00 committed by David Woodhouse
parent 8954da1f82
commit b2be05273a
8 changed files with 67 additions and 20 deletions

View file

@ -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 */
/*
@ -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
@ -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)
@ -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) ({ \
@ -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))