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 <b...@decadent.org.uk>
---
Changes since the previous version:
- Added note to Documentation/oops-tracing.txt
- Changed the commit message to distinguish taint numbers from taint
  flags
- Removed 'must' from last sentence of commit message; this patch
  converts all mainline architectures

Ben.

 Documentation/oops-tracing.txt |    1 +
 arch/parisc/include/asm/bug.h  |    8 ++++----
 arch/powerpc/include/asm/bug.h |    6 +++---
 arch/s390/include/asm/bug.h    |    8 ++++----
 arch/sh/include/asm/bug.h      |    4 ++--
 include/asm-generic/bug.h      |   34 ++++++++++++++++++++++++++++++++--
 kernel/panic.c                 |   24 ++++++++++++++++++++----
 lib/bug.c                      |    2 +-
 8 files changed, 67 insertions(+), 20 deletions(-)

diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index c10c022..069fab3 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -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.
 
diff --git a/arch/parisc/include/asm/bug.h b/arch/parisc/include/asm/bug.h
index 75e46c5..72cfdb0 100644
--- a/arch/parisc/include/asm/bug.h
+++ b/arch/parisc/include/asm/bug.h
@@ -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"           \
@@ -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"           \
@@ -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
diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
index 2c15212..065c590 100644
--- a/arch/powerpc/include/asm/bug.h
+++ b/arch/powerpc/include/asm/bug.h
@@ -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)
 
@@ -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));                         \
        }                                                       \
diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h
index 9beeb9d..bf90d1f 100644
--- a/arch/s390/include/asm/bug.h
+++ b/arch/s390/include/asm/bug.h
@@ -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);                        \
 })
diff --git a/arch/sh/include/asm/bug.h b/arch/sh/include/asm/bug.h
index d02c01b..6323f86 100644
--- a/arch/sh/include/asm/bug.h
+++ b/arch/sh/include/asm/bug.h
@@ -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"                      \
@@ -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)
 
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 18c435d..c2c9ba0 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -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))
 
diff --git a/kernel/panic.c b/kernel/panic.c
index 13d966b..8b821bc 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -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;
 
@@ -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, ...)
@@ -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
diff --git a/lib/bug.c b/lib/bug.c
index 300e41a..f13daf4 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -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;
        }
 
-- 
1.7.0.3



_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to