|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] x86/nmi: Fix shootdown of pcpus running in VMX non-root mode
In the case of a crash, nmi_shootdown_cpus() patches nmi_crash() into the IDT
of each processor, such that the next NMI it receives will force it into the
crash path.
c/s 7dd3b06ff "vmx: fix handling of NMI VMEXIT" fixed one issue but
inadvertently introduced another. The original use of self_nmi() would follow
vector #2, but a direct call to do_nmi() does not.
Introduce a function pointer which should be used in preference to direct
do_nmi() calls, which is updated on the crash path to point at do_nmi_crash()
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Tim Deegan <tim@xxxxxxx>
---
This patch very certainly functions correctly (it is in active use now in a
customer escalation), but I was wondering how paranoid we should be about
interleaved reads/writes and whether an atomic write would be better?
Performance is not a issue at all but in a crash senario we don't want to be
taking any chances with correctness.
---
xen/arch/x86/crash.c | 4 +++-
xen/arch/x86/hvm/vmx/vmx.c | 2 +-
xen/arch/x86/traps.c | 2 ++
xen/include/asm-x86/processor.h | 3 ++-
4 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c
index c0b83df..0822a68 100644
--- a/xen/arch/x86/crash.c
+++ b/xen/arch/x86/crash.c
@@ -36,7 +36,7 @@ static unsigned int crashing_cpu;
static DEFINE_PER_CPU_READ_MOSTLY(bool_t, crash_save_done);
/* This becomes the NMI handler for non-crashing CPUs, when Xen is crashing. */
-void do_nmi_crash(struct cpu_user_regs *regs)
+void do_nmi_crash(const struct cpu_user_regs *regs)
{
int cpu = smp_processor_id();
@@ -160,6 +160,8 @@ static void nmi_shootdown_cpus(void)
}
}
+ nmi_handler = do_nmi_crash;
+
/* Ensure the new callback function is set before sending out the NMI. */
wmb();
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 88b7821..67bdcb4 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2701,7 +2701,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
&& ((intr_info & INTR_INFO_INTR_TYPE_MASK) ==
(X86_EVENTTYPE_NMI << 8)) )
{
- do_nmi(regs);
+ nmi_handler(regs);
enable_nmis();
}
break;
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index f5516dc..890e22a 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -105,6 +105,8 @@ idt_entry_t *idt_tables[NR_CPUS] __read_mostly;
void (*ioemul_handle_quirk)(
u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs);
+void (*nmi_handler)(const struct cpu_user_regs *regs) __read_mostly = do_nmi;
+
static int debug_stack_lines = 20;
integer_param("debug_stack_lines", debug_stack_lines);
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index 20eade6..70c9abc 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -522,9 +522,10 @@ DECLARE_TRAP_HANDLER(alignment_check);
#undef DECLARE_TRAP_HANDLER_CONST
#undef DECLARE_TRAP_HANDLER
+extern void (*nmi_handler)(const struct cpu_user_regs *regs);
void trap_nop(void);
void enable_nmis(void);
-void noreturn do_nmi_crash(struct cpu_user_regs *regs);
+void noreturn do_nmi_crash(const struct cpu_user_regs *regs);
void do_reserved_trap(struct cpu_user_regs *regs);
void syscall_enter(void);
--
1.7.10.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |