aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/mce.h4
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c30
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel.c19
-rw-r--r--arch/x86/kernel/process.c2
-rw-r--r--arch/x86/kernel/smp.c2
5 files changed, 56 insertions, 1 deletions
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 38d3a1a8830f..2dbc0bf2b9f3 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -151,10 +151,12 @@ extern int mce_p5_enabled;
151#ifdef CONFIG_X86_MCE 151#ifdef CONFIG_X86_MCE
152int mcheck_init(void); 152int mcheck_init(void);
153void mcheck_cpu_init(struct cpuinfo_x86 *c); 153void mcheck_cpu_init(struct cpuinfo_x86 *c);
154void mcheck_cpu_clear(struct cpuinfo_x86 *c);
154void mcheck_vendor_init_severity(void); 155void mcheck_vendor_init_severity(void);
155#else 156#else
156static inline int mcheck_init(void) { return 0; } 157static inline int mcheck_init(void) { return 0; }
157static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {} 158static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {}
159static inline void mcheck_cpu_clear(struct cpuinfo_x86 *c) {}
158static inline void mcheck_vendor_init_severity(void) {} 160static inline void mcheck_vendor_init_severity(void) {}
159#endif 161#endif
160 162
@@ -181,12 +183,14 @@ DECLARE_PER_CPU(struct device *, mce_device);
181 183
182#ifdef CONFIG_X86_MCE_INTEL 184#ifdef CONFIG_X86_MCE_INTEL
183void mce_intel_feature_init(struct cpuinfo_x86 *c); 185void mce_intel_feature_init(struct cpuinfo_x86 *c);
186void mce_intel_feature_clear(struct cpuinfo_x86 *c);
184void cmci_clear(void); 187void cmci_clear(void);
185void cmci_reenable(void); 188void cmci_reenable(void);
186void cmci_rediscover(void); 189void cmci_rediscover(void);
187void cmci_recheck(void); 190void cmci_recheck(void);
188#else 191#else
189static inline void mce_intel_feature_init(struct cpuinfo_x86 *c) { } 192static inline void mce_intel_feature_init(struct cpuinfo_x86 *c) { }
193static inline void mce_intel_feature_clear(struct cpuinfo_x86 *c) { }
190static inline void cmci_clear(void) {} 194static inline void cmci_clear(void) {}
191static inline void cmci_reenable(void) {} 195static inline void cmci_reenable(void) {}
192static inline void cmci_rediscover(void) {} 196static inline void cmci_rediscover(void) {}
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 32b586ee006a..ee5272d77a16 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1606,6 +1606,17 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
1606 } 1606 }
1607} 1607}
1608 1608
1609static void __mcheck_cpu_clear_vendor(struct cpuinfo_x86 *c)
1610{
1611 switch (c->x86_vendor) {
1612 case X86_VENDOR_INTEL:
1613 mce_intel_feature_clear(c);
1614 break;
1615 default:
1616 break;
1617 }
1618}
1619
1609static void mce_start_timer(unsigned int cpu, struct timer_list *t) 1620static void mce_start_timer(unsigned int cpu, struct timer_list *t)
1610{ 1621{
1611 unsigned long iv = check_interval * HZ; 1622 unsigned long iv = check_interval * HZ;
@@ -1673,6 +1684,25 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)
1673} 1684}
1674 1685
1675/* 1686/*
1687 * Called for each booted CPU to clear some machine checks opt-ins
1688 */
1689void mcheck_cpu_clear(struct cpuinfo_x86 *c)
1690{
1691 if (mca_cfg.disabled)
1692 return;
1693
1694 if (!mce_available(c))
1695 return;
1696
1697 /*
1698 * Possibly to clear general settings generic to x86
1699 * __mcheck_cpu_clear_generic(c);
1700 */
1701 __mcheck_cpu_clear_vendor(c);
1702
1703}
1704
1705/*
1676 * mce_chrdev: Character device /dev/mcelog to read and clear the MCE log. 1706 * mce_chrdev: Character device /dev/mcelog to read and clear the MCE log.
1677 */ 1707 */
1678 1708
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 70f567f774ed..c5c003291861 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -434,7 +434,7 @@ static void intel_init_cmci(void)
434 cmci_recheck(); 434 cmci_recheck();
435} 435}
436 436
437void intel_init_lmce(void) 437static void intel_init_lmce(void)
438{ 438{
439 u64 val; 439 u64 val;
440 440
@@ -447,9 +447,26 @@ void intel_init_lmce(void)
447 wrmsrl(MSR_IA32_MCG_EXT_CTL, val | MCG_EXT_CTL_LMCE_EN); 447 wrmsrl(MSR_IA32_MCG_EXT_CTL, val | MCG_EXT_CTL_LMCE_EN);
448} 448}
449 449
450static void intel_clear_lmce(void)
451{
452 u64 val;
453
454 if (!lmce_supported())
455 return;
456
457 rdmsrl(MSR_IA32_MCG_EXT_CTL, val);
458 val &= ~MCG_EXT_CTL_LMCE_EN;
459 wrmsrl(MSR_IA32_MCG_EXT_CTL, val);
460}
461
450void mce_intel_feature_init(struct cpuinfo_x86 *c) 462void mce_intel_feature_init(struct cpuinfo_x86 *c)
451{ 463{
452 intel_init_thermal(c); 464 intel_init_thermal(c);
453 intel_init_cmci(); 465 intel_init_cmci();
454 intel_init_lmce(); 466 intel_init_lmce();
455} 467}
468
469void mce_intel_feature_clear(struct cpuinfo_x86 *c)
470{
471 intel_clear_lmce();
472}
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 397688beed4b..b20ef187ff41 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -29,6 +29,7 @@
29#include <asm/debugreg.h> 29#include <asm/debugreg.h>
30#include <asm/nmi.h> 30#include <asm/nmi.h>
31#include <asm/tlbflush.h> 31#include <asm/tlbflush.h>
32#include <asm/mce.h>
32 33
33/* 34/*
34 * per-CPU TSS segments. Threads are completely 'soft' on Linux, 35 * per-CPU TSS segments. Threads are completely 'soft' on Linux,
@@ -319,6 +320,7 @@ void stop_this_cpu(void *dummy)
319 */ 320 */
320 set_cpu_online(smp_processor_id(), false); 321 set_cpu_online(smp_processor_id(), false);
321 disable_local_APIC(); 322 disable_local_APIC();
323 mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
322 324
323 for (;;) 325 for (;;)
324 halt(); 326 halt();
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 15aaa69bbb5e..12c8286206ce 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -30,6 +30,7 @@
30#include <asm/proto.h> 30#include <asm/proto.h>
31#include <asm/apic.h> 31#include <asm/apic.h>
32#include <asm/nmi.h> 32#include <asm/nmi.h>
33#include <asm/mce.h>
33#include <asm/trace/irq_vectors.h> 34#include <asm/trace/irq_vectors.h>
34/* 35/*
35 * Some notes on x86 processor bugs affecting SMP operation: 36 * Some notes on x86 processor bugs affecting SMP operation:
@@ -243,6 +244,7 @@ static void native_stop_other_cpus(int wait)
243finish: 244finish:
244 local_irq_save(flags); 245 local_irq_save(flags);
245 disable_local_APIC(); 246 disable_local_APIC();
247 mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
246 local_irq_restore(flags); 248 local_irq_restore(flags);
247} 249}
248 250