x86, MCE, AMD: Disable error thresholding bank 4 on some models
authorBorislav Petkov <borislav.petkov@amd.com>
Fri, 20 Apr 2012 16:01:34 +0000 (18:01 +0200)
committerBorislav Petkov <borislav.petkov@amd.com>
Mon, 30 Apr 2012 11:22:54 +0000 (13:22 +0200)
Turn off MC4_MISC thresholding banks on models which have them but that
particular processor implementation does not supply applicable error
sources to be counted.

Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
arch/x86/kernel/cpu/mcheck/mce.c

index d086a09..888fbf9 100644 (file)
@@ -1423,6 +1423,43 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
                 */
                 if (c->x86 == 6 && banks > 0)
                        mce_banks[0].ctl = 0;
+
+                /*
+                 * Turn off MC4_MISC thresholding banks on those models since
+                 * they're not supported there.
+                 */
+                if (c->x86 == 0x15 &&
+                    (c->x86_model >= 0x10 && c->x86_model <= 0x1f)) {
+                        int i;
+                        u64 val, hwcr;
+                        bool need_toggle;
+                        u32 msrs[] = {
+                               0x00000413, /* MC4_MISC0 */
+                               0xc0000408, /* MC4_MISC1 */
+                        };
+
+                        rdmsrl(MSR_K7_HWCR, hwcr);
+
+                        /* McStatusWrEn has to be set */
+                        need_toggle = !(hwcr & BIT(18));
+
+                        if (need_toggle)
+                                wrmsrl(MSR_K7_HWCR, hwcr | BIT(18));
+
+                        for (i = 0; i < ARRAY_SIZE(msrs); i++) {
+                                rdmsrl(msrs[i], val);
+
+                                /* CntP bit set? */
+                                if (val & BIT(62)) {
+                                        val &= ~BIT(62);
+                                        wrmsrl(msrs[i], val);
+                                }
+                        }
+
+                        /* restore old settings */
+                        if (need_toggle)
+                                wrmsrl(MSR_K7_HWCR, hwcr);
+                }
        }
 
        if (c->x86_vendor == X86_VENDOR_INTEL) {