18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci#include <linux/module.h>
38c2ecf20Sopenharmony_ci#include <linux/slab.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <asm/cpu.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "mce_amd.h"
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_cistatic struct amd_decoder_ops fam_ops;
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistatic u8 xec_mask	 = 0xf;
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic void (*decode_dram_ecc)(int node_id, struct mce *m);
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_civoid amd_register_ecc_decoder(void (*f)(int, struct mce *))
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	decode_dram_ecc = f;
188c2ecf20Sopenharmony_ci}
198c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_civoid amd_unregister_ecc_decoder(void (*f)(int, struct mce *))
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	if (decode_dram_ecc) {
248c2ecf20Sopenharmony_ci		WARN_ON(decode_dram_ecc != f);
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci		decode_dram_ecc = NULL;
278c2ecf20Sopenharmony_ci	}
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/*
328c2ecf20Sopenharmony_ci * string representation for the different MCA reported error types, see F3x48
338c2ecf20Sopenharmony_ci * or MSR0000_0411.
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/* transaction type */
378c2ecf20Sopenharmony_cistatic const char * const tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/* cache level */
408c2ecf20Sopenharmony_cistatic const char * const ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* memory transaction type */
438c2ecf20Sopenharmony_cistatic const char * const rrrr_msgs[] = {
448c2ecf20Sopenharmony_ci       "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/* participating processor */
488c2ecf20Sopenharmony_ciconst char * const pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pp_msgs);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/* request timeout */
528c2ecf20Sopenharmony_cistatic const char * const to_msgs[] = { "no timeout", "timed out" };
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* memory or i/o */
558c2ecf20Sopenharmony_cistatic const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/* internal error type */
588c2ecf20Sopenharmony_cistatic const char * const uu_msgs[] = { "RESV", "RESV", "HWA", "RESV" };
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic const char * const f15h_mc1_mce_desc[] = {
618c2ecf20Sopenharmony_ci	"UC during a demand linefill from L2",
628c2ecf20Sopenharmony_ci	"Parity error during data load from IC",
638c2ecf20Sopenharmony_ci	"Parity error for IC valid bit",
648c2ecf20Sopenharmony_ci	"Main tag parity error",
658c2ecf20Sopenharmony_ci	"Parity error in prediction queue",
668c2ecf20Sopenharmony_ci	"PFB data/address parity error",
678c2ecf20Sopenharmony_ci	"Parity error in the branch status reg",
688c2ecf20Sopenharmony_ci	"PFB promotion address error",
698c2ecf20Sopenharmony_ci	"Tag error during probe/victimization",
708c2ecf20Sopenharmony_ci	"Parity error for IC probe tag valid bit",
718c2ecf20Sopenharmony_ci	"PFB non-cacheable bit parity error",
728c2ecf20Sopenharmony_ci	"PFB valid bit parity error",			/* xec = 0xd */
738c2ecf20Sopenharmony_ci	"Microcode Patch Buffer",			/* xec = 010 */
748c2ecf20Sopenharmony_ci	"uop queue",
758c2ecf20Sopenharmony_ci	"insn buffer",
768c2ecf20Sopenharmony_ci	"predecode buffer",
778c2ecf20Sopenharmony_ci	"fetch address FIFO",
788c2ecf20Sopenharmony_ci	"dispatch uop queue"
798c2ecf20Sopenharmony_ci};
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic const char * const f15h_mc2_mce_desc[] = {
828c2ecf20Sopenharmony_ci	"Fill ECC error on data fills",			/* xec = 0x4 */
838c2ecf20Sopenharmony_ci	"Fill parity error on insn fills",
848c2ecf20Sopenharmony_ci	"Prefetcher request FIFO parity error",
858c2ecf20Sopenharmony_ci	"PRQ address parity error",
868c2ecf20Sopenharmony_ci	"PRQ data parity error",
878c2ecf20Sopenharmony_ci	"WCC Tag ECC error",
888c2ecf20Sopenharmony_ci	"WCC Data ECC error",
898c2ecf20Sopenharmony_ci	"WCB Data parity error",
908c2ecf20Sopenharmony_ci	"VB Data ECC or parity error",
918c2ecf20Sopenharmony_ci	"L2 Tag ECC error",				/* xec = 0x10 */
928c2ecf20Sopenharmony_ci	"Hard L2 Tag ECC error",
938c2ecf20Sopenharmony_ci	"Multiple hits on L2 tag",
948c2ecf20Sopenharmony_ci	"XAB parity error",
958c2ecf20Sopenharmony_ci	"PRB address parity error"
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic const char * const mc4_mce_desc[] = {
998c2ecf20Sopenharmony_ci	"DRAM ECC error detected on the NB",
1008c2ecf20Sopenharmony_ci	"CRC error detected on HT link",
1018c2ecf20Sopenharmony_ci	"Link-defined sync error packets detected on HT link",
1028c2ecf20Sopenharmony_ci	"HT Master abort",
1038c2ecf20Sopenharmony_ci	"HT Target abort",
1048c2ecf20Sopenharmony_ci	"Invalid GART PTE entry during GART table walk",
1058c2ecf20Sopenharmony_ci	"Unsupported atomic RMW received from an IO link",
1068c2ecf20Sopenharmony_ci	"Watchdog timeout due to lack of progress",
1078c2ecf20Sopenharmony_ci	"DRAM ECC error detected on the NB",
1088c2ecf20Sopenharmony_ci	"SVM DMA Exclusion Vector error",
1098c2ecf20Sopenharmony_ci	"HT data error detected on link",
1108c2ecf20Sopenharmony_ci	"Protocol error (link, L3, probe filter)",
1118c2ecf20Sopenharmony_ci	"NB internal arrays parity error",
1128c2ecf20Sopenharmony_ci	"DRAM addr/ctl signals parity error",
1138c2ecf20Sopenharmony_ci	"IO link transmission error",
1148c2ecf20Sopenharmony_ci	"L3 data cache ECC error",			/* xec = 0x1c */
1158c2ecf20Sopenharmony_ci	"L3 cache tag error",
1168c2ecf20Sopenharmony_ci	"L3 LRU parity bits error",
1178c2ecf20Sopenharmony_ci	"ECC Error in the Probe Filter directory"
1188c2ecf20Sopenharmony_ci};
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistatic const char * const mc5_mce_desc[] = {
1218c2ecf20Sopenharmony_ci	"CPU Watchdog timer expire",
1228c2ecf20Sopenharmony_ci	"Wakeup array dest tag",
1238c2ecf20Sopenharmony_ci	"AG payload array",
1248c2ecf20Sopenharmony_ci	"EX payload array",
1258c2ecf20Sopenharmony_ci	"IDRF array",
1268c2ecf20Sopenharmony_ci	"Retire dispatch queue",
1278c2ecf20Sopenharmony_ci	"Mapper checkpoint array",
1288c2ecf20Sopenharmony_ci	"Physical register file EX0 port",
1298c2ecf20Sopenharmony_ci	"Physical register file EX1 port",
1308c2ecf20Sopenharmony_ci	"Physical register file AG0 port",
1318c2ecf20Sopenharmony_ci	"Physical register file AG1 port",
1328c2ecf20Sopenharmony_ci	"Flag register file",
1338c2ecf20Sopenharmony_ci	"DE error occurred",
1348c2ecf20Sopenharmony_ci	"Retire status queue"
1358c2ecf20Sopenharmony_ci};
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic const char * const mc6_mce_desc[] = {
1388c2ecf20Sopenharmony_ci	"Hardware Assertion",
1398c2ecf20Sopenharmony_ci	"Free List",
1408c2ecf20Sopenharmony_ci	"Physical Register File",
1418c2ecf20Sopenharmony_ci	"Retire Queue",
1428c2ecf20Sopenharmony_ci	"Scheduler table",
1438c2ecf20Sopenharmony_ci	"Status Register File",
1448c2ecf20Sopenharmony_ci};
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci/* Scalable MCA error strings */
1478c2ecf20Sopenharmony_cistatic const char * const smca_ls_mce_desc[] = {
1488c2ecf20Sopenharmony_ci	"Load queue parity error",
1498c2ecf20Sopenharmony_ci	"Store queue parity error",
1508c2ecf20Sopenharmony_ci	"Miss address buffer payload parity error",
1518c2ecf20Sopenharmony_ci	"Level 1 TLB parity error",
1528c2ecf20Sopenharmony_ci	"DC Tag error type 5",
1538c2ecf20Sopenharmony_ci	"DC Tag error type 6",
1548c2ecf20Sopenharmony_ci	"DC Tag error type 1",
1558c2ecf20Sopenharmony_ci	"Internal error type 1",
1568c2ecf20Sopenharmony_ci	"Internal error type 2",
1578c2ecf20Sopenharmony_ci	"System Read Data Error Thread 0",
1588c2ecf20Sopenharmony_ci	"System Read Data Error Thread 1",
1598c2ecf20Sopenharmony_ci	"DC Tag error type 2",
1608c2ecf20Sopenharmony_ci	"DC Data error type 1 and poison consumption",
1618c2ecf20Sopenharmony_ci	"DC Data error type 2",
1628c2ecf20Sopenharmony_ci	"DC Data error type 3",
1638c2ecf20Sopenharmony_ci	"DC Tag error type 4",
1648c2ecf20Sopenharmony_ci	"Level 2 TLB parity error",
1658c2ecf20Sopenharmony_ci	"PDC parity error",
1668c2ecf20Sopenharmony_ci	"DC Tag error type 3",
1678c2ecf20Sopenharmony_ci	"DC Tag error type 5",
1688c2ecf20Sopenharmony_ci	"L2 Fill Data error",
1698c2ecf20Sopenharmony_ci};
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cistatic const char * const smca_ls2_mce_desc[] = {
1728c2ecf20Sopenharmony_ci	"An ECC error was detected on a data cache read by a probe or victimization",
1738c2ecf20Sopenharmony_ci	"An ECC error or L2 poison was detected on a data cache read by a load",
1748c2ecf20Sopenharmony_ci	"An ECC error was detected on a data cache read-modify-write by a store",
1758c2ecf20Sopenharmony_ci	"An ECC error or poison bit mismatch was detected on a tag read by a probe or victimization",
1768c2ecf20Sopenharmony_ci	"An ECC error or poison bit mismatch was detected on a tag read by a load",
1778c2ecf20Sopenharmony_ci	"An ECC error or poison bit mismatch was detected on a tag read by a store",
1788c2ecf20Sopenharmony_ci	"An ECC error was detected on an EMEM read by a load",
1798c2ecf20Sopenharmony_ci	"An ECC error was detected on an EMEM read-modify-write by a store",
1808c2ecf20Sopenharmony_ci	"A parity error was detected in an L1 TLB entry by any access",
1818c2ecf20Sopenharmony_ci	"A parity error was detected in an L2 TLB entry by any access",
1828c2ecf20Sopenharmony_ci	"A parity error was detected in a PWC entry by any access",
1838c2ecf20Sopenharmony_ci	"A parity error was detected in an STQ entry by any access",
1848c2ecf20Sopenharmony_ci	"A parity error was detected in an LDQ entry by any access",
1858c2ecf20Sopenharmony_ci	"A parity error was detected in a MAB entry by any access",
1868c2ecf20Sopenharmony_ci	"A parity error was detected in an SCB entry state field by any access",
1878c2ecf20Sopenharmony_ci	"A parity error was detected in an SCB entry address field by any access",
1888c2ecf20Sopenharmony_ci	"A parity error was detected in an SCB entry data field by any access",
1898c2ecf20Sopenharmony_ci	"A parity error was detected in a WCB entry by any access",
1908c2ecf20Sopenharmony_ci	"A poisoned line was detected in an SCB entry by any access",
1918c2ecf20Sopenharmony_ci	"A SystemReadDataError error was reported on read data returned from L2 for a load",
1928c2ecf20Sopenharmony_ci	"A SystemReadDataError error was reported on read data returned from L2 for an SCB store",
1938c2ecf20Sopenharmony_ci	"A SystemReadDataError error was reported on read data returned from L2 for a WCB store",
1948c2ecf20Sopenharmony_ci	"A hardware assertion error was reported",
1958c2ecf20Sopenharmony_ci	"A parity error was detected in an STLF, SCB EMEM entry or SRB store data by any access",
1968c2ecf20Sopenharmony_ci};
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistatic const char * const smca_if_mce_desc[] = {
1998c2ecf20Sopenharmony_ci	"Op Cache Microtag Probe Port Parity Error",
2008c2ecf20Sopenharmony_ci	"IC Microtag or Full Tag Multi-hit Error",
2018c2ecf20Sopenharmony_ci	"IC Full Tag Parity Error",
2028c2ecf20Sopenharmony_ci	"IC Data Array Parity Error",
2038c2ecf20Sopenharmony_ci	"Decoupling Queue PhysAddr Parity Error",
2048c2ecf20Sopenharmony_ci	"L0 ITLB Parity Error",
2058c2ecf20Sopenharmony_ci	"L1 ITLB Parity Error",
2068c2ecf20Sopenharmony_ci	"L2 ITLB Parity Error",
2078c2ecf20Sopenharmony_ci	"BPQ Thread 0 Snoop Parity Error",
2088c2ecf20Sopenharmony_ci	"BPQ Thread 1 Snoop Parity Error",
2098c2ecf20Sopenharmony_ci	"L1 BTB Multi-Match Error",
2108c2ecf20Sopenharmony_ci	"L2 BTB Multi-Match Error",
2118c2ecf20Sopenharmony_ci	"L2 Cache Response Poison Error",
2128c2ecf20Sopenharmony_ci	"System Read Data Error",
2138c2ecf20Sopenharmony_ci	"Hardware Assertion Error",
2148c2ecf20Sopenharmony_ci	"L1-TLB Multi-Hit",
2158c2ecf20Sopenharmony_ci	"L2-TLB Multi-Hit",
2168c2ecf20Sopenharmony_ci	"BSR Parity Error",
2178c2ecf20Sopenharmony_ci	"CT MCE",
2188c2ecf20Sopenharmony_ci};
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic const char * const smca_l2_mce_desc[] = {
2218c2ecf20Sopenharmony_ci	"L2M Tag Multiple-Way-Hit error",
2228c2ecf20Sopenharmony_ci	"L2M Tag or State Array ECC Error",
2238c2ecf20Sopenharmony_ci	"L2M Data Array ECC Error",
2248c2ecf20Sopenharmony_ci	"Hardware Assert Error",
2258c2ecf20Sopenharmony_ci};
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic const char * const smca_de_mce_desc[] = {
2288c2ecf20Sopenharmony_ci	"Micro-op cache tag parity error",
2298c2ecf20Sopenharmony_ci	"Micro-op cache data parity error",
2308c2ecf20Sopenharmony_ci	"Instruction buffer parity error",
2318c2ecf20Sopenharmony_ci	"Micro-op queue parity error",
2328c2ecf20Sopenharmony_ci	"Instruction dispatch queue parity error",
2338c2ecf20Sopenharmony_ci	"Fetch address FIFO parity error",
2348c2ecf20Sopenharmony_ci	"Patch RAM data parity error",
2358c2ecf20Sopenharmony_ci	"Patch RAM sequencer parity error",
2368c2ecf20Sopenharmony_ci	"Micro-op buffer parity error",
2378c2ecf20Sopenharmony_ci	"Hardware Assertion MCA Error",
2388c2ecf20Sopenharmony_ci};
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cistatic const char * const smca_ex_mce_desc[] = {
2418c2ecf20Sopenharmony_ci	"Watchdog Timeout error",
2428c2ecf20Sopenharmony_ci	"Physical register file parity error",
2438c2ecf20Sopenharmony_ci	"Flag register file parity error",
2448c2ecf20Sopenharmony_ci	"Immediate displacement register file parity error",
2458c2ecf20Sopenharmony_ci	"Address generator payload parity error",
2468c2ecf20Sopenharmony_ci	"EX payload parity error",
2478c2ecf20Sopenharmony_ci	"Checkpoint queue parity error",
2488c2ecf20Sopenharmony_ci	"Retire dispatch queue parity error",
2498c2ecf20Sopenharmony_ci	"Retire status queue parity error",
2508c2ecf20Sopenharmony_ci	"Scheduling queue parity error",
2518c2ecf20Sopenharmony_ci	"Branch buffer queue parity error",
2528c2ecf20Sopenharmony_ci	"Hardware Assertion error",
2538c2ecf20Sopenharmony_ci	"Spec Map parity error",
2548c2ecf20Sopenharmony_ci	"Retire Map parity error",
2558c2ecf20Sopenharmony_ci};
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic const char * const smca_fp_mce_desc[] = {
2588c2ecf20Sopenharmony_ci	"Physical register file (PRF) parity error",
2598c2ecf20Sopenharmony_ci	"Freelist (FL) parity error",
2608c2ecf20Sopenharmony_ci	"Schedule queue parity error",
2618c2ecf20Sopenharmony_ci	"NSQ parity error",
2628c2ecf20Sopenharmony_ci	"Retire queue (RQ) parity error",
2638c2ecf20Sopenharmony_ci	"Status register file (SRF) parity error",
2648c2ecf20Sopenharmony_ci	"Hardware assertion",
2658c2ecf20Sopenharmony_ci};
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_cistatic const char * const smca_l3_mce_desc[] = {
2688c2ecf20Sopenharmony_ci	"Shadow Tag Macro ECC Error",
2698c2ecf20Sopenharmony_ci	"Shadow Tag Macro Multi-way-hit Error",
2708c2ecf20Sopenharmony_ci	"L3M Tag ECC Error",
2718c2ecf20Sopenharmony_ci	"L3M Tag Multi-way-hit Error",
2728c2ecf20Sopenharmony_ci	"L3M Data ECC Error",
2738c2ecf20Sopenharmony_ci	"SDP Parity Error or SystemReadDataError from XI",
2748c2ecf20Sopenharmony_ci	"L3 Victim Queue Parity Error",
2758c2ecf20Sopenharmony_ci	"L3 Hardware Assertion",
2768c2ecf20Sopenharmony_ci};
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_cistatic const char * const smca_cs_mce_desc[] = {
2798c2ecf20Sopenharmony_ci	"Illegal Request",
2808c2ecf20Sopenharmony_ci	"Address Violation",
2818c2ecf20Sopenharmony_ci	"Security Violation",
2828c2ecf20Sopenharmony_ci	"Illegal Response",
2838c2ecf20Sopenharmony_ci	"Unexpected Response",
2848c2ecf20Sopenharmony_ci	"Request or Probe Parity Error",
2858c2ecf20Sopenharmony_ci	"Read Response Parity Error",
2868c2ecf20Sopenharmony_ci	"Atomic Request Parity Error",
2878c2ecf20Sopenharmony_ci	"Probe Filter ECC Error",
2888c2ecf20Sopenharmony_ci};
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistatic const char * const smca_cs2_mce_desc[] = {
2918c2ecf20Sopenharmony_ci	"Illegal Request",
2928c2ecf20Sopenharmony_ci	"Address Violation",
2938c2ecf20Sopenharmony_ci	"Security Violation",
2948c2ecf20Sopenharmony_ci	"Illegal Response",
2958c2ecf20Sopenharmony_ci	"Unexpected Response",
2968c2ecf20Sopenharmony_ci	"Request or Probe Parity Error",
2978c2ecf20Sopenharmony_ci	"Read Response Parity Error",
2988c2ecf20Sopenharmony_ci	"Atomic Request Parity Error",
2998c2ecf20Sopenharmony_ci	"SDP read response had no match in the CS queue",
3008c2ecf20Sopenharmony_ci	"Probe Filter Protocol Error",
3018c2ecf20Sopenharmony_ci	"Probe Filter ECC Error",
3028c2ecf20Sopenharmony_ci	"SDP read response had an unexpected RETRY error",
3038c2ecf20Sopenharmony_ci	"Counter overflow error",
3048c2ecf20Sopenharmony_ci	"Counter underflow error",
3058c2ecf20Sopenharmony_ci};
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_cistatic const char * const smca_pie_mce_desc[] = {
3088c2ecf20Sopenharmony_ci	"Hardware Assert",
3098c2ecf20Sopenharmony_ci	"Register security violation",
3108c2ecf20Sopenharmony_ci	"Link Error",
3118c2ecf20Sopenharmony_ci	"Poison data consumption",
3128c2ecf20Sopenharmony_ci	"A deferred error was detected in the DF"
3138c2ecf20Sopenharmony_ci};
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic const char * const smca_umc_mce_desc[] = {
3168c2ecf20Sopenharmony_ci	"DRAM ECC error",
3178c2ecf20Sopenharmony_ci	"Data poison error",
3188c2ecf20Sopenharmony_ci	"SDP parity error",
3198c2ecf20Sopenharmony_ci	"Advanced peripheral bus error",
3208c2ecf20Sopenharmony_ci	"Address/Command parity error",
3218c2ecf20Sopenharmony_ci	"Write data CRC error",
3228c2ecf20Sopenharmony_ci	"DCQ SRAM ECC error",
3238c2ecf20Sopenharmony_ci	"AES SRAM ECC error",
3248c2ecf20Sopenharmony_ci};
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic const char * const smca_pb_mce_desc[] = {
3278c2ecf20Sopenharmony_ci	"An ECC error in the Parameter Block RAM array",
3288c2ecf20Sopenharmony_ci};
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic const char * const smca_psp_mce_desc[] = {
3318c2ecf20Sopenharmony_ci	"An ECC or parity error in a PSP RAM instance",
3328c2ecf20Sopenharmony_ci};
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_cistatic const char * const smca_psp2_mce_desc[] = {
3358c2ecf20Sopenharmony_ci	"High SRAM ECC or parity error",
3368c2ecf20Sopenharmony_ci	"Low SRAM ECC or parity error",
3378c2ecf20Sopenharmony_ci	"Instruction Cache Bank 0 ECC or parity error",
3388c2ecf20Sopenharmony_ci	"Instruction Cache Bank 1 ECC or parity error",
3398c2ecf20Sopenharmony_ci	"Instruction Tag Ram 0 parity error",
3408c2ecf20Sopenharmony_ci	"Instruction Tag Ram 1 parity error",
3418c2ecf20Sopenharmony_ci	"Data Cache Bank 0 ECC or parity error",
3428c2ecf20Sopenharmony_ci	"Data Cache Bank 1 ECC or parity error",
3438c2ecf20Sopenharmony_ci	"Data Cache Bank 2 ECC or parity error",
3448c2ecf20Sopenharmony_ci	"Data Cache Bank 3 ECC or parity error",
3458c2ecf20Sopenharmony_ci	"Data Tag Bank 0 parity error",
3468c2ecf20Sopenharmony_ci	"Data Tag Bank 1 parity error",
3478c2ecf20Sopenharmony_ci	"Data Tag Bank 2 parity error",
3488c2ecf20Sopenharmony_ci	"Data Tag Bank 3 parity error",
3498c2ecf20Sopenharmony_ci	"Dirty Data Ram parity error",
3508c2ecf20Sopenharmony_ci	"TLB Bank 0 parity error",
3518c2ecf20Sopenharmony_ci	"TLB Bank 1 parity error",
3528c2ecf20Sopenharmony_ci	"System Hub Read Buffer ECC or parity error",
3538c2ecf20Sopenharmony_ci};
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_cistatic const char * const smca_smu_mce_desc[] = {
3568c2ecf20Sopenharmony_ci	"An ECC or parity error in an SMU RAM instance",
3578c2ecf20Sopenharmony_ci};
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_cistatic const char * const smca_smu2_mce_desc[] = {
3608c2ecf20Sopenharmony_ci	"High SRAM ECC or parity error",
3618c2ecf20Sopenharmony_ci	"Low SRAM ECC or parity error",
3628c2ecf20Sopenharmony_ci	"Data Cache Bank A ECC or parity error",
3638c2ecf20Sopenharmony_ci	"Data Cache Bank B ECC or parity error",
3648c2ecf20Sopenharmony_ci	"Data Tag Cache Bank A ECC or parity error",
3658c2ecf20Sopenharmony_ci	"Data Tag Cache Bank B ECC or parity error",
3668c2ecf20Sopenharmony_ci	"Instruction Cache Bank A ECC or parity error",
3678c2ecf20Sopenharmony_ci	"Instruction Cache Bank B ECC or parity error",
3688c2ecf20Sopenharmony_ci	"Instruction Tag Cache Bank A ECC or parity error",
3698c2ecf20Sopenharmony_ci	"Instruction Tag Cache Bank B ECC or parity error",
3708c2ecf20Sopenharmony_ci	"System Hub Read Buffer ECC or parity error",
3718c2ecf20Sopenharmony_ci	"PHY RAM ECC error",
3728c2ecf20Sopenharmony_ci};
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cistatic const char * const smca_mp5_mce_desc[] = {
3758c2ecf20Sopenharmony_ci	"High SRAM ECC or parity error",
3768c2ecf20Sopenharmony_ci	"Low SRAM ECC or parity error",
3778c2ecf20Sopenharmony_ci	"Data Cache Bank A ECC or parity error",
3788c2ecf20Sopenharmony_ci	"Data Cache Bank B ECC or parity error",
3798c2ecf20Sopenharmony_ci	"Data Tag Cache Bank A ECC or parity error",
3808c2ecf20Sopenharmony_ci	"Data Tag Cache Bank B ECC or parity error",
3818c2ecf20Sopenharmony_ci	"Instruction Cache Bank A ECC or parity error",
3828c2ecf20Sopenharmony_ci	"Instruction Cache Bank B ECC or parity error",
3838c2ecf20Sopenharmony_ci	"Instruction Tag Cache Bank A ECC or parity error",
3848c2ecf20Sopenharmony_ci	"Instruction Tag Cache Bank B ECC or parity error",
3858c2ecf20Sopenharmony_ci};
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_cistatic const char * const smca_nbio_mce_desc[] = {
3888c2ecf20Sopenharmony_ci	"ECC or Parity error",
3898c2ecf20Sopenharmony_ci	"PCIE error",
3908c2ecf20Sopenharmony_ci	"SDP ErrEvent error",
3918c2ecf20Sopenharmony_ci	"SDP Egress Poison Error",
3928c2ecf20Sopenharmony_ci	"IOHC Internal Poison Error",
3938c2ecf20Sopenharmony_ci};
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_cistatic const char * const smca_pcie_mce_desc[] = {
3968c2ecf20Sopenharmony_ci	"CCIX PER Message logging",
3978c2ecf20Sopenharmony_ci	"CCIX Read Response with Status: Non-Data Error",
3988c2ecf20Sopenharmony_ci	"CCIX Write Response with Status: Non-Data Error",
3998c2ecf20Sopenharmony_ci	"CCIX Read Response with Status: Data Error",
4008c2ecf20Sopenharmony_ci	"CCIX Non-okay write response with data error",
4018c2ecf20Sopenharmony_ci};
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cistruct smca_mce_desc {
4048c2ecf20Sopenharmony_ci	const char * const *descs;
4058c2ecf20Sopenharmony_ci	unsigned int num_descs;
4068c2ecf20Sopenharmony_ci};
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic struct smca_mce_desc smca_mce_descs[] = {
4098c2ecf20Sopenharmony_ci	[SMCA_LS]	= { smca_ls_mce_desc,	ARRAY_SIZE(smca_ls_mce_desc)	},
4108c2ecf20Sopenharmony_ci	[SMCA_LS_V2]	= { smca_ls2_mce_desc,	ARRAY_SIZE(smca_ls2_mce_desc)	},
4118c2ecf20Sopenharmony_ci	[SMCA_IF]	= { smca_if_mce_desc,	ARRAY_SIZE(smca_if_mce_desc)	},
4128c2ecf20Sopenharmony_ci	[SMCA_L2_CACHE]	= { smca_l2_mce_desc,	ARRAY_SIZE(smca_l2_mce_desc)	},
4138c2ecf20Sopenharmony_ci	[SMCA_DE]	= { smca_de_mce_desc,	ARRAY_SIZE(smca_de_mce_desc)	},
4148c2ecf20Sopenharmony_ci	[SMCA_EX]	= { smca_ex_mce_desc,	ARRAY_SIZE(smca_ex_mce_desc)	},
4158c2ecf20Sopenharmony_ci	[SMCA_FP]	= { smca_fp_mce_desc,	ARRAY_SIZE(smca_fp_mce_desc)	},
4168c2ecf20Sopenharmony_ci	[SMCA_L3_CACHE]	= { smca_l3_mce_desc,	ARRAY_SIZE(smca_l3_mce_desc)	},
4178c2ecf20Sopenharmony_ci	[SMCA_CS]	= { smca_cs_mce_desc,	ARRAY_SIZE(smca_cs_mce_desc)	},
4188c2ecf20Sopenharmony_ci	[SMCA_CS_V2]	= { smca_cs2_mce_desc,	ARRAY_SIZE(smca_cs2_mce_desc)	},
4198c2ecf20Sopenharmony_ci	[SMCA_PIE]	= { smca_pie_mce_desc,	ARRAY_SIZE(smca_pie_mce_desc)	},
4208c2ecf20Sopenharmony_ci	[SMCA_UMC]	= { smca_umc_mce_desc,	ARRAY_SIZE(smca_umc_mce_desc)	},
4218c2ecf20Sopenharmony_ci	[SMCA_PB]	= { smca_pb_mce_desc,	ARRAY_SIZE(smca_pb_mce_desc)	},
4228c2ecf20Sopenharmony_ci	[SMCA_PSP]	= { smca_psp_mce_desc,	ARRAY_SIZE(smca_psp_mce_desc)	},
4238c2ecf20Sopenharmony_ci	[SMCA_PSP_V2]	= { smca_psp2_mce_desc,	ARRAY_SIZE(smca_psp2_mce_desc)	},
4248c2ecf20Sopenharmony_ci	[SMCA_SMU]	= { smca_smu_mce_desc,	ARRAY_SIZE(smca_smu_mce_desc)	},
4258c2ecf20Sopenharmony_ci	[SMCA_SMU_V2]	= { smca_smu2_mce_desc,	ARRAY_SIZE(smca_smu2_mce_desc)	},
4268c2ecf20Sopenharmony_ci	[SMCA_MP5]	= { smca_mp5_mce_desc,	ARRAY_SIZE(smca_mp5_mce_desc)	},
4278c2ecf20Sopenharmony_ci	[SMCA_NBIO]	= { smca_nbio_mce_desc,	ARRAY_SIZE(smca_nbio_mce_desc)	},
4288c2ecf20Sopenharmony_ci	[SMCA_PCIE]	= { smca_pcie_mce_desc,	ARRAY_SIZE(smca_pcie_mce_desc)	},
4298c2ecf20Sopenharmony_ci};
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_cistatic bool f12h_mc0_mce(u16 ec, u8 xec)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	bool ret = false;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	if (MEM_ERROR(ec)) {
4368c2ecf20Sopenharmony_ci		u8 ll = LL(ec);
4378c2ecf20Sopenharmony_ci		ret = true;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci		if (ll == LL_L2)
4408c2ecf20Sopenharmony_ci			pr_cont("during L1 linefill from L2.\n");
4418c2ecf20Sopenharmony_ci		else if (ll == LL_L1)
4428c2ecf20Sopenharmony_ci			pr_cont("Data/Tag %s error.\n", R4_MSG(ec));
4438c2ecf20Sopenharmony_ci		else
4448c2ecf20Sopenharmony_ci			ret = false;
4458c2ecf20Sopenharmony_ci	}
4468c2ecf20Sopenharmony_ci	return ret;
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic bool f10h_mc0_mce(u16 ec, u8 xec)
4508c2ecf20Sopenharmony_ci{
4518c2ecf20Sopenharmony_ci	if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
4528c2ecf20Sopenharmony_ci		pr_cont("during data scrub.\n");
4538c2ecf20Sopenharmony_ci		return true;
4548c2ecf20Sopenharmony_ci	}
4558c2ecf20Sopenharmony_ci	return f12h_mc0_mce(ec, xec);
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic bool k8_mc0_mce(u16 ec, u8 xec)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	if (BUS_ERROR(ec)) {
4618c2ecf20Sopenharmony_ci		pr_cont("during system linefill.\n");
4628c2ecf20Sopenharmony_ci		return true;
4638c2ecf20Sopenharmony_ci	}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	return f10h_mc0_mce(ec, xec);
4668c2ecf20Sopenharmony_ci}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_cistatic bool cat_mc0_mce(u16 ec, u8 xec)
4698c2ecf20Sopenharmony_ci{
4708c2ecf20Sopenharmony_ci	u8 r4	 = R4(ec);
4718c2ecf20Sopenharmony_ci	bool ret = true;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	if (MEM_ERROR(ec)) {
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci		if (TT(ec) != TT_DATA || LL(ec) != LL_L1)
4768c2ecf20Sopenharmony_ci			return false;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci		switch (r4) {
4798c2ecf20Sopenharmony_ci		case R4_DRD:
4808c2ecf20Sopenharmony_ci		case R4_DWR:
4818c2ecf20Sopenharmony_ci			pr_cont("Data/Tag parity error due to %s.\n",
4828c2ecf20Sopenharmony_ci				(r4 == R4_DRD ? "load/hw prf" : "store"));
4838c2ecf20Sopenharmony_ci			break;
4848c2ecf20Sopenharmony_ci		case R4_EVICT:
4858c2ecf20Sopenharmony_ci			pr_cont("Copyback parity error on a tag miss.\n");
4868c2ecf20Sopenharmony_ci			break;
4878c2ecf20Sopenharmony_ci		case R4_SNOOP:
4888c2ecf20Sopenharmony_ci			pr_cont("Tag parity error during snoop.\n");
4898c2ecf20Sopenharmony_ci			break;
4908c2ecf20Sopenharmony_ci		default:
4918c2ecf20Sopenharmony_ci			ret = false;
4928c2ecf20Sopenharmony_ci		}
4938c2ecf20Sopenharmony_ci	} else if (BUS_ERROR(ec)) {
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci		if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG)
4968c2ecf20Sopenharmony_ci			return false;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci		pr_cont("System read data error on a ");
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci		switch (r4) {
5018c2ecf20Sopenharmony_ci		case R4_RD:
5028c2ecf20Sopenharmony_ci			pr_cont("TLB reload.\n");
5038c2ecf20Sopenharmony_ci			break;
5048c2ecf20Sopenharmony_ci		case R4_DWR:
5058c2ecf20Sopenharmony_ci			pr_cont("store.\n");
5068c2ecf20Sopenharmony_ci			break;
5078c2ecf20Sopenharmony_ci		case R4_DRD:
5088c2ecf20Sopenharmony_ci			pr_cont("load.\n");
5098c2ecf20Sopenharmony_ci			break;
5108c2ecf20Sopenharmony_ci		default:
5118c2ecf20Sopenharmony_ci			ret = false;
5128c2ecf20Sopenharmony_ci		}
5138c2ecf20Sopenharmony_ci	} else {
5148c2ecf20Sopenharmony_ci		ret = false;
5158c2ecf20Sopenharmony_ci	}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	return ret;
5188c2ecf20Sopenharmony_ci}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_cistatic bool f15h_mc0_mce(u16 ec, u8 xec)
5218c2ecf20Sopenharmony_ci{
5228c2ecf20Sopenharmony_ci	bool ret = true;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	if (MEM_ERROR(ec)) {
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci		switch (xec) {
5278c2ecf20Sopenharmony_ci		case 0x0:
5288c2ecf20Sopenharmony_ci			pr_cont("Data Array access error.\n");
5298c2ecf20Sopenharmony_ci			break;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci		case 0x1:
5328c2ecf20Sopenharmony_ci			pr_cont("UC error during a linefill from L2/NB.\n");
5338c2ecf20Sopenharmony_ci			break;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci		case 0x2:
5368c2ecf20Sopenharmony_ci		case 0x11:
5378c2ecf20Sopenharmony_ci			pr_cont("STQ access error.\n");
5388c2ecf20Sopenharmony_ci			break;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci		case 0x3:
5418c2ecf20Sopenharmony_ci			pr_cont("SCB access error.\n");
5428c2ecf20Sopenharmony_ci			break;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci		case 0x10:
5458c2ecf20Sopenharmony_ci			pr_cont("Tag error.\n");
5468c2ecf20Sopenharmony_ci			break;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci		case 0x12:
5498c2ecf20Sopenharmony_ci			pr_cont("LDQ access error.\n");
5508c2ecf20Sopenharmony_ci			break;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci		default:
5538c2ecf20Sopenharmony_ci			ret = false;
5548c2ecf20Sopenharmony_ci		}
5558c2ecf20Sopenharmony_ci	} else if (BUS_ERROR(ec)) {
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci		if (!xec)
5588c2ecf20Sopenharmony_ci			pr_cont("System Read Data Error.\n");
5598c2ecf20Sopenharmony_ci		else
5608c2ecf20Sopenharmony_ci			pr_cont(" Internal error condition type %d.\n", xec);
5618c2ecf20Sopenharmony_ci	} else if (INT_ERROR(ec)) {
5628c2ecf20Sopenharmony_ci		if (xec <= 0x1f)
5638c2ecf20Sopenharmony_ci			pr_cont("Hardware Assert.\n");
5648c2ecf20Sopenharmony_ci		else
5658c2ecf20Sopenharmony_ci			ret = false;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	} else
5688c2ecf20Sopenharmony_ci		ret = false;
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	return ret;
5718c2ecf20Sopenharmony_ci}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_cistatic void decode_mc0_mce(struct mce *m)
5748c2ecf20Sopenharmony_ci{
5758c2ecf20Sopenharmony_ci	u16 ec = EC(m->status);
5768c2ecf20Sopenharmony_ci	u8 xec = XEC(m->status, xec_mask);
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "MC0 Error: ");
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	/* TLB error signatures are the same across families */
5818c2ecf20Sopenharmony_ci	if (TLB_ERROR(ec)) {
5828c2ecf20Sopenharmony_ci		if (TT(ec) == TT_DATA) {
5838c2ecf20Sopenharmony_ci			pr_cont("%s TLB %s.\n", LL_MSG(ec),
5848c2ecf20Sopenharmony_ci				((xec == 2) ? "locked miss"
5858c2ecf20Sopenharmony_ci					    : (xec ? "multimatch" : "parity")));
5868c2ecf20Sopenharmony_ci			return;
5878c2ecf20Sopenharmony_ci		}
5888c2ecf20Sopenharmony_ci	} else if (fam_ops.mc0_mce(ec, xec))
5898c2ecf20Sopenharmony_ci		;
5908c2ecf20Sopenharmony_ci	else
5918c2ecf20Sopenharmony_ci		pr_emerg(HW_ERR "Corrupted MC0 MCE info?\n");
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_cistatic bool k8_mc1_mce(u16 ec, u8 xec)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	u8 ll	 = LL(ec);
5978c2ecf20Sopenharmony_ci	bool ret = true;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	if (!MEM_ERROR(ec))
6008c2ecf20Sopenharmony_ci		return false;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	if (ll == 0x2)
6038c2ecf20Sopenharmony_ci		pr_cont("during a linefill from L2.\n");
6048c2ecf20Sopenharmony_ci	else if (ll == 0x1) {
6058c2ecf20Sopenharmony_ci		switch (R4(ec)) {
6068c2ecf20Sopenharmony_ci		case R4_IRD:
6078c2ecf20Sopenharmony_ci			pr_cont("Parity error during data load.\n");
6088c2ecf20Sopenharmony_ci			break;
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci		case R4_EVICT:
6118c2ecf20Sopenharmony_ci			pr_cont("Copyback Parity/Victim error.\n");
6128c2ecf20Sopenharmony_ci			break;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci		case R4_SNOOP:
6158c2ecf20Sopenharmony_ci			pr_cont("Tag Snoop error.\n");
6168c2ecf20Sopenharmony_ci			break;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci		default:
6198c2ecf20Sopenharmony_ci			ret = false;
6208c2ecf20Sopenharmony_ci			break;
6218c2ecf20Sopenharmony_ci		}
6228c2ecf20Sopenharmony_ci	} else
6238c2ecf20Sopenharmony_ci		ret = false;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	return ret;
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_cistatic bool cat_mc1_mce(u16 ec, u8 xec)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	u8 r4    = R4(ec);
6318c2ecf20Sopenharmony_ci	bool ret = true;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	if (!MEM_ERROR(ec))
6348c2ecf20Sopenharmony_ci		return false;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	if (TT(ec) != TT_INSTR)
6378c2ecf20Sopenharmony_ci		return false;
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci	if (r4 == R4_IRD)
6408c2ecf20Sopenharmony_ci		pr_cont("Data/tag array parity error for a tag hit.\n");
6418c2ecf20Sopenharmony_ci	else if (r4 == R4_SNOOP)
6428c2ecf20Sopenharmony_ci		pr_cont("Tag error during snoop/victimization.\n");
6438c2ecf20Sopenharmony_ci	else if (xec == 0x0)
6448c2ecf20Sopenharmony_ci		pr_cont("Tag parity error from victim castout.\n");
6458c2ecf20Sopenharmony_ci	else if (xec == 0x2)
6468c2ecf20Sopenharmony_ci		pr_cont("Microcode patch RAM parity error.\n");
6478c2ecf20Sopenharmony_ci	else
6488c2ecf20Sopenharmony_ci		ret = false;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	return ret;
6518c2ecf20Sopenharmony_ci}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistatic bool f15h_mc1_mce(u16 ec, u8 xec)
6548c2ecf20Sopenharmony_ci{
6558c2ecf20Sopenharmony_ci	bool ret = true;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	if (!MEM_ERROR(ec))
6588c2ecf20Sopenharmony_ci		return false;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	switch (xec) {
6618c2ecf20Sopenharmony_ci	case 0x0 ... 0xa:
6628c2ecf20Sopenharmony_ci		pr_cont("%s.\n", f15h_mc1_mce_desc[xec]);
6638c2ecf20Sopenharmony_ci		break;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	case 0xd:
6668c2ecf20Sopenharmony_ci		pr_cont("%s.\n", f15h_mc1_mce_desc[xec-2]);
6678c2ecf20Sopenharmony_ci		break;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	case 0x10:
6708c2ecf20Sopenharmony_ci		pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
6718c2ecf20Sopenharmony_ci		break;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	case 0x11 ... 0x15:
6748c2ecf20Sopenharmony_ci		pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
6758c2ecf20Sopenharmony_ci		break;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	default:
6788c2ecf20Sopenharmony_ci		ret = false;
6798c2ecf20Sopenharmony_ci	}
6808c2ecf20Sopenharmony_ci	return ret;
6818c2ecf20Sopenharmony_ci}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_cistatic void decode_mc1_mce(struct mce *m)
6848c2ecf20Sopenharmony_ci{
6858c2ecf20Sopenharmony_ci	u16 ec = EC(m->status);
6868c2ecf20Sopenharmony_ci	u8 xec = XEC(m->status, xec_mask);
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "MC1 Error: ");
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	if (TLB_ERROR(ec))
6918c2ecf20Sopenharmony_ci		pr_cont("%s TLB %s.\n", LL_MSG(ec),
6928c2ecf20Sopenharmony_ci			(xec ? "multimatch" : "parity error"));
6938c2ecf20Sopenharmony_ci	else if (BUS_ERROR(ec)) {
6948c2ecf20Sopenharmony_ci		bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci		pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
6978c2ecf20Sopenharmony_ci	} else if (INT_ERROR(ec)) {
6988c2ecf20Sopenharmony_ci		if (xec <= 0x3f)
6998c2ecf20Sopenharmony_ci			pr_cont("Hardware Assert.\n");
7008c2ecf20Sopenharmony_ci		else
7018c2ecf20Sopenharmony_ci			goto wrong_mc1_mce;
7028c2ecf20Sopenharmony_ci	} else if (fam_ops.mc1_mce(ec, xec))
7038c2ecf20Sopenharmony_ci		;
7048c2ecf20Sopenharmony_ci	else
7058c2ecf20Sopenharmony_ci		goto wrong_mc1_mce;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	return;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ciwrong_mc1_mce:
7108c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cistatic bool k8_mc2_mce(u16 ec, u8 xec)
7148c2ecf20Sopenharmony_ci{
7158c2ecf20Sopenharmony_ci	bool ret = true;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	if (xec == 0x1)
7188c2ecf20Sopenharmony_ci		pr_cont(" in the write data buffers.\n");
7198c2ecf20Sopenharmony_ci	else if (xec == 0x3)
7208c2ecf20Sopenharmony_ci		pr_cont(" in the victim data buffers.\n");
7218c2ecf20Sopenharmony_ci	else if (xec == 0x2 && MEM_ERROR(ec))
7228c2ecf20Sopenharmony_ci		pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec));
7238c2ecf20Sopenharmony_ci	else if (xec == 0x0) {
7248c2ecf20Sopenharmony_ci		if (TLB_ERROR(ec))
7258c2ecf20Sopenharmony_ci			pr_cont("%s error in a Page Descriptor Cache or Guest TLB.\n",
7268c2ecf20Sopenharmony_ci				TT_MSG(ec));
7278c2ecf20Sopenharmony_ci		else if (BUS_ERROR(ec))
7288c2ecf20Sopenharmony_ci			pr_cont(": %s/ECC error in data read from NB: %s.\n",
7298c2ecf20Sopenharmony_ci				R4_MSG(ec), PP_MSG(ec));
7308c2ecf20Sopenharmony_ci		else if (MEM_ERROR(ec)) {
7318c2ecf20Sopenharmony_ci			u8 r4 = R4(ec);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci			if (r4 >= 0x7)
7348c2ecf20Sopenharmony_ci				pr_cont(": %s error during data copyback.\n",
7358c2ecf20Sopenharmony_ci					R4_MSG(ec));
7368c2ecf20Sopenharmony_ci			else if (r4 <= 0x1)
7378c2ecf20Sopenharmony_ci				pr_cont(": %s parity/ECC error during data "
7388c2ecf20Sopenharmony_ci					"access from L2.\n", R4_MSG(ec));
7398c2ecf20Sopenharmony_ci			else
7408c2ecf20Sopenharmony_ci				ret = false;
7418c2ecf20Sopenharmony_ci		} else
7428c2ecf20Sopenharmony_ci			ret = false;
7438c2ecf20Sopenharmony_ci	} else
7448c2ecf20Sopenharmony_ci		ret = false;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	return ret;
7478c2ecf20Sopenharmony_ci}
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_cistatic bool f15h_mc2_mce(u16 ec, u8 xec)
7508c2ecf20Sopenharmony_ci{
7518c2ecf20Sopenharmony_ci	bool ret = true;
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	if (TLB_ERROR(ec)) {
7548c2ecf20Sopenharmony_ci		if (xec == 0x0)
7558c2ecf20Sopenharmony_ci			pr_cont("Data parity TLB read error.\n");
7568c2ecf20Sopenharmony_ci		else if (xec == 0x1)
7578c2ecf20Sopenharmony_ci			pr_cont("Poison data provided for TLB fill.\n");
7588c2ecf20Sopenharmony_ci		else
7598c2ecf20Sopenharmony_ci			ret = false;
7608c2ecf20Sopenharmony_ci	} else if (BUS_ERROR(ec)) {
7618c2ecf20Sopenharmony_ci		if (xec > 2)
7628c2ecf20Sopenharmony_ci			ret = false;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci		pr_cont("Error during attempted NB data read.\n");
7658c2ecf20Sopenharmony_ci	} else if (MEM_ERROR(ec)) {
7668c2ecf20Sopenharmony_ci		switch (xec) {
7678c2ecf20Sopenharmony_ci		case 0x4 ... 0xc:
7688c2ecf20Sopenharmony_ci			pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x4]);
7698c2ecf20Sopenharmony_ci			break;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci		case 0x10 ... 0x14:
7728c2ecf20Sopenharmony_ci			pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x7]);
7738c2ecf20Sopenharmony_ci			break;
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci		default:
7768c2ecf20Sopenharmony_ci			ret = false;
7778c2ecf20Sopenharmony_ci		}
7788c2ecf20Sopenharmony_ci	} else if (INT_ERROR(ec)) {
7798c2ecf20Sopenharmony_ci		if (xec <= 0x3f)
7808c2ecf20Sopenharmony_ci			pr_cont("Hardware Assert.\n");
7818c2ecf20Sopenharmony_ci		else
7828c2ecf20Sopenharmony_ci			ret = false;
7838c2ecf20Sopenharmony_ci	}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci	return ret;
7868c2ecf20Sopenharmony_ci}
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_cistatic bool f16h_mc2_mce(u16 ec, u8 xec)
7898c2ecf20Sopenharmony_ci{
7908c2ecf20Sopenharmony_ci	u8 r4 = R4(ec);
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	if (!MEM_ERROR(ec))
7938c2ecf20Sopenharmony_ci		return false;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	switch (xec) {
7968c2ecf20Sopenharmony_ci	case 0x04 ... 0x05:
7978c2ecf20Sopenharmony_ci		pr_cont("%cBUFF parity error.\n", (r4 == R4_RD) ? 'I' : 'O');
7988c2ecf20Sopenharmony_ci		break;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	case 0x09 ... 0x0b:
8018c2ecf20Sopenharmony_ci	case 0x0d ... 0x0f:
8028c2ecf20Sopenharmony_ci		pr_cont("ECC error in L2 tag (%s).\n",
8038c2ecf20Sopenharmony_ci			((r4 == R4_GEN)   ? "BankReq" :
8048c2ecf20Sopenharmony_ci			((r4 == R4_SNOOP) ? "Prb"     : "Fill")));
8058c2ecf20Sopenharmony_ci		break;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	case 0x10 ... 0x19:
8088c2ecf20Sopenharmony_ci	case 0x1b:
8098c2ecf20Sopenharmony_ci		pr_cont("ECC error in L2 data array (%s).\n",
8108c2ecf20Sopenharmony_ci			(((r4 == R4_RD) && !(xec & 0x3)) ? "Hit"  :
8118c2ecf20Sopenharmony_ci			((r4 == R4_GEN)   ? "Attr" :
8128c2ecf20Sopenharmony_ci			((r4 == R4_EVICT) ? "Vict" : "Fill"))));
8138c2ecf20Sopenharmony_ci		break;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	case 0x1c ... 0x1d:
8168c2ecf20Sopenharmony_ci	case 0x1f:
8178c2ecf20Sopenharmony_ci		pr_cont("Parity error in L2 attribute bits (%s).\n",
8188c2ecf20Sopenharmony_ci			((r4 == R4_RD)  ? "Hit"  :
8198c2ecf20Sopenharmony_ci			((r4 == R4_GEN) ? "Attr" : "Fill")));
8208c2ecf20Sopenharmony_ci		break;
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	default:
8238c2ecf20Sopenharmony_ci		return false;
8248c2ecf20Sopenharmony_ci	}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	return true;
8278c2ecf20Sopenharmony_ci}
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_cistatic void decode_mc2_mce(struct mce *m)
8308c2ecf20Sopenharmony_ci{
8318c2ecf20Sopenharmony_ci	u16 ec = EC(m->status);
8328c2ecf20Sopenharmony_ci	u8 xec = XEC(m->status, xec_mask);
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "MC2 Error: ");
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	if (!fam_ops.mc2_mce(ec, xec))
8378c2ecf20Sopenharmony_ci		pr_cont(HW_ERR "Corrupted MC2 MCE info?\n");
8388c2ecf20Sopenharmony_ci}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_cistatic void decode_mc3_mce(struct mce *m)
8418c2ecf20Sopenharmony_ci{
8428c2ecf20Sopenharmony_ci	u16 ec = EC(m->status);
8438c2ecf20Sopenharmony_ci	u8 xec = XEC(m->status, xec_mask);
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	if (boot_cpu_data.x86 >= 0x14) {
8468c2ecf20Sopenharmony_ci		pr_emerg("You shouldn't be seeing MC3 MCE on this cpu family,"
8478c2ecf20Sopenharmony_ci			 " please report on LKML.\n");
8488c2ecf20Sopenharmony_ci		return;
8498c2ecf20Sopenharmony_ci	}
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "MC3 Error");
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	if (xec == 0x0) {
8548c2ecf20Sopenharmony_ci		u8 r4 = R4(ec);
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci		if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
8578c2ecf20Sopenharmony_ci			goto wrong_mc3_mce;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci		pr_cont(" during %s.\n", R4_MSG(ec));
8608c2ecf20Sopenharmony_ci	} else
8618c2ecf20Sopenharmony_ci		goto wrong_mc3_mce;
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	return;
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci wrong_mc3_mce:
8668c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "Corrupted MC3 MCE info?\n");
8678c2ecf20Sopenharmony_ci}
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_cistatic void decode_mc4_mce(struct mce *m)
8708c2ecf20Sopenharmony_ci{
8718c2ecf20Sopenharmony_ci	unsigned int fam = x86_family(m->cpuid);
8728c2ecf20Sopenharmony_ci	int node_id = amd_get_nb_id(m->extcpu);
8738c2ecf20Sopenharmony_ci	u16 ec = EC(m->status);
8748c2ecf20Sopenharmony_ci	u8 xec = XEC(m->status, 0x1f);
8758c2ecf20Sopenharmony_ci	u8 offset = 0;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "MC4 Error (node %d): ", node_id);
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	switch (xec) {
8808c2ecf20Sopenharmony_ci	case 0x0 ... 0xe:
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci		/* special handling for DRAM ECCs */
8838c2ecf20Sopenharmony_ci		if (xec == 0x0 || xec == 0x8) {
8848c2ecf20Sopenharmony_ci			/* no ECCs on F11h */
8858c2ecf20Sopenharmony_ci			if (fam == 0x11)
8868c2ecf20Sopenharmony_ci				goto wrong_mc4_mce;
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci			pr_cont("%s.\n", mc4_mce_desc[xec]);
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci			if (decode_dram_ecc)
8918c2ecf20Sopenharmony_ci				decode_dram_ecc(node_id, m);
8928c2ecf20Sopenharmony_ci			return;
8938c2ecf20Sopenharmony_ci		}
8948c2ecf20Sopenharmony_ci		break;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	case 0xf:
8978c2ecf20Sopenharmony_ci		if (TLB_ERROR(ec))
8988c2ecf20Sopenharmony_ci			pr_cont("GART Table Walk data error.\n");
8998c2ecf20Sopenharmony_ci		else if (BUS_ERROR(ec))
9008c2ecf20Sopenharmony_ci			pr_cont("DMA Exclusion Vector Table Walk error.\n");
9018c2ecf20Sopenharmony_ci		else
9028c2ecf20Sopenharmony_ci			goto wrong_mc4_mce;
9038c2ecf20Sopenharmony_ci		return;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	case 0x19:
9068c2ecf20Sopenharmony_ci		if (fam == 0x15 || fam == 0x16)
9078c2ecf20Sopenharmony_ci			pr_cont("Compute Unit Data Error.\n");
9088c2ecf20Sopenharmony_ci		else
9098c2ecf20Sopenharmony_ci			goto wrong_mc4_mce;
9108c2ecf20Sopenharmony_ci		return;
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	case 0x1c ... 0x1f:
9138c2ecf20Sopenharmony_ci		offset = 13;
9148c2ecf20Sopenharmony_ci		break;
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	default:
9178c2ecf20Sopenharmony_ci		goto wrong_mc4_mce;
9188c2ecf20Sopenharmony_ci	}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	pr_cont("%s.\n", mc4_mce_desc[xec - offset]);
9218c2ecf20Sopenharmony_ci	return;
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci wrong_mc4_mce:
9248c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "Corrupted MC4 MCE info?\n");
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_cistatic void decode_mc5_mce(struct mce *m)
9288c2ecf20Sopenharmony_ci{
9298c2ecf20Sopenharmony_ci	unsigned int fam = x86_family(m->cpuid);
9308c2ecf20Sopenharmony_ci	u16 ec = EC(m->status);
9318c2ecf20Sopenharmony_ci	u8 xec = XEC(m->status, xec_mask);
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	if (fam == 0xf || fam == 0x11)
9348c2ecf20Sopenharmony_ci		goto wrong_mc5_mce;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "MC5 Error: ");
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	if (INT_ERROR(ec)) {
9398c2ecf20Sopenharmony_ci		if (xec <= 0x1f) {
9408c2ecf20Sopenharmony_ci			pr_cont("Hardware Assert.\n");
9418c2ecf20Sopenharmony_ci			return;
9428c2ecf20Sopenharmony_ci		} else
9438c2ecf20Sopenharmony_ci			goto wrong_mc5_mce;
9448c2ecf20Sopenharmony_ci	}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	if (xec == 0x0 || xec == 0xc)
9478c2ecf20Sopenharmony_ci		pr_cont("%s.\n", mc5_mce_desc[xec]);
9488c2ecf20Sopenharmony_ci	else if (xec <= 0xd)
9498c2ecf20Sopenharmony_ci		pr_cont("%s parity error.\n", mc5_mce_desc[xec]);
9508c2ecf20Sopenharmony_ci	else
9518c2ecf20Sopenharmony_ci		goto wrong_mc5_mce;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	return;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci wrong_mc5_mce:
9568c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "Corrupted MC5 MCE info?\n");
9578c2ecf20Sopenharmony_ci}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_cistatic void decode_mc6_mce(struct mce *m)
9608c2ecf20Sopenharmony_ci{
9618c2ecf20Sopenharmony_ci	u8 xec = XEC(m->status, xec_mask);
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "MC6 Error: ");
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci	if (xec > 0x5)
9668c2ecf20Sopenharmony_ci		goto wrong_mc6_mce;
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	pr_cont("%s parity error.\n", mc6_mce_desc[xec]);
9698c2ecf20Sopenharmony_ci	return;
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci wrong_mc6_mce:
9728c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "Corrupted MC6 MCE info?\n");
9738c2ecf20Sopenharmony_ci}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci/* Decode errors according to Scalable MCA specification */
9768c2ecf20Sopenharmony_cistatic void decode_smca_error(struct mce *m)
9778c2ecf20Sopenharmony_ci{
9788c2ecf20Sopenharmony_ci	struct smca_hwid *hwid;
9798c2ecf20Sopenharmony_ci	enum smca_bank_types bank_type;
9808c2ecf20Sopenharmony_ci	const char *ip_name;
9818c2ecf20Sopenharmony_ci	u8 xec = XEC(m->status, xec_mask);
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	if (m->bank >= ARRAY_SIZE(smca_banks))
9848c2ecf20Sopenharmony_ci		return;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	hwid = smca_banks[m->bank].hwid;
9878c2ecf20Sopenharmony_ci	if (!hwid)
9888c2ecf20Sopenharmony_ci		return;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	bank_type = hwid->bank_type;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	if (bank_type == SMCA_RESERVED) {
9938c2ecf20Sopenharmony_ci		pr_emerg(HW_ERR "Bank %d is reserved.\n", m->bank);
9948c2ecf20Sopenharmony_ci		return;
9958c2ecf20Sopenharmony_ci	}
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	ip_name = smca_get_long_name(bank_type);
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "%s Ext. Error Code: %d", ip_name, xec);
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	/* Only print the decode of valid error codes */
10028c2ecf20Sopenharmony_ci	if (xec < smca_mce_descs[bank_type].num_descs)
10038c2ecf20Sopenharmony_ci		pr_cont(", %s.\n", smca_mce_descs[bank_type].descs[xec]);
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	if (bank_type == SMCA_UMC && xec == 0 && decode_dram_ecc)
10068c2ecf20Sopenharmony_ci		decode_dram_ecc(topology_die_id(m->extcpu), m);
10078c2ecf20Sopenharmony_ci}
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_cistatic inline void amd_decode_err_code(u16 ec)
10108c2ecf20Sopenharmony_ci{
10118c2ecf20Sopenharmony_ci	if (INT_ERROR(ec)) {
10128c2ecf20Sopenharmony_ci		pr_emerg(HW_ERR "internal: %s\n", UU_MSG(ec));
10138c2ecf20Sopenharmony_ci		return;
10148c2ecf20Sopenharmony_ci	}
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec));
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	if (BUS_ERROR(ec))
10198c2ecf20Sopenharmony_ci		pr_cont(", mem/io: %s", II_MSG(ec));
10208c2ecf20Sopenharmony_ci	else
10218c2ecf20Sopenharmony_ci		pr_cont(", tx: %s", TT_MSG(ec));
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	if (MEM_ERROR(ec) || BUS_ERROR(ec)) {
10248c2ecf20Sopenharmony_ci		pr_cont(", mem-tx: %s", R4_MSG(ec));
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci		if (BUS_ERROR(ec))
10278c2ecf20Sopenharmony_ci			pr_cont(", part-proc: %s (%s)", PP_MSG(ec), TO_MSG(ec));
10288c2ecf20Sopenharmony_ci	}
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci	pr_cont("\n");
10318c2ecf20Sopenharmony_ci}
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_cistatic const char *decode_error_status(struct mce *m)
10348c2ecf20Sopenharmony_ci{
10358c2ecf20Sopenharmony_ci	if (m->status & MCI_STATUS_UC) {
10368c2ecf20Sopenharmony_ci		if (m->status & MCI_STATUS_PCC)
10378c2ecf20Sopenharmony_ci			return "System Fatal error.";
10388c2ecf20Sopenharmony_ci		if (m->mcgstatus & MCG_STATUS_RIPV)
10398c2ecf20Sopenharmony_ci			return "Uncorrected, software restartable error.";
10408c2ecf20Sopenharmony_ci		return "Uncorrected, software containable error.";
10418c2ecf20Sopenharmony_ci	}
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	if (m->status & MCI_STATUS_DEFERRED)
10448c2ecf20Sopenharmony_ci		return "Deferred error, no action required.";
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	return "Corrected error, no action required.";
10478c2ecf20Sopenharmony_ci}
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_cistatic int
10508c2ecf20Sopenharmony_ciamd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
10518c2ecf20Sopenharmony_ci{
10528c2ecf20Sopenharmony_ci	struct mce *m = (struct mce *)data;
10538c2ecf20Sopenharmony_ci	unsigned int fam = x86_family(m->cpuid);
10548c2ecf20Sopenharmony_ci	int ecc;
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	if (m->kflags & MCE_HANDLED_CEC)
10578c2ecf20Sopenharmony_ci		return NOTIFY_DONE;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "%s\n", decode_error_status(m));
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
10628c2ecf20Sopenharmony_ci		m->extcpu,
10638c2ecf20Sopenharmony_ci		fam, x86_model(m->cpuid), x86_stepping(m->cpuid),
10648c2ecf20Sopenharmony_ci		m->bank,
10658c2ecf20Sopenharmony_ci		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
10668c2ecf20Sopenharmony_ci		((m->status & MCI_STATUS_UC)	? "UE"	  :
10678c2ecf20Sopenharmony_ci		 (m->status & MCI_STATUS_DEFERRED) ? "-"  : "CE"),
10688c2ecf20Sopenharmony_ci		((m->status & MCI_STATUS_MISCV)	? "MiscV" : "-"),
10698c2ecf20Sopenharmony_ci		((m->status & MCI_STATUS_ADDRV)	? "AddrV" : "-"),
10708c2ecf20Sopenharmony_ci		((m->status & MCI_STATUS_PCC)	? "PCC"	  : "-"));
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_SMCA)) {
10738c2ecf20Sopenharmony_ci		u32 low, high;
10748c2ecf20Sopenharmony_ci		u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci		if (!rdmsr_safe(addr, &low, &high) &&
10778c2ecf20Sopenharmony_ci		    (low & MCI_CONFIG_MCAX))
10788c2ecf20Sopenharmony_ci			pr_cont("|%s", ((m->status & MCI_STATUS_TCC) ? "TCC" : "-"));
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci		pr_cont("|%s", ((m->status & MCI_STATUS_SYNDV) ? "SyndV" : "-"));
10818c2ecf20Sopenharmony_ci	}
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	/* do the two bits[14:13] together */
10848c2ecf20Sopenharmony_ci	ecc = (m->status >> 45) & 0x3;
10858c2ecf20Sopenharmony_ci	if (ecc)
10868c2ecf20Sopenharmony_ci		pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	if (fam >= 0x15) {
10898c2ecf20Sopenharmony_ci		pr_cont("|%s", (m->status & MCI_STATUS_DEFERRED ? "Deferred" : "-"));
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci		/* F15h, bank4, bit 43 is part of McaStatSubCache. */
10928c2ecf20Sopenharmony_ci		if (fam != 0x15 || m->bank != 4)
10938c2ecf20Sopenharmony_ci			pr_cont("|%s", (m->status & MCI_STATUS_POISON ? "Poison" : "-"));
10948c2ecf20Sopenharmony_ci	}
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	if (fam >= 0x17)
10978c2ecf20Sopenharmony_ci		pr_cont("|%s", (m->status & MCI_STATUS_SCRUB ? "Scrub" : "-"));
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	pr_cont("]: 0x%016llx\n", m->status);
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	if (m->status & MCI_STATUS_ADDRV)
11028c2ecf20Sopenharmony_ci		pr_emerg(HW_ERR "Error Addr: 0x%016llx\n", m->addr);
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	if (m->ppin)
11058c2ecf20Sopenharmony_ci		pr_emerg(HW_ERR "PPIN: 0x%016llx\n", m->ppin);
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_SMCA)) {
11088c2ecf20Sopenharmony_ci		pr_emerg(HW_ERR "IPID: 0x%016llx", m->ipid);
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci		if (m->status & MCI_STATUS_SYNDV)
11118c2ecf20Sopenharmony_ci			pr_cont(", Syndrome: 0x%016llx", m->synd);
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci		pr_cont("\n");
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci		decode_smca_error(m);
11168c2ecf20Sopenharmony_ci		goto err_code;
11178c2ecf20Sopenharmony_ci	}
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	if (m->tsc)
11208c2ecf20Sopenharmony_ci		pr_emerg(HW_ERR "TSC: %llu\n", m->tsc);
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	/* Doesn't matter which member to test. */
11238c2ecf20Sopenharmony_ci	if (!fam_ops.mc0_mce)
11248c2ecf20Sopenharmony_ci		goto err_code;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	switch (m->bank) {
11278c2ecf20Sopenharmony_ci	case 0:
11288c2ecf20Sopenharmony_ci		decode_mc0_mce(m);
11298c2ecf20Sopenharmony_ci		break;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	case 1:
11328c2ecf20Sopenharmony_ci		decode_mc1_mce(m);
11338c2ecf20Sopenharmony_ci		break;
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	case 2:
11368c2ecf20Sopenharmony_ci		decode_mc2_mce(m);
11378c2ecf20Sopenharmony_ci		break;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	case 3:
11408c2ecf20Sopenharmony_ci		decode_mc3_mce(m);
11418c2ecf20Sopenharmony_ci		break;
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	case 4:
11448c2ecf20Sopenharmony_ci		decode_mc4_mce(m);
11458c2ecf20Sopenharmony_ci		break;
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci	case 5:
11488c2ecf20Sopenharmony_ci		decode_mc5_mce(m);
11498c2ecf20Sopenharmony_ci		break;
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	case 6:
11528c2ecf20Sopenharmony_ci		decode_mc6_mce(m);
11538c2ecf20Sopenharmony_ci		break;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	default:
11568c2ecf20Sopenharmony_ci		break;
11578c2ecf20Sopenharmony_ci	}
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci err_code:
11608c2ecf20Sopenharmony_ci	amd_decode_err_code(m->status & 0xffff);
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	m->kflags |= MCE_HANDLED_EDAC;
11638c2ecf20Sopenharmony_ci	return NOTIFY_OK;
11648c2ecf20Sopenharmony_ci}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_cistatic struct notifier_block amd_mce_dec_nb = {
11678c2ecf20Sopenharmony_ci	.notifier_call	= amd_decode_mce,
11688c2ecf20Sopenharmony_ci	.priority	= MCE_PRIO_EDAC,
11698c2ecf20Sopenharmony_ci};
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_cistatic int __init mce_amd_init(void)
11728c2ecf20Sopenharmony_ci{
11738c2ecf20Sopenharmony_ci	struct cpuinfo_x86 *c = &boot_cpu_data;
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	if (c->x86_vendor != X86_VENDOR_AMD &&
11768c2ecf20Sopenharmony_ci	    c->x86_vendor != X86_VENDOR_HYGON)
11778c2ecf20Sopenharmony_ci		return -ENODEV;
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
11808c2ecf20Sopenharmony_ci		return -ENODEV;
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_SMCA)) {
11838c2ecf20Sopenharmony_ci		xec_mask = 0x3f;
11848c2ecf20Sopenharmony_ci		goto out;
11858c2ecf20Sopenharmony_ci	}
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	switch (c->x86) {
11888c2ecf20Sopenharmony_ci	case 0xf:
11898c2ecf20Sopenharmony_ci		fam_ops.mc0_mce = k8_mc0_mce;
11908c2ecf20Sopenharmony_ci		fam_ops.mc1_mce = k8_mc1_mce;
11918c2ecf20Sopenharmony_ci		fam_ops.mc2_mce = k8_mc2_mce;
11928c2ecf20Sopenharmony_ci		break;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	case 0x10:
11958c2ecf20Sopenharmony_ci		fam_ops.mc0_mce = f10h_mc0_mce;
11968c2ecf20Sopenharmony_ci		fam_ops.mc1_mce = k8_mc1_mce;
11978c2ecf20Sopenharmony_ci		fam_ops.mc2_mce = k8_mc2_mce;
11988c2ecf20Sopenharmony_ci		break;
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	case 0x11:
12018c2ecf20Sopenharmony_ci		fam_ops.mc0_mce = k8_mc0_mce;
12028c2ecf20Sopenharmony_ci		fam_ops.mc1_mce = k8_mc1_mce;
12038c2ecf20Sopenharmony_ci		fam_ops.mc2_mce = k8_mc2_mce;
12048c2ecf20Sopenharmony_ci		break;
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	case 0x12:
12078c2ecf20Sopenharmony_ci		fam_ops.mc0_mce = f12h_mc0_mce;
12088c2ecf20Sopenharmony_ci		fam_ops.mc1_mce = k8_mc1_mce;
12098c2ecf20Sopenharmony_ci		fam_ops.mc2_mce = k8_mc2_mce;
12108c2ecf20Sopenharmony_ci		break;
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	case 0x14:
12138c2ecf20Sopenharmony_ci		fam_ops.mc0_mce = cat_mc0_mce;
12148c2ecf20Sopenharmony_ci		fam_ops.mc1_mce = cat_mc1_mce;
12158c2ecf20Sopenharmony_ci		fam_ops.mc2_mce = k8_mc2_mce;
12168c2ecf20Sopenharmony_ci		break;
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci	case 0x15:
12198c2ecf20Sopenharmony_ci		xec_mask = c->x86_model == 0x60 ? 0x3f : 0x1f;
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci		fam_ops.mc0_mce = f15h_mc0_mce;
12228c2ecf20Sopenharmony_ci		fam_ops.mc1_mce = f15h_mc1_mce;
12238c2ecf20Sopenharmony_ci		fam_ops.mc2_mce = f15h_mc2_mce;
12248c2ecf20Sopenharmony_ci		break;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	case 0x16:
12278c2ecf20Sopenharmony_ci		xec_mask = 0x1f;
12288c2ecf20Sopenharmony_ci		fam_ops.mc0_mce = cat_mc0_mce;
12298c2ecf20Sopenharmony_ci		fam_ops.mc1_mce = cat_mc1_mce;
12308c2ecf20Sopenharmony_ci		fam_ops.mc2_mce = f16h_mc2_mce;
12318c2ecf20Sopenharmony_ci		break;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	case 0x17:
12348c2ecf20Sopenharmony_ci	case 0x18:
12358c2ecf20Sopenharmony_ci		pr_warn_once("Decoding supported only on Scalable MCA processors.\n");
12368c2ecf20Sopenharmony_ci		return -EINVAL;
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	default:
12398c2ecf20Sopenharmony_ci		printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86);
12408c2ecf20Sopenharmony_ci		return -EINVAL;
12418c2ecf20Sopenharmony_ci	}
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ciout:
12448c2ecf20Sopenharmony_ci	pr_info("MCE: In-kernel MCE decoding enabled.\n");
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci	mce_register_decode_chain(&amd_mce_dec_nb);
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	return 0;
12498c2ecf20Sopenharmony_ci}
12508c2ecf20Sopenharmony_ciearly_initcall(mce_amd_init);
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci#ifdef MODULE
12538c2ecf20Sopenharmony_cistatic void __exit mce_amd_exit(void)
12548c2ecf20Sopenharmony_ci{
12558c2ecf20Sopenharmony_ci	mce_unregister_decode_chain(&amd_mce_dec_nb);
12568c2ecf20Sopenharmony_ci}
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("AMD MCE decoder");
12598c2ecf20Sopenharmony_ciMODULE_ALIAS("edac-mce-amd");
12608c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
12618c2ecf20Sopenharmony_cimodule_exit(mce_amd_exit);
12628c2ecf20Sopenharmony_ci#endif
1263