|
@@ -846,6 +846,58 @@ static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * proc handler for /proc/sys/kernel/nmi_watchdog
|
|
|
+ */
|
|
|
+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_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 (atomic_read(&nmi_active) < 0) {
|
|
|
+ printk(KERN_WARNING "NMI watchdog is permanently disabled\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nmi_watchdog == NMI_DEFAULT) {
|
|
|
+ if (nmi_known_cpu() > 0)
|
|
|
+ nmi_watchdog = NMI_LOCAL_APIC;
|
|
|
+ else
|
|
|
+ nmi_watchdog = NMI_IO_APIC;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nmi_watchdog == NMI_LOCAL_APIC)
|
|
|
+ {
|
|
|
+ if (nmi_watchdog_enabled)
|
|
|
+ enable_lapic_nmi_watchdog();
|
|
|
+ else
|
|
|
+ disable_lapic_nmi_watchdog();
|
|
|
+ } else if (nmi_watchdog == NMI_IO_APIC) {
|
|
|
+ /* FIXME
|
|
|
+ * for some reason these functions don't work
|
|
|
+ */
|
|
|
+ printk("Can not enable/disable NMI on IO APIC\n");
|
|
|
+ return -EINVAL;
|
|
|
+#if 0
|
|
|
+ if (nmi_watchdog_enabled)
|
|
|
+ enable_timer_nmi_watchdog();
|
|
|
+ else
|
|
|
+ disable_timer_nmi_watchdog();
|
|
|
+#endif
|
|
|
+ } else {
|
|
|
+ printk( KERN_WARNING
|
|
|
+ "NMI watchdog doesn't know what hardware to touch\n");
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
#endif
|
|
|
|
|
|
EXPORT_SYMBOL(nmi_active);
|