Add F15h decoding support Signed-off-by: Borislav Petkov --- amd.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ amd.h | 3 - mcelog.c | 2 mcelog.h | 1 4 files changed, 165 insertions(+), 1 deletion(-) Index: mcelog-189/amd.c =================================================================== --- mcelog-189.orig/amd.c +++ mcelog-189/amd.c @@ -72,6 +72,43 @@ static char *nbextendederr[] = { "L3 Cache LRU Error" }; +static const char * const f15h_mc1_mce_desc[] = { + "UC during a demand linefill from L2", + "Parity error during data load from IC", + "Parity error for IC valid bit", + "Main tag parity error", + "Parity error in prediction queue", + "PFB data/address parity error", + "Parity error in the branch status reg", + "PFB promotion address error", + "Tag error during probe/victimization", + "Parity error for IC probe tag valid bit", + "PFB non-cacheable bit parity error", + "PFB valid bit parity error", /* xec = 0xd */ + "Microcode Patch Buffer", /* xec = 010 */ + "uop queue", + "insn buffer", + "predecode buffer", + "fetch address FIFO" +}; + +static const char * const f15h_mc2_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 or parity 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 const char * const mc4_mce_desc[] = { "DRAM ECC error detected on the NB", "CRC error detected on HT link", @@ -161,6 +198,8 @@ enum cputype select_amd_cputype(u32 fami return CPU_F12H; case 0x14: return CPU_F14H; + case 0x15: + return CPU_F15H; default: break; } @@ -435,6 +474,53 @@ static bool cat_mc0_mce(u16 ec, u8 xec) return ret; } +static bool f15h_mc0_mce(u16 ec, u8 xec) +{ + bool ret = true; + + if (MEM_ERROR(ec)) { + + switch (xec) { + case 0x0: + Wprintf("Data Array access error.\n"); + break; + + case 0x1: + Wprintf("UC error during a linefill from L2/NB.\n"); + break; + + case 0x2: + case 0x11: + Wprintf("STQ access error.\n"); + break; + + case 0x3: + Wprintf("SCB access error.\n"); + break; + + case 0x10: + Wprintf("Tag error.\n"); + break; + + case 0x12: + Wprintf("LDQ access error.\n"); + break; + + default: + ret = false; + } + } else if (BUS_ERROR(ec)) { + + if (!xec) + Wprintf("System Read Data Error.\n"); + else + Wprintf(" Internal error condition type %d.\n", xec); + } else + ret = false; + + return ret; +} + static void decode_mc0_mce(struct amd_decoder_ops *ops, struct mce *m) { u16 ec = EC(m->status); @@ -481,6 +567,36 @@ static bool cat_mc1_mce(u16 ec, u8 xec) return ret; } +static bool f15h_mc1_mce(u16 ec, u8 xec) +{ + bool ret = true; + + if (!MEM_ERROR(ec)) + return false; + + switch (xec) { + case 0x0 ... 0xa: + Wprintf("%s.\n", f15h_mc1_mce_desc[xec]); + break; + + case 0xd: + Wprintf("%s.\n", f15h_mc1_mce_desc[xec-2]); + break; + + case 0x10: + Wprintf("%s.\n", f15h_mc1_mce_desc[xec-4]); + break; + + case 0x11 ... 0x14: + Wprintf("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]); + break; + + default: + ret = false; + } + return ret; +} + static void decode_mc1_mce(struct amd_decoder_ops *ops, struct mce *m) { u16 ec = EC(m->status); @@ -537,6 +653,40 @@ static bool k8_mc2_mce(u16 ec, u8 xec) return ret; } +static bool f15h_mc2_mce(u16 ec, u8 xec) +{ + bool ret = true; + + if (TLB_ERROR(ec)) { + if (xec == 0x0) + Wprintf("Data parity TLB read error.\n"); + else if (xec == 0x1) + Wprintf("Poison data provided for TLB fill.\n"); + else + ret = false; + } else if (BUS_ERROR(ec)) { + if (xec > 2) + ret = false; + + Wprintf("Error during attempted NB data read.\n"); + } else if (MEM_ERROR(ec)) { + switch (xec) { + case 0x4 ... 0xc: + Wprintf("%s.\n", f15h_mc2_mce_desc[xec - 0x4]); + break; + + case 0x10 ... 0x14: + Wprintf("%s.\n", f15h_mc2_mce_desc[xec - 0x7]); + break; + + default: + ret = false; + } + } + + return ret; +} + static void decode_mc2_mce(struct amd_decoder_ops *ops, struct mce *m) { u16 ec = EC(m->status); @@ -741,6 +891,12 @@ struct amd_decoder_ops fam_ops[] = { .mc1_mce = cat_mc1_mce, .mc2_mce = k8_mc2_mce, }, + [AMD_F15H] = { + .cpu = AMD_F15H, + .mc0_mce = f15h_mc0_mce, + .mc1_mce = f15h_mc1_mce, + .mc2_mce = f15h_mc2_mce, + }, }; static void __decode_amd_mc(enum cputype cpu, struct mce *mce) @@ -760,6 +916,10 @@ static void __decode_amd_mc(enum cputype case CPU_F14H: ops = &fam_ops[AMD_F14H]; break; + case CPU_F15H: + xec_mask = 0x1f; + ops = &fam_ops[AMD_F15H]; + break; default: Eprintf("Huh? What family is it: 0x%x?!\n", cpu); return;