Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 228934
b: refs/heads/master
c: 1c7b74d
h: refs/heads/master
v: v3
  • Loading branch information
Huang Ying authored and Ingo Molnar committed Jan 7, 2011
1 parent 66e3cb0 commit 42870e0
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4158755d3136f4cb05c1a8a260e9c06f93baeb48
refs/heads/master: 1c7b74d46fed530cca22a9a54140cdac2815c797
12 changes: 11 additions & 1 deletion trunk/arch/x86/include/asm/mach_traps.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@

#include <asm/mc146818rtc.h>

#define NMI_REASON_PORT 0x61

#define NMI_REASON_SERR 0x80
#define NMI_REASON_IOCHK 0x40
#define NMI_REASON_MASK (NMI_REASON_SERR | NMI_REASON_IOCHK)

#define NMI_REASON_CLEAR_SERR 0x04
#define NMI_REASON_CLEAR_IOCHK 0x08
#define NMI_REASON_CLEAR_MASK 0x0f

static inline unsigned char get_nmi_reason(void)
{
return inb(0x61);
return inb(NMI_REASON_PORT);
}

static inline void reassert_nmi(void)
Expand Down
51 changes: 26 additions & 25 deletions trunk/arch/x86/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,15 @@ static int __init setup_unknown_nmi_panic(char *str)
__setup("unknown_nmi_panic", setup_unknown_nmi_panic);

static notrace __kprobes void
mem_parity_error(unsigned char reason, struct pt_regs *regs)
pci_serr_error(unsigned char reason, struct pt_regs *regs)
{
printk(KERN_EMERG
"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
reason, smp_processor_id());

printk(KERN_EMERG
"You have some hardware problem, likely on the PCI bus.\n");
pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
reason, smp_processor_id());

/*
* On some machines, PCI SERR line is used to report memory
* errors. EDAC makes use of it.
*/
#if defined(CONFIG_EDAC)
if (edac_handler_set()) {
edac_atomic_assert_error();
Expand All @@ -329,36 +329,38 @@ mem_parity_error(unsigned char reason, struct pt_regs *regs)
if (panic_on_unrecovered_nmi)
panic("NMI: Not continuing");

printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
pr_emerg("Dazed and confused, but trying to continue\n");

/* Clear and disable the memory parity error line. */
reason = (reason & 0xf) | 4;
outb(reason, 0x61);
/* Clear and disable the PCI SERR error line. */
reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR;
outb(reason, NMI_REASON_PORT);
}

static notrace __kprobes void
io_check_error(unsigned char reason, struct pt_regs *regs)
{
unsigned long i;

printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
pr_emerg(
"NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
reason, smp_processor_id());
show_registers(regs);

if (panic_on_io_nmi)
panic("NMI IOCK error: Not continuing");

/* Re-enable the IOCK line, wait for a few seconds */
reason = (reason & 0xf) | 8;
outb(reason, 0x61);
reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
outb(reason, NMI_REASON_PORT);

i = 20000;
while (--i) {
touch_nmi_watchdog();
udelay(100);
}

reason &= ~8;
outb(reason, 0x61);
reason &= ~NMI_REASON_CLEAR_IOCHK;
outb(reason, NMI_REASON_PORT);
}

static notrace __kprobes void
Expand All @@ -377,15 +379,14 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
return;
}
#endif
printk(KERN_EMERG
"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
reason, smp_processor_id());
pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
reason, smp_processor_id());

printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
pr_emerg("Do you have a strange power saving mode enabled?\n");
if (unknown_nmi_panic || panic_on_unrecovered_nmi)
panic("NMI: Not continuing");

printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
pr_emerg("Dazed and confused, but trying to continue\n");
}

static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
Expand All @@ -399,7 +400,7 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
if (!cpu)
reason = get_nmi_reason();

if (!(reason & 0xc0)) {
if (!(reason & NMI_REASON_MASK)) {
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
== NOTIFY_STOP)
return;
Expand All @@ -417,9 +418,9 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
return;

/* AK: following checks seem to be broken on modern chipsets. FIXME */
if (reason & 0x80)
mem_parity_error(reason, regs);
if (reason & 0x40)
if (reason & NMI_REASON_SERR)
pci_serr_error(reason, regs);
if (reason & NMI_REASON_IOCHK)
io_check_error(reason, regs);
#ifdef CONFIG_X86_32
/*
Expand Down

0 comments on commit 42870e0

Please sign in to comment.