summaryrefslogtreecommitdiffstats
path: root/kernel/watchdog.c
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2015-11-05 21:44:41 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-05 22:34:48 -0500
commit55537871ef666b4153fd1ef8782e4a13fee142cc (patch)
tree9e71e9e7db5b2f4f04e9d9c48d801717bb11eed7 /kernel/watchdog.c
parentee7fed540563b27e1028bec0b509921496c91bf9 (diff)
kernel/watchdog.c: perform all-CPU backtrace in case of hard lockup
In many cases of hardlockup reports, it's actually not possible to know why it triggered, because the CPU that got stuck is usually waiting on a resource (with IRQs disabled) in posession of some other CPU is holding. IOW, we are often looking at the stacktrace of the victim and not the actual offender. Introduce sysctl / cmdline parameter that makes it possible to have hardlockup detector perform all-CPU backtrace. Signed-off-by: Jiri Kosina <jkosina@suse.cz> Reviewed-by: Aaron Tomlin <atomlin@redhat.com> Cc: Ulrich Obergfell <uobergfe@redhat.com> Acked-by: Don Zickus <dzickus@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/watchdog.c')
-rw-r--r--kernel/watchdog.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 452e4ed507e5..f6b32b8cbffe 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -57,8 +57,10 @@ int __read_mostly watchdog_thresh = 10;
57 57
58#ifdef CONFIG_SMP 58#ifdef CONFIG_SMP
59int __read_mostly sysctl_softlockup_all_cpu_backtrace; 59int __read_mostly sysctl_softlockup_all_cpu_backtrace;
60int __read_mostly sysctl_hardlockup_all_cpu_backtrace;
60#else 61#else
61#define sysctl_softlockup_all_cpu_backtrace 0 62#define sysctl_softlockup_all_cpu_backtrace 0
63#define sysctl_hardlockup_all_cpu_backtrace 0
62#endif 64#endif
63static struct cpumask watchdog_cpumask __read_mostly; 65static struct cpumask watchdog_cpumask __read_mostly;
64unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask); 66unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
@@ -112,6 +114,7 @@ static unsigned long soft_lockup_nmi_warn;
112#ifdef CONFIG_HARDLOCKUP_DETECTOR 114#ifdef CONFIG_HARDLOCKUP_DETECTOR
113static int hardlockup_panic = 115static int hardlockup_panic =
114 CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE; 116 CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE;
117static unsigned long hardlockup_allcpu_dumped;
115/* 118/*
116 * We may not want to enable hard lockup detection by default in all cases, 119 * We may not want to enable hard lockup detection by default in all cases,
117 * for example when running the kernel as a guest on a hypervisor. In these 120 * for example when running the kernel as a guest on a hypervisor. In these
@@ -173,6 +176,13 @@ static int __init softlockup_all_cpu_backtrace_setup(char *str)
173 return 1; 176 return 1;
174} 177}
175__setup("softlockup_all_cpu_backtrace=", softlockup_all_cpu_backtrace_setup); 178__setup("softlockup_all_cpu_backtrace=", softlockup_all_cpu_backtrace_setup);
179static int __init hardlockup_all_cpu_backtrace_setup(char *str)
180{
181 sysctl_hardlockup_all_cpu_backtrace =
182 !!simple_strtol(str, NULL, 0);
183 return 1;
184}
185__setup("hardlockup_all_cpu_backtrace=", hardlockup_all_cpu_backtrace_setup);
176#endif 186#endif
177 187
178/* 188/*
@@ -318,17 +328,30 @@ static void watchdog_overflow_callback(struct perf_event *event,
318 */ 328 */
319 if (is_hardlockup()) { 329 if (is_hardlockup()) {
320 int this_cpu = smp_processor_id(); 330 int this_cpu = smp_processor_id();
331 struct pt_regs *regs = get_irq_regs();
321 332
322 /* only print hardlockups once */ 333 /* only print hardlockups once */
323 if (__this_cpu_read(hard_watchdog_warn) == true) 334 if (__this_cpu_read(hard_watchdog_warn) == true)
324 return; 335 return;
325 336
326 if (hardlockup_panic) 337 pr_emerg("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
327 panic("Watchdog detected hard LOCKUP on cpu %d", 338 print_modules();
328 this_cpu); 339 print_irqtrace_events(current);
340 if (regs)
341 show_regs(regs);
329 else 342 else
330 WARN(1, "Watchdog detected hard LOCKUP on cpu %d", 343 dump_stack();
331 this_cpu); 344
345 /*
346 * Perform all-CPU dump only once to avoid multiple hardlockups
347 * generating interleaving traces
348 */
349 if (sysctl_hardlockup_all_cpu_backtrace &&
350 !test_and_set_bit(0, &hardlockup_allcpu_dumped))
351 trigger_allbutself_cpu_backtrace();
352
353 if (hardlockup_panic)
354 panic("Hard LOCKUP");
332 355
333 __this_cpu_write(hard_watchdog_warn, true); 356 __this_cpu_write(hard_watchdog_warn, true);
334 return; 357 return;