blob: 68d758aca8cdf308f8a85eb8122635a54ffe6f88 [file] [log] [blame]
Don Zickus1d489222011-09-30 15:06:19 -04001/*
2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
4 *
5 * Pentium III FXSR, SSE support
6 * Gareth Hughes <gareth@valinux.com>, May 2000
7 */
8
9/*
10 * Handle hardware traps and faults.
11 */
12#include <linux/spinlock.h>
13#include <linux/kprobes.h>
14#include <linux/kdebug.h>
15#include <linux/nmi.h>
16
17#if defined(CONFIG_EDAC)
18#include <linux/edac.h>
19#endif
20
21#include <linux/atomic.h>
22#include <asm/traps.h>
23#include <asm/mach_traps.h>
24
25static int ignore_nmis;
26
27int unknown_nmi_panic;
28/*
29 * Prevent NMI reason port (0x61) being accessed simultaneously, can
30 * only be used in NMI handler.
31 */
32static DEFINE_RAW_SPINLOCK(nmi_reason_lock);
33
34static int __init setup_unknown_nmi_panic(char *str)
35{
36 unknown_nmi_panic = 1;
37 return 1;
38}
39__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
40
41static notrace __kprobes void
42pci_serr_error(unsigned char reason, struct pt_regs *regs)
43{
44 pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
45 reason, smp_processor_id());
46
47 /*
48 * On some machines, PCI SERR line is used to report memory
49 * errors. EDAC makes use of it.
50 */
51#if defined(CONFIG_EDAC)
52 if (edac_handler_set()) {
53 edac_atomic_assert_error();
54 return;
55 }
56#endif
57
58 if (panic_on_unrecovered_nmi)
59 panic("NMI: Not continuing");
60
61 pr_emerg("Dazed and confused, but trying to continue\n");
62
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);
66}
67
68static notrace __kprobes void
69io_check_error(unsigned char reason, struct pt_regs *regs)
70{
71 unsigned long i;
72
73 pr_emerg(
74 "NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
75 reason, smp_processor_id());
76 show_registers(regs);
77
78 if (panic_on_io_nmi)
79 panic("NMI IOCK error: Not continuing");
80
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);
84
85 i = 20000;
86 while (--i) {
87 touch_nmi_watchdog();
88 udelay(100);
89 }
90
91 reason &= ~NMI_REASON_CLEAR_IOCHK;
92 outb(reason, NMI_REASON_PORT);
93}
94
95static notrace __kprobes void
96unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
97{
98 if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
99 NOTIFY_STOP)
100 return;
101#ifdef CONFIG_MCA
102 /*
103 * Might actually be able to figure out what the guilty party
104 * is:
105 */
106 if (MCA_bus) {
107 mca_handle_nmi();
108 return;
109 }
110#endif
111 pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
112 reason, smp_processor_id());
113
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");
117
118 pr_emerg("Dazed and confused, but trying to continue\n");
119}
120
121static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
122{
123 unsigned char reason = 0;
124
125 /*
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.
129 */
130 if (notify_die(DIE_NMI, "nmi", regs, 0, 2, SIGINT) == NOTIFY_STOP)
131 return;
132
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();
136
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);
142#ifdef CONFIG_X86_32
143 /*
144 * Reassert NMI in case it became active
145 * meanwhile as it's edge-triggered:
146 */
147 reassert_nmi();
148#endif
149 raw_spin_unlock(&nmi_reason_lock);
150 return;
151 }
152 raw_spin_unlock(&nmi_reason_lock);
153
154 unknown_nmi_error(reason, regs);
155}
156
157dotraplinkage notrace __kprobes void
158do_nmi(struct pt_regs *regs, long error_code)
159{
160 nmi_enter();
161
162 inc_irq_stat(__nmi_count);
163
164 if (!ignore_nmis)
165 default_do_nmi(regs);
166
167 nmi_exit();
168}
169
170void stop_nmi(void)
171{
172 ignore_nmis++;
173}
174
175void restart_nmi(void)
176{
177 ignore_nmis--;
178}