aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/mce.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/mce.c')
-rw-r--r--arch/x86_64/kernel/mce.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 183dc610542954..13a2eada6c9520 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -15,6 +15,7 @@
#include <linux/sysdev.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
+#include <linux/capability.h>
#include <linux/cpu.h>
#include <linux/percpu.h>
#include <linux/ctype.h>
@@ -23,9 +24,10 @@
#include <asm/mce.h>
#include <asm/kdebug.h>
#include <asm/uaccess.h>
+#include <asm/smp.h>
#define MISC_MCELOG_MINOR 227
-#define NR_BANKS 5
+#define NR_BANKS 6
static int mce_dont_init;
@@ -91,6 +93,7 @@ void mce_log(struct mce *mce)
static void print_mce(struct mce *m)
{
printk(KERN_EMERG "\n"
+ KERN_EMERG "HARDWARE ERROR\n"
KERN_EMERG
"CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
m->cpu, m->mcgstatus, m->bank, m->status);
@@ -109,6 +112,9 @@ static void print_mce(struct mce *m)
if (m->misc)
printk("MISC %Lx ", m->misc);
printk("\n");
+ printk(KERN_EMERG "This is not a software problem!\n");
+ printk(KERN_EMERG
+ "Run through mcelog --ascii to decode and contact your hardware vendor\n");
}
static void mce_panic(char *msg, struct mce *backup, unsigned long start)
@@ -168,12 +174,12 @@ void do_machine_check(struct pt_regs * regs, long error_code)
int panicm_found = 0;
if (regs)
- notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL);
+ notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL);
if (!banks)
return;
memset(&m, 0, sizeof(struct mce));
- m.cpu = hard_smp_processor_id();
+ m.cpu = safe_smp_processor_id();
rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
if (!(m.mcgstatus & MCG_STATUS_RIPV))
kill_it = 1;
@@ -573,6 +579,10 @@ ACCESSOR(bank1ctl,bank[1],mce_restart())
ACCESSOR(bank2ctl,bank[2],mce_restart())
ACCESSOR(bank3ctl,bank[3],mce_restart())
ACCESSOR(bank4ctl,bank[4],mce_restart())
+ACCESSOR(bank5ctl,bank[5],mce_restart())
+static struct sysdev_attribute * bank_attributes[NR_BANKS] = {
+ &attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl,
+ &attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl};
ACCESSOR(tolerant,tolerant,)
ACCESSOR(check_interval,check_interval,mce_restart())
@@ -580,6 +590,7 @@ ACCESSOR(check_interval,check_interval,mce_restart())
static __cpuinit int mce_create_device(unsigned int cpu)
{
int err;
+ int i;
if (!mce_available(&cpu_data[cpu]))
return -EIO;
@@ -589,11 +600,9 @@ static __cpuinit int mce_create_device(unsigned int cpu)
err = sysdev_register(&per_cpu(device_mce,cpu));
if (!err) {
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank0ctl);
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank1ctl);
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank2ctl);
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank3ctl);
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank4ctl);
+ for (i = 0; i < banks; i++)
+ sysdev_create_file(&per_cpu(device_mce,cpu),
+ bank_attributes[i]);
sysdev_create_file(&per_cpu(device_mce,cpu), &attr_tolerant);
sysdev_create_file(&per_cpu(device_mce,cpu), &attr_check_interval);
}
@@ -603,11 +612,11 @@ static __cpuinit int mce_create_device(unsigned int cpu)
#ifdef CONFIG_HOTPLUG_CPU
static __cpuinit void mce_remove_device(unsigned int cpu)
{
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank0ctl);
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank1ctl);
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank2ctl);
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank3ctl);
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank4ctl);
+ int i;
+
+ for (i = 0; i < banks; i++)
+ sysdev_remove_file(&per_cpu(device_mce,cpu),
+ bank_attributes[i]);
sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_tolerant);
sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval);
sysdev_unregister(&per_cpu(device_mce,cpu));