diff options
| -rw-r--r-- | arch/x86/include/asm/hardirq.h | 6 | ||||
| -rw-r--r-- | arch/x86/include/asm/mce.h | 14 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/common.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 103 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/therm_throt.c | 29 | ||||
| -rw-r--r-- | arch/x86/kernel/irq.c | 12 | ||||
| -rw-r--r-- | arch/x86/kernel/setup.c | 3 | ||||
| -rw-r--r-- | drivers/edac/edac_mce_amd.c | 21 | ||||
| -rw-r--r-- | include/trace/events/mce.h | 69 |
9 files changed, 198 insertions, 63 deletions
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 82e3e8f01043..108eb6fd1ae7 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
| @@ -20,11 +20,11 @@ typedef struct { | |||
| 20 | unsigned int irq_call_count; | 20 | unsigned int irq_call_count; |
| 21 | unsigned int irq_tlb_count; | 21 | unsigned int irq_tlb_count; |
| 22 | #endif | 22 | #endif |
| 23 | #ifdef CONFIG_X86_MCE | 23 | #ifdef CONFIG_X86_THERMAL_VECTOR |
| 24 | unsigned int irq_thermal_count; | 24 | unsigned int irq_thermal_count; |
| 25 | # ifdef CONFIG_X86_MCE_THRESHOLD | 25 | #endif |
| 26 | #ifdef CONFIG_X86_MCE_THRESHOLD | ||
| 26 | unsigned int irq_threshold_count; | 27 | unsigned int irq_threshold_count; |
| 27 | # endif | ||
| 28 | #endif | 28 | #endif |
| 29 | } ____cacheline_aligned irq_cpustat_t; | 29 | } ____cacheline_aligned irq_cpustat_t; |
| 30 | 30 | ||
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index f1363b72364f..858baa061cfc 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
| @@ -108,6 +108,8 @@ struct mce_log { | |||
| 108 | #define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9) | 108 | #define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9) |
| 109 | #define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0) | 109 | #define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0) |
| 110 | 110 | ||
| 111 | extern struct atomic_notifier_head x86_mce_decoder_chain; | ||
| 112 | |||
| 111 | #ifdef __KERNEL__ | 113 | #ifdef __KERNEL__ |
| 112 | 114 | ||
| 113 | #include <linux/percpu.h> | 115 | #include <linux/percpu.h> |
| @@ -118,9 +120,11 @@ extern int mce_disabled; | |||
| 118 | extern int mce_p5_enabled; | 120 | extern int mce_p5_enabled; |
| 119 | 121 | ||
| 120 | #ifdef CONFIG_X86_MCE | 122 | #ifdef CONFIG_X86_MCE |
| 121 | void mcheck_init(struct cpuinfo_x86 *c); | 123 | int mcheck_init(void); |
| 124 | void mcheck_cpu_init(struct cpuinfo_x86 *c); | ||
| 122 | #else | 125 | #else |
| 123 | static inline void mcheck_init(struct cpuinfo_x86 *c) {} | 126 | static inline int mcheck_init(void) { return 0; } |
| 127 | static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {} | ||
| 124 | #endif | 128 | #endif |
| 125 | 129 | ||
| 126 | #ifdef CONFIG_X86_ANCIENT_MCE | 130 | #ifdef CONFIG_X86_ANCIENT_MCE |
| @@ -214,5 +218,11 @@ void intel_init_thermal(struct cpuinfo_x86 *c); | |||
| 214 | 218 | ||
| 215 | void mce_log_therm_throt_event(__u64 status); | 219 | void mce_log_therm_throt_event(__u64 status); |
| 216 | 220 | ||
| 221 | #ifdef CONFIG_X86_THERMAL_VECTOR | ||
| 222 | extern void mcheck_intel_therm_init(void); | ||
| 223 | #else | ||
| 224 | static inline void mcheck_intel_therm_init(void) { } | ||
| 225 | #endif | ||
| 226 | |||
| 217 | #endif /* __KERNEL__ */ | 227 | #endif /* __KERNEL__ */ |
| 218 | #endif /* _ASM_X86_MCE_H */ | 228 | #endif /* _ASM_X86_MCE_H */ |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index cc25c2b4a567..9053be5d95cd 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
| @@ -837,10 +837,8 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) | |||
| 837 | boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; | 837 | boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; |
| 838 | } | 838 | } |
| 839 | 839 | ||
| 840 | #ifdef CONFIG_X86_MCE | ||
| 841 | /* Init Machine Check Exception if available. */ | 840 | /* Init Machine Check Exception if available. */ |
| 842 | mcheck_init(c); | 841 | mcheck_cpu_init(c); |
| 843 | #endif | ||
| 844 | 842 | ||
| 845 | select_idle_routine(c); | 843 | select_idle_routine(c); |
| 846 | 844 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 721a77ca8115..0bcaa3875863 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
| @@ -46,6 +46,9 @@ | |||
| 46 | 46 | ||
| 47 | #include "mce-internal.h" | 47 | #include "mce-internal.h" |
| 48 | 48 | ||
| 49 | #define CREATE_TRACE_POINTS | ||
| 50 | #include <trace/events/mce.h> | ||
| 51 | |||
| 49 | int mce_disabled __read_mostly; | 52 | int mce_disabled __read_mostly; |
| 50 | 53 | ||
| 51 | #define MISC_MCELOG_MINOR 227 | 54 | #define MISC_MCELOG_MINOR 227 |
| @@ -85,18 +88,26 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_wait); | |||
| 85 | static DEFINE_PER_CPU(struct mce, mces_seen); | 88 | static DEFINE_PER_CPU(struct mce, mces_seen); |
| 86 | static int cpu_missing; | 89 | static int cpu_missing; |
| 87 | 90 | ||
| 88 | static void default_decode_mce(struct mce *m) | 91 | /* |
| 92 | * CPU/chipset specific EDAC code can register a notifier call here to print | ||
| 93 | * MCE errors in a human-readable form. | ||
| 94 | */ | ||
| 95 | ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); | ||
| 96 | EXPORT_SYMBOL_GPL(x86_mce_decoder_chain); | ||
| 97 | |||
| 98 | static int default_decode_mce(struct notifier_block *nb, unsigned long val, | ||
| 99 | void *data) | ||
| 89 | { | 100 | { |
| 90 | pr_emerg("No human readable MCE decoding support on this CPU type.\n"); | 101 | pr_emerg("No human readable MCE decoding support on this CPU type.\n"); |
| 91 | pr_emerg("Run the message through 'mcelog --ascii' to decode.\n"); | 102 | pr_emerg("Run the message through 'mcelog --ascii' to decode.\n"); |
| 103 | |||
| 104 | return NOTIFY_STOP; | ||
| 92 | } | 105 | } |
| 93 | 106 | ||
| 94 | /* | 107 | static struct notifier_block mce_dec_nb = { |
| 95 | * CPU/chipset specific EDAC code can register a callback here to print | 108 | .notifier_call = default_decode_mce, |
| 96 | * MCE errors in a human-readable form: | 109 | .priority = -1, |
| 97 | */ | 110 | }; |
| 98 | void (*x86_mce_decode_callback)(struct mce *m) = default_decode_mce; | ||
| 99 | EXPORT_SYMBOL(x86_mce_decode_callback); | ||
| 100 | 111 | ||
| 101 | /* MCA banks polled by the period polling timer for corrected events */ | 112 | /* MCA banks polled by the period polling timer for corrected events */ |
| 102 | DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { | 113 | DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { |
| @@ -141,6 +152,9 @@ void mce_log(struct mce *mce) | |||
| 141 | { | 152 | { |
| 142 | unsigned next, entry; | 153 | unsigned next, entry; |
| 143 | 154 | ||
| 155 | /* Emit the trace record: */ | ||
| 156 | trace_mce_record(mce); | ||
| 157 | |||
| 144 | mce->finished = 0; | 158 | mce->finished = 0; |
| 145 | wmb(); | 159 | wmb(); |
| 146 | for (;;) { | 160 | for (;;) { |
| @@ -204,9 +218,9 @@ static void print_mce(struct mce *m) | |||
| 204 | 218 | ||
| 205 | /* | 219 | /* |
| 206 | * Print out human-readable details about the MCE error, | 220 | * Print out human-readable details about the MCE error, |
| 207 | * (if the CPU has an implementation for that): | 221 | * (if the CPU has an implementation for that) |
| 208 | */ | 222 | */ |
| 209 | x86_mce_decode_callback(m); | 223 | atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m); |
| 210 | } | 224 | } |
| 211 | 225 | ||
| 212 | static void print_mce_head(void) | 226 | static void print_mce_head(void) |
| @@ -1122,7 +1136,7 @@ static int check_interval = 5 * 60; /* 5 minutes */ | |||
| 1122 | static DEFINE_PER_CPU(int, mce_next_interval); /* in jiffies */ | 1136 | static DEFINE_PER_CPU(int, mce_next_interval); /* in jiffies */ |
| 1123 | static DEFINE_PER_CPU(struct timer_list, mce_timer); | 1137 | static DEFINE_PER_CPU(struct timer_list, mce_timer); |
| 1124 | 1138 | ||
| 1125 | static void mcheck_timer(unsigned long data) | 1139 | static void mce_start_timer(unsigned long data) |
| 1126 | { | 1140 | { |
| 1127 | struct timer_list *t = &per_cpu(mce_timer, data); | 1141 | struct timer_list *t = &per_cpu(mce_timer, data); |
| 1128 | int *n; | 1142 | int *n; |
| @@ -1187,7 +1201,7 @@ int mce_notify_irq(void) | |||
| 1187 | } | 1201 | } |
| 1188 | EXPORT_SYMBOL_GPL(mce_notify_irq); | 1202 | EXPORT_SYMBOL_GPL(mce_notify_irq); |
| 1189 | 1203 | ||
| 1190 | static int mce_banks_init(void) | 1204 | static int __cpuinit __mcheck_cpu_mce_banks_init(void) |
| 1191 | { | 1205 | { |
| 1192 | int i; | 1206 | int i; |
| 1193 | 1207 | ||
| @@ -1206,7 +1220,7 @@ static int mce_banks_init(void) | |||
| 1206 | /* | 1220 | /* |
| 1207 | * Initialize Machine Checks for a CPU. | 1221 | * Initialize Machine Checks for a CPU. |
| 1208 | */ | 1222 | */ |
| 1209 | static int __cpuinit mce_cap_init(void) | 1223 | static int __cpuinit __mcheck_cpu_cap_init(void) |
