2 * Non Fatal Machine Check Exception Reporting
4 * (C) Copyright 2002 Dave Jones. <davej@codemonkey.org.uk>
6 * This file contains routines to check for non-fatal MCEs every 15s
10 #include <linux/init.h>
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <linux/jiffies.h>
14 #include <linux/config.h>
15 #include <linux/irq.h>
16 #include <linux/workqueue.h>
17 #include <linux/interrupt.h>
18 #include <linux/smp.h>
19 #include <linux/module.h>
21 #include <asm/processor.h>
22 #include <asm/system.h>
27 static struct timer_list mce_timer;
31 #define MCE_RATE 15*HZ /* timer rate is 15s */
33 static void mce_checkregs (void *info)
39 for (i=firstbank; i<nr_mce_banks; i++) {
40 rdmsr (MSR_IA32_MC0_STATUS+i*4, low, high);
43 printk (KERN_EMERG "MCE: The hardware reports a non fatal, correctable incident occurred on CPU %d.\n",
45 printk (KERN_EMERG "Bank %d: %08x%08x\n", i, high, low);
47 /* Scrub the error so we don't pick it up in MCE_RATE seconds time. */
48 wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
57 static void do_mce_timer(void *data)
59 smp_call_function (mce_checkregs, NULL, 1, 1);
62 static DECLARE_WORK(mce_work, do_mce_timer, NULL);
64 static void mce_timerfunc (unsigned long data)
68 if (num_online_cpus() > 1)
69 schedule_work (&mce_work);
71 mce_timer.expires = jiffies + MCE_RATE;
72 add_timer (&mce_timer);
75 static int __init init_nonfatal_mce_checker(void)
77 struct cpuinfo_x86 *c = &boot_cpu_data;
79 /* Check for MCE support */
80 if (!cpu_has(c, X86_FEATURE_MCE))
83 /* Check for PPro style MCA */
84 if (!cpu_has(c, X86_FEATURE_MCA))
87 /* Some Athlons misbehave when we frob bank 0 */
88 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
89 boot_cpu_data.x86 == 6)
95 /* Set the timer to check for non-fatal
96 errors every MCE_RATE seconds */
97 init_timer (&mce_timer);
98 mce_timer.expires = jiffies + MCE_RATE;
100 mce_timer.function = &mce_timerfunc;
101 add_timer (&mce_timer);
103 printk(KERN_INFO "Machine check exception polling timer started.\n");
107 module_init(init_nonfatal_mce_checker);