x86: Must use a softirq to defer dom0 NMI
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 18 Jun 2008 13:17:10 +0000 (14:17 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 18 Jun 2008 13:17:10 +0000 (14:17 +0100)
notification. tasklet_schedule() contains a spinlock and is unsafe in
NMI context.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/traps.c
xen/include/asm-x86/softirq.h

index 218ede342a0dd422de7aff8d33f6fdc5f8f56c42..89032bb91d964c8796235a166f639a96c4892370 100644 (file)
@@ -2678,14 +2678,12 @@ asmlinkage void do_general_protection(struct cpu_user_regs *regs)
     panic("GENERAL PROTECTION FAULT\n[error_code=%04x]\n", regs->error_code);
 }
 
-static void nmi_action(unsigned long unused)
+static void nmi_mce_softirq(void)
 {
     /* Only used to defer wakeup of dom0,vcpu0 to a safe (non-NMI) context. */
     vcpu_kick(dom0->vcpu[0]);
 }
 
-static DECLARE_TASKLET(nmi_tasklet, nmi_action, 0);
-
 static void nmi_dom0_report(unsigned int reason_idx)
 {
     struct domain *d;
@@ -2696,8 +2694,9 @@ static void nmi_dom0_report(unsigned int reason_idx)
 
     set_bit(reason_idx, nmi_reason(d));
 
+    /* Not safe to wake a vcpu here, or even to schedule a tasklet! */
     if ( !test_and_set_bool(v->nmi_pending) )
-        tasklet_schedule(&nmi_tasklet); /* not safe to wake a vcpu here */
+        raise_softirq(NMI_MCE_SOFTIRQ);
 }
 
 asmlinkage void mem_parity_error(struct cpu_user_regs *regs)
@@ -2975,6 +2974,8 @@ void __init trap_init(void)
     percpu_traps_init();
 
     cpu_init();
+
+    open_softirq(NMI_MCE_SOFTIRQ, nmi_mce_softirq);
 }
 
 long register_guest_nmi_callback(unsigned long address)
index 3444d300c0dfd9b918ee560d4da283bb917a09d1..5f09a38964a1ad079409aa2a76579425f5143157 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SOFTIRQ_H__
 #define __ASM_SOFTIRQ_H__
 
-#define NR_ARCH_SOFTIRQS    0
+#define NMI_MCE_SOFTIRQ     (NR_COMMON_SOFTIRQS + 0)
+
+#define NR_ARCH_SOFTIRQS    1
 
 #endif /* __ASM_SOFTIRQ_H__ */