# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID c6f7774cae63932f327413586d58f3c7d08cb378
# Parent 8bcfcfc13e21d1a771e9b19daa31f1683996411e
Pass NMIs to DOM0 via a dedicated callback, core Xen support.
This patch adds core and generic x86 support code to enable Xen to
pass NMI's to a dedicated NMI callback in DOM0 instead of raising a
VIRQ.
Introduces the nmi_op hypercall to allow DOM0 to (un)register the NMI
handler.
Signed-off-by: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>
diff -r 8bcfcfc13e21 -r c6f7774cae63 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Wed Jan 11 15:51:18 2006
+++ b/xen/arch/x86/traps.c Wed Jan 11 15:51:56 2006
@@ -1080,26 +1080,23 @@
return 0;
}
-
-/* Defer dom0 notification to softirq context (unsafe in NMI context). */
-static unsigned long nmi_dom0_softirq_reason;
-#define NMI_DOM0_PARITY_ERR 0
-#define NMI_DOM0_IO_ERR 1
-#define NMI_DOM0_UNKNOWN 2
-
-static void nmi_dom0_softirq(void)
-{
- if ( dom0 == NULL )
+static void nmi_softirq(void)
+{
+ /* Only used to defer wakeup of dom0,vcpu0 to a safe (non-NMI) context. */
+ evtchn_notify(dom0->vcpu[0]);
+}
+
+static void nmi_dom0_report(unsigned int reason_idx)
+{
+ struct domain *d;
+
+ if ( (d = dom0) == NULL )
return;
- if ( test_and_clear_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason) )
- send_guest_virq(dom0->vcpu[0], VIRQ_PARITY_ERR);
-
- if ( test_and_clear_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason) )
- send_guest_virq(dom0->vcpu[0], VIRQ_IO_ERR);
-
- if ( test_and_clear_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason) )
- send_guest_virq(dom0->vcpu[0], VIRQ_NMI);
+ set_bit(reason_idx, &d->shared_info->arch.nmi_reason);
+
+ if ( test_and_set_bit(_VCPUF_nmi_pending, &d->vcpu[0]->vcpu_flags) )
+ raise_softirq(NMI_SOFTIRQ); /* not safe to wake up a vcpu here */
}
asmlinkage void mem_parity_error(struct cpu_user_regs *regs)
@@ -1107,8 +1104,7 @@
switch ( opt_nmi[0] )
{
case 'd': /* 'dom0' */
- set_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason);
- raise_softirq(NMI_DOM0_SOFTIRQ);
+ nmi_dom0_report(_XEN_NMIREASON_parity_error);
case 'i': /* 'ignore' */
break;
default: /* 'fatal' */
@@ -1127,8 +1123,7 @@
switch ( opt_nmi[0] )
{
case 'd': /* 'dom0' */
- set_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason);
- raise_softirq(NMI_DOM0_SOFTIRQ);
+ nmi_dom0_report(_XEN_NMIREASON_io_error);
case 'i': /* 'ignore' */
break;
default: /* 'fatal' */
@@ -1147,8 +1142,7 @@
switch ( opt_nmi[0] )
{
case 'd': /* 'dom0' */
- set_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason);
- raise_softirq(NMI_DOM0_SOFTIRQ);
+ nmi_dom0_report(_XEN_NMIREASON_unknown);
case 'i': /* 'ignore' */
break;
default: /* 'fatal' */
@@ -1347,7 +1341,7 @@
cpu_init();
- open_softirq(NMI_DOM0_SOFTIRQ, nmi_dom0_softirq);
+ open_softirq(NMI_SOFTIRQ, nmi_softirq);
}
diff -r 8bcfcfc13e21 -r c6f7774cae63 xen/common/kernel.c
--- a/xen/common/kernel.c Wed Jan 11 15:51:18 2006
+++ b/xen/common/kernel.c Wed Jan 11 15:51:56 2006
@@ -11,6 +11,7 @@
#include <xen/compile.h>
#include <xen/sched.h>
#include <asm/current.h>
+#include <public/nmi.h>
#include <public/version.h>
void cmdline_parse(char *cmdline)
@@ -148,6 +149,30 @@
return -ENOSYS;
}
+long do_nmi_op(unsigned int cmd, void *arg)
+{
+ long rc = 0;
+
+ switch ( cmd )
+ {
+ case XENNMI_register_callback:
+ if ( (current->domain->domain_id != 0) || (current->vcpu_id != 0) )
+ rc = -EINVAL;
+ else
+ current->nmi_addr = (unsigned long)arg;
+ printk("***** NMI handler at 0x%lx\n", current->nmi_addr);
+ break;
+ case XENNMI_unregister_callback:
+ current->nmi_addr = 0;
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ return rc;
+}
+
long do_vm_assist(unsigned int cmd, unsigned int type)
{
return vm_assist(current->domain, cmd, type);
diff -r 8bcfcfc13e21 -r c6f7774cae63 xen/include/asm-x86/nmi.h
--- a/xen/include/asm-x86/nmi.h Wed Jan 11 15:51:18 2006
+++ b/xen/include/asm-x86/nmi.h Wed Jan 11 15:51:56 2006
@@ -1,6 +1,8 @@
#ifndef ASM_NMI_H
#define ASM_NMI_H
+
+#include <public/nmi.h>
struct cpu_user_regs;
diff -r 8bcfcfc13e21 -r c6f7774cae63 xen/include/public/arch-x86_32.h
--- a/xen/include/public/arch-x86_32.h Wed Jan 11 15:51:18 2006
+++ b/xen/include/public/arch-x86_32.h Wed Jan 11 15:51:56 2006
@@ -135,6 +135,7 @@
unsigned long max_pfn; /* max pfn that appears in table */
/* Frame containing list of mfns containing list of mfns containing p2m. */
unsigned long pfn_to_mfn_frame_list_list;
+ unsigned long nmi_reason;
} arch_shared_info_t;
typedef struct {
diff -r 8bcfcfc13e21 -r c6f7774cae63 xen/include/public/arch-x86_64.h
--- a/xen/include/public/arch-x86_64.h Wed Jan 11 15:51:18 2006
+++ b/xen/include/public/arch-x86_64.h Wed Jan 11 15:51:56 2006
@@ -202,6 +202,7 @@
unsigned long max_pfn; /* max pfn that appears in table */
/* Frame containing list of mfns containing list of mfns containing p2m. */
unsigned long pfn_to_mfn_frame_list_list;
+ unsigned long nmi_reason;
} arch_shared_info_t;
typedef struct {
diff -r 8bcfcfc13e21 -r c6f7774cae63 xen/include/public/xen.h
--- a/xen/include/public/xen.h Wed Jan 11 15:51:18 2006
+++ b/xen/include/public/xen.h Wed Jan 11 15:51:56 2006
@@ -59,6 +59,7 @@
#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
#define __HYPERVISOR_mmuext_op 26
#define __HYPERVISOR_acm_op 27
+#define __HYPERVISOR_nmi_op 28
/*
* VIRTUAL INTERRUPTS
@@ -69,10 +70,7 @@
#define VIRQ_DEBUG 1 /* Request guest to dump debug info. */
#define VIRQ_CONSOLE 2 /* (DOM0) Bytes received on emergency console. */
#define VIRQ_DOM_EXC 3 /* (DOM0) Exceptional event for some domain. */
-#define VIRQ_PARITY_ERR 4 /* (DOM0) NMI parity error (port 0x61, bit 7). */
-#define VIRQ_IO_ERR 5 /* (DOM0) NMI I/O error (port 0x61, bit 6). */
#define VIRQ_DEBUGGER 6 /* (DOM0) A domain has paused for debugging. */
-#define VIRQ_NMI 7 /* (DOM0) Unknown NMI (not from ISA port 0x61).*/
#define NR_VIRQS 8
/*
diff -r 8bcfcfc13e21 -r c6f7774cae63 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h Wed Jan 11 15:51:18 2006
+++ b/xen/include/xen/sched.h Wed Jan 11 15:51:56 2006
@@ -80,6 +80,8 @@
/* Bitmask of CPUs on which this VCPU may run. */
cpumask_t cpu_affinity;
+
+ unsigned long nmi_addr; /* NMI callback address. */
/* Bitmask of CPUs which are holding onto this VCPU's state. */
cpumask_t vcpu_dirty_cpumask;
@@ -361,6 +363,12 @@
/* VCPU is not-runnable */
#define _VCPUF_down 5
#define VCPUF_down (1UL<<_VCPUF_down)
+ /* NMI callback pending for this VCPU? */
+#define _VCPUF_nmi_pending 8
+#define VCPUF_nmi_pending (1UL<<_VCPUF_nmi_pending)
+ /* Avoid NMI reentry by allowing NMIs to be masked for short periods. */
+#define _VCPUF_nmi_masked 9
+#define VCPUF_nmi_masked (1UL<<_VCPUF_nmi_masked)
/*
* Per-domain flags (domain_flags).
diff -r 8bcfcfc13e21 -r c6f7774cae63 xen/include/xen/softirq.h
--- a/xen/include/xen/softirq.h Wed Jan 11 15:51:18 2006
+++ b/xen/include/xen/softirq.h Wed Jan 11 15:51:56 2006
@@ -6,7 +6,7 @@
#define SCHEDULE_SOFTIRQ 1
#define NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ 2
#define KEYPRESS_SOFTIRQ 3
-#define NMI_DOM0_SOFTIRQ 4
+#define NMI_SOFTIRQ 4
#define PAGE_SCRUB_SOFTIRQ 5
#define DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ 6
#define NR_SOFTIRQS 7
diff -r 8bcfcfc13e21 -r c6f7774cae63 xen/include/public/nmi.h
--- /dev/null Wed Jan 11 15:51:18 2006
+++ b/xen/include/public/nmi.h Wed Jan 11 15:51:56 2006
@@ -0,0 +1,54 @@
+/******************************************************************************
+ * nmi.h
+ *
+ * NMI callback registration and reason codes.
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xxxxxxxxxxxxx>
+ */
+
+#ifndef __XEN_PUBLIC_NMI_H__
+#define __XEN_PUBLIC_NMI_H__
+
+/*
+ * NMI reason codes:
+ * Currently these are x86-specific, stored in arch_shared_info.nmi_reason.
+ */
+ /* I/O-check error reported via ISA port 0x61, bit 6. */
+#define _XEN_NMIREASON_io_error 0
+#define XEN_NMIREASON_io_error (1UL << _XEN_NMIREASON_io_error)
+ /* Parity error reported via ISA port 0x61, bit 7. */
+#define _XEN_NMIREASON_parity_error 1
+#define XEN_NMIREASON_parity_error (1UL << _XEN_NMIREASON_parity_error)
+ /* Unknown hardware-generated NMI. */
+#define _XEN_NMIREASON_unknown 2
+#define XEN_NMIREASON_unknown (1UL << _XEN_NMIREASON_unknown)
+
+/*
+ * long nmi_op(unsigned int cmd, void *arg)
+ * NB. All ops return zero on success, else a negative error code.
+ */
+
+/*
+ * Register NMI callback for this (calling) VCPU. Currently this only makes
+ * sense for domain 0, vcpu 0. All other callers will be returned EINVAL.
+ * arg == address of callback function.
+ */
+#define XENNMI_register_callback 0
+
+/*
+ * Deregister NMI callback for this (calling) VCPU.
+ * arg == NULL.
+ */
+#define XENNMI_unregister_callback 1
+
+#endif /* __XEN_PUBLIC_NMI_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|