diff options
| -rw-r--r-- | arch/x86/include/asm/mce.h | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_64.c | 16 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 3 |
3 files changed, 18 insertions, 6 deletions
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 125cd8714622..9b9523699dbc 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
| @@ -119,11 +119,14 @@ extern atomic_t mce_entry; | |||
| 119 | 119 | ||
| 120 | extern void do_machine_check(struct pt_regs *, long); | 120 | extern void do_machine_check(struct pt_regs *, long); |
| 121 | 121 | ||
| 122 | typedef DECLARE_BITMAP(mce_banks_t, MAX_NR_BANKS); | ||
| 123 | DECLARE_PER_CPU(mce_banks_t, mce_poll_banks); | ||
| 124 | |||
| 122 | enum mcp_flags { | 125 | enum mcp_flags { |
| 123 | MCP_TIMESTAMP = (1 << 0), /* log time stamp */ | 126 | MCP_TIMESTAMP = (1 << 0), /* log time stamp */ |
| 124 | MCP_UC = (1 << 1), /* log uncorrected errors */ | 127 | MCP_UC = (1 << 1), /* log uncorrected errors */ |
| 125 | }; | 128 | }; |
| 126 | extern void machine_check_poll(enum mcp_flags flags); | 129 | extern void machine_check_poll(enum mcp_flags flags, mce_banks_t *b); |
| 127 | 130 | ||
| 128 | extern int mce_notify_user(void); | 131 | extern int mce_notify_user(void); |
| 129 | 132 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 9017609cadd9..a8ff38bfa6ed 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c | |||
| @@ -62,6 +62,11 @@ static char *trigger_argv[2] = { trigger, NULL }; | |||
| 62 | 62 | ||
| 63 | static DECLARE_WAIT_QUEUE_HEAD(mce_wait); | 63 | static DECLARE_WAIT_QUEUE_HEAD(mce_wait); |
| 64 | 64 | ||
| 65 | /* MCA banks polled by the period polling timer for corrected events */ | ||
| 66 | DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { | ||
| 67 | [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL | ||
| 68 | }; | ||
| 69 | |||
| 65 | /* Do initial initialization of a struct mce */ | 70 | /* Do initial initialization of a struct mce */ |
| 66 | void mce_setup(struct mce *m) | 71 | void mce_setup(struct mce *m) |
| 67 | { | 72 | { |
| @@ -191,7 +196,7 @@ static inline void mce_get_rip(struct mce *m, struct pt_regs *regs) | |||
| 191 | * | 196 | * |
| 192 | * This is executed in standard interrupt context. | 197 | * This is executed in standard interrupt context. |
| 193 | */ | 198 | */ |
| 194 | void machine_check_poll(enum mcp_flags flags) | 199 | void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) |
| 195 | { | 200 | { |
| 196 | struct mce m; | 201 | struct mce m; |
| 197 | int i; | 202 | int i; |
| @@ -200,7 +205,7 @@ void machine_check_poll(enum mcp_flags flags) | |||
| 200 | 205 | ||
| 201 | rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); | 206 | rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); |
| 202 | for (i = 0; i < banks; i++) { | 207 | for (i = 0; i < banks; i++) { |
| 203 | if (!bank[i]) | 208 | if (!bank[i] || !test_bit(i, *b)) |
| 204 | continue; | 209 | continue; |
| 205 | 210 | ||
| 206 | m.misc = 0; | 211 | m.misc = 0; |
| @@ -458,7 +463,8 @@ static void mcheck_timer(unsigned long data) | |||
| 458 | WARN_ON(smp_processor_id() != data); | 463 | WARN_ON(smp_processor_id() != data); |
| 459 | 464 | ||
| 460 | if (mce_available(¤t_cpu_data)) | 465 | if (mce_available(¤t_cpu_data)) |
| 461 | machine_check_poll(MCP_TIMESTAMP); | 466 | machine_check_poll(MCP_TIMESTAMP, |
| 467 | &__get_cpu_var(mce_poll_banks)); | ||
| 462 | 468 | ||
| 463 | /* | 469 | /* |
| 464 | * Alert userspace if needed. If we logged an MCE, reduce the | 470 | * Alert userspace if needed. If we logged an MCE, reduce the |
| @@ -572,11 +578,13 @@ static void mce_init(void *dummy) | |||
| 572 | { | 578 | { |
| 573 | u64 cap; | 579 | u64 cap; |
| 574 | int i; | 580 | int i; |
| 581 | mce_banks_t all_banks; | ||
| 575 | 582 | ||
| 576 | /* | 583 | /* |
| 577 | * Log the machine checks left over from the previous reset. | 584 | * Log the machine checks left over from the previous reset. |
| 578 | */ | 585 | */ |
| 579 | machine_check_poll(MCP_UC); | 586 | bitmap_fill(all_banks, MAX_NR_BANKS); |
| 587 | machine_check_poll(MCP_UC, &all_banks); | ||
| 580 | 588 | ||
| 581 | set_in_cr4(X86_CR4_MCE); | 589 | set_in_cr4(X86_CR4_MCE); |
| 582 | 590 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index 49705be98209..ee8bfcd3aa32 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c | |||
| @@ -231,7 +231,8 @@ static void amd_threshold_interrupt(void) | |||
| 231 | 231 | ||
| 232 | /* Log the machine check that caused the threshold | 232 | /* Log the machine check that caused the threshold |
| 233 | event. */ | 233 | event. */ |
| 234 | machine_check_poll(MCP_TIMESTAMP); | 234 | machine_check_poll(MCP_TIMESTAMP, |
| 235 | &__get_cpu_var(mce_poll_banks)); | ||
| 235 | 236 | ||
| 236 | if (high & MASK_OVERFLOW_HI) { | 237 | if (high & MASK_OVERFLOW_HI) { |
| 237 | rdmsrl(address, m.misc); | 238 | rdmsrl(address, m.misc); |
