linux/arch/x86/kernel/cpu/mcheck/non-fatal.c
<<
>>
Prefs
   1/*
   2 * Non Fatal Machine Check Exception Reporting
   3 *
   4 * (C) Copyright 2002 Dave Jones. <davej@codemonkey.org.uk>
   5 *
   6 * This file contains routines to check for non-fatal MCEs every 15s
   7 *
   8 */
   9
  10#include <linux/init.h>
  11#include <linux/types.h>
  12#include <linux/kernel.h>
  13#include <linux/jiffies.h>
  14#include <linux/workqueue.h>
  15#include <linux/interrupt.h>
  16#include <linux/smp.h>
  17#include <linux/module.h>
  18
  19#include <asm/processor.h> 
  20#include <asm/system.h>
  21#include <asm/msr.h>
  22
  23#include "mce.h"
  24
  25static int firstbank;
  26
  27#define MCE_RATE        15*HZ   /* timer rate is 15s */
  28
  29static void mce_checkregs (void *info)
  30{
  31        u32 low, high;
  32        int i;
  33
  34        for (i=firstbank; i<nr_mce_banks; i++) {
  35                rdmsr (MSR_IA32_MC0_STATUS+i*4, low, high);
  36
  37                if (high & (1<<31)) {
  38                        printk(KERN_INFO "MCE: The hardware reports a non "
  39                                "fatal, correctable incident occurred on "
  40                                "CPU %d.\n",
  41                                smp_processor_id());
  42                        printk (KERN_INFO "Bank %d: %08x%08x\n", i, high, low);
  43
  44                        /* Scrub the error so we don't pick it up in MCE_RATE seconds time. */
  45                        wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
  46
  47                        /* Serialize */
  48                        wmb();
  49                        add_taint(TAINT_MACHINE_CHECK);
  50                }
  51        }
  52}
  53
  54static void mce_work_fn(struct work_struct *work);
  55static DECLARE_DELAYED_WORK(mce_work, mce_work_fn);
  56
  57static void mce_work_fn(struct work_struct *work)
  58{ 
  59        on_each_cpu(mce_checkregs, NULL, 1, 1);
  60        schedule_delayed_work(&mce_work, round_jiffies_relative(MCE_RATE));
  61} 
  62
  63static int __init init_nonfatal_mce_checker(void)
  64{
  65        struct cpuinfo_x86 *c = &boot_cpu_data;
  66
  67        /* Check for MCE support */
  68        if (!cpu_has(c, X86_FEATURE_MCE))
  69                return -ENODEV;
  70
  71        /* Check for PPro style MCA */
  72        if (!cpu_has(c, X86_FEATURE_MCA))
  73                return -ENODEV;
  74
  75        /* Some Athlons misbehave when we frob bank 0 */
  76        if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
  77                boot_cpu_data.x86 == 6)
  78                        firstbank = 1;
  79        else
  80                        firstbank = 0;
  81
  82        /*
  83         * Check for non-fatal errors every MCE_RATE s
  84         */
  85        schedule_delayed_work(&mce_work, round_jiffies_relative(MCE_RATE));
  86        printk(KERN_INFO "Machine check exception polling timer started.\n");
  87        return 0;
  88}
  89module_init(init_nonfatal_mce_checker);
  90
  91MODULE_LICENSE("GPL");
  92