linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Corey Minyard <cminyard@mvista.com>
To: linux-kernel@vger.kernel.org
Subject: [PATCH] NMI request/release
Date: Mon, 21 Oct 2002 20:32:47 -0500	[thread overview]
Message-ID: <3DB4AABF.9020400@mvista.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 518 bytes --]

The attached patch implements a way to request to receive an NMI if it 
comes from an otherwise unknown source.  I needed this for handling NMIs 
with the IPMI watchdog.  This function was discussed a little a while 
back on the mailing list, but nothing was done about it, so I 
implemented a request/release for NMIs.  The code is in 
arch/i386/kernel/traps.c, but it's pretty generic and could possibly 
live in kernel.  I'm not sure, though.

This is relative to 2.5.44.  I have a 2.4 version of it, too.

-Corey


[-- Attachment #2: linux-nmi.diff --]
[-- Type: text/plain, Size: 4761 bytes --]

diff -urN linux.orig/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- linux.orig/arch/i386/kernel/i386_ksyms.c	Mon Oct 21 13:25:58 2002
+++ linux/arch/i386/kernel/i386_ksyms.c	Mon Oct 21 20:04:35 2002
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/tty.h>
+#include <linux/nmi.h>
 #include <linux/highmem.h>
 
 #include <asm/semaphore.h>
@@ -89,6 +90,9 @@
 EXPORT_SYMBOL(get_cmos_time);
 EXPORT_SYMBOL(cpu_khz);
 EXPORT_SYMBOL(apm_info);
+
+EXPORT_SYMBOL(request_nmi);
+EXPORT_SYMBOL(release_nmi);
 
 #ifdef CONFIG_DEBUG_IOVIRT
 EXPORT_SYMBOL(__io_virt_debug);
diff -urN linux.orig/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- linux.orig/arch/i386/kernel/traps.c	Mon Oct 21 13:25:45 2002
+++ linux/arch/i386/kernel/traps.c	Mon Oct 21 20:06:43 2002
@@ -485,6 +485,95 @@
 	printk("Do you have a strange power saving mode enabled?\n");
 }
 
+/* A list of handlers for NMIs.  This list will be called in order
+   when an NMI from an otherwise unidentifiable source somes in.  If
+   one of these handles the NMI, it should return 1.  NMI handlers
+   cannot claim spinlocks, so we have to handle mutex in a different
+   manner.  A spinlock protects the list from multiple writers.  When
+   something is removed from the list, it will check to see that
+   calling_nmi_handlers is 0 before returning.  If it is not zero,
+   another processor is handling an NMI, and it should wait until it
+   goes to zero to return and allow the user to free that data. */
+static volatile struct nmi_handler *nmi_handler_list = NULL;
+static spinlock_t                  nmi_handler_lock = SPIN_LOCK_UNLOCKED;
+static atomic_t                    calling_nmi_handlers = ATOMIC_INIT(0);
+
+int request_nmi(struct nmi_handler *handler)
+{
+	volatile struct nmi_handler *curr;
+
+	spin_lock(&nmi_handler_lock);
+
+	/* Make sure the thing is not already in the list. */
+	curr = nmi_handler_list;
+	while (curr) {
+		if (curr == handler) {
+			break;
+		}
+		curr = curr->next;
+	}
+	if (curr)
+		return EBUSY;
+
+	handler->next = nmi_handler_list;
+	xchg(&nmi_handler_list, handler);
+
+	spin_unlock(&nmi_handler_lock);
+	return 0;
+}
+
+void release_nmi(struct nmi_handler *handler)
+{
+	volatile struct nmi_handler *curr, *prev;
+
+	spin_lock(&nmi_handler_lock);
+
+	/* Find it in the list. */
+	curr = nmi_handler_list;
+	prev = NULL;
+	while (curr) {
+		if (curr == handler) {
+			break;
+		}
+		prev = curr;
+		curr = curr->next;
+	}
+
+	if (curr) {
+		/* If it was found, remove it from the list.  We
+                   assume the write operation here is atomic. */
+		if (prev)
+			xchg(&(prev->next), curr->next);
+		else
+			xchg(&nmi_handler_list, curr->next);
+
+		/* If some other part of the kernel is handling an
+		   NMI, we make sure that we don't release the handler
+		   (or really, allow the user to release the handler)
+		   until it has finished handling the NMI. */
+		while (atomic_read(&calling_nmi_handlers))
+			;
+	}
+	spin_unlock(&nmi_handler_lock);
+}
+
+static int call_nmi_handlers(struct pt_regs * regs)
+{
+	volatile struct nmi_handler *curr;
+	int                         handled = 0;
+
+	atomic_inc(&calling_nmi_handlers);
+	smp_mb();
+	curr = nmi_handler_list;
+	while (curr) {
+		handled |= curr->handler(curr->dev_id, regs);
+		curr = curr->next;
+	}
+	smp_mb();
+	atomic_dec(&calling_nmi_handlers);
+	return handled;
+}
+
 static void default_do_nmi(struct pt_regs * regs)
 {
 	unsigned char reason = inb(0x61);
@@ -500,6 +589,12 @@
 			return;
 		}
 #endif
+
+		/* Check our handler list to see if anyone can handle this
+		   nmi. */
+		if (call_nmi_handlers(regs))
+			return;
+
 		unknown_nmi_error(reason, regs);
 		return;
 	}
diff -urN linux.orig/include/asm-i386/irq.h linux/include/asm-i386/irq.h
--- linux.orig/include/asm-i386/irq.h	Mon Oct 21 13:24:41 2002
+++ linux/include/asm-i386/irq.h	Mon Oct 21 20:03:52 2002
@@ -28,4 +28,16 @@
 #define ARCH_HAS_NMI_WATCHDOG		/* See include/linux/nmi.h */
 #endif
 
+
+/* Structure for handling NMIs */
+#define HAVE_NMI_HANDLER	1
+struct nmi_handler
+{
+	char *dev_name;
+	void *dev_id;
+	int  (*handler)(void *dev_id, struct pt_regs *regs);
+
+	volatile struct nmi_handler *next;
+};
+
 #endif /* _ASM_IRQ_H */
diff -urN linux.orig/include/linux/nmi.h linux/include/linux/nmi.h
--- linux.orig/include/linux/nmi.h	Thu Jun 20 17:53:40 2002
+++ linux/include/linux/nmi.h	Mon Oct 21 20:03:53 2002
@@ -19,4 +19,11 @@
 # define touch_nmi_watchdog() do { } while(0)
 #endif
 
+/**
+ * Register a handler to get called when an NMI occurs.  If the handler
+ * actually handles the NMI, it should return 1.
+ */
+int request_nmi(struct nmi_handler *handler);
+void release_nmi(struct nmi_handler *handler);
+
 #endif

             reply	other threads:[~2002-10-22  1:26 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-10-22  1:32 Corey Minyard [this message]
2002-10-22  2:10 ` [PATCH] NMI request/release John Levon
2002-10-22  2:32   ` Corey Minyard
2002-10-22  2:53     ` John Levon
2002-10-22 13:02       ` Corey Minyard
2002-10-22 15:09         ` John Levon
2002-10-22 16:03           ` Corey Minyard
2002-10-22 17:23         ` Robert Love
2002-10-22 18:08           ` Corey Minyard
2002-10-22 18:16             ` Robert Love
2002-10-22 20:04             ` Dipankar Sarma
2002-10-22 17:53         ` Dipankar Sarma
2002-10-22 18:05           ` Corey Minyard
2002-10-22 18:08             ` Dipankar Sarma
2002-10-22 18:29               ` Corey Minyard
2002-10-22 19:08                 ` John Levon
2002-10-22 21:36                   ` [PATCH] NMI request/release, version 3 Corey Minyard
2002-10-23 17:33                     ` Dipankar Sarma
2002-10-23 18:03                       ` Corey Minyard
2002-10-23 18:57                         ` Dipankar Sarma
2002-10-23 20:14                           ` [PATCH] NMI request/release, version 4 Corey Minyard
2002-10-23 20:50                             ` Dipankar Sarma
2002-10-23 21:53                               ` Corey Minyard
2002-10-24  7:41                                 ` Dipankar Sarma
2002-10-24 13:08                                   ` Corey Minyard
2002-10-24  7:50                             ` Dipankar Sarma
2002-10-24 13:05                               ` Corey Minyard
2002-10-24 13:28                               ` [PATCH] NMI request/release, version 5 - I think this one's ready Corey Minyard
2002-10-24 14:46                                 ` John Levon
2002-10-24 15:36                                   ` Corey Minyard
2002-10-24 17:18                                     ` John Levon
2002-10-24 17:43                                       ` Corey Minyard
2002-10-24 18:04                                         ` John Levon
2002-10-24 18:32                                           ` Corey Minyard
2002-10-24 18:47                                             ` John Levon
2002-10-24 20:03                                       ` Corey Minyard
2002-10-24 20:29                                         ` John Levon
2002-10-25  1:22                                           ` [PATCH] NMI request/release, version 6 - "Well I thought the last one was ready" Corey Minyard
2002-10-25  1:39                                             ` John Levon
2002-10-25  1:58                                               ` Jeff Garzik
2002-10-25  2:01                                               ` [PATCH] NMI request/release, version 7 - minor cleanups Corey Minyard
2002-10-25 13:26                                                 ` [PATCH] NMI request/release, version 8 Corey Minyard
2002-10-22 12:23   ` [PATCH] NMI request/release Suparna Bhattacharya

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3DB4AABF.9020400@mvista.com \
    --to=cminyard@mvista.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).