aboutsummaryrefslogtreecommitdiff
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorAndi Kleen <andi@firstfloor.org>2009-02-12 13:39:31 +0100
committerH. Peter Anvin <hpa@linux.intel.com>2009-02-17 15:32:56 -0800
commitd6b75584a3eaab8cb2ab3e8cf90c5e57c1928a85 (patch)
treec7ebdcaed69bf744fb94c783101d9447c89cef54 /arch/x86/kernel
parent5b4408fdaa62474dd9485cddb9126370d90d4b82 (diff)
x86, mce: disable machine checks on offlined CPUs
Impact: Lower priority bug fix Offlined CPUs could still get machine checks, but the machine check handler cannot handle them properly, leading to an unconditional crash. Disable machine checks on CPUs that are going down. Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_64.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index 4e2b1bc5131..1db94c0d5aa 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -906,6 +906,27 @@ static __cpuinit void mce_remove_device(unsigned int cpu)
cpu_clear(cpu, mce_device_initialized);
}
+/* Make sure there are no machine checks on offlined CPUs. */
+static void __cpuexit mce_disable_cpu(void *h)
+{
+ int i;
+
+ if (!mce_available(&current_cpu_data))
+ return;
+ for (i = 0; i < banks; i++)
+ wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+}
+
+static void __cpuexit mce_reenable_cpu(void *h)
+{
+ int i;
+
+ if (!mce_available(&current_cpu_data))
+ return;
+ for (i = 0; i < banks; i++)
+ wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]);
+}
+
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
static int __cpuinit mce_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
@@ -929,11 +950,13 @@ static int __cpuinit mce_cpu_callback(struct notifier_block *nfb,
case CPU_DOWN_PREPARE:
case CPU_DOWN_PREPARE_FROZEN:
del_timer_sync(t);
+ smp_call_function_single(cpu, mce_disable_cpu, NULL, 1);
break;
case CPU_DOWN_FAILED:
case CPU_DOWN_FAILED_FROZEN:
t->expires = round_jiffies_relative(jiffies + next_interval);
add_timer_on(t, cpu);
+ smp_call_function_single(cpu, mce_reenable_cpu, NULL, 1);
break;
}
return NOTIFY_OK;