All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.