Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

watchdog: enable the new user interface of the watchdog mechanism

With the current user interface of the watchdog mechanism it is only
possible to disable or enable both lockup detectors at the same time.
This series introduces new kernel parameters and changes the semantics of
some existing kernel parameters, so that the hard lockup detector and the
soft lockup detector can be disabled or enabled individually. With this
series applied, the user interface is as follows.

- parameters in /proc/sys/kernel

. soft_watchdog
This is a new parameter to control and examine the run state of
the soft lockup detector.

. nmi_watchdog
The semantics of this parameter have changed. It can now be used
to control and examine the run state of the hard lockup detector.

. watchdog
This parameter is still available to control the run state of both
lockup detectors at the same time. If this parameter is examined,
it shows the logical OR of soft_watchdog and nmi_watchdog.

. watchdog_thresh
The semantics of this parameter are not affected by the patch.

- kernel command line parameters

. nosoftlockup
The semantics of this parameter have changed. It can now be used
to disable the soft lockup detector at boot time.

. nmi_watchdog=0 or nmi_watchdog=1
Disable or enable the hard lockup detector at boot time. The patch
introduces '=1' as a new option.

. nowatchdog
The semantics of this parameter are not affected by the patch. It
is still available to disable both lockup detectors at boot time.

Also, remove the proc_dowatchdog() function which is no longer needed.

[dzickus@redhat.com: wrote changelog]
[dzickus@redhat.com: update documentation for kernel params and sysctl]
Signed-off-by: Ulrich Obergfell <uobergfe@redhat.com>
Signed-off-by: Don Zickus <dzickus@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Ulrich Obergfell and committed by
Linus Torvalds
195daf66 bcfba4f4

+97 -89
+4 -2
Documentation/kernel-parameters.txt
··· 2236 2236 2237 2237 nmi_watchdog= [KNL,BUGS=X86] Debugging features for SMP kernels 2238 2238 Format: [panic,][nopanic,][num] 2239 - Valid num: 0 2239 + Valid num: 0 or 1 2240 2240 0 - turn nmi_watchdog off 2241 + 1 - turn nmi_watchdog on 2241 2242 When panic is specified, panic when an NMI watchdog 2242 2243 timeout occurs (or 'nopanic' to override the opposite 2243 2244 default). ··· 2465 2464 2466 2465 nousb [USB] Disable the USB subsystem 2467 2466 2468 - nowatchdog [KNL] Disable the lockup detector (NMI watchdog). 2467 + nowatchdog [KNL] Disable both lockup detectors, i.e. 2468 + soft-lockup and NMI watchdog (hard-lockup). 2469 2469 2470 2470 nowb [ARM] 2471 2471
+53 -9
Documentation/sysctl/kernel.txt
··· 77 77 - shmmax [ sysv ipc ] 78 78 - shmmni 79 79 - softlockup_all_cpu_backtrace 80 + - soft_watchdog 80 81 - stop-a [ SPARC only ] 81 82 - sysrq ==> Documentation/sysrq.txt 82 83 - sysctl_writes_strict 83 84 - tainted 84 85 - threads-max 85 86 - unknown_nmi_panic 87 + - watchdog 86 88 - watchdog_thresh 87 89 - version 88 90 ··· 419 417 420 418 nmi_watchdog: 421 419 422 - Enables/Disables the NMI watchdog on x86 systems. When the value is 423 - non-zero the NMI watchdog is enabled and will continuously test all 424 - online cpus to determine whether or not they are still functioning 425 - properly. Currently, passing "nmi_watchdog=" parameter at boot time is 426 - required for this function to work. 420 + This parameter can be used to control the NMI watchdog 421 + (i.e. the hard lockup detector) on x86 systems. 427 422 428 - If LAPIC NMI watchdog method is in use (nmi_watchdog=2 kernel 429 - parameter), the NMI watchdog shares registers with oprofile. By 430 - disabling the NMI watchdog, oprofile may have more registers to 431 - utilize. 423 + 0 - disable the hard lockup detector 424 + 1 - enable the hard lockup detector 425 + 426 + The hard lockup detector monitors each CPU for its ability to respond to 427 + timer interrupts. The mechanism utilizes CPU performance counter registers 428 + that are programmed to generate Non-Maskable Interrupts (NMIs) periodically 429 + while a CPU is busy. Hence, the alternative name 'NMI watchdog'. 430 + 431 + The NMI watchdog is disabled by default if the kernel is running as a guest 432 + in a KVM virtual machine. This default can be overridden by adding 433 + 434 + nmi_watchdog=1 435 + 436 + to the guest kernel command line (see Documentation/kernel-parameters.txt). 432 437 433 438 ============================================================== 434 439 ··· 825 816 826 817 ============================================================== 827 818 819 + soft_watchdog 820 + 821 + This parameter can be used to control the soft lockup detector. 822 + 823 + 0 - disable the soft lockup detector 824 + 1 - enable the soft lockup detector 825 + 826 + The soft lockup detector monitors CPUs for threads that are hogging the CPUs 827 + without rescheduling voluntarily, and thus prevent the 'watchdog/N' threads 828 + from running. The mechanism depends on the CPUs ability to respond to timer 829 + interrupts which are needed for the 'watchdog/N' threads to be woken up by 830 + the watchdog timer function, otherwise the NMI watchdog - if enabled - can 831 + detect a hard lockup condition. 832 + 833 + ============================================================== 834 + 828 835 tainted: 829 836 830 837 Non-zero if the kernel has been tainted. Numeric values, which ··· 880 855 881 856 NMI switch that most IA32 servers have fires unknown NMI up, for 882 857 example. If a system hangs up, try pressing the NMI switch. 858 + 859 + ============================================================== 860 + 861 + watchdog: 862 + 863 + This parameter can be used to disable or enable the soft lockup detector 864 + _and_ the NMI watchdog (i.e. the hard lockup detector) at the same time. 865 + 866 + 0 - disable both lockup detectors 867 + 1 - enable both lockup detectors 868 + 869 + The soft lockup detector and the NMI watchdog can also be disabled or 870 + enabled individually, using the soft_watchdog and nmi_watchdog parameters. 871 + If the watchdog parameter is read, for example by executing 872 + 873 + cat /proc/sys/kernel/watchdog 874 + 875 + the output of this command (0 or 1) shows the logical OR of soft_watchdog 876 + and nmi_watchdog. 883 877 884 878 ============================================================== 885 879
-2
include/linux/nmi.h
··· 82 82 void __user *, size_t *, loff_t *); 83 83 extern int proc_watchdog_thresh(struct ctl_table *, int , 84 84 void __user *, size_t *, loff_t *); 85 - extern int proc_dowatchdog(struct ctl_table *, int , 86 - void __user *, size_t *, loff_t *); 87 85 #endif 88 86 89 87 #ifdef CONFIG_HAVE_ACPI_APEI_NMI
+24 -11
kernel/sysctl.c
··· 846 846 .data = &watchdog_user_enabled, 847 847 .maxlen = sizeof (int), 848 848 .mode = 0644, 849 - .proc_handler = proc_dowatchdog, 849 + .proc_handler = proc_watchdog, 850 850 .extra1 = &zero, 851 851 .extra2 = &one, 852 852 }, ··· 855 855 .data = &watchdog_thresh, 856 856 .maxlen = sizeof(int), 857 857 .mode = 0644, 858 - .proc_handler = proc_dowatchdog, 858 + .proc_handler = proc_watchdog_thresh, 859 859 .extra1 = &zero, 860 860 .extra2 = &sixty, 861 + }, 862 + { 863 + .procname = "nmi_watchdog", 864 + .data = &nmi_watchdog_enabled, 865 + .maxlen = sizeof (int), 866 + .mode = 0644, 867 + .proc_handler = proc_nmi_watchdog, 868 + .extra1 = &zero, 869 + #if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR) 870 + .extra2 = &one, 871 + #else 872 + .extra2 = &zero, 873 + #endif 874 + }, 875 + { 876 + .procname = "soft_watchdog", 877 + .data = &soft_watchdog_enabled, 878 + .maxlen = sizeof (int), 879 + .mode = 0644, 880 + .proc_handler = proc_soft_watchdog, 881 + .extra1 = &zero, 882 + .extra2 = &one, 861 883 }, 862 884 { 863 885 .procname = "softlockup_panic", ··· 901 879 .extra2 = &one, 902 880 }, 903 881 #endif /* CONFIG_SMP */ 904 - { 905 - .procname = "nmi_watchdog", 906 - .data = &watchdog_user_enabled, 907 - .maxlen = sizeof (int), 908 - .mode = 0644, 909 - .proc_handler = proc_dowatchdog, 910 - .extra1 = &zero, 911 - .extra2 = &one, 912 - }, 913 882 #endif 914 883 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) 915 884 {
+16 -65
kernel/watchdog.c
··· 110 110 else if (!strncmp(str, "nopanic", 7)) 111 111 hardlockup_panic = 0; 112 112 else if (!strncmp(str, "0", 1)) 113 - watchdog_user_enabled = 0; 114 - else if (!strncmp(str, "1", 1) || !strncmp(str, "2", 1)) { 115 - /* 116 - * Setting 'nmi_watchdog=1' or 'nmi_watchdog=2' (legacy option) 117 - * has the same effect. 118 - */ 119 - watchdog_user_enabled = 1; 120 - watchdog_enable_hardlockup_detector(true); 121 - } 113 + watchdog_enabled &= ~NMI_WATCHDOG_ENABLED; 114 + else if (!strncmp(str, "1", 1)) 115 + watchdog_enabled |= NMI_WATCHDOG_ENABLED; 122 116 return 1; 123 117 } 124 118 __setup("nmi_watchdog=", hardlockup_panic_setup); ··· 131 137 132 138 static int __init nowatchdog_setup(char *str) 133 139 { 134 - watchdog_user_enabled = 0; 140 + watchdog_enabled = 0; 135 141 return 1; 136 142 } 137 143 __setup("nowatchdog", nowatchdog_setup); 138 144 139 - /* deprecated */ 140 145 static int __init nosoftlockup_setup(char *str) 141 146 { 142 - watchdog_user_enabled = 0; 147 + watchdog_enabled &= ~SOFT_WATCHDOG_ENABLED; 143 148 return 1; 144 149 } 145 150 __setup("nosoftlockup", nosoftlockup_setup); 146 - /* */ 151 + 147 152 #ifdef CONFIG_SMP 148 153 static int __init softlockup_all_cpu_backtrace_setup(char *str) 149 154 { ··· 257 264 { 258 265 unsigned long now = get_timestamp(); 259 266 260 - /* Warn about unreasonable delays: */ 261 - if (time_after(now, touch_ts + get_softlockup_thresh())) 262 - return now - touch_ts; 263 - 267 + if (watchdog_enabled & SOFT_WATCHDOG_ENABLED) { 268 + /* Warn about unreasonable delays. */ 269 + if (time_after(now, touch_ts + get_softlockup_thresh())) 270 + return now - touch_ts; 271 + } 264 272 return 0; 265 273 } 266 274 ··· 525 531 { 526 532 struct perf_event_attr *wd_attr; 527 533 struct perf_event *event = per_cpu(watchdog_ev, cpu); 534 + 535 + /* nothing to do if the hard lockup detector is disabled */ 536 + if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED)) 537 + goto out; 528 538 529 539 /* 530 540 * Some kernels need to default hard lockup detection to ··· 854 856 mutex_unlock(&watchdog_proc_mutex); 855 857 return err; 856 858 } 857 - 858 - /* 859 - * proc handler for /proc/sys/kernel/nmi_watchdog,watchdog_thresh 860 - */ 861 - 862 - int proc_dowatchdog(struct ctl_table *table, int write, 863 - void __user *buffer, size_t *lenp, loff_t *ppos) 864 - { 865 - int err, old_thresh, old_enabled; 866 - bool old_hardlockup; 867 - 868 - mutex_lock(&watchdog_proc_mutex); 869 - old_thresh = ACCESS_ONCE(watchdog_thresh); 870 - old_enabled = ACCESS_ONCE(watchdog_user_enabled); 871 - old_hardlockup = watchdog_hardlockup_detector_is_enabled(); 872 - 873 - err = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 874 - if (err || !write) 875 - goto out; 876 - 877 - set_sample_period(); 878 - /* 879 - * Watchdog threads shouldn't be enabled if they are 880 - * disabled. The 'watchdog_running' variable check in 881 - * watchdog_*_all_cpus() function takes care of this. 882 - */ 883 - if (watchdog_user_enabled && watchdog_thresh) { 884 - /* 885 - * Prevent a change in watchdog_thresh accidentally overriding 886 - * the enablement of the hardlockup detector. 887 - */ 888 - if (watchdog_user_enabled != old_enabled) 889 - watchdog_enable_hardlockup_detector(true); 890 - err = watchdog_enable_all_cpus(old_thresh != watchdog_thresh); 891 - } else 892 - watchdog_disable_all_cpus(); 893 - 894 - /* Restore old values on failure */ 895 - if (err) { 896 - watchdog_thresh = old_thresh; 897 - watchdog_user_enabled = old_enabled; 898 - watchdog_enable_hardlockup_detector(old_hardlockup); 899 - } 900 - out: 901 - mutex_unlock(&watchdog_proc_mutex); 902 - return err; 903 - } 904 859 #endif /* CONFIG_SYSCTL */ 905 860 906 861 void __init lockup_detector_init(void) 907 862 { 908 863 set_sample_period(); 909 864 910 - if (watchdog_user_enabled) 865 + if (watchdog_enabled) 911 866 watchdog_enable_all_cpus(false); 912 867 }