diff options
| -rw-r--r-- | arch/x86/include/asm/mce.h | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 30 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_intel.c | 19 | ||||
| -rw-r--r-- | arch/x86/kernel/process.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/smp.c | 2 |
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 |
| 152 | int mcheck_init(void); | 152 | int mcheck_init(void); |
| 153 | void mcheck_cpu_init(struct cpuinfo_x86 *c); | 153 | void mcheck_cpu_init(struct cpuinfo_x86 *c); |
| 154 | void mcheck_cpu_clear(struct cpuinfo_x86 *c); | ||
| 154 | void mcheck_vendor_init_severity(void); | 155 | void mcheck_vendor_init_severity(void); |
| 155 | #else | 156 | #else |
| 156 | static inline int mcheck_init(void) { return 0; } | 157 | static inline int mcheck_init(void) { return 0; } |
| 157 | static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {} | 158 | static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {} |
| 159 | static inline void mcheck_cpu_clear(struct cpuinfo_x86 *c) {} | ||
| 158 | static inline void mcheck_vendor_init_severity(void) {} | 160 | static 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 |
| 183 | void mce_intel_feature_init(struct cpuinfo_x86 *c); | 185 | void mce_intel_feature_init(struct cpuinfo_x86 *c); |
| 186 | void mce_intel_feature_clear(struct cpuinfo_x86 *c); | ||
| 184 | void cmci_clear(void); | 187 | void cmci_clear(void); |
| 185 | void cmci_reenable(void); | 188 | void cmci_reenable(void); |
| 186 | void cmci_rediscover(void); | 189 | void cmci_rediscover(void); |
| 187 | void cmci_recheck(void); | 190 | void cmci_recheck(void); |
| 188 | #else | 191 | #else |
| 189 | static inline void mce_intel_feature_init(struct cpuinfo_x86 *c) { } | 192 | static inline void mce_intel_feature_init(struct cpuinfo_x86 *c) { } |
| 193 | static inline void mce_intel_feature_clear(struct cpuinfo_x86 *c) { } | ||
| 190 | static inline void cmci_clear(void) {} | 194 | static inline void cmci_clear(void) {} |
| 191 | static inline void cmci_reenable(void) {} | 195 | static inline void cmci_reenable(void) {} |
| 192 | static inline void cmci_rediscover(void) {} | 196 | static 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 | ||
| 1609 | static 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 | |||
| 1609 | static void mce_start_timer(unsigned int cpu, struct timer_list *t) | 1620 | static 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 | */ | ||
| 1689 | void 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 | ||
| 437 | void intel_init_lmce(void) | 437 | static 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 | ||
| 450 | static 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 | |||
| 450 | void mce_intel_feature_init(struct cpuinfo_x86 *c) | 462 | void 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 | |||
| 469 | void 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) | |||
| 243 | finish: | 244 | finish: |
| 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 | ||
