aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/traps.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 23f6ac05d04c..613b3d284a89 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -84,6 +84,11 @@ EXPORT_SYMBOL_GPL(used_vectors);
84static int ignore_nmis; 84static int ignore_nmis;
85 85
86int unknown_nmi_panic; 86int unknown_nmi_panic;
87/*
88 * Prevent NMI reason port (0x61) being accessed simultaneously, can
89 * only be used in NMI handler.
90 */
91static DEFINE_RAW_SPINLOCK(nmi_reason_lock);
87 92
88static inline void conditional_sti(struct pt_regs *regs) 93static inline void conditional_sti(struct pt_regs *regs)
89{ 94{
@@ -392,7 +397,6 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
392static notrace __kprobes void default_do_nmi(struct pt_regs *regs) 397static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
393{ 398{
394 unsigned char reason = 0; 399 unsigned char reason = 0;
395 int cpu;
396 400
397 /* 401 /*
398 * CPU-specific NMI must be processed before non-CPU-specific 402 * CPU-specific NMI must be processed before non-CPU-specific
@@ -402,13 +406,12 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
402 if (notify_die(DIE_NMI, "nmi", regs, 0, 2, SIGINT) == NOTIFY_STOP) 406 if (notify_die(DIE_NMI, "nmi", regs, 0, 2, SIGINT) == NOTIFY_STOP)
403 return; 407 return;
404 408
405 cpu = smp_processor_id(); 409 /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
406 410 raw_spin_lock(&nmi_reason_lock);
407 /* Only the BSP gets external NMIs from the system. */ 411 reason = get_nmi_reason();
408 if (!cpu)
409 reason = get_nmi_reason();
410 412
411 if (!(reason & NMI_REASON_MASK)) { 413 if (!(reason & NMI_REASON_MASK)) {
414 raw_spin_unlock(&nmi_reason_lock);
412 unknown_nmi_error(reason, regs); 415 unknown_nmi_error(reason, regs);
413 416
414 return; 417 return;
@@ -426,6 +429,7 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
426 */ 429 */
427 reassert_nmi(); 430 reassert_nmi();
428#endif 431#endif
432 raw_spin_unlock(&nmi_reason_lock);
429} 433}
430 434
431dotraplinkage notrace __kprobes void 435dotraplinkage notrace __kprobes void