aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDon Zickus <dzickus@redhat.com>2011-01-06 16:18:51 -0500
committerIngo Molnar <mingo@elte.hu>2011-01-07 09:08:53 -0500
commitab846f13f69fa64f8ed69ce0c3e239e075910d23 (patch)
tree737dbe8e6c0fbbdef041cce46b040a606435121b
parentc410b8307702c1e1f35be3fd868ad18e4ba0410f (diff)
x86, NMI: Allow NMI reason io port (0x61) to be processed on any CPU
In original NMI handler, NMI reason io port (0x61) is only processed on BSP. This makes it impossible to hot-remove BSP. To solve the issue, a raw spinlock is used to allow the port to be processed on any CPU. Originally-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Don Zickus <dzickus@redhat.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <1294348732-15030-6-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-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