2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
5 * Pentium III FXSR, SSE support
6 * Gareth Hughes <gareth@valinux.com>, May 2000
10 * Handle hardware traps and faults.
12 #include <linux/spinlock.h>
13 #include <linux/kprobes.h>
14 #include <linux/kdebug.h>
15 #include <linux/nmi.h>
17 #if defined(CONFIG_EDAC)
18 #include <linux/edac.h>
21 #include <linux/atomic.h>
22 #include <asm/traps.h>
23 #include <asm/mach_traps.h>
25 static int ignore_nmis;
27 int unknown_nmi_panic;
29 * Prevent NMI reason port (0x61) being accessed simultaneously, can
30 * only be used in NMI handler.
32 static DEFINE_RAW_SPINLOCK(nmi_reason_lock);
34 static int __init setup_unknown_nmi_panic(char *str)
36 unknown_nmi_panic = 1;
39 __setup("unknown_nmi_panic", setup_unknown_nmi_panic);
41 static notrace __kprobes void
42 pci_serr_error(unsigned char reason, struct pt_regs *regs)
44 pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
45 reason, smp_processor_id());
48 * On some machines, PCI SERR line is used to report memory
49 * errors. EDAC makes use of it.
51 #if defined(CONFIG_EDAC)
52 if (edac_handler_set()) {
53 edac_atomic_assert_error();
58 if (panic_on_unrecovered_nmi)
59 panic("NMI: Not continuing");
61 pr_emerg("Dazed and confused, but trying to continue\n");
63 /* Clear and disable the PCI SERR error line. */
64 reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR;
65 outb(reason, NMI_REASON_PORT);
68 static notrace __kprobes void
69 io_check_error(unsigned char reason, struct pt_regs *regs)
74 "NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
75 reason, smp_processor_id());
79 panic("NMI IOCK error: Not continuing");
81 /* Re-enable the IOCK line, wait for a few seconds */
82 reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
83 outb(reason, NMI_REASON_PORT);
91 reason &= ~NMI_REASON_CLEAR_IOCHK;
92 outb(reason, NMI_REASON_PORT);
95 static notrace __kprobes void
96 unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
98 if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
103 * Might actually be able to figure out what the guilty party
111 pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
112 reason, smp_processor_id());
114 pr_emerg("Do you have a strange power saving mode enabled?\n");
115 if (unknown_nmi_panic || panic_on_unrecovered_nmi)
116 panic("NMI: Not continuing");
118 pr_emerg("Dazed and confused, but trying to continue\n");
121 static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
123 unsigned char reason = 0;
126 * CPU-specific NMI must be processed before non-CPU-specific
127 * NMI, otherwise we may lose it, because the CPU-specific
128 * NMI can not be detected/processed on other CPUs.
130 if (notify_die(DIE_NMI, "nmi", regs, 0, 2, SIGINT) == NOTIFY_STOP)
133 /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
134 raw_spin_lock(&nmi_reason_lock);
135 reason = get_nmi_reason();
137 if (reason & NMI_REASON_MASK) {
138 if (reason & NMI_REASON_SERR)
139 pci_serr_error(reason, regs);
140 else if (reason & NMI_REASON_IOCHK)
141 io_check_error(reason, regs);
144 * Reassert NMI in case it became active
145 * meanwhile as it's edge-triggered:
149 raw_spin_unlock(&nmi_reason_lock);
152 raw_spin_unlock(&nmi_reason_lock);
154 unknown_nmi_error(reason, regs);
157 dotraplinkage notrace __kprobes void
158 do_nmi(struct pt_regs *regs, long error_code)
162 inc_irq_stat(__nmi_count);
165 default_do_nmi(regs);
175 void restart_nmi(void)