EDAC, MCE: Add F15h CU MCE decoder
authorBorislav Petkov <borislav.petkov@amd.com>
Tue, 21 Sep 2010 18:45:10 +0000 (20:45 +0200)
committerBorislav Petkov <borislav.petkov@amd.com>
Fri, 7 Jan 2011 10:54:16 +0000 (11:54 +0100)
MCE bank 2 is redefined from a BU to a CU (Combined Unit) bank on F15h.
Add a decoder function for CU MCEs.

Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
drivers/edac/mce_amd.c

index 158cd5fa2146389259fffec1fe1449777ae0a89b..7eb27062f2efb993bb50a4a74d026b6ff334df53 100644 (file)
@@ -95,6 +95,23 @@ static const char * const f15h_ic_mce_desc[] = {
        "fetch address FIFO"
 };
 
+static const char * const f15h_cu_mce_desc[] = {
+       "Fill ECC error on data fills",                 /* xec = 0x4 */
+       "Fill parity error on insn fills",
+       "Prefetcher request FIFO parity error",
+       "PRQ address parity error",
+       "PRQ data parity error",
+       "WCC Tag ECC error",
+       "WCC Data ECC error",
+       "WCB Data parity error",
+       "VB Data/ECC error",
+       "L2 Tag ECC error",                             /* xec = 0x10 */
+       "Hard L2 Tag ECC error",
+       "Multiple hits on L2 tag",
+       "XAB parity error",
+       "PRB address parity error"
+};
+
 static bool f12h_dc_mce(u16 ec, u8 xec)
 {
        bool ret = false;
@@ -405,6 +422,46 @@ wrong_bu_mce:
        pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
 }
 
+static void amd_decode_cu_mce(struct mce *m)
+{
+       u16 ec = m->status & 0xffff;
+       u8 xec = (m->status >> 16) & xec_mask;
+
+       pr_emerg(HW_ERR "Combined Unit Error: ");
+
+       if (TLB_ERROR(ec)) {
+               if (xec == 0x0)
+                       pr_cont("Data parity TLB read error.\n");
+               else if (xec == 0x1)
+                       pr_cont("Poison data provided for TLB fill.\n");
+               else
+                       goto wrong_cu_mce;
+       } else if (BUS_ERROR(ec)) {
+               if (xec > 2)
+                       goto wrong_cu_mce;
+
+               pr_cont("Error during attempted NB data read.\n");
+       } else if (MEM_ERROR(ec)) {
+               switch (xec) {
+               case 0x4 ... 0xc:
+                       pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x4]);
+                       break;
+
+               case 0x10 ... 0x14:
+                       pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x7]);
+                       break;
+
+               default:
+                       goto wrong_cu_mce;
+               }
+       }
+
+       return;
+
+wrong_cu_mce:
+       pr_emerg(HW_ERR "Corrupted CU MCE info?\n");
+}
+
 static void amd_decode_ls_mce(struct mce *m)
 {
        u16 ec = m->status & 0xffff;
@@ -665,7 +722,10 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
                break;
 
        case 2:
-               amd_decode_bu_mce(m);
+               if (boot_cpu_data.x86 == 0x15)
+                       amd_decode_cu_mce(m);
+               else
+                       amd_decode_bu_mce(m);
                break;
 
        case 3: