[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Pass NMIs to DOM0 via a dedicated callback, core Xen support.
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |