138 lines
3.0 KiB
Diff
138 lines
3.0 KiB
Diff
|
Add F14h decoding support
|
||
|
|
||
|
Signed-off-by: Borislav Petkov <bp@suse.de>
|
||
|
---
|
||
|
amd.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
amd.h | 3 +-
|
||
|
mcelog.c | 2 +
|
||
|
mcelog.h | 1
|
||
|
4 files changed, 93 insertions(+), 1 deletion(-)
|
||
|
|
||
|
Index: mcelog-189/amd.c
|
||
|
===================================================================
|
||
|
--- mcelog-189.orig/amd.c
|
||
|
+++ mcelog-189/amd.c
|
||
|
@@ -159,6 +159,8 @@ enum cputype select_amd_cputype(u32 fami
|
||
|
return CPU_F11H;
|
||
|
case 0x12:
|
||
|
return CPU_F12H;
|
||
|
+ case 0x14:
|
||
|
+ return CPU_F14H;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
@@ -381,6 +383,58 @@ static bool k8_mc0_mce(u16 ec, u8 xec)
|
||
|
return f10h_mc0_mce(ec, xec);
|
||
|
}
|
||
|
|
||
|
+static bool cat_mc0_mce(u16 ec, u8 xec)
|
||
|
+{
|
||
|
+ u8 r4 = R4(ec);
|
||
|
+ bool ret = true;
|
||
|
+
|
||
|
+ if (MEM_ERROR(ec)) {
|
||
|
+
|
||
|
+ if (TT(ec) != TT_DATA || LL(ec) != LL_L1)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ switch (r4) {
|
||
|
+ case R4_DRD:
|
||
|
+ case R4_DWR:
|
||
|
+ Wprintf("Data/Tag parity error due to %s.\n",
|
||
|
+ (r4 == R4_DRD ? "load/hw prf" : "store"));
|
||
|
+ break;
|
||
|
+ case R4_EVICT:
|
||
|
+ Wprintf("Copyback parity error on a tag miss.\n");
|
||
|
+ break;
|
||
|
+ case R4_SNOOP:
|
||
|
+ Wprintf("Tag parity error during snoop.\n");
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ ret = false;
|
||
|
+ }
|
||
|
+ } else if (BUS_ERROR(ec)) {
|
||
|
+
|
||
|
+ if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ Wprintf("System read data error on a ");
|
||
|
+
|
||
|
+ switch (r4) {
|
||
|
+ case R4_RD:
|
||
|
+ Wprintf("TLB reload.\n");
|
||
|
+ break;
|
||
|
+ case R4_DWR:
|
||
|
+ Wprintf("store.\n");
|
||
|
+ break;
|
||
|
+ case R4_DRD:
|
||
|
+ Wprintf("load.\n");
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ ret = false;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ ret = false;
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
static void decode_mc0_mce(struct amd_decoder_ops *ops, struct mce *m)
|
||
|
{
|
||
|
u16 ec = EC(m->status);
|
||
|
@@ -402,6 +456,31 @@ static void decode_mc0_mce(struct amd_de
|
||
|
Eprintf("Corrupted MC0 MCE info?\n");
|
||
|
}
|
||
|
|
||
|
+static bool cat_mc1_mce(u16 ec, u8 xec)
|
||
|
+{
|
||
|
+ u8 r4 = R4(ec);
|
||
|
+ bool ret = true;
|
||
|
+
|
||
|
+ if (!MEM_ERROR(ec))
|
||
|
+ return false;
|
||
|
+
|
||
|
+ if (TT(ec) != TT_INSTR)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ if (r4 == R4_IRD)
|
||
|
+ Wprintf("Data/tag array parity error for a tag hit.\n");
|
||
|
+ else if (r4 == R4_SNOOP)
|
||
|
+ Wprintf("Tag error during snoop/victimization.\n");
|
||
|
+ else if (xec == 0x0)
|
||
|
+ Wprintf("Tag parity error from victim castout.\n");
|
||
|
+ else if (xec == 0x2)
|
||
|
+ Wprintf("Microcode patch RAM parity error.\n");
|
||
|
+ else
|
||
|
+ ret = false;
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
static void decode_mc1_mce(struct amd_decoder_ops *ops, struct mce *m)
|
||
|
{
|
||
|
u16 ec = EC(m->status);
|
||
|
@@ -656,6 +735,12 @@ struct amd_decoder_ops fam_ops[] = {
|
||
|
.mc1_mce = k8_mc1_mce,
|
||
|
.mc2_mce = k8_mc2_mce,
|
||
|
},
|
||
|
+ [AMD_F14H] = {
|
||
|
+ .cpu = AMD_F14H,
|
||
|
+ .mc0_mce = cat_mc0_mce,
|
||
|
+ .mc1_mce = cat_mc1_mce,
|
||
|
+ .mc2_mce = k8_mc2_mce,
|
||
|
+ },
|
||
|
};
|
||
|
|
||
|
static void __decode_amd_mc(enum cputype cpu, struct mce *mce)
|
||
|
@@ -672,6 +757,9 @@ static void __decode_amd_mc(enum cputype
|
||
|
case CPU_F12H:
|
||
|
ops = &fam_ops[AMD_F12H];
|
||
|
break;
|
||
|
+ case CPU_F14H:
|
||
|
+ ops = &fam_ops[AMD_F14H];
|
||
|
+ break;
|
||
|
default:
|
||
|
Eprintf("Huh? What family is it: 0x%x?!\n", cpu);
|
||
|
return;
|