# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1193054672 -3600
# Node ID 42d8dadb5864eac0140262b9475a7b1ed150b607
# Parent 183a2d6eaadf5a24e231de4b473d0ff683ebd2c2
x86: Allow NMI callback CS to be specified via set_trap_table()
hypercall.
Based on a patch by Jan Beulich.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/traps.c | 37 ++++++++++++++++++++++++++++++
xen/arch/x86/x86_32/asm-offsets.c | 5 +++-
xen/arch/x86/x86_32/entry.S | 6 +++-
xen/arch/x86/x86_64/asm-offsets.c | 5 +++-
xen/arch/x86/x86_64/compat/entry.S | 6 +++-
xen/arch/x86/x86_64/compat/traps.c | 6 ++++
xen/common/kernel.c | 34 ---------------------------
xen/include/asm-ia64/linux-null/asm/nmi.h | 8 +++++-
xen/include/asm-powerpc/nmi.h | 3 ++
xen/include/asm-x86/nmi.h | 15 ++++++++++++
xen/include/xen/nmi.h | 15 ------------
xen/include/xen/sched.h | 2 -
12 files changed, 84 insertions(+), 58 deletions(-)
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/arch/x86/traps.c Mon Oct 22 13:04:32 2007 +0100
@@ -2229,6 +2229,37 @@ void __init trap_init(void)
open_softirq(NMI_SOFTIRQ, nmi_softirq);
}
+long register_guest_nmi_callback(unsigned long address)
+{
+ struct vcpu *v = current;
+ struct domain *d = current->domain;
+ struct trap_info *t = &v->arch.guest_context.trap_ctxt[TRAP_nmi];
+
+ t->vector = TRAP_nmi;
+ t->flags = 0;
+ t->cs = !IS_COMPAT(d) ? FLAT_KERNEL_CS : FLAT_COMPAT_KERNEL_CS;
+ t->address = address;
+ TI_SET_IF(t, 1);
+
+ /*
+ * If no handler was registered we can 'lose the NMI edge'. Re-assert it
+ * now.
+ */
+ if ( (v->vcpu_id == 0) && (arch_get_nmi_reason(d) != 0) )
+ v->nmi_pending = 1;
+
+ return 0;
+}
+
+long unregister_guest_nmi_callback(void)
+{
+ struct vcpu *v = current;
+ struct trap_info *t = &v->arch.guest_context.trap_ctxt[TRAP_nmi];
+
+ memset(t, 0, sizeof(*t));
+
+ return 0;
+}
long do_set_trap_table(XEN_GUEST_HANDLE(trap_info_t) traps)
{
@@ -2261,6 +2292,12 @@ long do_set_trap_table(XEN_GUEST_HANDLE(
if ( cur.address == 0 )
break;
+
+ if ( (cur.vector == TRAP_nmi) && !TI_GET_IF(&cur) )
+ {
+ rc = -EINVAL;
+ break;
+ }
fixup_guest_code_selector(current->domain, cur.cs);
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/arch/x86/x86_32/asm-offsets.c
--- a/xen/arch/x86/x86_32/asm-offsets.c Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/arch/x86/x86_32/asm-offsets.c Mon Oct 22 13:04:32 2007 +0100
@@ -66,7 +66,10 @@ void __dummy__(void)
arch.guest_context.kernel_sp);
OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags);
OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
- OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr);
+ OFFSET(VCPU_nmi_cs, struct vcpu,
+ arch.guest_context.trap_ctxt[TRAP_nmi].cs);
+ OFFSET(VCPU_nmi_addr, struct vcpu,
+ arch.guest_context.trap_ctxt[TRAP_nmi].address);
OFFSET(VCPU_nmi_pending, struct vcpu, nmi_pending);
OFFSET(VCPU_nmi_masked, struct vcpu, nmi_masked);
DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events);
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/arch/x86/x86_32/entry.S Mon Oct 22 13:04:32 2007 +0100
@@ -257,13 +257,15 @@ process_nmi:
testb $1,VCPU_nmi_masked(%ebx)
jnz test_guest_events
movb $0,VCPU_nmi_pending(%ebx)
- movl VCPU_nmi_addr(%ebx),%eax
+ movzwl VCPU_nmi_cs(%ebx),%eax
+ movl VCPU_nmi_addr(%ebx),%ecx
test %eax,%eax
jz test_guest_events
movb $1,VCPU_nmi_masked(%ebx)
sti
leal VCPU_trap_bounce(%ebx),%edx
- movl %eax,TRAPBOUNCE_eip(%edx)
+ movw %ax,TRAPBOUNCE_cs(%edx)
+ movl %ecx,TRAPBOUNCE_eip(%edx)
movw $FLAT_KERNEL_CS,TRAPBOUNCE_cs(%edx)
movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx)
call create_bounce_frame
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/arch/x86/x86_64/asm-offsets.c
--- a/xen/arch/x86/x86_64/asm-offsets.c Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/arch/x86/x86_64/asm-offsets.c Mon Oct 22 13:04:32 2007 +0100
@@ -75,7 +75,10 @@ void __dummy__(void)
OFFSET(VCPU_kernel_ss, struct vcpu, arch.guest_context.kernel_ss);
OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags);
OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
- OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr);
+ OFFSET(VCPU_nmi_cs, struct vcpu,
+ arch.guest_context.trap_ctxt[TRAP_nmi].cs);
+ OFFSET(VCPU_nmi_addr, struct vcpu,
+ arch.guest_context.trap_ctxt[TRAP_nmi].address);
OFFSET(VCPU_nmi_pending, struct vcpu, nmi_pending);
OFFSET(VCPU_nmi_masked, struct vcpu, nmi_masked);
DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events);
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/arch/x86/x86_64/compat/entry.S
--- a/xen/arch/x86/x86_64/compat/entry.S Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/arch/x86/x86_64/compat/entry.S Mon Oct 22 13:04:32 2007 +0100
@@ -131,13 +131,15 @@ compat_process_nmi:
testb $1,VCPU_nmi_masked(%rbx)
jnz compat_test_guest_events
movb $0,VCPU_nmi_pending(%rbx)
- movl VCPU_nmi_addr(%rbx),%eax
+ movzwl VCPU_nmi_cs(%rbx),%eax
+ movl VCPU_nmi_addr(%rbx),%ecx
testl %eax,%eax
jz compat_test_guest_events
movb $1,VCPU_nmi_masked(%rbx)
sti
leaq VCPU_trap_bounce(%rbx),%rdx
- movl %eax,TRAPBOUNCE_eip(%rdx)
+ movw %ax,TRAPBOUNCE_cs(%rdx)
+ movl %ecx,TRAPBOUNCE_eip(%rdx)
movw $FLAT_COMPAT_KERNEL_CS,TRAPBOUNCE_cs(%rdx)
movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
call compat_create_bounce_frame
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/arch/x86/x86_64/compat/traps.c
--- a/xen/arch/x86/x86_64/compat/traps.c Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/arch/x86/x86_64/compat/traps.c Mon Oct 22 13:04:32 2007 +0100
@@ -294,6 +294,12 @@ int compat_set_trap_table(XEN_GUEST_HAND
if ( cur.address == 0 )
break;
+ if ( (cur.vector == TRAP_nmi) && !TI_GET_IF(&cur) )
+ {
+ rc = -EINVAL;
+ break;
+ }
+
fixup_guest_code_selector(current->domain, cur.cs);
XLAT_trap_info(dst + cur.vector, &cur);
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/common/kernel.c
--- a/xen/common/kernel.c Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/common/kernel.c Mon Oct 22 13:04:32 2007 +0100
@@ -247,40 +247,6 @@ DO(xen_version)(int cmd, XEN_GUEST_HANDL
return -ENOSYS;
}
-#ifndef COMPAT
-
-long register_guest_nmi_callback(unsigned long address)
-{
- struct vcpu *v = current;
- struct domain *d = current->domain;
-
- if ( (d->domain_id != 0) || (v->vcpu_id != 0) )
- return -EINVAL;
-
- v->nmi_addr = address;
-#ifdef CONFIG_X86
- /*
- * If no handler was registered we can 'lose the NMI edge'. Re-assert it
- * now.
- */
- if ( arch_get_nmi_reason(d) != 0 )
- v->nmi_pending = 1;
-#endif
-
- return 0;
-}
-
-long unregister_guest_nmi_callback(void)
-{
- struct vcpu *v = current;
-
- v->nmi_addr = 0;
-
- return 0;
-}
-
-#endif
-
DO(nmi_op)(unsigned int cmd, XEN_GUEST_HANDLE(void) arg)
{
struct xennmi_callback cb;
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/include/asm-ia64/linux-null/asm/nmi.h
--- a/xen/include/asm-ia64/linux-null/asm/nmi.h Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/include/asm-ia64/linux-null/asm/nmi.h Mon Oct 22 13:04:32 2007 +0100
@@ -1,1 +1,7 @@
-/* This file is intentionally left empty. */
+#ifndef __IA64_NMI_H__
+#define __IA64_NMI_H__
+
+#define register_guest_nmi_callback(a) (-ENOSYS)
+#define unregister_guest_nmi_callback() (-ENOSYS)
+
+#endif /* __IA64_NMI_H__ */
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/include/asm-powerpc/nmi.h
--- a/xen/include/asm-powerpc/nmi.h Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/include/asm-powerpc/nmi.h Mon Oct 22 13:04:32 2007 +0100
@@ -3,4 +3,7 @@
#include <public/nmi.h>
+#define register_guest_nmi_callback(a) (-ENOSYS)
+#define unregister_guest_nmi_callback() (-ENOSYS)
+
#endif /* ASM_NMI_H */
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/include/asm-x86/nmi.h
--- a/xen/include/asm-x86/nmi.h Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/include/asm-x86/nmi.h Mon Oct 22 13:04:32 2007 +0100
@@ -23,4 +23,19 @@ void set_nmi_callback(nmi_callback_t cal
*/
void unset_nmi_callback(void);
+/**
+ * register_guest_nmi_callback
+ *
+ * The default NMI handler passes the NMI to a guest callback. This
+ * function registers the address of that callback.
+ */
+long register_guest_nmi_callback(unsigned long address);
+
+/**
+ * unregister_guest_nmi_callback
+ *
+ * Unregister a guest NMI handler.
+ */
+long unregister_guest_nmi_callback(void);
+
#endif /* ASM_NMI_H */
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/include/xen/nmi.h
--- a/xen/include/xen/nmi.h Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/include/xen/nmi.h Mon Oct 22 13:04:32 2007 +0100
@@ -11,19 +11,4 @@
#include <asm/nmi.h>
-/**
- * register_guest_nmi_callback
- *
- * The default NMI handler passes the NMI to a guest callback. This
- * function registers the address of that callback.
- */
-extern long register_guest_nmi_callback(unsigned long address);
-
-/**
- * unregister_guest_nmi_callback
- *
- * Unregister a guest NMI handler.
- */
-extern long unregister_guest_nmi_callback(void);
-
#endif /* __XEN_NMI_H__ */
diff -r 183a2d6eaadf -r 42d8dadb5864 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h Mon Oct 22 11:11:04 2007 +0100
+++ b/xen/include/xen/sched.h Mon Oct 22 13:04:32 2007 +0100
@@ -131,8 +131,6 @@ struct vcpu
/* 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;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|