From: Borislav Petkov <bp@suse.de>
Subject: Add F15h decoding support

Signed-off-by: Borislav Petkov <bp@suse.de>
Index: mcelog-1.0.1/amd.c
===================================================================
--- mcelog-1.0.1.orig/amd.c
+++ mcelog-1.0.1/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;
Index: mcelog-1.0.1/mcelog.h
===================================================================
--- mcelog-1.0.1.orig/mcelog.h
+++ mcelog-1.0.1/mcelog.h
@@ -111,6 +111,7 @@ enum cputype {
 	CPU_F11H,
 	CPU_F12H,
 	CPU_F14H,
+	CPU_F15H,
 	CPU_P4,
 	CPU_NEHALEM,
 	CPU_DUNNINGTON,
Index: mcelog-1.0.1/amd.h
===================================================================
--- mcelog-1.0.1.orig/amd.h
+++ mcelog-1.0.1/amd.h
@@ -97,4 +97,5 @@ enum rrrr_ids {
 	case CPU_F10H: \
 	case CPU_F11H: \
 	case CPU_F12H: \
-	case CPU_F14H
+	case CPU_F14H: \
+	case CPU_F15H
Index: mcelog-1.0.1/mcelog.c
===================================================================
--- mcelog-1.0.1.orig/mcelog.c
+++ mcelog-1.0.1/mcelog.c
@@ -226,6 +226,7 @@ static char *cputype_name[] = {
 	[CPU_F11H] = "AMD Griffin",
 	[CPU_F12H] = "AMD Llano",
 	[CPU_F14H] = "AMD Bobcat",
+	[CPU_F15H] = "AMD Bulldozer",
 	[CPU_P4] = "Intel P4",
 	[CPU_NEHALEM] = "Intel Xeon 5500 series / Core i3/5/7 (\"Nehalem/Westmere\")",
 	[CPU_DUNNINGTON] = "Intel Xeon 7400 series",
@@ -248,6 +249,7 @@ static struct config_choice cpu_choices[
 	{ "f11h", CPU_F11H },
 	{ "f12h", CPU_F12H },
 	{ "f14h", CPU_F14H },
+	{ "f15h", CPU_F15H },
 	{ "p4", CPU_P4 },
 	{ "dunnington", CPU_DUNNINGTON },
 	{ "xeon74xx", CPU_DUNNINGTON },
