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