| From 6dcbfe4f0b4e17e289d56fa534b7ce5a6b7f63a3 Mon Sep 17 00:00:00 2001 |
| From: Borislav Petkov <borislav.petkov@amd.com> |
| Date: Fri, 8 Oct 2010 12:08:34 +0200 |
| Subject: x86, AMD, MCE thresholding: Fix the MCi_MISCj iteration order |
| |
| From: Borislav Petkov <borislav.petkov@amd.com> |
| |
| commit 6dcbfe4f0b4e17e289d56fa534b7ce5a6b7f63a3 upstream. |
| |
| This fixes possible cases of not collecting valid error info in |
| the MCE error thresholding groups on F10h hardware. |
| |
| The current code contains a subtle problem of checking only the |
| Valid bit of MSR0000_0413 (which is MC4_MISC0 - DRAM |
| thresholding group) in its first iteration and breaking out if |
| the bit is cleared. |
| |
| But (!), this MSR contains an offset value, BlkPtr[31:24], which |
| points to the remaining MSRs in this thresholding group which |
| might contain valid information too. But if we bail out only |
| after we checked the valid bit in the first MSR and not the |
| block pointer too, we miss that other information. |
| |
| The thing is, MC4_MISC0[BlkPtr] is not predicated on |
| MCi_STATUS[MiscV] or MC4_MISC0[Valid] and should be checked |
| prior to iterating over the MCI_MISCj thresholding group, |
| irrespective of the MC4_MISC0[Valid] setting. |
| |
| Signed-off-by: Borislav Petkov <borislav.petkov@amd.com> |
| Signed-off-by: Ingo Molnar <mingo@elte.hu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/x86/kernel/cpu/mcheck/mce_amd.c | 9 +++------ |
| 1 file changed, 3 insertions(+), 6 deletions(-) |
| |
| --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c |
| +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c |
| @@ -141,6 +141,7 @@ void mce_amd_feature_init(struct cpuinfo |
| address = (low & MASK_BLKPTR_LO) >> 21; |
| if (!address) |
| break; |
| + |
| address += MCG_XBLK_ADDR; |
| } else |
| ++address; |
| @@ -148,12 +149,8 @@ void mce_amd_feature_init(struct cpuinfo |
| if (rdmsr_safe(address, &low, &high)) |
| break; |
| |
| - if (!(high & MASK_VALID_HI)) { |
| - if (block) |
| - continue; |
| - else |
| - break; |
| - } |
| + if (!(high & MASK_VALID_HI)) |
| + continue; |
| |
| if (!(high & MASK_CNTP_HI) || |
| (high & MASK_LOCKED_HI)) |