xen/x86-nmi-inject.patch

277 lines
10 KiB
Diff

Index: 2007-05-14/xen/arch/x86/physdev.c
===================================================================
--- 2007-05-14.orig/xen/arch/x86/physdev.c 2007-04-23 10:01:42.000000000 +0200
+++ 2007-05-14/xen/arch/x86/physdev.c 2007-05-14 14:40:35.000000000 +0200
@@ -143,6 +143,56 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
break;
}
+ case PHYSDEVOP_send_nmi: {
+ struct physdev_send_nmi send_nmi;
+ struct domain *d;
+
+ ret = -EFAULT;
+ if ( copy_from_guest(&send_nmi, arg, 1) != 0 )
+ break;
+
+ ret = -EPERM;
+ if ( send_nmi.domain == DOMID_SELF )
+ d = rcu_lock_current_domain();
+ else if ( IS_PRIV(current->domain) )
+ d = rcu_lock_domain_by_id(send_nmi.domain);
+ else
+ break;
+ ret = -ESRCH;
+ if ( d == NULL )
+ break;
+
+ switch ( send_nmi.vcpu )
+ {
+ struct vcpu *v;
+
+ case XEN_SEND_NMI_ALL:
+ case XEN_SEND_NMI_ALL_BUT_SELF:
+ for_each_vcpu(d, v)
+ {
+ if ( (send_nmi.vcpu == XEN_SEND_NMI_ALL || v != current) &&
+ !xchg(&v->nmi_pending, 1) )
+ vcpu_kick(v);
+ }
+ ret = 0;
+ break;
+ case 0 ... MAX_VIRT_CPUS - 1:
+ if ( (v = d->vcpu[send_nmi.vcpu]) != NULL )
+ {
+ if ( !xchg(&v->nmi_pending, 1) )
+ vcpu_kick(v);
+ ret = 0;
+ }
+ break;
+ default:
+ ret = EINVAL;
+ break;
+ }
+
+ rcu_unlock_domain(d);
+ break;
+ }
+
default:
ret = -ENOSYS;
break;
Index: 2007-05-14/xen/arch/x86/traps.c
===================================================================
--- 2007-05-14.orig/xen/arch/x86/traps.c 2007-05-14 14:40:32.000000000 +0200
+++ 2007-05-14/xen/arch/x86/traps.c 2007-05-14 14:40:35.000000000 +0200
@@ -2517,6 +2517,12 @@ long do_set_trap_table(XEN_GUEST_HANDLE(
if ( cur.address == 0 )
break;
+ if ( cur.vector == 2 && !TI_GET_IF(&cur) )
+ {
+ rc = -EINVAL;
+ break;
+ }
+
fixup_guest_code_selector(current->domain, cur.cs);
memcpy(&dst[cur.vector], &cur, sizeof(cur));
Index: 2007-05-14/xen/arch/x86/x86_32/asm-offsets.c
===================================================================
--- 2007-05-14.orig/xen/arch/x86/x86_32/asm-offsets.c 2007-05-14 14:40:29.000000000 +0200
+++ 2007-05-14/xen/arch/x86/x86_32/asm-offsets.c 2007-05-14 14:40:35.000000000 +0200
@@ -68,6 +68,7 @@ void __dummy__(void)
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[2].cs);
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);
Index: 2007-05-14/xen/arch/x86/x86_32/entry.S
===================================================================
--- 2007-05-14.orig/xen/arch/x86/x86_32/entry.S 2007-05-03 09:45:09.000000000 +0200
+++ 2007-05-14/xen/arch/x86/x86_32/entry.S 2007-05-14 14:40:35.000000000 +0200
@@ -263,14 +263,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 $FLAT_KERNEL_CS,TRAPBOUNCE_cs(%edx)
+ movl %ecx,TRAPBOUNCE_eip(%edx)
+ movw %ax,TRAPBOUNCE_cs(%edx)
movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx)
call create_bounce_frame
jmp test_all_events
Index: 2007-05-14/xen/arch/x86/x86_64/asm-offsets.c
===================================================================
--- 2007-05-14.orig/xen/arch/x86/x86_64/asm-offsets.c 2007-05-14 14:40:29.000000000 +0200
+++ 2007-05-14/xen/arch/x86/x86_64/asm-offsets.c 2007-05-14 14:40:35.000000000 +0200
@@ -77,6 +77,7 @@ void __dummy__(void)
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[2].cs);
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);
Index: 2007-05-14/xen/arch/x86/x86_64/compat/entry.S
===================================================================
--- 2007-05-14.orig/xen/arch/x86/x86_64/compat/entry.S 2007-05-03 09:45:09.000000000 +0200
+++ 2007-05-14/xen/arch/x86/x86_64/compat/entry.S 2007-05-14 14:40:35.000000000 +0200
@@ -119,14 +119,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 $FLAT_COMPAT_KERNEL_CS,TRAPBOUNCE_cs(%rdx)
+ movl %ecx,TRAPBOUNCE_eip(%rdx)
+ movw %ax,TRAPBOUNCE_cs(%rdx)
movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
call compat_create_bounce_frame
jmp compat_test_all_events
Index: 2007-05-14/xen/arch/x86/x86_64/compat/traps.c
===================================================================
--- 2007-05-14.orig/xen/arch/x86/x86_64/compat/traps.c 2007-04-23 10:01:42.000000000 +0200
+++ 2007-05-14/xen/arch/x86/x86_64/compat/traps.c 2007-05-14 14:40:35.000000000 +0200
@@ -288,6 +288,12 @@ int compat_set_trap_table(XEN_GUEST_HAND
if ( cur.address == 0 )
break;
+ if ( cur.vector == 2 && !TI_GET_IF(&cur) )
+ {
+ rc = -EINVAL;
+ break;
+ }
+
fixup_guest_code_selector(current->domain, cur.cs);
XLAT_trap_info(dst + cur.vector, &cur);
Index: 2007-05-14/xen/arch/x86/x86_64/physdev.c
===================================================================
--- 2007-05-14.orig/xen/arch/x86/x86_64/physdev.c 2007-04-23 10:01:43.000000000 +0200
+++ 2007-05-14/xen/arch/x86/x86_64/physdev.c 2007-05-14 14:40:35.000000000 +0200
@@ -30,6 +30,10 @@
#define physdev_irq_status_query compat_physdev_irq_status_query
#define physdev_irq_status_query_t physdev_irq_status_query_compat_t
+#define xen_physdev_send_nmi physdev_send_nmi
+CHECK_physdev_send_nmi;
+#undef xen_physdev_send_nmi
+
#define COMPAT
#undef guest_handle_okay
#define guest_handle_okay compat_handle_okay
Index: 2007-05-14/xen/common/kernel.c
===================================================================
--- 2007-05-14.orig/xen/common/kernel.c 2007-05-14 14:40:27.000000000 +0200
+++ 2007-05-14/xen/common/kernel.c 2007-05-14 14:40:35.000000000 +0200
@@ -246,16 +246,20 @@ long register_guest_nmi_callback(unsigne
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
+ v->arch.guest_context.trap_ctxt[2].vector = 2;
+ v->arch.guest_context.trap_ctxt[2].flags = 0;
+ TI_SET_IF(v->arch.guest_context.trap_ctxt + 2, 1);
+ v->arch.guest_context.trap_ctxt[2].cs =
+ !is_pv_32on64_domain(d) ? FLAT_KERNEL_CS : FLAT_COMPAT_KERNEL_CS;
+
/*
* If no handler was registered we can 'lose the NMI edge'. Re-assert it
* now.
*/
- if ( arch_get_nmi_reason(d) != 0 )
+ if ( d->domain_id == 0 && v->vcpu_id == 0 &&
+ arch_get_nmi_reason(d) != 0 )
v->nmi_pending = 1;
#endif
@@ -266,6 +270,11 @@ long unregister_guest_nmi_callback(void)
{
struct vcpu *v = current;
+#ifdef CONFIG_X86
+ v->arch.guest_context.trap_ctxt[2].cs = 0;
+ v->arch.guest_context.trap_ctxt[2].vector = 0;
+ v->arch.guest_context.trap_ctxt[2].flags = 0;
+#endif
v->nmi_addr = 0;
return 0;
Index: 2007-05-14/xen/include/public/physdev.h
===================================================================
--- 2007-05-14.orig/xen/include/public/physdev.h 2007-04-23 10:01:47.000000000 +0200
+++ 2007-05-14/xen/include/public/physdev.h 2007-05-14 14:40:35.000000000 +0200
@@ -119,6 +119,22 @@ typedef struct physdev_irq physdev_irq_t
DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
/*
+ * Allocate or free a physical upcall vector for the specified IRQ line.
+ * @arg == pointer to physdev_irq structure.
+ */
+#define PHYSDEVOP_send_nmi 13
+struct physdev_send_nmi {
+ /* IN */
+ domid_t domain;
+ uint32_t vcpu;
+};
+typedef struct physdev_send_nmi physdev_send_nmi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_send_nmi_t);
+
+#define XEN_SEND_NMI_ALL (~(uint32_t)0)
+#define XEN_SEND_NMI_ALL_BUT_SELF (~(uint32_t)1)
+
+/*
* Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
* hypercall since 0x00030202.
*/
Index: 2007-05-14/xen/include/xen/sched.h
===================================================================
--- 2007-05-14.orig/xen/include/xen/sched.h 2007-05-03 09:45:09.000000000 +0200
+++ 2007-05-14/xen/include/xen/sched.h 2007-05-14 14:40:35.000000000 +0200
@@ -128,7 +128,11 @@ struct vcpu
/* Bitmask of CPUs on which this VCPU may run. */
cpumask_t cpu_affinity;
+#ifndef CONFIG_X86
unsigned long nmi_addr; /* NMI callback address. */
+#else
+# define nmi_addr arch.guest_context.trap_ctxt[2].address
+#endif
/* Bitmask of CPUs which are holding onto this VCPU's state. */
cpumask_t vcpu_dirty_cpumask;
Index: 2007-05-14/xen/include/xlat.lst
===================================================================
--- 2007-05-14.orig/xen/include/xlat.lst 2007-05-03 09:45:09.000000000 +0200
+++ 2007-05-14/xen/include/xlat.lst 2007-05-14 14:40:35.000000000 +0200
@@ -35,6 +35,7 @@
! memory_map memory.h
! memory_reservation memory.h
! translate_gpfn_list memory.h
+? physdev_send_nmi physdev.h
! sched_poll sched.h
? sched_remote_shutdown sched.h
? sched_shutdown sched.h