Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2048

kernel-2.6.18-238.el5.src.rpm

From: Don Zickus <dzickus@redhat.com>
Date: Mon, 10 May 2010 16:13:22 -0400
Subject: [misc] nmi_watchdog: add /proc/sys/kernel/nmi_watchdog
Message-id: <1273508002-2207-1-git-send-email-dzickus@redhat.com>
Patchwork-id: 24925
O-Subject: [RHEL-6 PATCH] [x86] nmi_watchdog: add /proc/sys/kernel/nmi_watchdog
Bugzilla: 455323
RH-Acked-by: Jarod Wilson <jarod@redhat.com>

https://bugzilla.redhat.com/show_bug.cgi?id=455323

Upstream added this /proc command a long time ago to easily turn
nmi_watchdog on and off.  RHEL-5 doesn't have this ability and some
scripts would like to use this to make it easy to port between
RHEL-5, RHEL-6 and upstream.

The support was easy enough to add.

Tested on x86_64 and i386 both bare-metal and FV guests.

Please ACK.

Signed-off-by: Don Zickus <dzickus@redhat.com>

diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 8a17646..8a948b1 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -30,6 +30,7 @@
 
 unsigned int nmi_watchdog = NMI_NONE;
 int unknown_nmi_panic;
+int nmi_watchdog_enabled;
 static unsigned int nmi_hz = HZ;
 extern void show_registers(struct pt_regs *regs);
 
@@ -457,6 +458,35 @@ int proc_unknown_nmi_panic(ctl_table *table, int write, struct file *file,
 	return 0;
 }
 
+/*
+ * proc handler for /proc/sys/kernel/nmi_watchdog
+ */
+int proc_nmi_enabled(ctl_table *table, int write, struct file *file,
+			void __user *buffer, size_t *length, loff_t *ppos)
+{
+	int old_state;
+
+	nmi_watchdog_enabled = (atomic_read(&nmi_watchdog_active) > 0) ? 1 : 0;
+	old_state = nmi_watchdog_enabled;
+	proc_dointvec(table, write, file, buffer, length, ppos);
+	if (!!old_state == !!nmi_watchdog_enabled)
+		return 0;
+
+	if (nmi_watchdog_enabled) {
+		if (nmi_watchdog == NMI_LOCAL_APIC)
+			enable_lapic_nmi_watchdog();
+		else if (nmi_watchdog == NMI_IO_APIC)
+			acpi_nmi_enable();
+	} else {
+		if (nmi_watchdog == NMI_LOCAL_APIC)
+			disable_lapic_nmi_watchdog();
+		else if (nmi_watchdog == NMI_IO_APIC)
+			acpi_nmi_disable();
+	}
+
+	return 0;
+}
+
 #endif
 
 EXPORT_SYMBOL(nmi_active);
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 638aa5f..cb6f1ca 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -29,6 +29,7 @@
 #include <asm/intel_arch_perfmon.h>
 
 int unknown_nmi_panic;
+int nmi_watchdog_enabled;
 int panic_on_unrecovered_nmi;
 static atomic_t lapic_nmi_reserved = ATOMIC_INIT(0);
 
@@ -506,6 +507,35 @@ int proc_unknown_nmi_panic(struct ctl_table *table, int write, struct file *file
 	return 0;
 }
 
+/*
+ * proc handler for /proc/sys/kernel/nmi_enabled
+ */
+int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
+			void __user *buffer, size_t *length, loff_t *ppos)
+{
+	int old_state;
+
+	nmi_watchdog_enabled = (atomic_read(&nmi_watchdog_active) > 0) ? 1 : 0;
+	old_state = nmi_watchdog_enabled;
+	proc_dointvec(table, write, file, buffer, length, ppos);
+	if (!!old_state == !!nmi_watchdog_enabled)
+		return 0;
+
+	if (nmi_watchdog_enabled) {
+		if (nmi_watchdog == NMI_LOCAL_APIC)
+			enable_lapic_nmi_watchdog();
+		else if (nmi_watchdog == NMI_IO_APIC)
+			acpi_nmi_enable();
+	} else {
+		if (nmi_watchdog == NMI_LOCAL_APIC)
+			disable_lapic_nmi_watchdog();
+		else if (nmi_watchdog == NMI_IO_APIC)
+			acpi_nmi_disable();
+	}
+
+	return 0;
+}
+
 #endif
 
 EXPORT_SYMBOL(nmi_active);
diff --git a/include/asm-i386/nmi.h b/include/asm-i386/nmi.h
index 48edc43..9ce2f8d 100644
--- a/include/asm-i386/nmi.h
+++ b/include/asm-i386/nmi.h
@@ -63,5 +63,6 @@ extern unsigned int nmi_watchdog;
 #define NMI_INVALID	3
 
 extern int unknown_nmi_panic;
+extern int nmi_watchdog_enabled;
 
 #endif /* ASM_NMI_H */
diff --git a/include/asm-x86_64/mach-xen/asm/nmi.h b/include/asm-x86_64/mach-xen/asm/nmi.h
index cc2b01b..1bb3bc2 100644
--- a/include/asm-x86_64/mach-xen/asm/nmi.h
+++ b/include/asm-x86_64/mach-xen/asm/nmi.h
@@ -70,6 +70,7 @@ static inline unsigned char get_nmi_reason(void)
 
 extern int panic_on_timeout;
 extern int unknown_nmi_panic;
+extern int nmi_watchdog_enabled;
 
 void lapic_watchdog_stop(void);
 int lapic_watchdog_probe(void);
diff --git a/include/asm-x86_64/nmi.h b/include/asm-x86_64/nmi.h
index 7d82b1a..d696395 100644
--- a/include/asm-x86_64/nmi.h
+++ b/include/asm-x86_64/nmi.h
@@ -62,6 +62,7 @@ extern void die_nmi(char *str, struct pt_regs *regs);
 
 extern int panic_on_timeout;
 extern int unknown_nmi_panic;
+extern int nmi_watchdog_enabled;
 
 extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
 extern int avail_to_resrv_perfctr_nmi(unsigned int);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index adfb1c9..5b302a0 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -165,6 +165,7 @@ enum
 	KERN_HUNG_TASK_CHECK_COUNT=83,
 	KERN_HUNG_TASK_TIMEOUT_SECS=84,
 	KERN_HUNG_TASK_WARNINGS=85,
+	KERN_NMI_WATCHDOG=86,
 };
 
 
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 494f90b..aa705cf 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -88,6 +88,8 @@ extern int vm_devzero_optimized;
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
 extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *,
 				  void __user *, size_t *, loff_t *);
+extern int proc_nmi_enabled(ctl_table *, int, struct file *,
+				  void __user *, size_t *, loff_t *);
 #endif
 
 #ifdef CONFIG_DETECT_SOFTLOCKUP
@@ -748,6 +750,14 @@ static ctl_table kern_table[] = {
 		.mode           = 0644,
 		.proc_handler   = &proc_unknown_nmi_panic,
 	},
+	{
+		.ctl_name       = KERN_NMI_WATCHDOG,
+		.procname       = "nmi_watchdog",
+		.data           = &nmi_watchdog_enabled,
+		.maxlen         = sizeof (int),
+		.mode           = 0644,
+		.proc_handler   = &proc_nmi_enabled,
+	},
 #endif
 #if defined(CONFIG_X86)
 	{