aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/nmi.c
diff options
context:
space:
mode:
authorIan.Campbell@xensource.com <Ian.Campbell@xensource.com>2006-01-13 14:59:40 +0000
committerIan.Campbell@xensource.com <Ian.Campbell@xensource.com>2006-01-13 14:59:40 +0000
commit82f5d7e034952c4c035682c4ba8ed74158234e14 (patch)
tree56f9c0e34e0c47aa97ebfcaf8e9d4b2166761113 /xen/arch/x86/nmi.c
parent723bbd528ff0bcfb7c8dda05486aa69fbf0080f3 (diff)
downloadxen-82f5d7e034952c4c035682c4ba8ed74158234e14.tar.gz
xen-82f5d7e034952c4c035682c4ba8ed74158234e14.tar.bz2
xen-82f5d7e034952c4c035682c4ba8ed74158234e14.zip
Debug keyhandlers for triggering an NMI and examine current NMI state.
Add 'N' keyhandler to dump the current per CPU NMI counts and the current NMI mask/pending status. Add 'n' keyhandler to trigger an NMI by sending an IPI. For some reason the destination shorthand for self is not valid when used with the NMI delivery mode so we send the IPI to our own APIC ID explicitly. Signed-off-by: Ian Campbell <Ian.Campbell@XenSource.com>
Diffstat (limited to 'xen/arch/x86/nmi.c')
-rw-r--r--xen/arch/x86/nmi.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c
index d2ccd4e7e4..f8c34a1c27 100644
--- a/xen/arch/x86/nmi.c
+++ b/xen/arch/x86/nmi.c
@@ -23,12 +23,14 @@
#include <xen/sched.h>
#include <xen/console.h>
#include <xen/smp.h>
+#include <xen/keyhandler.h>
#include <asm/current.h>
#include <asm/mc146818rtc.h>
#include <asm/msr.h>
#include <asm/mpspec.h>
#include <asm/debugger.h>
#include <asm/div64.h>
+#include <asm/apic.h>
unsigned int nmi_watchdog = NMI_NONE;
static spinlock_t watchdog_lock = SPIN_LOCK_UNLOCKED;
@@ -448,3 +450,26 @@ void nmi_watchdog_tick(struct cpu_user_regs * regs)
write_watchdog_counter(NULL);
}
}
+
+/*
+ * For some reason the destination shorthand for self is not valid
+ * when used with the NMI delivery mode. This is documented in Tables
+ * 8-3 and 8-4 in IA32 Reference Manual Volume 3. We send the IPI to
+ * our own APIC ID explicitly which is valid.
+ */
+static void do_nmi_trigger(unsigned char key) {
+ u32 id = apic_read(APIC_ID);
+
+ printk("triggering NMI on APIC ID %x\n", id);
+
+ apic_wait_icr_idle();
+ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id));
+ apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_INT_ASSERT);
+}
+
+static __init int register_nmi_trigger(void)
+{
+ register_keyhandler('n', do_nmi_trigger, "trigger an NMI");
+ return 0;
+}
+__initcall(register_nmi_trigger);