| Subject: printk-kill.patch |
| From: Ingo Molnar <mingo@elte.hu> |
| Date: Fri, 22 Jul 2011 17:58:40 +0200 |
| |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| --- |
| include/linux/printk.h | 3 ++- |
| kernel/printk.c | 33 +++++++++++++++++++++++++++++++++ |
| kernel/watchdog.c | 15 +++++++++++++-- |
| 3 files changed, 48 insertions(+), 3 deletions(-) |
| |
| Index: linux-stable/include/linux/printk.h |
| =================================================================== |
| --- linux-stable.orig/include/linux/printk.h |
| +++ linux-stable/include/linux/printk.h |
| @@ -99,9 +99,11 @@ int no_printk(const char *fmt, ...) |
| extern asmlinkage __printf(1, 2) |
| void early_printk(const char *fmt, ...); |
| void early_vprintk(const char *fmt, va_list ap); |
| +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); |
| @@ -138,7 +140,6 @@ extern int __printk_ratelimit(const char |
| #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; |
| Index: linux-stable/kernel/printk.c |
| =================================================================== |
| --- linux-stable.orig/kernel/printk.c |
| +++ linux-stable/kernel/printk.c |
| @@ -1246,6 +1246,32 @@ asmlinkage void early_printk(const char |
| 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; |
| @@ -1508,6 +1534,13 @@ asmlinkage int vprintk_emit(int facility |
| int this_cpu; |
| int printed_len = 0; |
| |
| + /* |
| + * 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(); |
| |
| Index: linux-stable/kernel/watchdog.c |
| =================================================================== |
| --- linux-stable.orig/kernel/watchdog.c |
| +++ linux-stable/kernel/watchdog.c |
| @@ -202,6 +202,8 @@ static int is_softlockup(unsigned long t |
| |
| #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, |
| @@ -236,10 +238,19 @@ static void watchdog_overflow_callback(s |
| 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; |