diff options
-rw-r--r-- | arch/x86/kernel/traps.c | 16 |
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); | |||
84 | static int ignore_nmis; | 84 | static int ignore_nmis; |
85 | 85 | ||
86 | int unknown_nmi_panic; | 86 | int unknown_nmi_panic; |
87 | /* | ||
88 | * Prevent NMI reason port (0x61) being accessed simultaneously, can | ||
89 | * only be used in NMI handler. | ||
90 | */ | ||
91 | static DEFINE_RAW_SPINLOCK(nmi_reason_lock); | ||
87 | 92 | ||
88 | static inline void conditional_sti(struct pt_regs *regs) | 93 | static inline void conditional_sti(struct pt_regs *regs) |
89 | { | 94 | { |
@@ -392,7 +397,6 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs) | |||
392 | static notrace __kprobes void default_do_nmi(struct pt_regs *regs) | 397 | static 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 | ||
431 | dotraplinkage notrace __kprobes void | 435 | dotraplinkage notrace __kprobes void |