diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
-rw-r--r-- | Documentation/sysctl/kernel.txt | 12 | ||||
-rw-r--r-- | include/linux/nmi.h | 1 | ||||
-rw-r--r-- | kernel/sysctl.c | 9 | ||||
-rw-r--r-- | kernel/watchdog.c | 33 |
5 files changed, 55 insertions, 5 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 6263a2da3e2f..0231f4508abe 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1269,6 +1269,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
1269 | Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0. | 1269 | Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0. |
1270 | Default: 1024 | 1270 | Default: 1024 |
1271 | 1271 | ||
1272 | hardlockup_all_cpu_backtrace= | ||
1273 | [KNL] Should the hard-lockup detector generate | ||
1274 | backtraces on all cpus. | ||
1275 | Format: <integer> | ||
1276 | |||
1272 | hashdist= [KNL,NUMA] Large hashes allocated during boot | 1277 | hashdist= [KNL,NUMA] Large hashes allocated during boot |
1273 | are distributed across NUMA nodes. Defaults on | 1278 | are distributed across NUMA nodes. Defaults on |
1274 | for 64-bit NUMA, off otherwise. | 1279 | for 64-bit NUMA, off otherwise. |
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 6fccb69c03e7..af70d1541d3a 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt | |||
@@ -33,6 +33,7 @@ show up in /proc/sys/kernel: | |||
33 | - domainname | 33 | - domainname |
34 | - hostname | 34 | - hostname |
35 | - hotplug | 35 | - hotplug |
36 | - hardlockup_all_cpu_backtrace | ||
36 | - hung_task_panic | 37 | - hung_task_panic |
37 | - hung_task_check_count | 38 | - hung_task_check_count |
38 | - hung_task_timeout_secs | 39 | - hung_task_timeout_secs |
@@ -293,6 +294,17 @@ domain names are in general different. For a detailed discussion | |||
293 | see the hostname(1) man page. | 294 | see the hostname(1) man page. |
294 | 295 | ||
295 | ============================================================== | 296 | ============================================================== |
297 | hardlockup_all_cpu_backtrace: | ||
298 | |||
299 | This value controls the hard lockup detector behavior when a hard | ||
300 | lockup condition is detected as to whether or not to gather further | ||
301 | debug information. If enabled, arch-specific all-CPU stack dumping | ||
302 | will be initiated. | ||
303 | |||
304 | 0: do nothing. This is the default behavior. | ||
305 | |||
306 | 1: on detection capture more debug information. | ||
307 | ============================================================== | ||
296 | 308 | ||
297 | hotplug: | 309 | hotplug: |
298 | 310 | ||
diff --git a/include/linux/nmi.h b/include/linux/nmi.h index 78488e099ce7..7ec5b86735f3 100644 --- a/include/linux/nmi.h +++ b/include/linux/nmi.h | |||
@@ -73,6 +73,7 @@ extern int watchdog_user_enabled; | |||
73 | extern int watchdog_thresh; | 73 | extern int watchdog_thresh; |
74 | extern unsigned long *watchdog_cpumask_bits; | 74 | extern unsigned long *watchdog_cpumask_bits; |
75 | extern int sysctl_softlockup_all_cpu_backtrace; | 75 | extern int sysctl_softlockup_all_cpu_backtrace; |
76 | extern int sysctl_hardlockup_all_cpu_backtrace; | ||
76 | struct ctl_table; | 77 | struct ctl_table; |
77 | extern int proc_watchdog(struct ctl_table *, int , | 78 | extern int proc_watchdog(struct ctl_table *, int , |
78 | void __user *, size_t *, loff_t *); | 79 | void __user *, size_t *, loff_t *); |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 96c856b04081..1a5faa3e1521 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -898,6 +898,15 @@ static struct ctl_table kern_table[] = { | |||
898 | .extra1 = &zero, | 898 | .extra1 = &zero, |
899 | .extra2 = &one, | 899 | .extra2 = &one, |
900 | }, | 900 | }, |
901 | { | ||
902 | .procname = "hardlockup_all_cpu_backtrace", | ||
903 | .data = &sysctl_hardlockup_all_cpu_backtrace, | ||
904 | .maxlen = sizeof(int), | ||
905 | .mode = 0644, | ||
906 | .proc_handler = proc_dointvec_minmax, | ||
907 | .extra1 = &zero, | ||
908 | .extra2 = &one, | ||
909 | }, | ||
901 | #endif /* CONFIG_SMP */ | 910 | #endif /* CONFIG_SMP */ |
902 | #endif | 911 | #endif |
903 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) | 912 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) |
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 |
59 | int __read_mostly sysctl_softlockup_all_cpu_backtrace; | 59 | int __read_mostly sysctl_softlockup_all_cpu_backtrace; |
60 | int __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 |
63 | static struct cpumask watchdog_cpumask __read_mostly; | 65 | static struct cpumask watchdog_cpumask __read_mostly; |
64 | unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask); | 66 | unsigned 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 |
113 | static int hardlockup_panic = | 115 | static int hardlockup_panic = |
114 | CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE; | 116 | CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE; |
117 | static 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); |
179 | static 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; |