diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-07-22 17:58:40 +0200 |
---|---|---|
committer | Clark Williams <williams@redhat.com> | 2012-04-10 16:40:09 -0500 |
commit | 380adfc71a6a9c88f4c843ad51d48bdde2aac959 (patch) | |
tree | 788afb5540fda4037c14801c24be81a7affb0f60 | |
parent | 7d77369a3c89b65eeeb1b030d23c6abee3c36982 (diff) |
printk-kill.patch
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | include/linux/printk.h | 3 | ||||
-rw-r--r-- | kernel/printk.c | 33 | ||||
-rw-r--r-- | kernel/watchdog.c | 15 |
3 files changed, 48 insertions, 3 deletions
diff --git a/include/linux/printk.h b/include/linux/printk.h index c8d7f7be2e5b..d5e6eed93fb7 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -91,9 +91,11 @@ int no_printk(const char *fmt, ...) #ifdef CONFIG_EARLY_PRINTK extern asmlinkage __printf(1, 2) void early_printk(const char *fmt, ...); +extern void printk_kill(void); #else static inline __printf(1, 2) __cold void early_printk(const char *s, ...) { } +static inline void printk_kill(void) { } #endif extern int printk_needs_cpu(int cpu); @@ -119,7 +121,6 @@ extern int __printk_ratelimit(const char *func); #define printk_ratelimit() __printk_ratelimit(__func__) extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, unsigned int interval_msec); - extern int printk_delay_msec; extern int dmesg_restrict; extern int kptr_restrict; diff --git a/kernel/printk.c b/kernel/printk.c index c4426061e228..5a172f9e5027 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -538,6 +538,32 @@ asmlinkage void early_printk(const char *fmt, ...) early_vprintk(fmt, ap); va_end(ap); } + +/* + * This is independent of any log levels - a global + * kill switch that turns off all of printk. + * + * Used by the NMI watchdog if early-printk is enabled. + */ +static bool __read_mostly printk_killswitch; + +void printk_kill(void) +{ + printk_killswitch = true; +} + +static int forced_early_printk(const char *fmt, va_list ap) +{ + if (!printk_killswitch) + return 0; + early_vprintk(fmt, ap); + return 1; +} +#else +static inline int forced_early_printk(const char *fmt, va_list ap) +{ + return 0; +} #endif static bool __read_mostly ignore_loglevel; @@ -862,6 +888,13 @@ asmlinkage int vprintk(const char *fmt, va_list args) size_t plen; char special; + /* + * Fall back to early_printk if a debugging subsystem has + * killed printk output + */ + if (unlikely(forced_early_printk(fmt, args))) + return 1; + boot_delay_msec(); printk_delay(); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index df30ee08bdd4..de08263ff8ae 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -201,6 +201,8 @@ static int is_softlockup(unsigned long touch_ts) #ifdef CONFIG_HARDLOCKUP_DETECTOR +static DEFINE_RAW_SPINLOCK(watchdog_output_lock); + static struct perf_event_attr wd_hw_attr = { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES, @@ -235,10 +237,19 @@ static void watchdog_overflow_callback(struct perf_event *event, if (__this_cpu_read(hard_watchdog_warn) == true) return; - if (hardlockup_panic) + /* + * If early-printk is enabled then make sure we do not + * lock up in printk() and kill console logging: + */ + printk_kill(); + + if (hardlockup_panic) { panic("Watchdog detected hard LOCKUP on cpu %d", this_cpu); - else + } else { + raw_spin_lock(&watchdog_output_lock); WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu); + raw_spin_unlock(&watchdog_output_lock); + } __this_cpu_write(hard_watchdog_warn, true); return; |