diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck/mce.c')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 2afcbd253e1d..b772dd6ad450 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -437,6 +437,14 @@ static inline void mce_gather_info(struct mce *m, struct pt_regs *regs) | |||
437 | if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) { | 437 | if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) { |
438 | m->ip = regs->ip; | 438 | m->ip = regs->ip; |
439 | m->cs = regs->cs; | 439 | m->cs = regs->cs; |
440 | |||
441 | /* | ||
442 | * When in VM86 mode make the cs look like ring 3 | ||
443 | * always. This is a lie, but it's better than passing | ||
444 | * the additional vm86 bit around everywhere. | ||
445 | */ | ||
446 | if (v8086_mode(regs)) | ||
447 | m->cs |= 3; | ||
440 | } | 448 | } |
441 | /* Use accurate RIP reporting if available. */ | 449 | /* Use accurate RIP reporting if available. */ |
442 | if (rip_msr) | 450 | if (rip_msr) |
@@ -641,16 +649,18 @@ EXPORT_SYMBOL_GPL(machine_check_poll); | |||
641 | * Do a quick check if any of the events requires a panic. | 649 | * Do a quick check if any of the events requires a panic. |
642 | * This decides if we keep the events around or clear them. | 650 | * This decides if we keep the events around or clear them. |
643 | */ | 651 | */ |
644 | static int mce_no_way_out(struct mce *m, char **msg) | 652 | static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp) |
645 | { | 653 | { |
646 | int i; | 654 | int i, ret = 0; |
647 | 655 | ||
648 | for (i = 0; i < banks; i++) { | 656 | for (i = 0; i < banks; i++) { |
649 | m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i)); | 657 | m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i)); |
658 | if (m->status & MCI_STATUS_VAL) | ||
659 | __set_bit(i, validp); | ||
650 | if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY) | 660 | if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY) |
651 | return 1; | 661 | ret = 1; |
652 | } | 662 | } |
653 | return 0; | 663 | return ret; |
654 | } | 664 | } |
655 | 665 | ||
656 | /* | 666 | /* |
@@ -1013,6 +1023,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
1013 | */ | 1023 | */ |
1014 | int kill_it = 0; | 1024 | int kill_it = 0; |
1015 | DECLARE_BITMAP(toclear, MAX_NR_BANKS); | 1025 | DECLARE_BITMAP(toclear, MAX_NR_BANKS); |
1026 | DECLARE_BITMAP(valid_banks, MAX_NR_BANKS); | ||
1016 | char *msg = "Unknown"; | 1027 | char *msg = "Unknown"; |
1017 | 1028 | ||
1018 | atomic_inc(&mce_entry); | 1029 | atomic_inc(&mce_entry); |
@@ -1027,7 +1038,8 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
1027 | final = &__get_cpu_var(mces_seen); | 1038 | final = &__get_cpu_var(mces_seen); |
1028 | *final = m; | 1039 | *final = m; |
1029 | 1040 | ||
1030 | no_way_out = mce_no_way_out(&m, &msg); | 1041 | memset(valid_banks, 0, sizeof(valid_banks)); |
1042 | no_way_out = mce_no_way_out(&m, &msg, valid_banks); | ||
1031 | 1043 | ||
1032 | barrier(); | 1044 | barrier(); |
1033 | 1045 | ||
@@ -1047,6 +1059,8 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
1047 | order = mce_start(&no_way_out); | 1059 | order = mce_start(&no_way_out); |
1048 | for (i = 0; i < banks; i++) { | 1060 | for (i = 0; i < banks; i++) { |
1049 | __clear_bit(i, toclear); | 1061 | __clear_bit(i, toclear); |
1062 | if (!test_bit(i, valid_banks)) | ||
1063 | continue; | ||
1050 | if (!mce_banks[i].ctl) | 1064 | if (!mce_banks[i].ctl) |
1051 | continue; | 1065 | continue; |
1052 | 1066 | ||