From d9a2559fc45a21e727e44a5261695dbbba8a517b Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 18 Jun 2008 14:17:10 +0100 Subject: [PATCH] x86: Must use a softirq to defer dom0 NMI notification. tasklet_schedule() contains a spinlock and is unsafe in NMI context. Signed-off-by: Keir Fraser --- xen/arch/x86/traps.c | 9 +++++---- xen/include/asm-x86/softirq.h | 4 +++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 218ede342a..89032bb91d 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -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) diff --git a/xen/include/asm-x86/softirq.h b/xen/include/asm-x86/softirq.h index 3444d300c0..5f09a38964 100644 --- a/xen/include/asm-x86/softirq.h +++ b/xen/include/asm-x86/softirq.h @@ -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__ */ -- 2.30.2