[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] x86: fix MCE/NMI injection



This attempts to address all the concerns raised in
http://lists.xensource.com/archives/html/xen-devel/2009-11/msg01195.html,
but I'm nevertheless still not convinced that all aspects of the
injection handling really work reliably. In particular, while the
patch here on top of the fixes for the problems menioned in the
referenced mail also adds code to keep send_guest_trap() from
injecting multiple events at a time, I don't think the is the right
mechanism - it should be possible to handle NMI/MCE nested within
each other.

Another fix on top of the ones for the earlier described problems is
that the vCPU affinity restore logic didn't account for software
injected NMIs - these never set cpu_affinity_tmp, but due to it most
likely being different from cpu_affinity it would have got restored
(to a potentially random value) nevertheless.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

--- 2009-11-30.orig/xen/arch/x86/cpu/mcheck/mctelem.c   2009-07-03 
10:20:56.000000000 +0200
+++ 2009-11-30/xen/arch/x86/cpu/mcheck/mctelem.c        2009-12-01 
08:39:49.000000000 +0100
@@ -122,15 +122,6 @@ static struct mc_telem_ctl {
 /* Lock protecting all processing lists */
 static DEFINE_SPINLOCK(processing_lock);
 
-static void *cmpxchgptr(void *ptr, void *old, void *new)
-{
-       unsigned long *ulp = (unsigned long *)ptr;
-       unsigned long a = (unsigned long)old;
-       unsigned long b = (unsigned long)new;
-
-       return (void *)cmpxchg(ulp, a, b);
-}
-
 static void mctelem_xchg_head(struct mctelem_ent **headp,
                                struct mctelem_ent **old,
                                struct mctelem_ent *new)
--- 2009-11-30.orig/xen/arch/x86/nmi.c  2009-08-17 11:37:44.000000000 +0200
+++ 2009-11-30/xen/arch/x86/nmi.c       2009-11-30 14:04:54.000000000 +0100
@@ -475,10 +475,11 @@ static void do_nmi_stats(unsigned char k
          ((v = d->vcpu[0]) == NULL) )
         return;
 
-    if ( v->nmi_pending || (v->trap_priority >= VCPU_TRAP_NMI) )
+    i = v->async_exception_mask & (1 << VCPU_TRAP_NMI);
+    if ( v->nmi_pending || i )
         printk("dom0 vpu0: NMI %s%s\n",
                v->nmi_pending ? "pending " : "",
-               (v->trap_priority >= VCPU_TRAP_NMI)  ? "masked " : "");
+               i ? "masked " : "");
     else
         printk("dom0 vcpu0: NMI neither pending nor masked\n");
 }
--- 2009-11-30.orig/xen/arch/x86/traps.c        2009-11-30 10:18:36.000000000 
+0100
+++ 2009-11-30/xen/arch/x86/traps.c     2009-12-01 08:46:06.000000000 +0100
@@ -51,6 +51,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/atomic.h>
+#include <asm/bitops.h>
 #include <asm/desc.h>
 #include <asm/debugreg.h>
 #include <asm/smp.h>
@@ -2893,6 +2894,82 @@ static void nmi_mce_softirq(void)
      * a safe (non-NMI/MCE) context.
      */
     vcpu_kick(st->vcpu);
+    st->vcpu = NULL;
+}
+
+void async_exception_cleanup(struct vcpu *curr)
+{
+    int trap;
+
+    if ( !curr->async_exception_mask )
+        return;
+
+    /* Restore affinity.  */
+    if ( !cpus_empty(curr->cpu_affinity_tmp) &&
+         !cpus_equal(curr->cpu_affinity_tmp, curr->cpu_affinity) )
+    {
+        vcpu_set_affinity(curr, &curr->cpu_affinity_tmp);
+        cpus_clear(curr->cpu_affinity_tmp);
+    }
+
+    if ( !(curr->async_exception_mask & (curr->async_exception_mask - 1)) )
+        trap = __scanbit(curr->async_exception_mask, VCPU_TRAP_NONE);
+    else
+        for ( trap = VCPU_TRAP_NONE + 1; trap <= VCPU_TRAP_LAST; ++trap )
+            if ( (curr->async_exception_mask ^
+                  curr->async_exception_state(trap).old_mask) == (1 << trap) )
+                break;
+    ASSERT(trap <= VCPU_TRAP_LAST);
+
+    /* inject vMCE to PV_Guest including DOM0. */
+    if ( trap == VCPU_TRAP_MCE )
+    {
+        gdprintk(XENLOG_DEBUG, "MCE: Return from vMCE# trap!\n");
+        if ( curr->vcpu_id == 0 )
+        {
+            struct domain *d = curr->domain;
+
+            if ( !d->arch.vmca_msrs.nr_injection )
+            {
+                printk(XENLOG_WARNING "MCE: ret from vMCE#, "
+                       "no injection node\n");
+                goto end;
+            }
+
+            d->arch.vmca_msrs.nr_injection--;
+            if ( !list_empty(&d->arch.vmca_msrs.impact_header) )
+            {
+                struct bank_entry *entry;
+
+                entry = list_entry(d->arch.vmca_msrs.impact_header.next,
+                                   struct bank_entry, list);
+                gdprintk(XENLOG_DEBUG, "MCE: delete last injection node\n");
+                list_del(&entry->list);
+            }
+            else
+                printk(XENLOG_ERR "MCE: didn't found last injection node\n");
+
+            /* further injection */
+            if ( d->arch.vmca_msrs.nr_injection > 0 &&
+                 guest_has_trap_callback(d, 0, TRAP_machine_check) &&
+                 !test_and_set_bool(curr->mce_pending) )
+            {
+                int cpu = smp_processor_id();
+                cpumask_t affinity;
+
+                curr->cpu_affinity_tmp = curr->cpu_affinity;
+                cpus_clear(affinity);
+                cpu_set(cpu, affinity);
+                printk(XENLOG_DEBUG "MCE: CPU%d set affinity, old %d\n",
+                       cpu, curr->processor);
+                vcpu_set_affinity(curr, &affinity);
+            }
+        }
+    }
+
+end:
+    /* Restore previous asynchronous exception mask. */
+    curr->async_exception_mask = curr->async_exception_state(trap).old_mask;
 }
 
 static void nmi_dom0_report(unsigned int reason_idx)
@@ -3256,7 +3333,7 @@ int guest_has_trap_callback(struct domai
 int send_guest_trap(struct domain *d, uint16_t vcpuid, unsigned int trap_nr)
 {
     struct vcpu *v;
-    struct softirq_trap *st;
+    struct softirq_trap *st = &per_cpu(softirq_trap, smp_processor_id());
 
     BUG_ON(d == NULL);
     BUG_ON(vcpuid >= d->max_vcpus);
@@ -3264,25 +3341,27 @@ int send_guest_trap(struct domain *d, ui
 
     switch (trap_nr) {
     case TRAP_nmi:
+        if ( cmpxchgptr(&st->vcpu, NULL, v) )
+            return -EBUSY;
         if ( !test_and_set_bool(v->nmi_pending) ) {
-               st = &per_cpu(softirq_trap, smp_processor_id());
-               st->domain = dom0;
-               st->vcpu = dom0->vcpu[0];
-               st->processor = st->vcpu->processor;
+               st->domain = d;
+               st->processor = v->processor;
 
                /* not safe to wake up a vcpu here */
                raise_softirq(NMI_MCE_SOFTIRQ);
                return 0;
         }
+        st->vcpu = NULL;
         break;
 
     case TRAP_machine_check:
+        if ( cmpxchgptr(&st->vcpu, NULL, v) )
+            return -EBUSY;
 
         /* We are called by the machine check (exception or polling) handlers
          * on the physical CPU that reported a machine check error. */
 
         if ( !test_and_set_bool(v->mce_pending) ) {
-                st = &per_cpu(softirq_trap, smp_processor_id());
                 st->domain = d;
                 st->vcpu = v;
                 st->processor = v->processor;
@@ -3291,6 +3370,7 @@ int send_guest_trap(struct domain *d, ui
                 raise_softirq(NMI_MCE_SOFTIRQ);
                 return 0;
         }
+        st->vcpu = NULL;
         break;
     }
 
--- 2009-11-30.orig/xen/arch/x86/x86_32/asm-offsets.c   2008-12-10 
09:14:08.000000000 +0100
+++ 2009-11-30/xen/arch/x86/x86_32/asm-offsets.c        2009-11-30 
14:17:29.000000000 +0100
@@ -68,8 +68,9 @@ void __dummy__(void)
     OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags);
     OFFSET(VCPU_nmi_pending, struct vcpu, nmi_pending);
     OFFSET(VCPU_mce_pending, struct vcpu, mce_pending);
-    OFFSET(VCPU_old_trap_priority, struct vcpu, old_trap_priority);
-    OFFSET(VCPU_trap_priority, struct vcpu, trap_priority);
+    OFFSET(VCPU_nmi_old_mask, struct vcpu, nmi_state.old_mask);
+    OFFSET(VCPU_mce_old_mask, struct vcpu, mce_state.old_mask);
+    OFFSET(VCPU_async_exception_mask, struct vcpu, async_exception_mask);
     DEFINE(VCPU_TRAP_NMI, VCPU_TRAP_NMI);
     DEFINE(VCPU_TRAP_MCE, VCPU_TRAP_MCE);
     DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events);
--- 2009-11-30.orig/xen/arch/x86/x86_32/entry.S 2008-07-21 08:36:45.000000000 
+0200
+++ 2009-11-30/xen/arch/x86/x86_32/entry.S      2009-11-30 14:16:47.000000000 
+0100
@@ -259,31 +259,33 @@ process_softirqs:
         ALIGN
 /* %ebx: struct vcpu */
 process_mce:
-        cmpw $VCPU_TRAP_MCE,VCPU_trap_priority(%ebx)
-        jae  test_guest_events
+        testb $1 << VCPU_TRAP_MCE,VCPU_async_exception_mask(%ebx)
+        jnz  test_guest_events
         sti
         movb $0,VCPU_mce_pending(%ebx)
         call set_guest_machinecheck_trapbounce
         test %eax,%eax
         jz   test_all_events
-        movw VCPU_trap_priority(%ebx),%dx           # safe priority for the
-        movw %dx,VCPU_old_trap_priority(%ebx)       # iret hypercall
-        movw $VCPU_TRAP_MCE,VCPU_trap_priority(%ebx)
+        movzbl VCPU_async_exception_mask(%ebx),%edx # save mask for the
+        movb %dl,VCPU_mce_old_mask(%ebx)            # iret hypercall
+        orl  $1 << VCPU_TRAP_MCE,%edx
+        movb %dl,VCPU_async_exception_mask(%ebx)
         jmp process_trap
 
         ALIGN
 /* %ebx: struct vcpu */
 process_nmi:
-        cmpw $VCPU_TRAP_NMI,VCPU_trap_priority(%ebx)
-        jae  test_guest_events
+        cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%ebx)
+        jnz  test_guest_events
         sti
         movb $0,VCPU_nmi_pending(%ebx)
         call set_guest_nmi_trapbounce
         test %eax,%eax
         jz   test_all_events
-        movw VCPU_trap_priority(%ebx),%dx           # safe priority for the
-        movw %dx,VCPU_old_trap_priority(%ebx)       # iret hypercall
-        movw $VCPU_TRAP_NMI,VCPU_trap_priority(%ebx)
+        movzbl VCPU_async_exception_mask(%ebx),%edx # save mask for the
+        movb %dl,VCPU_nmi_old_mask(%ebx)            # iret hypercall
+        orl  $1 << VCPU_TRAP_NMI,%edx
+        movb %dl,VCPU_async_exception_mask(%ebx)
         /* FALLTHROUGH */
 process_trap:
         leal VCPU_trap_bounce(%ebx),%edx
--- 2009-11-30.orig/xen/arch/x86/x86_32/traps.c 2009-11-30 10:18:36.000000000 
+0100
+++ 2009-11-30/xen/arch/x86/x86_32/traps.c      2009-11-30 15:47:00.000000000 
+0100
@@ -13,6 +13,7 @@
 #include <xen/nmi.h>
 #include <asm/current.h>
 #include <asm/flushtlb.h>
+#include <asm/traps.h>
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
 
@@ -274,17 +275,11 @@ unsigned long do_iret(void)
             goto exit_and_crash;
     }
 
-    /* Restore affinity.  */
-    if ((v->trap_priority >= VCPU_TRAP_NMI)
-       && !cpus_equal(v->cpu_affinity_tmp, v->cpu_affinity))
-        vcpu_set_affinity(v, &v->cpu_affinity_tmp);
-
-    /* Restore previous trap priority */
-    v->trap_priority = v->old_trap_priority;
-
     /* Restore upcall mask from supplied EFLAGS.IF. */
     vcpu_info(v, evtchn_upcall_mask) = !(eflags & X86_EFLAGS_IF);
 
+    async_exception_cleanup(v);
+
     /*
      * The hypercall exit path will overwrite EAX with this return
      * value.
--- 2009-11-30.orig/xen/arch/x86/x86_64/asm-offsets.c   2009-10-15 
11:42:12.000000000 +0200
+++ 2009-11-30/xen/arch/x86/x86_64/asm-offsets.c        2009-11-30 
14:17:49.000000000 +0100
@@ -93,8 +93,9 @@ void __dummy__(void)
     OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags);
     OFFSET(VCPU_nmi_pending, struct vcpu, nmi_pending);
     OFFSET(VCPU_mce_pending, struct vcpu, mce_pending);
-    OFFSET(VCPU_old_trap_priority, struct vcpu, old_trap_priority);
-    OFFSET(VCPU_trap_priority, struct vcpu, trap_priority);
+    OFFSET(VCPU_nmi_old_mask, struct vcpu, nmi_state.old_mask);
+    OFFSET(VCPU_mce_old_mask, struct vcpu, mce_state.old_mask);
+    OFFSET(VCPU_async_exception_mask, struct vcpu, async_exception_mask);
     DEFINE(VCPU_TRAP_NMI, VCPU_TRAP_NMI);
     DEFINE(VCPU_TRAP_MCE, VCPU_TRAP_MCE);
     DEFINE(_VGCF_failsafe_disables_events, _VGCF_failsafe_disables_events);
--- 2009-11-30.orig/xen/arch/x86/x86_64/compat/entry.S  2009-03-24 
09:04:02.000000000 +0100
+++ 2009-11-30/xen/arch/x86/x86_64/compat/entry.S       2009-11-30 
14:21:59.000000000 +0100
@@ -132,31 +132,33 @@ compat_process_softirqs:
        ALIGN
 /* %rbx: struct vcpu */
 compat_process_mce:
-        cmpw $VCPU_TRAP_MCE,VCPU_trap_priority(%rbx)
-        jae  compat_test_guest_events
+        testb $1 << VCPU_TRAP_MCE,VCPU_async_exception_mask(%rbx)
+        jnz  compat_test_guest_events
         sti
         movb $0,VCPU_mce_pending(%rbx)
         call set_guest_machinecheck_trapbounce
         testl %eax,%eax
         jz    compat_test_all_events
-        movw VCPU_trap_priority(%rbx),%dx           # safe priority for the
-        movw %dx,VCPU_old_trap_priority(%rbx)       # iret hypercall
-        movw  $VCPU_TRAP_MCE,VCPU_trap_priority(%rbx)
+        movzbl VCPU_async_exception_mask(%rbx),%edx # save mask for the
+        movb %dl,VCPU_mce_old_mask(%rbx)            # iret hypercall
+        orl  $1 << VCPU_TRAP_MCE,%edx
+        movb %dl,VCPU_async_exception_mask(%rbx)
         jmp   compat_process_trap
 
        ALIGN
 /* %rbx: struct vcpu */
 compat_process_nmi:
-        cmpw $VCPU_TRAP_NMI,VCPU_trap_priority(%rbx)
-        jae   compat_test_guest_events
+        cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
+        jnz  compat_test_guest_events
         sti
         movb  $0,VCPU_nmi_pending(%rbx)
         call  set_guest_nmi_trapbounce
         testl %eax,%eax
         jz    compat_test_all_events
-        movw VCPU_trap_priority(%rbx),%dx           # safe priority for the
-        movw %dx,VCPU_old_trap_priority(%rbx)       # iret hypercall
-        movw  $VCPU_TRAP_NMI,VCPU_trap_priority(%rbx)
+        movzbl VCPU_async_exception_mask(%rbx),%edx # save mask for the
+        movb %dl,VCPU_nmi_old_mask(%rbx)            # iret hypercall
+        orl  $1 << VCPU_TRAP_NMI,%edx
+        movb %dl,VCPU_async_exception_mask(%rbx)
         /* FALLTHROUGH */
 compat_process_trap:
         leaq  VCPU_trap_bounce(%rbx),%rdx
--- 2009-11-30.orig/xen/arch/x86/x86_64/compat/traps.c  2009-10-15 
11:42:12.000000000 +0200
+++ 2009-11-30/xen/arch/x86/x86_64/compat/traps.c       2009-11-30 
15:32:19.000000000 +0100
@@ -147,17 +147,11 @@ unsigned int compat_iret(void)
     else
         regs->_esp += 16;
 
-    /* Restore affinity.  */
-    if ((v->trap_priority >= VCPU_TRAP_NMI)
-       && !cpus_equal(v->cpu_affinity_tmp, v->cpu_affinity))
-        vcpu_set_affinity(v, &v->cpu_affinity_tmp);
-
-    /* Restore previous trap priority */
-    v->trap_priority = v->old_trap_priority;
-
     /* Restore upcall mask from supplied EFLAGS.IF. */
     vcpu_info(v, evtchn_upcall_mask) = !(eflags & X86_EFLAGS_IF);
 
+    async_exception_cleanup(v);
+
     /*
      * The hypercall exit path will overwrite EAX with this return
      * value.
--- 2009-11-30.orig/xen/arch/x86/x86_64/entry.S 2008-07-21 08:36:45.000000000 
+0200
+++ 2009-11-30/xen/arch/x86/x86_64/entry.S      2009-11-30 14:20:05.000000000 
+0100
@@ -234,31 +234,33 @@ process_softirqs:
         ALIGN
 /* %rbx: struct vcpu */
 process_mce:
-        cmpw $VCPU_TRAP_MCE,VCPU_trap_priority(%rbx)
-        jae  test_guest_events
+        testb $1 << VCPU_TRAP_MCE,VCPU_async_exception_mask(%rbx)
+        jnz  test_guest_events
         sti
         movb $0,VCPU_mce_pending(%rbx)
         call set_guest_machinecheck_trapbounce
         test %eax,%eax
         jz   test_all_events
-        movw VCPU_trap_priority(%rbx),%dx           # safe priority for the
-        movw %dx,VCPU_old_trap_priority(%rbx)       # iret hypercall
-        movw $VCPU_TRAP_MCE,VCPU_trap_priority(%rbx)
+        movzbl VCPU_async_exception_mask(%rbx),%edx # save mask for the
+        movb %dl,VCPU_mce_old_mask(%rbx)            # iret hypercall
+        orl  $1 << VCPU_TRAP_MCE,%edx
+        movb %dl,VCPU_async_exception_mask(%rbx)
         jmp  process_trap
 
         ALIGN
 /* %rbx: struct vcpu */
 process_nmi:
-        cmpw $VCPU_TRAP_NMI,VCPU_trap_priority(%rbx)
-        jae  test_guest_events
+        cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
+        jnz  test_guest_events
         sti
         movb $0,VCPU_nmi_pending(%rbx)
         call set_guest_nmi_trapbounce
         test %eax,%eax
         jz   test_all_events
-        movw VCPU_trap_priority(%rbx),%dx           # safe priority for the
-        movw %dx,VCPU_old_trap_priority(%rbx)       # iret hypercall
-        movw $VCPU_TRAP_NMI,VCPU_trap_priority(%rbx)
+        movzbl VCPU_async_exception_mask(%rbx),%edx # save mask for the
+        movb %dl,VCPU_nmi_old_mask(%rbx)            # iret hypercall
+        orl  $1 << VCPU_TRAP_NMI,%edx
+        movb %dl,VCPU_async_exception_mask(%rbx)
         /* FALLTHROUGH */
 process_trap:
         leaq VCPU_trap_bounce(%rbx),%rdx
--- 2009-11-30.orig/xen/arch/x86/x86_64/traps.c 2009-11-30 10:18:36.000000000 
+0100
+++ 2009-11-30/xen/arch/x86/x86_64/traps.c      2009-11-30 15:34:01.000000000 
+0100
@@ -274,9 +274,6 @@ unsigned long do_iret(void)
     struct cpu_user_regs *regs = guest_cpu_user_regs();
     struct iret_context iret_saved;
     struct vcpu *v = current;
-    struct domain *d = v->domain;
-    struct bank_entry *entry;
-    int cpu = smp_processor_id();
 
     if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp,
                                  sizeof(iret_saved))) )
@@ -312,60 +309,11 @@ unsigned long do_iret(void)
         regs->rcx = iret_saved.rcx;
     }
 
-    /* Restore affinity.  */
-    if ((v->trap_priority >= VCPU_TRAP_NMI)
-       && !cpus_equal(v->cpu_affinity_tmp, v->cpu_affinity))
-        vcpu_set_affinity(v, &v->cpu_affinity_tmp);
-
-   /* inject vMCE to PV_Guest including DOM0. */
-    if (v->trap_priority >= VCPU_TRAP_NMI) {
-        printk(KERN_DEBUG "MCE: Return from vMCE# trap!\n");
-        if ( v->vcpu_id == 0 ) {
-            if ( !d->arch.vmca_msrs.nr_injection ) {
-                printk(KERN_WARNING "MCE: Ret from vMCE#, "
-                       "No injection Node\n");
-                goto end;
-            }
-
-            d->arch.vmca_msrs.nr_injection--;
-            if (!list_empty(&d->arch.vmca_msrs.impact_header)) {
-                entry = list_entry(d->arch.vmca_msrs.impact_header.next,
-                    struct bank_entry, list);
-                printk(KERN_DEBUG "MCE: Delete last injection Node\n");
-                list_del(&entry->list);
-            }
-            else
-                printk(KERN_DEBUG "MCE: Not found last injection "
-                    "Node, something Wrong!\n");
-
-            /* futher injection*/
-            if ( d->arch.vmca_msrs.nr_injection > 0) {
-                if ( d->arch.vmca_msrs.nr_injection > 0 &&
-                        guest_has_trap_callback(d, v->vcpu_id,
-                            TRAP_machine_check) &&
-                        !test_and_set_bool(dom0->vcpu[0]->mce_pending)) {
-                    cpumask_t affinity;
-
-                    dom0->vcpu[0]->cpu_affinity_tmp =
-                            dom0->vcpu[0]->cpu_affinity;
-                    cpus_clear(affinity);
-                    cpu_set(cpu, affinity);
-                    printk(KERN_DEBUG "MCE: CPU%d set affinity, old %d\n", cpu,
-                        dom0->vcpu[0]->processor);
-                    vcpu_set_affinity(dom0->vcpu[0], &affinity);
-                    vcpu_kick(dom0->vcpu[0]);
-                }
-            }
-        }
-    } /* end of outer-if */
-
-end:
-    /* Restore previous trap priority */
-    v->trap_priority = v->old_trap_priority;
-
     /* Restore upcall mask from supplied EFLAGS.IF. */
     vcpu_info(v, evtchn_upcall_mask) = !(iret_saved.rflags & X86_EFLAGS_IF);
 
+    async_exception_cleanup(v);
+
     /* Saved %rax gets written back to regs->rax in entry.S. */
     return iret_saved.rax;
 
--- 2009-11-30.orig/xen/common/domain.c 2009-11-12 17:04:47.000000000 +0100
+++ 2009-11-30/xen/common/domain.c      2009-11-30 16:00:51.000000000 +0100
@@ -726,10 +726,11 @@ void vcpu_reset(struct vcpu *v)
     v->fpu_initialised = 0;
     v->fpu_dirtied     = 0;
     v->is_initialised  = 0;
-    v->nmi_pending     = 0;
-    v->mce_pending     = 0;
-    v->old_trap_priority = VCPU_TRAP_NONE;
-    v->trap_priority   = VCPU_TRAP_NONE;
+#ifdef VCPU_TRAP_LAST
+    v->async_exception_mask = 0;
+    memset(v->async_exception_state, 0, sizeof(v->async_exception_state));
+#endif
+    cpus_clear(v->cpu_affinity_tmp);
     clear_bit(_VPF_blocked, &v->pause_flags);
 
     domain_unlock(v->domain);
@@ -855,6 +856,7 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
 
         break;
 
+#ifdef VCPU_TRAP_NMI
     case VCPUOP_send_nmi:
         if ( !guest_handle_is_null(arg) )
             return -EINVAL;
@@ -863,6 +865,7 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
             vcpu_kick(v);
 
         break;
+#endif
 
     default:
         rc = arch_do_vcpu_op(cmd, v, arg);
--- 2009-11-30.orig/xen/include/asm-x86/domain.h        2009-11-26 
10:17:42.000000000 +0100
+++ 2009-11-30/xen/include/asm-x86/domain.h     2009-11-30 15:29:09.000000000 
+0100
@@ -18,6 +18,16 @@
 #endif
 #define is_pv_32on64_vcpu(v)   (is_pv_32on64_domain((v)->domain))
 
+#define VCPU_TRAP_NMI          1
+#define VCPU_TRAP_MCE          2
+#define VCPU_TRAP_LAST         VCPU_TRAP_MCE
+
+#define nmi_state              async_exception_state(VCPU_TRAP_NMI)
+#define mce_state              async_exception_state(VCPU_TRAP_MCE)
+
+#define nmi_pending            nmi_state.pending
+#define mce_pending            mce_state.pending
+
 struct trap_bounce {
     uint32_t      error_code;
     uint8_t       flags; /* TBF_ */
--- 2009-11-30.orig/xen/include/asm-x86/system.h        2008-12-17 
16:52:27.000000000 +0100
+++ 2009-11-30/xen/include/asm-x86/system.h     2009-12-01 08:46:35.000000000 
+0100
@@ -134,6 +134,13 @@ static always_inline unsigned long __cmp
 
 #define __HAVE_ARCH_CMPXCHG
 
+#define cmpxchgptr(ptr,o,n) ({                                          \
+    const __typeof__(**(ptr)) *__o = (o);                               \
+    __typeof__(**(ptr)) *__n = (n);                                     \
+    ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)__o,            \
+                                   (unsigned long)__n,sizeof(*(ptr)))); \
+})
+
 /*
  * Both Intel and AMD agree that, from a programmer's viewpoint:
  *  Loads cannot be reordered relative to other loads.
--- 2009-11-30.orig/xen/include/asm-x86/traps.h 2009-08-17 11:37:45.000000000 
+0200
+++ 2009-11-30/xen/include/asm-x86/traps.h      2009-11-30 15:37:29.000000000 
+0100
@@ -29,6 +29,8 @@ struct softirq_trap {
 struct cpu_user_regs;
 
 extern void machine_check_vector(struct cpu_user_regs *regs, long error_code);
+
+void async_exception_cleanup(struct vcpu *);
  
 /**
  * guest_has_trap_callback
--- 2009-11-30.orig/xen/include/xen/sched.h     2009-10-22 08:18:54.000000000 
+0200
+++ 2009-11-30/xen/include/xen/sched.h  2009-11-30 15:27:57.000000000 +0100
@@ -113,20 +113,16 @@ struct vcpu 
     bool_t           is_initialised;
     /* Currently running on a CPU? */
     bool_t           is_running;
-    /* MCE callback pending for this VCPU? */
-    bool_t           mce_pending;
-    /* NMI callback pending for this VCPU? */
-    bool_t           nmi_pending;
-
-    /* Higher priorized traps may interrupt lower priorized traps,
-     * lower priorized traps wait until higher priorized traps finished.
-     * Note: This concept is known as "system priority level" (spl)
-     * in the UNIX world. */
-    uint16_t         old_trap_priority;
-    uint16_t         trap_priority;
+
+#ifdef VCPU_TRAP_LAST
 #define VCPU_TRAP_NONE    0
-#define VCPU_TRAP_NMI     1
-#define VCPU_TRAP_MCE     2
+    struct {
+        bool_t           pending;
+        uint8_t          old_mask;
+    }                async_exception_state[VCPU_TRAP_LAST];
+#define async_exception_state(t) async_exception_state[(t)-1]
+    uint8_t          async_exception_mask;
+#endif
 
     /* Require shutdown to be deferred for some asynchronous operation? */
     bool_t           defer_shutdown;


Attachment: xen-x86-async-exception.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.