360 lines
14 KiB
Diff
360 lines
14 KiB
Diff
Index: 2007-02-20/xen/arch/x86/physdev.c
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/arch/x86/physdev.c 2007-02-20 10:41:50.000000000 +0100
|
|
+++ 2007-02-20/xen/arch/x86/physdev.c 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -143,6 +143,57 @@ 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 = current->domain;
|
|
+ else if ( !IS_PRIV(current->domain) )
|
|
+ break;
|
|
+ else
|
|
+ d = find_domain_by_id(send_nmi.domain);
|
|
+ ret = -ESRCH;
|
|
+ if ( !d )
|
|
+ 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) &&
|
|
+ !test_and_set_bit(_VCPUF_nmi_pending, &v->vcpu_flags) )
|
|
+ vcpu_kick(v);
|
|
+ }
|
|
+ ret = 0;
|
|
+ break;
|
|
+ case 0 ... MAX_VIRT_CPUS - 1:
|
|
+ if ( (v = d->vcpu[send_nmi.vcpu]) != NULL )
|
|
+ {
|
|
+ if ( !test_and_set_bit(_VCPUF_nmi_pending, &v->vcpu_flags) )
|
|
+ vcpu_kick(v);
|
|
+ ret = 0;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ ret = EINVAL;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if ( send_nmi.domain != DOMID_SELF )
|
|
+ put_domain(d);
|
|
+ break;
|
|
+ }
|
|
+
|
|
default:
|
|
ret = -ENOSYS;
|
|
break;
|
|
Index: 2007-02-20/xen/arch/x86/traps.c
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/arch/x86/traps.c 2007-02-20 10:56:27.000000000 +0100
|
|
+++ 2007-02-20/xen/arch/x86/traps.c 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -2516,6 +2516,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-02-20/xen/arch/x86/x86_32/asm-offsets.c
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/arch/x86/x86_32/asm-offsets.c 2006-12-13 11:15:54.000000000 +0100
|
|
+++ 2007-02-20/xen/arch/x86/x86_32/asm-offsets.c 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -68,6 +68,7 @@ void __dummy__(void)
|
|
OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
|
|
OFFSET(VCPU_flags, struct vcpu, vcpu_flags);
|
|
OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr);
|
|
+ OFFSET(VCPU_nmi_cs, struct vcpu, arch.guest_context.trap_ctxt[2].cs);
|
|
DEFINE(_VCPUF_nmi_pending, _VCPUF_nmi_pending);
|
|
DEFINE(_VCPUF_nmi_masked, _VCPUF_nmi_masked);
|
|
DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events);
|
|
Index: 2007-02-20/xen/arch/x86/x86_32/entry.S
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/arch/x86/x86_32/entry.S 2007-02-20 10:56:03.000000000 +0100
|
|
+++ 2007-02-20/xen/arch/x86/x86_32/entry.S 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -232,7 +232,7 @@ test_all_events:
|
|
shl $IRQSTAT_shift,%eax
|
|
test %ecx,irq_stat(%eax,1)
|
|
jnz process_softirqs
|
|
- btr $_VCPUF_nmi_pending,VCPU_flags(%ebx)
|
|
+ lock btrl $_VCPUF_nmi_pending,VCPU_flags(%ebx)
|
|
jc process_nmi
|
|
test_guest_events:
|
|
movl VCPU_vcpu_info(%ebx),%eax
|
|
@@ -259,19 +259,20 @@ process_softirqs:
|
|
|
|
ALIGN
|
|
process_nmi:
|
|
- movl VCPU_nmi_addr(%ebx),%eax
|
|
+ movzwl VCPU_nmi_cs(%ebx),%eax
|
|
+ movl VCPU_nmi_addr(%ebx),%ecx
|
|
test %eax,%eax
|
|
jz test_all_events
|
|
- bts $_VCPUF_nmi_masked,VCPU_flags(%ebx)
|
|
+ lock btsl $_VCPUF_nmi_masked,VCPU_flags(%ebx)
|
|
jc 1f
|
|
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)
|
|
movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx)
|
|
call create_bounce_frame
|
|
jmp test_all_events
|
|
-1: bts $_VCPUF_nmi_pending,VCPU_flags(%ebx)
|
|
+1: lock btsl $_VCPUF_nmi_pending,VCPU_flags(%ebx)
|
|
jmp test_guest_events
|
|
|
|
bad_hypercall:
|
|
Index: 2007-02-20/xen/arch/x86/x86_64/asm-offsets.c
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/arch/x86/x86_64/asm-offsets.c 2007-02-20 10:41:52.000000000 +0100
|
|
+++ 2007-02-20/xen/arch/x86/x86_64/asm-offsets.c 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -76,6 +76,7 @@ void __dummy__(void)
|
|
OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
|
|
OFFSET(VCPU_flags, struct vcpu, vcpu_flags);
|
|
OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr);
|
|
+ OFFSET(VCPU_nmi_cs, struct vcpu, arch.guest_context.trap_ctxt[2].cs);
|
|
DEFINE(_VCPUF_nmi_pending, _VCPUF_nmi_pending);
|
|
DEFINE(_VCPUF_nmi_masked, _VCPUF_nmi_masked);
|
|
DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events);
|
|
Index: 2007-02-20/xen/arch/x86/x86_64/compat/entry.S
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/arch/x86/x86_64/compat/entry.S 2007-02-20 10:56:03.000000000 +0100
|
|
+++ 2007-02-20/xen/arch/x86/x86_64/compat/entry.S 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -68,7 +68,7 @@ compat_test_all_events:
|
|
leaq irq_stat(%rip),%rcx
|
|
testl $~0,(%rcx,%rax,1)
|
|
jnz compat_process_softirqs
|
|
- btrq $_VCPUF_nmi_pending,VCPU_flags(%rbx)
|
|
+ lock btrl $_VCPUF_nmi_pending,VCPU_flags(%rbx)
|
|
jc compat_process_nmi
|
|
compat_test_guest_events:
|
|
movq VCPU_vcpu_info(%rbx),%rax
|
|
@@ -82,7 +82,7 @@ compat_test_guest_events:
|
|
movl VCPU_event_addr(%rbx),%eax
|
|
movl %eax,TRAPBOUNCE_eip(%rdx)
|
|
movl VCPU_event_sel(%rbx),%eax
|
|
- movl %eax,TRAPBOUNCE_cs(%rdx)
|
|
+ movw %ax,TRAPBOUNCE_cs(%rdx)
|
|
movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
|
|
call compat_create_bounce_frame
|
|
jmp compat_test_all_events
|
|
@@ -97,20 +97,21 @@ compat_process_softirqs:
|
|
ALIGN
|
|
/* %rbx: struct vcpu */
|
|
compat_process_nmi:
|
|
- movl VCPU_nmi_addr(%rbx),%eax
|
|
+ movzwl VCPU_nmi_cs(%rbx),%eax
|
|
+ movl VCPU_nmi_addr(%rbx),%ecx
|
|
testl %eax,%eax
|
|
jz compat_test_all_events
|
|
- btsq $_VCPUF_nmi_masked,VCPU_flags(%rbx)
|
|
+ lock btsl $_VCPUF_nmi_masked,VCPU_flags(%rbx)
|
|
jc 1f
|
|
sti
|
|
leaq VCPU_trap_bounce(%rbx),%rdx
|
|
- movl %eax,TRAPBOUNCE_eip(%rdx)
|
|
- movl $FLAT_COMPAT_KERNEL_CS,TRAPBOUNCE_cs(%rdx)
|
|
+ movl %ecx,TRAPBOUNCE_eip(%rdx)
|
|
+ movw %ax,TRAPBOUNCE_cs(%rdx)
|
|
movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
|
|
call compat_create_bounce_frame
|
|
jmp compat_test_all_events
|
|
1:
|
|
- btsq $_VCPUF_nmi_pending,VCPU_flags(%rbx)
|
|
+ lock btsl $_VCPUF_nmi_pending,VCPU_flags(%rbx)
|
|
jmp compat_test_guest_events
|
|
|
|
compat_bad_hypercall:
|
|
@@ -145,7 +146,7 @@ compat_failsafe_callback:
|
|
movl VCPU_failsafe_addr(%rbx),%eax
|
|
movl %eax,TRAPBOUNCE_eip(%rdx)
|
|
movl VCPU_failsafe_sel(%rbx),%eax
|
|
- movl %eax,TRAPBOUNCE_cs(%rdx)
|
|
+ movw %ax,TRAPBOUNCE_cs(%rdx)
|
|
movw $TBF_FAILSAFE,TRAPBOUNCE_flags(%rdx)
|
|
btq $_VGCF_failsafe_disables_events,VCPU_guest_context_flags(%rbx)
|
|
jnc 1f
|
|
Index: 2007-02-20/xen/arch/x86/x86_64/compat/traps.c
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/arch/x86/x86_64/compat/traps.c 2007-02-20 10:41:57.000000000 +0100
|
|
+++ 2007-02-20/xen/arch/x86/x86_64/compat/traps.c 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -287,6 +287,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-02-20/xen/arch/x86/x86_64/entry.S
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/arch/x86/x86_64/entry.S 2007-02-20 10:56:03.000000000 +0100
|
|
+++ 2007-02-20/xen/arch/x86/x86_64/entry.S 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -177,7 +177,7 @@ test_all_events:
|
|
leaq irq_stat(%rip),%rcx
|
|
testl $~0,(%rcx,%rax,1)
|
|
jnz process_softirqs
|
|
- btr $_VCPUF_nmi_pending,VCPU_flags(%rbx)
|
|
+ lock btrl $_VCPUF_nmi_pending,VCPU_flags(%rbx)
|
|
jc process_nmi
|
|
test_guest_events:
|
|
movq VCPU_vcpu_info(%rbx),%rax
|
|
@@ -207,7 +207,7 @@ process_nmi:
|
|
movq VCPU_nmi_addr(%rbx),%rax
|
|
test %rax,%rax
|
|
jz test_all_events
|
|
- bts $_VCPUF_nmi_masked,VCPU_flags(%rbx)
|
|
+ lock btsl $_VCPUF_nmi_masked,VCPU_flags(%rbx)
|
|
jc 1f
|
|
sti
|
|
leaq VCPU_trap_bounce(%rbx),%rdx
|
|
@@ -215,7 +215,7 @@ process_nmi:
|
|
movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx)
|
|
call create_bounce_frame
|
|
jmp test_all_events
|
|
-1: bts $_VCPUF_nmi_pending,VCPU_flags(%rbx)
|
|
+1: lock btsl $_VCPUF_nmi_pending,VCPU_flags(%rbx)
|
|
jmp test_guest_events
|
|
|
|
bad_hypercall:
|
|
Index: 2007-02-20/xen/arch/x86/x86_64/physdev.c
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/arch/x86/x86_64/physdev.c 2007-02-20 10:41:50.000000000 +0100
|
|
+++ 2007-02-20/xen/arch/x86/x86_64/physdev.c 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -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-02-20/xen/common/kernel.c
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/common/kernel.c 2007-02-20 10:41:46.000000000 +0100
|
|
+++ 2007-02-20/xen/common/kernel.c 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -247,16 +247,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_COMPAT(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 )
|
|
set_bit(_VCPUF_nmi_pending, &v->vcpu_flags);
|
|
#endif
|
|
|
|
@@ -267,6 +271,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-02-20/xen/include/public/physdev.h
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/include/public/physdev.h 2006-12-13 11:15:56.000000000 +0100
|
|
+++ 2007-02-20/xen/include/public/physdev.h 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -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-02-20/xen/include/xen/sched.h
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/include/xen/sched.h 2007-02-20 10:42:03.000000000 +0100
|
|
+++ 2007-02-20/xen/include/xen/sched.h 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -108,7 +108,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-02-20/xen/include/xlat.lst
|
|
===================================================================
|
|
--- 2007-02-20.orig/xen/include/xlat.lst 2007-02-20 10:41:58.000000000 +0100
|
|
+++ 2007-02-20/xen/include/xlat.lst 2007-02-20 10:56:30.000000000 +0100
|
|
@@ -40,6 +40,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
|