1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun #include <linux/module.h>
3*4882a593Smuzhiyun #include <linux/slab.h>
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <asm/cpu.h>
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include "mce_amd.h"
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun static struct amd_decoder_ops fam_ops;
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun static u8 xec_mask = 0xf;
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun static void (*decode_dram_ecc)(int node_id, struct mce *m);
14*4882a593Smuzhiyun
amd_register_ecc_decoder(void (* f)(int,struct mce *))15*4882a593Smuzhiyun void amd_register_ecc_decoder(void (*f)(int, struct mce *))
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun decode_dram_ecc = f;
18*4882a593Smuzhiyun }
19*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
20*4882a593Smuzhiyun
amd_unregister_ecc_decoder(void (* f)(int,struct mce *))21*4882a593Smuzhiyun void amd_unregister_ecc_decoder(void (*f)(int, struct mce *))
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun if (decode_dram_ecc) {
24*4882a593Smuzhiyun WARN_ON(decode_dram_ecc != f);
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun decode_dram_ecc = NULL;
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /*
32*4882a593Smuzhiyun * string representation for the different MCA reported error types, see F3x48
33*4882a593Smuzhiyun * or MSR0000_0411.
34*4882a593Smuzhiyun */
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /* transaction type */
37*4882a593Smuzhiyun static const char * const tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* cache level */
40*4882a593Smuzhiyun static const char * const ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* memory transaction type */
43*4882a593Smuzhiyun static const char * const rrrr_msgs[] = {
44*4882a593Smuzhiyun "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* participating processor */
48*4882a593Smuzhiyun const char * const pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
49*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pp_msgs);
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun /* request timeout */
52*4882a593Smuzhiyun static const char * const to_msgs[] = { "no timeout", "timed out" };
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* memory or i/o */
55*4882a593Smuzhiyun static const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /* internal error type */
58*4882a593Smuzhiyun static const char * const uu_msgs[] = { "RESV", "RESV", "HWA", "RESV" };
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun static const char * const f15h_mc1_mce_desc[] = {
61*4882a593Smuzhiyun "UC during a demand linefill from L2",
62*4882a593Smuzhiyun "Parity error during data load from IC",
63*4882a593Smuzhiyun "Parity error for IC valid bit",
64*4882a593Smuzhiyun "Main tag parity error",
65*4882a593Smuzhiyun "Parity error in prediction queue",
66*4882a593Smuzhiyun "PFB data/address parity error",
67*4882a593Smuzhiyun "Parity error in the branch status reg",
68*4882a593Smuzhiyun "PFB promotion address error",
69*4882a593Smuzhiyun "Tag error during probe/victimization",
70*4882a593Smuzhiyun "Parity error for IC probe tag valid bit",
71*4882a593Smuzhiyun "PFB non-cacheable bit parity error",
72*4882a593Smuzhiyun "PFB valid bit parity error", /* xec = 0xd */
73*4882a593Smuzhiyun "Microcode Patch Buffer", /* xec = 010 */
74*4882a593Smuzhiyun "uop queue",
75*4882a593Smuzhiyun "insn buffer",
76*4882a593Smuzhiyun "predecode buffer",
77*4882a593Smuzhiyun "fetch address FIFO",
78*4882a593Smuzhiyun "dispatch uop queue"
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun static const char * const f15h_mc2_mce_desc[] = {
82*4882a593Smuzhiyun "Fill ECC error on data fills", /* xec = 0x4 */
83*4882a593Smuzhiyun "Fill parity error on insn fills",
84*4882a593Smuzhiyun "Prefetcher request FIFO parity error",
85*4882a593Smuzhiyun "PRQ address parity error",
86*4882a593Smuzhiyun "PRQ data parity error",
87*4882a593Smuzhiyun "WCC Tag ECC error",
88*4882a593Smuzhiyun "WCC Data ECC error",
89*4882a593Smuzhiyun "WCB Data parity error",
90*4882a593Smuzhiyun "VB Data ECC or parity error",
91*4882a593Smuzhiyun "L2 Tag ECC error", /* xec = 0x10 */
92*4882a593Smuzhiyun "Hard L2 Tag ECC error",
93*4882a593Smuzhiyun "Multiple hits on L2 tag",
94*4882a593Smuzhiyun "XAB parity error",
95*4882a593Smuzhiyun "PRB address parity error"
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun static const char * const mc4_mce_desc[] = {
99*4882a593Smuzhiyun "DRAM ECC error detected on the NB",
100*4882a593Smuzhiyun "CRC error detected on HT link",
101*4882a593Smuzhiyun "Link-defined sync error packets detected on HT link",
102*4882a593Smuzhiyun "HT Master abort",
103*4882a593Smuzhiyun "HT Target abort",
104*4882a593Smuzhiyun "Invalid GART PTE entry during GART table walk",
105*4882a593Smuzhiyun "Unsupported atomic RMW received from an IO link",
106*4882a593Smuzhiyun "Watchdog timeout due to lack of progress",
107*4882a593Smuzhiyun "DRAM ECC error detected on the NB",
108*4882a593Smuzhiyun "SVM DMA Exclusion Vector error",
109*4882a593Smuzhiyun "HT data error detected on link",
110*4882a593Smuzhiyun "Protocol error (link, L3, probe filter)",
111*4882a593Smuzhiyun "NB internal arrays parity error",
112*4882a593Smuzhiyun "DRAM addr/ctl signals parity error",
113*4882a593Smuzhiyun "IO link transmission error",
114*4882a593Smuzhiyun "L3 data cache ECC error", /* xec = 0x1c */
115*4882a593Smuzhiyun "L3 cache tag error",
116*4882a593Smuzhiyun "L3 LRU parity bits error",
117*4882a593Smuzhiyun "ECC Error in the Probe Filter directory"
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun static const char * const mc5_mce_desc[] = {
121*4882a593Smuzhiyun "CPU Watchdog timer expire",
122*4882a593Smuzhiyun "Wakeup array dest tag",
123*4882a593Smuzhiyun "AG payload array",
124*4882a593Smuzhiyun "EX payload array",
125*4882a593Smuzhiyun "IDRF array",
126*4882a593Smuzhiyun "Retire dispatch queue",
127*4882a593Smuzhiyun "Mapper checkpoint array",
128*4882a593Smuzhiyun "Physical register file EX0 port",
129*4882a593Smuzhiyun "Physical register file EX1 port",
130*4882a593Smuzhiyun "Physical register file AG0 port",
131*4882a593Smuzhiyun "Physical register file AG1 port",
132*4882a593Smuzhiyun "Flag register file",
133*4882a593Smuzhiyun "DE error occurred",
134*4882a593Smuzhiyun "Retire status queue"
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun static const char * const mc6_mce_desc[] = {
138*4882a593Smuzhiyun "Hardware Assertion",
139*4882a593Smuzhiyun "Free List",
140*4882a593Smuzhiyun "Physical Register File",
141*4882a593Smuzhiyun "Retire Queue",
142*4882a593Smuzhiyun "Scheduler table",
143*4882a593Smuzhiyun "Status Register File",
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /* Scalable MCA error strings */
147*4882a593Smuzhiyun static const char * const smca_ls_mce_desc[] = {
148*4882a593Smuzhiyun "Load queue parity error",
149*4882a593Smuzhiyun "Store queue parity error",
150*4882a593Smuzhiyun "Miss address buffer payload parity error",
151*4882a593Smuzhiyun "Level 1 TLB parity error",
152*4882a593Smuzhiyun "DC Tag error type 5",
153*4882a593Smuzhiyun "DC Tag error type 6",
154*4882a593Smuzhiyun "DC Tag error type 1",
155*4882a593Smuzhiyun "Internal error type 1",
156*4882a593Smuzhiyun "Internal error type 2",
157*4882a593Smuzhiyun "System Read Data Error Thread 0",
158*4882a593Smuzhiyun "System Read Data Error Thread 1",
159*4882a593Smuzhiyun "DC Tag error type 2",
160*4882a593Smuzhiyun "DC Data error type 1 and poison consumption",
161*4882a593Smuzhiyun "DC Data error type 2",
162*4882a593Smuzhiyun "DC Data error type 3",
163*4882a593Smuzhiyun "DC Tag error type 4",
164*4882a593Smuzhiyun "Level 2 TLB parity error",
165*4882a593Smuzhiyun "PDC parity error",
166*4882a593Smuzhiyun "DC Tag error type 3",
167*4882a593Smuzhiyun "DC Tag error type 5",
168*4882a593Smuzhiyun "L2 Fill Data error",
169*4882a593Smuzhiyun };
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun static const char * const smca_ls2_mce_desc[] = {
172*4882a593Smuzhiyun "An ECC error was detected on a data cache read by a probe or victimization",
173*4882a593Smuzhiyun "An ECC error or L2 poison was detected on a data cache read by a load",
174*4882a593Smuzhiyun "An ECC error was detected on a data cache read-modify-write by a store",
175*4882a593Smuzhiyun "An ECC error or poison bit mismatch was detected on a tag read by a probe or victimization",
176*4882a593Smuzhiyun "An ECC error or poison bit mismatch was detected on a tag read by a load",
177*4882a593Smuzhiyun "An ECC error or poison bit mismatch was detected on a tag read by a store",
178*4882a593Smuzhiyun "An ECC error was detected on an EMEM read by a load",
179*4882a593Smuzhiyun "An ECC error was detected on an EMEM read-modify-write by a store",
180*4882a593Smuzhiyun "A parity error was detected in an L1 TLB entry by any access",
181*4882a593Smuzhiyun "A parity error was detected in an L2 TLB entry by any access",
182*4882a593Smuzhiyun "A parity error was detected in a PWC entry by any access",
183*4882a593Smuzhiyun "A parity error was detected in an STQ entry by any access",
184*4882a593Smuzhiyun "A parity error was detected in an LDQ entry by any access",
185*4882a593Smuzhiyun "A parity error was detected in a MAB entry by any access",
186*4882a593Smuzhiyun "A parity error was detected in an SCB entry state field by any access",
187*4882a593Smuzhiyun "A parity error was detected in an SCB entry address field by any access",
188*4882a593Smuzhiyun "A parity error was detected in an SCB entry data field by any access",
189*4882a593Smuzhiyun "A parity error was detected in a WCB entry by any access",
190*4882a593Smuzhiyun "A poisoned line was detected in an SCB entry by any access",
191*4882a593Smuzhiyun "A SystemReadDataError error was reported on read data returned from L2 for a load",
192*4882a593Smuzhiyun "A SystemReadDataError error was reported on read data returned from L2 for an SCB store",
193*4882a593Smuzhiyun "A SystemReadDataError error was reported on read data returned from L2 for a WCB store",
194*4882a593Smuzhiyun "A hardware assertion error was reported",
195*4882a593Smuzhiyun "A parity error was detected in an STLF, SCB EMEM entry or SRB store data by any access",
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun static const char * const smca_if_mce_desc[] = {
199*4882a593Smuzhiyun "Op Cache Microtag Probe Port Parity Error",
200*4882a593Smuzhiyun "IC Microtag or Full Tag Multi-hit Error",
201*4882a593Smuzhiyun "IC Full Tag Parity Error",
202*4882a593Smuzhiyun "IC Data Array Parity Error",
203*4882a593Smuzhiyun "Decoupling Queue PhysAddr Parity Error",
204*4882a593Smuzhiyun "L0 ITLB Parity Error",
205*4882a593Smuzhiyun "L1 ITLB Parity Error",
206*4882a593Smuzhiyun "L2 ITLB Parity Error",
207*4882a593Smuzhiyun "BPQ Thread 0 Snoop Parity Error",
208*4882a593Smuzhiyun "BPQ Thread 1 Snoop Parity Error",
209*4882a593Smuzhiyun "L1 BTB Multi-Match Error",
210*4882a593Smuzhiyun "L2 BTB Multi-Match Error",
211*4882a593Smuzhiyun "L2 Cache Response Poison Error",
212*4882a593Smuzhiyun "System Read Data Error",
213*4882a593Smuzhiyun "Hardware Assertion Error",
214*4882a593Smuzhiyun "L1-TLB Multi-Hit",
215*4882a593Smuzhiyun "L2-TLB Multi-Hit",
216*4882a593Smuzhiyun "BSR Parity Error",
217*4882a593Smuzhiyun "CT MCE",
218*4882a593Smuzhiyun };
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun static const char * const smca_l2_mce_desc[] = {
221*4882a593Smuzhiyun "L2M Tag Multiple-Way-Hit error",
222*4882a593Smuzhiyun "L2M Tag or State Array ECC Error",
223*4882a593Smuzhiyun "L2M Data Array ECC Error",
224*4882a593Smuzhiyun "Hardware Assert Error",
225*4882a593Smuzhiyun };
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun static const char * const smca_de_mce_desc[] = {
228*4882a593Smuzhiyun "Micro-op cache tag parity error",
229*4882a593Smuzhiyun "Micro-op cache data parity error",
230*4882a593Smuzhiyun "Instruction buffer parity error",
231*4882a593Smuzhiyun "Micro-op queue parity error",
232*4882a593Smuzhiyun "Instruction dispatch queue parity error",
233*4882a593Smuzhiyun "Fetch address FIFO parity error",
234*4882a593Smuzhiyun "Patch RAM data parity error",
235*4882a593Smuzhiyun "Patch RAM sequencer parity error",
236*4882a593Smuzhiyun "Micro-op buffer parity error",
237*4882a593Smuzhiyun "Hardware Assertion MCA Error",
238*4882a593Smuzhiyun };
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun static const char * const smca_ex_mce_desc[] = {
241*4882a593Smuzhiyun "Watchdog Timeout error",
242*4882a593Smuzhiyun "Physical register file parity error",
243*4882a593Smuzhiyun "Flag register file parity error",
244*4882a593Smuzhiyun "Immediate displacement register file parity error",
245*4882a593Smuzhiyun "Address generator payload parity error",
246*4882a593Smuzhiyun "EX payload parity error",
247*4882a593Smuzhiyun "Checkpoint queue parity error",
248*4882a593Smuzhiyun "Retire dispatch queue parity error",
249*4882a593Smuzhiyun "Retire status queue parity error",
250*4882a593Smuzhiyun "Scheduling queue parity error",
251*4882a593Smuzhiyun "Branch buffer queue parity error",
252*4882a593Smuzhiyun "Hardware Assertion error",
253*4882a593Smuzhiyun "Spec Map parity error",
254*4882a593Smuzhiyun "Retire Map parity error",
255*4882a593Smuzhiyun };
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun static const char * const smca_fp_mce_desc[] = {
258*4882a593Smuzhiyun "Physical register file (PRF) parity error",
259*4882a593Smuzhiyun "Freelist (FL) parity error",
260*4882a593Smuzhiyun "Schedule queue parity error",
261*4882a593Smuzhiyun "NSQ parity error",
262*4882a593Smuzhiyun "Retire queue (RQ) parity error",
263*4882a593Smuzhiyun "Status register file (SRF) parity error",
264*4882a593Smuzhiyun "Hardware assertion",
265*4882a593Smuzhiyun };
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun static const char * const smca_l3_mce_desc[] = {
268*4882a593Smuzhiyun "Shadow Tag Macro ECC Error",
269*4882a593Smuzhiyun "Shadow Tag Macro Multi-way-hit Error",
270*4882a593Smuzhiyun "L3M Tag ECC Error",
271*4882a593Smuzhiyun "L3M Tag Multi-way-hit Error",
272*4882a593Smuzhiyun "L3M Data ECC Error",
273*4882a593Smuzhiyun "SDP Parity Error or SystemReadDataError from XI",
274*4882a593Smuzhiyun "L3 Victim Queue Parity Error",
275*4882a593Smuzhiyun "L3 Hardware Assertion",
276*4882a593Smuzhiyun };
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun static const char * const smca_cs_mce_desc[] = {
279*4882a593Smuzhiyun "Illegal Request",
280*4882a593Smuzhiyun "Address Violation",
281*4882a593Smuzhiyun "Security Violation",
282*4882a593Smuzhiyun "Illegal Response",
283*4882a593Smuzhiyun "Unexpected Response",
284*4882a593Smuzhiyun "Request or Probe Parity Error",
285*4882a593Smuzhiyun "Read Response Parity Error",
286*4882a593Smuzhiyun "Atomic Request Parity Error",
287*4882a593Smuzhiyun "Probe Filter ECC Error",
288*4882a593Smuzhiyun };
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun static const char * const smca_cs2_mce_desc[] = {
291*4882a593Smuzhiyun "Illegal Request",
292*4882a593Smuzhiyun "Address Violation",
293*4882a593Smuzhiyun "Security Violation",
294*4882a593Smuzhiyun "Illegal Response",
295*4882a593Smuzhiyun "Unexpected Response",
296*4882a593Smuzhiyun "Request or Probe Parity Error",
297*4882a593Smuzhiyun "Read Response Parity Error",
298*4882a593Smuzhiyun "Atomic Request Parity Error",
299*4882a593Smuzhiyun "SDP read response had no match in the CS queue",
300*4882a593Smuzhiyun "Probe Filter Protocol Error",
301*4882a593Smuzhiyun "Probe Filter ECC Error",
302*4882a593Smuzhiyun "SDP read response had an unexpected RETRY error",
303*4882a593Smuzhiyun "Counter overflow error",
304*4882a593Smuzhiyun "Counter underflow error",
305*4882a593Smuzhiyun };
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun static const char * const smca_pie_mce_desc[] = {
308*4882a593Smuzhiyun "Hardware Assert",
309*4882a593Smuzhiyun "Register security violation",
310*4882a593Smuzhiyun "Link Error",
311*4882a593Smuzhiyun "Poison data consumption",
312*4882a593Smuzhiyun "A deferred error was detected in the DF"
313*4882a593Smuzhiyun };
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun static const char * const smca_umc_mce_desc[] = {
316*4882a593Smuzhiyun "DRAM ECC error",
317*4882a593Smuzhiyun "Data poison error",
318*4882a593Smuzhiyun "SDP parity error",
319*4882a593Smuzhiyun "Advanced peripheral bus error",
320*4882a593Smuzhiyun "Address/Command parity error",
321*4882a593Smuzhiyun "Write data CRC error",
322*4882a593Smuzhiyun "DCQ SRAM ECC error",
323*4882a593Smuzhiyun "AES SRAM ECC error",
324*4882a593Smuzhiyun };
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun static const char * const smca_pb_mce_desc[] = {
327*4882a593Smuzhiyun "An ECC error in the Parameter Block RAM array",
328*4882a593Smuzhiyun };
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun static const char * const smca_psp_mce_desc[] = {
331*4882a593Smuzhiyun "An ECC or parity error in a PSP RAM instance",
332*4882a593Smuzhiyun };
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun static const char * const smca_psp2_mce_desc[] = {
335*4882a593Smuzhiyun "High SRAM ECC or parity error",
336*4882a593Smuzhiyun "Low SRAM ECC or parity error",
337*4882a593Smuzhiyun "Instruction Cache Bank 0 ECC or parity error",
338*4882a593Smuzhiyun "Instruction Cache Bank 1 ECC or parity error",
339*4882a593Smuzhiyun "Instruction Tag Ram 0 parity error",
340*4882a593Smuzhiyun "Instruction Tag Ram 1 parity error",
341*4882a593Smuzhiyun "Data Cache Bank 0 ECC or parity error",
342*4882a593Smuzhiyun "Data Cache Bank 1 ECC or parity error",
343*4882a593Smuzhiyun "Data Cache Bank 2 ECC or parity error",
344*4882a593Smuzhiyun "Data Cache Bank 3 ECC or parity error",
345*4882a593Smuzhiyun "Data Tag Bank 0 parity error",
346*4882a593Smuzhiyun "Data Tag Bank 1 parity error",
347*4882a593Smuzhiyun "Data Tag Bank 2 parity error",
348*4882a593Smuzhiyun "Data Tag Bank 3 parity error",
349*4882a593Smuzhiyun "Dirty Data Ram parity error",
350*4882a593Smuzhiyun "TLB Bank 0 parity error",
351*4882a593Smuzhiyun "TLB Bank 1 parity error",
352*4882a593Smuzhiyun "System Hub Read Buffer ECC or parity error",
353*4882a593Smuzhiyun };
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun static const char * const smca_smu_mce_desc[] = {
356*4882a593Smuzhiyun "An ECC or parity error in an SMU RAM instance",
357*4882a593Smuzhiyun };
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun static const char * const smca_smu2_mce_desc[] = {
360*4882a593Smuzhiyun "High SRAM ECC or parity error",
361*4882a593Smuzhiyun "Low SRAM ECC or parity error",
362*4882a593Smuzhiyun "Data Cache Bank A ECC or parity error",
363*4882a593Smuzhiyun "Data Cache Bank B ECC or parity error",
364*4882a593Smuzhiyun "Data Tag Cache Bank A ECC or parity error",
365*4882a593Smuzhiyun "Data Tag Cache Bank B ECC or parity error",
366*4882a593Smuzhiyun "Instruction Cache Bank A ECC or parity error",
367*4882a593Smuzhiyun "Instruction Cache Bank B ECC or parity error",
368*4882a593Smuzhiyun "Instruction Tag Cache Bank A ECC or parity error",
369*4882a593Smuzhiyun "Instruction Tag Cache Bank B ECC or parity error",
370*4882a593Smuzhiyun "System Hub Read Buffer ECC or parity error",
371*4882a593Smuzhiyun "PHY RAM ECC error",
372*4882a593Smuzhiyun };
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun static const char * const smca_mp5_mce_desc[] = {
375*4882a593Smuzhiyun "High SRAM ECC or parity error",
376*4882a593Smuzhiyun "Low SRAM ECC or parity error",
377*4882a593Smuzhiyun "Data Cache Bank A ECC or parity error",
378*4882a593Smuzhiyun "Data Cache Bank B ECC or parity error",
379*4882a593Smuzhiyun "Data Tag Cache Bank A ECC or parity error",
380*4882a593Smuzhiyun "Data Tag Cache Bank B ECC or parity error",
381*4882a593Smuzhiyun "Instruction Cache Bank A ECC or parity error",
382*4882a593Smuzhiyun "Instruction Cache Bank B ECC or parity error",
383*4882a593Smuzhiyun "Instruction Tag Cache Bank A ECC or parity error",
384*4882a593Smuzhiyun "Instruction Tag Cache Bank B ECC or parity error",
385*4882a593Smuzhiyun };
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun static const char * const smca_nbio_mce_desc[] = {
388*4882a593Smuzhiyun "ECC or Parity error",
389*4882a593Smuzhiyun "PCIE error",
390*4882a593Smuzhiyun "SDP ErrEvent error",
391*4882a593Smuzhiyun "SDP Egress Poison Error",
392*4882a593Smuzhiyun "IOHC Internal Poison Error",
393*4882a593Smuzhiyun };
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun static const char * const smca_pcie_mce_desc[] = {
396*4882a593Smuzhiyun "CCIX PER Message logging",
397*4882a593Smuzhiyun "CCIX Read Response with Status: Non-Data Error",
398*4882a593Smuzhiyun "CCIX Write Response with Status: Non-Data Error",
399*4882a593Smuzhiyun "CCIX Read Response with Status: Data Error",
400*4882a593Smuzhiyun "CCIX Non-okay write response with data error",
401*4882a593Smuzhiyun };
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun struct smca_mce_desc {
404*4882a593Smuzhiyun const char * const *descs;
405*4882a593Smuzhiyun unsigned int num_descs;
406*4882a593Smuzhiyun };
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun static struct smca_mce_desc smca_mce_descs[] = {
409*4882a593Smuzhiyun [SMCA_LS] = { smca_ls_mce_desc, ARRAY_SIZE(smca_ls_mce_desc) },
410*4882a593Smuzhiyun [SMCA_LS_V2] = { smca_ls2_mce_desc, ARRAY_SIZE(smca_ls2_mce_desc) },
411*4882a593Smuzhiyun [SMCA_IF] = { smca_if_mce_desc, ARRAY_SIZE(smca_if_mce_desc) },
412*4882a593Smuzhiyun [SMCA_L2_CACHE] = { smca_l2_mce_desc, ARRAY_SIZE(smca_l2_mce_desc) },
413*4882a593Smuzhiyun [SMCA_DE] = { smca_de_mce_desc, ARRAY_SIZE(smca_de_mce_desc) },
414*4882a593Smuzhiyun [SMCA_EX] = { smca_ex_mce_desc, ARRAY_SIZE(smca_ex_mce_desc) },
415*4882a593Smuzhiyun [SMCA_FP] = { smca_fp_mce_desc, ARRAY_SIZE(smca_fp_mce_desc) },
416*4882a593Smuzhiyun [SMCA_L3_CACHE] = { smca_l3_mce_desc, ARRAY_SIZE(smca_l3_mce_desc) },
417*4882a593Smuzhiyun [SMCA_CS] = { smca_cs_mce_desc, ARRAY_SIZE(smca_cs_mce_desc) },
418*4882a593Smuzhiyun [SMCA_CS_V2] = { smca_cs2_mce_desc, ARRAY_SIZE(smca_cs2_mce_desc) },
419*4882a593Smuzhiyun [SMCA_PIE] = { smca_pie_mce_desc, ARRAY_SIZE(smca_pie_mce_desc) },
420*4882a593Smuzhiyun [SMCA_UMC] = { smca_umc_mce_desc, ARRAY_SIZE(smca_umc_mce_desc) },
421*4882a593Smuzhiyun [SMCA_PB] = { smca_pb_mce_desc, ARRAY_SIZE(smca_pb_mce_desc) },
422*4882a593Smuzhiyun [SMCA_PSP] = { smca_psp_mce_desc, ARRAY_SIZE(smca_psp_mce_desc) },
423*4882a593Smuzhiyun [SMCA_PSP_V2] = { smca_psp2_mce_desc, ARRAY_SIZE(smca_psp2_mce_desc) },
424*4882a593Smuzhiyun [SMCA_SMU] = { smca_smu_mce_desc, ARRAY_SIZE(smca_smu_mce_desc) },
425*4882a593Smuzhiyun [SMCA_SMU_V2] = { smca_smu2_mce_desc, ARRAY_SIZE(smca_smu2_mce_desc) },
426*4882a593Smuzhiyun [SMCA_MP5] = { smca_mp5_mce_desc, ARRAY_SIZE(smca_mp5_mce_desc) },
427*4882a593Smuzhiyun [SMCA_NBIO] = { smca_nbio_mce_desc, ARRAY_SIZE(smca_nbio_mce_desc) },
428*4882a593Smuzhiyun [SMCA_PCIE] = { smca_pcie_mce_desc, ARRAY_SIZE(smca_pcie_mce_desc) },
429*4882a593Smuzhiyun };
430*4882a593Smuzhiyun
f12h_mc0_mce(u16 ec,u8 xec)431*4882a593Smuzhiyun static bool f12h_mc0_mce(u16 ec, u8 xec)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun bool ret = false;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun if (MEM_ERROR(ec)) {
436*4882a593Smuzhiyun u8 ll = LL(ec);
437*4882a593Smuzhiyun ret = true;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun if (ll == LL_L2)
440*4882a593Smuzhiyun pr_cont("during L1 linefill from L2.\n");
441*4882a593Smuzhiyun else if (ll == LL_L1)
442*4882a593Smuzhiyun pr_cont("Data/Tag %s error.\n", R4_MSG(ec));
443*4882a593Smuzhiyun else
444*4882a593Smuzhiyun ret = false;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun return ret;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
f10h_mc0_mce(u16 ec,u8 xec)449*4882a593Smuzhiyun static bool f10h_mc0_mce(u16 ec, u8 xec)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
452*4882a593Smuzhiyun pr_cont("during data scrub.\n");
453*4882a593Smuzhiyun return true;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun return f12h_mc0_mce(ec, xec);
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
k8_mc0_mce(u16 ec,u8 xec)458*4882a593Smuzhiyun static bool k8_mc0_mce(u16 ec, u8 xec)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun if (BUS_ERROR(ec)) {
461*4882a593Smuzhiyun pr_cont("during system linefill.\n");
462*4882a593Smuzhiyun return true;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun return f10h_mc0_mce(ec, xec);
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
cat_mc0_mce(u16 ec,u8 xec)468*4882a593Smuzhiyun static bool cat_mc0_mce(u16 ec, u8 xec)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun u8 r4 = R4(ec);
471*4882a593Smuzhiyun bool ret = true;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun if (MEM_ERROR(ec)) {
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun if (TT(ec) != TT_DATA || LL(ec) != LL_L1)
476*4882a593Smuzhiyun return false;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun switch (r4) {
479*4882a593Smuzhiyun case R4_DRD:
480*4882a593Smuzhiyun case R4_DWR:
481*4882a593Smuzhiyun pr_cont("Data/Tag parity error due to %s.\n",
482*4882a593Smuzhiyun (r4 == R4_DRD ? "load/hw prf" : "store"));
483*4882a593Smuzhiyun break;
484*4882a593Smuzhiyun case R4_EVICT:
485*4882a593Smuzhiyun pr_cont("Copyback parity error on a tag miss.\n");
486*4882a593Smuzhiyun break;
487*4882a593Smuzhiyun case R4_SNOOP:
488*4882a593Smuzhiyun pr_cont("Tag parity error during snoop.\n");
489*4882a593Smuzhiyun break;
490*4882a593Smuzhiyun default:
491*4882a593Smuzhiyun ret = false;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun } else if (BUS_ERROR(ec)) {
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG)
496*4882a593Smuzhiyun return false;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun pr_cont("System read data error on a ");
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun switch (r4) {
501*4882a593Smuzhiyun case R4_RD:
502*4882a593Smuzhiyun pr_cont("TLB reload.\n");
503*4882a593Smuzhiyun break;
504*4882a593Smuzhiyun case R4_DWR:
505*4882a593Smuzhiyun pr_cont("store.\n");
506*4882a593Smuzhiyun break;
507*4882a593Smuzhiyun case R4_DRD:
508*4882a593Smuzhiyun pr_cont("load.\n");
509*4882a593Smuzhiyun break;
510*4882a593Smuzhiyun default:
511*4882a593Smuzhiyun ret = false;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun } else {
514*4882a593Smuzhiyun ret = false;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun return ret;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
f15h_mc0_mce(u16 ec,u8 xec)520*4882a593Smuzhiyun static bool f15h_mc0_mce(u16 ec, u8 xec)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun bool ret = true;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun if (MEM_ERROR(ec)) {
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun switch (xec) {
527*4882a593Smuzhiyun case 0x0:
528*4882a593Smuzhiyun pr_cont("Data Array access error.\n");
529*4882a593Smuzhiyun break;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun case 0x1:
532*4882a593Smuzhiyun pr_cont("UC error during a linefill from L2/NB.\n");
533*4882a593Smuzhiyun break;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun case 0x2:
536*4882a593Smuzhiyun case 0x11:
537*4882a593Smuzhiyun pr_cont("STQ access error.\n");
538*4882a593Smuzhiyun break;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun case 0x3:
541*4882a593Smuzhiyun pr_cont("SCB access error.\n");
542*4882a593Smuzhiyun break;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun case 0x10:
545*4882a593Smuzhiyun pr_cont("Tag error.\n");
546*4882a593Smuzhiyun break;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun case 0x12:
549*4882a593Smuzhiyun pr_cont("LDQ access error.\n");
550*4882a593Smuzhiyun break;
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun default:
553*4882a593Smuzhiyun ret = false;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun } else if (BUS_ERROR(ec)) {
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (!xec)
558*4882a593Smuzhiyun pr_cont("System Read Data Error.\n");
559*4882a593Smuzhiyun else
560*4882a593Smuzhiyun pr_cont(" Internal error condition type %d.\n", xec);
561*4882a593Smuzhiyun } else if (INT_ERROR(ec)) {
562*4882a593Smuzhiyun if (xec <= 0x1f)
563*4882a593Smuzhiyun pr_cont("Hardware Assert.\n");
564*4882a593Smuzhiyun else
565*4882a593Smuzhiyun ret = false;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun } else
568*4882a593Smuzhiyun ret = false;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun return ret;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
decode_mc0_mce(struct mce * m)573*4882a593Smuzhiyun static void decode_mc0_mce(struct mce *m)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun u16 ec = EC(m->status);
576*4882a593Smuzhiyun u8 xec = XEC(m->status, xec_mask);
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun pr_emerg(HW_ERR "MC0 Error: ");
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /* TLB error signatures are the same across families */
581*4882a593Smuzhiyun if (TLB_ERROR(ec)) {
582*4882a593Smuzhiyun if (TT(ec) == TT_DATA) {
583*4882a593Smuzhiyun pr_cont("%s TLB %s.\n", LL_MSG(ec),
584*4882a593Smuzhiyun ((xec == 2) ? "locked miss"
585*4882a593Smuzhiyun : (xec ? "multimatch" : "parity")));
586*4882a593Smuzhiyun return;
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun } else if (fam_ops.mc0_mce(ec, xec))
589*4882a593Smuzhiyun ;
590*4882a593Smuzhiyun else
591*4882a593Smuzhiyun pr_emerg(HW_ERR "Corrupted MC0 MCE info?\n");
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
k8_mc1_mce(u16 ec,u8 xec)594*4882a593Smuzhiyun static bool k8_mc1_mce(u16 ec, u8 xec)
595*4882a593Smuzhiyun {
596*4882a593Smuzhiyun u8 ll = LL(ec);
597*4882a593Smuzhiyun bool ret = true;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun if (!MEM_ERROR(ec))
600*4882a593Smuzhiyun return false;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun if (ll == 0x2)
603*4882a593Smuzhiyun pr_cont("during a linefill from L2.\n");
604*4882a593Smuzhiyun else if (ll == 0x1) {
605*4882a593Smuzhiyun switch (R4(ec)) {
606*4882a593Smuzhiyun case R4_IRD:
607*4882a593Smuzhiyun pr_cont("Parity error during data load.\n");
608*4882a593Smuzhiyun break;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun case R4_EVICT:
611*4882a593Smuzhiyun pr_cont("Copyback Parity/Victim error.\n");
612*4882a593Smuzhiyun break;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun case R4_SNOOP:
615*4882a593Smuzhiyun pr_cont("Tag Snoop error.\n");
616*4882a593Smuzhiyun break;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun default:
619*4882a593Smuzhiyun ret = false;
620*4882a593Smuzhiyun break;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun } else
623*4882a593Smuzhiyun ret = false;
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun return ret;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun
cat_mc1_mce(u16 ec,u8 xec)628*4882a593Smuzhiyun static bool cat_mc1_mce(u16 ec, u8 xec)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun u8 r4 = R4(ec);
631*4882a593Smuzhiyun bool ret = true;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun if (!MEM_ERROR(ec))
634*4882a593Smuzhiyun return false;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun if (TT(ec) != TT_INSTR)
637*4882a593Smuzhiyun return false;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun if (r4 == R4_IRD)
640*4882a593Smuzhiyun pr_cont("Data/tag array parity error for a tag hit.\n");
641*4882a593Smuzhiyun else if (r4 == R4_SNOOP)
642*4882a593Smuzhiyun pr_cont("Tag error during snoop/victimization.\n");
643*4882a593Smuzhiyun else if (xec == 0x0)
644*4882a593Smuzhiyun pr_cont("Tag parity error from victim castout.\n");
645*4882a593Smuzhiyun else if (xec == 0x2)
646*4882a593Smuzhiyun pr_cont("Microcode patch RAM parity error.\n");
647*4882a593Smuzhiyun else
648*4882a593Smuzhiyun ret = false;
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun return ret;
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun
f15h_mc1_mce(u16 ec,u8 xec)653*4882a593Smuzhiyun static bool f15h_mc1_mce(u16 ec, u8 xec)
654*4882a593Smuzhiyun {
655*4882a593Smuzhiyun bool ret = true;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun if (!MEM_ERROR(ec))
658*4882a593Smuzhiyun return false;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun switch (xec) {
661*4882a593Smuzhiyun case 0x0 ... 0xa:
662*4882a593Smuzhiyun pr_cont("%s.\n", f15h_mc1_mce_desc[xec]);
663*4882a593Smuzhiyun break;
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun case 0xd:
666*4882a593Smuzhiyun pr_cont("%s.\n", f15h_mc1_mce_desc[xec-2]);
667*4882a593Smuzhiyun break;
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun case 0x10:
670*4882a593Smuzhiyun pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
671*4882a593Smuzhiyun break;
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun case 0x11 ... 0x15:
674*4882a593Smuzhiyun pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
675*4882a593Smuzhiyun break;
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun default:
678*4882a593Smuzhiyun ret = false;
679*4882a593Smuzhiyun }
680*4882a593Smuzhiyun return ret;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun
decode_mc1_mce(struct mce * m)683*4882a593Smuzhiyun static void decode_mc1_mce(struct mce *m)
684*4882a593Smuzhiyun {
685*4882a593Smuzhiyun u16 ec = EC(m->status);
686*4882a593Smuzhiyun u8 xec = XEC(m->status, xec_mask);
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun pr_emerg(HW_ERR "MC1 Error: ");
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun if (TLB_ERROR(ec))
691*4882a593Smuzhiyun pr_cont("%s TLB %s.\n", LL_MSG(ec),
692*4882a593Smuzhiyun (xec ? "multimatch" : "parity error"));
693*4882a593Smuzhiyun else if (BUS_ERROR(ec)) {
694*4882a593Smuzhiyun bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
697*4882a593Smuzhiyun } else if (INT_ERROR(ec)) {
698*4882a593Smuzhiyun if (xec <= 0x3f)
699*4882a593Smuzhiyun pr_cont("Hardware Assert.\n");
700*4882a593Smuzhiyun else
701*4882a593Smuzhiyun goto wrong_mc1_mce;
702*4882a593Smuzhiyun } else if (fam_ops.mc1_mce(ec, xec))
703*4882a593Smuzhiyun ;
704*4882a593Smuzhiyun else
705*4882a593Smuzhiyun goto wrong_mc1_mce;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun return;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun wrong_mc1_mce:
710*4882a593Smuzhiyun pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun
k8_mc2_mce(u16 ec,u8 xec)713*4882a593Smuzhiyun static bool k8_mc2_mce(u16 ec, u8 xec)
714*4882a593Smuzhiyun {
715*4882a593Smuzhiyun bool ret = true;
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun if (xec == 0x1)
718*4882a593Smuzhiyun pr_cont(" in the write data buffers.\n");
719*4882a593Smuzhiyun else if (xec == 0x3)
720*4882a593Smuzhiyun pr_cont(" in the victim data buffers.\n");
721*4882a593Smuzhiyun else if (xec == 0x2 && MEM_ERROR(ec))
722*4882a593Smuzhiyun pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec));
723*4882a593Smuzhiyun else if (xec == 0x0) {
724*4882a593Smuzhiyun if (TLB_ERROR(ec))
725*4882a593Smuzhiyun pr_cont("%s error in a Page Descriptor Cache or Guest TLB.\n",
726*4882a593Smuzhiyun TT_MSG(ec));
727*4882a593Smuzhiyun else if (BUS_ERROR(ec))
728*4882a593Smuzhiyun pr_cont(": %s/ECC error in data read from NB: %s.\n",
729*4882a593Smuzhiyun R4_MSG(ec), PP_MSG(ec));
730*4882a593Smuzhiyun else if (MEM_ERROR(ec)) {
731*4882a593Smuzhiyun u8 r4 = R4(ec);
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun if (r4 >= 0x7)
734*4882a593Smuzhiyun pr_cont(": %s error during data copyback.\n",
735*4882a593Smuzhiyun R4_MSG(ec));
736*4882a593Smuzhiyun else if (r4 <= 0x1)
737*4882a593Smuzhiyun pr_cont(": %s parity/ECC error during data "
738*4882a593Smuzhiyun "access from L2.\n", R4_MSG(ec));
739*4882a593Smuzhiyun else
740*4882a593Smuzhiyun ret = false;
741*4882a593Smuzhiyun } else
742*4882a593Smuzhiyun ret = false;
743*4882a593Smuzhiyun } else
744*4882a593Smuzhiyun ret = false;
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun return ret;
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
f15h_mc2_mce(u16 ec,u8 xec)749*4882a593Smuzhiyun static bool f15h_mc2_mce(u16 ec, u8 xec)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun bool ret = true;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (TLB_ERROR(ec)) {
754*4882a593Smuzhiyun if (xec == 0x0)
755*4882a593Smuzhiyun pr_cont("Data parity TLB read error.\n");
756*4882a593Smuzhiyun else if (xec == 0x1)
757*4882a593Smuzhiyun pr_cont("Poison data provided for TLB fill.\n");
758*4882a593Smuzhiyun else
759*4882a593Smuzhiyun ret = false;
760*4882a593Smuzhiyun } else if (BUS_ERROR(ec)) {
761*4882a593Smuzhiyun if (xec > 2)
762*4882a593Smuzhiyun ret = false;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun pr_cont("Error during attempted NB data read.\n");
765*4882a593Smuzhiyun } else if (MEM_ERROR(ec)) {
766*4882a593Smuzhiyun switch (xec) {
767*4882a593Smuzhiyun case 0x4 ... 0xc:
768*4882a593Smuzhiyun pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x4]);
769*4882a593Smuzhiyun break;
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun case 0x10 ... 0x14:
772*4882a593Smuzhiyun pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x7]);
773*4882a593Smuzhiyun break;
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun default:
776*4882a593Smuzhiyun ret = false;
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun } else if (INT_ERROR(ec)) {
779*4882a593Smuzhiyun if (xec <= 0x3f)
780*4882a593Smuzhiyun pr_cont("Hardware Assert.\n");
781*4882a593Smuzhiyun else
782*4882a593Smuzhiyun ret = false;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun return ret;
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun
f16h_mc2_mce(u16 ec,u8 xec)788*4882a593Smuzhiyun static bool f16h_mc2_mce(u16 ec, u8 xec)
789*4882a593Smuzhiyun {
790*4882a593Smuzhiyun u8 r4 = R4(ec);
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun if (!MEM_ERROR(ec))
793*4882a593Smuzhiyun return false;
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun switch (xec) {
796*4882a593Smuzhiyun case 0x04 ... 0x05:
797*4882a593Smuzhiyun pr_cont("%cBUFF parity error.\n", (r4 == R4_RD) ? 'I' : 'O');
798*4882a593Smuzhiyun break;
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun case 0x09 ... 0x0b:
801*4882a593Smuzhiyun case 0x0d ... 0x0f:
802*4882a593Smuzhiyun pr_cont("ECC error in L2 tag (%s).\n",
803*4882a593Smuzhiyun ((r4 == R4_GEN) ? "BankReq" :
804*4882a593Smuzhiyun ((r4 == R4_SNOOP) ? "Prb" : "Fill")));
805*4882a593Smuzhiyun break;
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun case 0x10 ... 0x19:
808*4882a593Smuzhiyun case 0x1b:
809*4882a593Smuzhiyun pr_cont("ECC error in L2 data array (%s).\n",
810*4882a593Smuzhiyun (((r4 == R4_RD) && !(xec & 0x3)) ? "Hit" :
811*4882a593Smuzhiyun ((r4 == R4_GEN) ? "Attr" :
812*4882a593Smuzhiyun ((r4 == R4_EVICT) ? "Vict" : "Fill"))));
813*4882a593Smuzhiyun break;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun case 0x1c ... 0x1d:
816*4882a593Smuzhiyun case 0x1f:
817*4882a593Smuzhiyun pr_cont("Parity error in L2 attribute bits (%s).\n",
818*4882a593Smuzhiyun ((r4 == R4_RD) ? "Hit" :
819*4882a593Smuzhiyun ((r4 == R4_GEN) ? "Attr" : "Fill")));
820*4882a593Smuzhiyun break;
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun default:
823*4882a593Smuzhiyun return false;
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun return true;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun
decode_mc2_mce(struct mce * m)829*4882a593Smuzhiyun static void decode_mc2_mce(struct mce *m)
830*4882a593Smuzhiyun {
831*4882a593Smuzhiyun u16 ec = EC(m->status);
832*4882a593Smuzhiyun u8 xec = XEC(m->status, xec_mask);
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun pr_emerg(HW_ERR "MC2 Error: ");
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun if (!fam_ops.mc2_mce(ec, xec))
837*4882a593Smuzhiyun pr_cont(HW_ERR "Corrupted MC2 MCE info?\n");
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun
decode_mc3_mce(struct mce * m)840*4882a593Smuzhiyun static void decode_mc3_mce(struct mce *m)
841*4882a593Smuzhiyun {
842*4882a593Smuzhiyun u16 ec = EC(m->status);
843*4882a593Smuzhiyun u8 xec = XEC(m->status, xec_mask);
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun if (boot_cpu_data.x86 >= 0x14) {
846*4882a593Smuzhiyun pr_emerg("You shouldn't be seeing MC3 MCE on this cpu family,"
847*4882a593Smuzhiyun " please report on LKML.\n");
848*4882a593Smuzhiyun return;
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun pr_emerg(HW_ERR "MC3 Error");
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun if (xec == 0x0) {
854*4882a593Smuzhiyun u8 r4 = R4(ec);
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
857*4882a593Smuzhiyun goto wrong_mc3_mce;
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun pr_cont(" during %s.\n", R4_MSG(ec));
860*4882a593Smuzhiyun } else
861*4882a593Smuzhiyun goto wrong_mc3_mce;
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun return;
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun wrong_mc3_mce:
866*4882a593Smuzhiyun pr_emerg(HW_ERR "Corrupted MC3 MCE info?\n");
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun
decode_mc4_mce(struct mce * m)869*4882a593Smuzhiyun static void decode_mc4_mce(struct mce *m)
870*4882a593Smuzhiyun {
871*4882a593Smuzhiyun unsigned int fam = x86_family(m->cpuid);
872*4882a593Smuzhiyun int node_id = amd_get_nb_id(m->extcpu);
873*4882a593Smuzhiyun u16 ec = EC(m->status);
874*4882a593Smuzhiyun u8 xec = XEC(m->status, 0x1f);
875*4882a593Smuzhiyun u8 offset = 0;
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun pr_emerg(HW_ERR "MC4 Error (node %d): ", node_id);
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun switch (xec) {
880*4882a593Smuzhiyun case 0x0 ... 0xe:
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun /* special handling for DRAM ECCs */
883*4882a593Smuzhiyun if (xec == 0x0 || xec == 0x8) {
884*4882a593Smuzhiyun /* no ECCs on F11h */
885*4882a593Smuzhiyun if (fam == 0x11)
886*4882a593Smuzhiyun goto wrong_mc4_mce;
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun pr_cont("%s.\n", mc4_mce_desc[xec]);
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun if (decode_dram_ecc)
891*4882a593Smuzhiyun decode_dram_ecc(node_id, m);
892*4882a593Smuzhiyun return;
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun break;
895*4882a593Smuzhiyun
896*4882a593Smuzhiyun case 0xf:
897*4882a593Smuzhiyun if (TLB_ERROR(ec))
898*4882a593Smuzhiyun pr_cont("GART Table Walk data error.\n");
899*4882a593Smuzhiyun else if (BUS_ERROR(ec))
900*4882a593Smuzhiyun pr_cont("DMA Exclusion Vector Table Walk error.\n");
901*4882a593Smuzhiyun else
902*4882a593Smuzhiyun goto wrong_mc4_mce;
903*4882a593Smuzhiyun return;
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun case 0x19:
906*4882a593Smuzhiyun if (fam == 0x15 || fam == 0x16)
907*4882a593Smuzhiyun pr_cont("Compute Unit Data Error.\n");
908*4882a593Smuzhiyun else
909*4882a593Smuzhiyun goto wrong_mc4_mce;
910*4882a593Smuzhiyun return;
911*4882a593Smuzhiyun
912*4882a593Smuzhiyun case 0x1c ... 0x1f:
913*4882a593Smuzhiyun offset = 13;
914*4882a593Smuzhiyun break;
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun default:
917*4882a593Smuzhiyun goto wrong_mc4_mce;
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun pr_cont("%s.\n", mc4_mce_desc[xec - offset]);
921*4882a593Smuzhiyun return;
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun wrong_mc4_mce:
924*4882a593Smuzhiyun pr_emerg(HW_ERR "Corrupted MC4 MCE info?\n");
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun
decode_mc5_mce(struct mce * m)927*4882a593Smuzhiyun static void decode_mc5_mce(struct mce *m)
928*4882a593Smuzhiyun {
929*4882a593Smuzhiyun unsigned int fam = x86_family(m->cpuid);
930*4882a593Smuzhiyun u16 ec = EC(m->status);
931*4882a593Smuzhiyun u8 xec = XEC(m->status, xec_mask);
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun if (fam == 0xf || fam == 0x11)
934*4882a593Smuzhiyun goto wrong_mc5_mce;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun pr_emerg(HW_ERR "MC5 Error: ");
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun if (INT_ERROR(ec)) {
939*4882a593Smuzhiyun if (xec <= 0x1f) {
940*4882a593Smuzhiyun pr_cont("Hardware Assert.\n");
941*4882a593Smuzhiyun return;
942*4882a593Smuzhiyun } else
943*4882a593Smuzhiyun goto wrong_mc5_mce;
944*4882a593Smuzhiyun }
945*4882a593Smuzhiyun
946*4882a593Smuzhiyun if (xec == 0x0 || xec == 0xc)
947*4882a593Smuzhiyun pr_cont("%s.\n", mc5_mce_desc[xec]);
948*4882a593Smuzhiyun else if (xec <= 0xd)
949*4882a593Smuzhiyun pr_cont("%s parity error.\n", mc5_mce_desc[xec]);
950*4882a593Smuzhiyun else
951*4882a593Smuzhiyun goto wrong_mc5_mce;
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun return;
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun wrong_mc5_mce:
956*4882a593Smuzhiyun pr_emerg(HW_ERR "Corrupted MC5 MCE info?\n");
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun
decode_mc6_mce(struct mce * m)959*4882a593Smuzhiyun static void decode_mc6_mce(struct mce *m)
960*4882a593Smuzhiyun {
961*4882a593Smuzhiyun u8 xec = XEC(m->status, xec_mask);
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun pr_emerg(HW_ERR "MC6 Error: ");
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun if (xec > 0x5)
966*4882a593Smuzhiyun goto wrong_mc6_mce;
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun pr_cont("%s parity error.\n", mc6_mce_desc[xec]);
969*4882a593Smuzhiyun return;
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun wrong_mc6_mce:
972*4882a593Smuzhiyun pr_emerg(HW_ERR "Corrupted MC6 MCE info?\n");
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun /* Decode errors according to Scalable MCA specification */
decode_smca_error(struct mce * m)976*4882a593Smuzhiyun static void decode_smca_error(struct mce *m)
977*4882a593Smuzhiyun {
978*4882a593Smuzhiyun struct smca_hwid *hwid;
979*4882a593Smuzhiyun enum smca_bank_types bank_type;
980*4882a593Smuzhiyun const char *ip_name;
981*4882a593Smuzhiyun u8 xec = XEC(m->status, xec_mask);
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun if (m->bank >= ARRAY_SIZE(smca_banks))
984*4882a593Smuzhiyun return;
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun hwid = smca_banks[m->bank].hwid;
987*4882a593Smuzhiyun if (!hwid)
988*4882a593Smuzhiyun return;
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun bank_type = hwid->bank_type;
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun if (bank_type == SMCA_RESERVED) {
993*4882a593Smuzhiyun pr_emerg(HW_ERR "Bank %d is reserved.\n", m->bank);
994*4882a593Smuzhiyun return;
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun ip_name = smca_get_long_name(bank_type);
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun pr_emerg(HW_ERR "%s Ext. Error Code: %d", ip_name, xec);
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun /* Only print the decode of valid error codes */
1002*4882a593Smuzhiyun if (xec < smca_mce_descs[bank_type].num_descs)
1003*4882a593Smuzhiyun pr_cont(", %s.\n", smca_mce_descs[bank_type].descs[xec]);
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun if (bank_type == SMCA_UMC && xec == 0 && decode_dram_ecc)
1006*4882a593Smuzhiyun decode_dram_ecc(topology_die_id(m->extcpu), m);
1007*4882a593Smuzhiyun }
1008*4882a593Smuzhiyun
amd_decode_err_code(u16 ec)1009*4882a593Smuzhiyun static inline void amd_decode_err_code(u16 ec)
1010*4882a593Smuzhiyun {
1011*4882a593Smuzhiyun if (INT_ERROR(ec)) {
1012*4882a593Smuzhiyun pr_emerg(HW_ERR "internal: %s\n", UU_MSG(ec));
1013*4882a593Smuzhiyun return;
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec));
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun if (BUS_ERROR(ec))
1019*4882a593Smuzhiyun pr_cont(", mem/io: %s", II_MSG(ec));
1020*4882a593Smuzhiyun else
1021*4882a593Smuzhiyun pr_cont(", tx: %s", TT_MSG(ec));
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun if (MEM_ERROR(ec) || BUS_ERROR(ec)) {
1024*4882a593Smuzhiyun pr_cont(", mem-tx: %s", R4_MSG(ec));
1025*4882a593Smuzhiyun
1026*4882a593Smuzhiyun if (BUS_ERROR(ec))
1027*4882a593Smuzhiyun pr_cont(", part-proc: %s (%s)", PP_MSG(ec), TO_MSG(ec));
1028*4882a593Smuzhiyun }
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun pr_cont("\n");
1031*4882a593Smuzhiyun }
1032*4882a593Smuzhiyun
decode_error_status(struct mce * m)1033*4882a593Smuzhiyun static const char *decode_error_status(struct mce *m)
1034*4882a593Smuzhiyun {
1035*4882a593Smuzhiyun if (m->status & MCI_STATUS_UC) {
1036*4882a593Smuzhiyun if (m->status & MCI_STATUS_PCC)
1037*4882a593Smuzhiyun return "System Fatal error.";
1038*4882a593Smuzhiyun if (m->mcgstatus & MCG_STATUS_RIPV)
1039*4882a593Smuzhiyun return "Uncorrected, software restartable error.";
1040*4882a593Smuzhiyun return "Uncorrected, software containable error.";
1041*4882a593Smuzhiyun }
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun if (m->status & MCI_STATUS_DEFERRED)
1044*4882a593Smuzhiyun return "Deferred error, no action required.";
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun return "Corrected error, no action required.";
1047*4882a593Smuzhiyun }
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun static int
amd_decode_mce(struct notifier_block * nb,unsigned long val,void * data)1050*4882a593Smuzhiyun amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
1051*4882a593Smuzhiyun {
1052*4882a593Smuzhiyun struct mce *m = (struct mce *)data;
1053*4882a593Smuzhiyun unsigned int fam = x86_family(m->cpuid);
1054*4882a593Smuzhiyun int ecc;
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun if (m->kflags & MCE_HANDLED_CEC)
1057*4882a593Smuzhiyun return NOTIFY_DONE;
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun pr_emerg(HW_ERR "%s\n", decode_error_status(m));
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
1062*4882a593Smuzhiyun m->extcpu,
1063*4882a593Smuzhiyun fam, x86_model(m->cpuid), x86_stepping(m->cpuid),
1064*4882a593Smuzhiyun m->bank,
1065*4882a593Smuzhiyun ((m->status & MCI_STATUS_OVER) ? "Over" : "-"),
1066*4882a593Smuzhiyun ((m->status & MCI_STATUS_UC) ? "UE" :
1067*4882a593Smuzhiyun (m->status & MCI_STATUS_DEFERRED) ? "-" : "CE"),
1068*4882a593Smuzhiyun ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
1069*4882a593Smuzhiyun ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"),
1070*4882a593Smuzhiyun ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"));
1071*4882a593Smuzhiyun
1072*4882a593Smuzhiyun if (boot_cpu_has(X86_FEATURE_SMCA)) {
1073*4882a593Smuzhiyun u32 low, high;
1074*4882a593Smuzhiyun u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank);
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun if (!rdmsr_safe(addr, &low, &high) &&
1077*4882a593Smuzhiyun (low & MCI_CONFIG_MCAX))
1078*4882a593Smuzhiyun pr_cont("|%s", ((m->status & MCI_STATUS_TCC) ? "TCC" : "-"));
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun pr_cont("|%s", ((m->status & MCI_STATUS_SYNDV) ? "SyndV" : "-"));
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun /* do the two bits[14:13] together */
1084*4882a593Smuzhiyun ecc = (m->status >> 45) & 0x3;
1085*4882a593Smuzhiyun if (ecc)
1086*4882a593Smuzhiyun pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
1087*4882a593Smuzhiyun
1088*4882a593Smuzhiyun if (fam >= 0x15) {
1089*4882a593Smuzhiyun pr_cont("|%s", (m->status & MCI_STATUS_DEFERRED ? "Deferred" : "-"));
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun /* F15h, bank4, bit 43 is part of McaStatSubCache. */
1092*4882a593Smuzhiyun if (fam != 0x15 || m->bank != 4)
1093*4882a593Smuzhiyun pr_cont("|%s", (m->status & MCI_STATUS_POISON ? "Poison" : "-"));
1094*4882a593Smuzhiyun }
1095*4882a593Smuzhiyun
1096*4882a593Smuzhiyun if (fam >= 0x17)
1097*4882a593Smuzhiyun pr_cont("|%s", (m->status & MCI_STATUS_SCRUB ? "Scrub" : "-"));
1098*4882a593Smuzhiyun
1099*4882a593Smuzhiyun pr_cont("]: 0x%016llx\n", m->status);
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun if (m->status & MCI_STATUS_ADDRV)
1102*4882a593Smuzhiyun pr_emerg(HW_ERR "Error Addr: 0x%016llx\n", m->addr);
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun if (m->ppin)
1105*4882a593Smuzhiyun pr_emerg(HW_ERR "PPIN: 0x%016llx\n", m->ppin);
1106*4882a593Smuzhiyun
1107*4882a593Smuzhiyun if (boot_cpu_has(X86_FEATURE_SMCA)) {
1108*4882a593Smuzhiyun pr_emerg(HW_ERR "IPID: 0x%016llx", m->ipid);
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun if (m->status & MCI_STATUS_SYNDV)
1111*4882a593Smuzhiyun pr_cont(", Syndrome: 0x%016llx", m->synd);
1112*4882a593Smuzhiyun
1113*4882a593Smuzhiyun pr_cont("\n");
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun decode_smca_error(m);
1116*4882a593Smuzhiyun goto err_code;
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun if (m->tsc)
1120*4882a593Smuzhiyun pr_emerg(HW_ERR "TSC: %llu\n", m->tsc);
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun /* Doesn't matter which member to test. */
1123*4882a593Smuzhiyun if (!fam_ops.mc0_mce)
1124*4882a593Smuzhiyun goto err_code;
1125*4882a593Smuzhiyun
1126*4882a593Smuzhiyun switch (m->bank) {
1127*4882a593Smuzhiyun case 0:
1128*4882a593Smuzhiyun decode_mc0_mce(m);
1129*4882a593Smuzhiyun break;
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun case 1:
1132*4882a593Smuzhiyun decode_mc1_mce(m);
1133*4882a593Smuzhiyun break;
1134*4882a593Smuzhiyun
1135*4882a593Smuzhiyun case 2:
1136*4882a593Smuzhiyun decode_mc2_mce(m);
1137*4882a593Smuzhiyun break;
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun case 3:
1140*4882a593Smuzhiyun decode_mc3_mce(m);
1141*4882a593Smuzhiyun break;
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun case 4:
1144*4882a593Smuzhiyun decode_mc4_mce(m);
1145*4882a593Smuzhiyun break;
1146*4882a593Smuzhiyun
1147*4882a593Smuzhiyun case 5:
1148*4882a593Smuzhiyun decode_mc5_mce(m);
1149*4882a593Smuzhiyun break;
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyun case 6:
1152*4882a593Smuzhiyun decode_mc6_mce(m);
1153*4882a593Smuzhiyun break;
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun default:
1156*4882a593Smuzhiyun break;
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun err_code:
1160*4882a593Smuzhiyun amd_decode_err_code(m->status & 0xffff);
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun m->kflags |= MCE_HANDLED_EDAC;
1163*4882a593Smuzhiyun return NOTIFY_OK;
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun
1166*4882a593Smuzhiyun static struct notifier_block amd_mce_dec_nb = {
1167*4882a593Smuzhiyun .notifier_call = amd_decode_mce,
1168*4882a593Smuzhiyun .priority = MCE_PRIO_EDAC,
1169*4882a593Smuzhiyun };
1170*4882a593Smuzhiyun
mce_amd_init(void)1171*4882a593Smuzhiyun static int __init mce_amd_init(void)
1172*4882a593Smuzhiyun {
1173*4882a593Smuzhiyun struct cpuinfo_x86 *c = &boot_cpu_data;
1174*4882a593Smuzhiyun
1175*4882a593Smuzhiyun if (c->x86_vendor != X86_VENDOR_AMD &&
1176*4882a593Smuzhiyun c->x86_vendor != X86_VENDOR_HYGON)
1177*4882a593Smuzhiyun return -ENODEV;
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
1180*4882a593Smuzhiyun return -ENODEV;
1181*4882a593Smuzhiyun
1182*4882a593Smuzhiyun if (boot_cpu_has(X86_FEATURE_SMCA)) {
1183*4882a593Smuzhiyun xec_mask = 0x3f;
1184*4882a593Smuzhiyun goto out;
1185*4882a593Smuzhiyun }
1186*4882a593Smuzhiyun
1187*4882a593Smuzhiyun switch (c->x86) {
1188*4882a593Smuzhiyun case 0xf:
1189*4882a593Smuzhiyun fam_ops.mc0_mce = k8_mc0_mce;
1190*4882a593Smuzhiyun fam_ops.mc1_mce = k8_mc1_mce;
1191*4882a593Smuzhiyun fam_ops.mc2_mce = k8_mc2_mce;
1192*4882a593Smuzhiyun break;
1193*4882a593Smuzhiyun
1194*4882a593Smuzhiyun case 0x10:
1195*4882a593Smuzhiyun fam_ops.mc0_mce = f10h_mc0_mce;
1196*4882a593Smuzhiyun fam_ops.mc1_mce = k8_mc1_mce;
1197*4882a593Smuzhiyun fam_ops.mc2_mce = k8_mc2_mce;
1198*4882a593Smuzhiyun break;
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun case 0x11:
1201*4882a593Smuzhiyun fam_ops.mc0_mce = k8_mc0_mce;
1202*4882a593Smuzhiyun fam_ops.mc1_mce = k8_mc1_mce;
1203*4882a593Smuzhiyun fam_ops.mc2_mce = k8_mc2_mce;
1204*4882a593Smuzhiyun break;
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun case 0x12:
1207*4882a593Smuzhiyun fam_ops.mc0_mce = f12h_mc0_mce;
1208*4882a593Smuzhiyun fam_ops.mc1_mce = k8_mc1_mce;
1209*4882a593Smuzhiyun fam_ops.mc2_mce = k8_mc2_mce;
1210*4882a593Smuzhiyun break;
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun case 0x14:
1213*4882a593Smuzhiyun fam_ops.mc0_mce = cat_mc0_mce;
1214*4882a593Smuzhiyun fam_ops.mc1_mce = cat_mc1_mce;
1215*4882a593Smuzhiyun fam_ops.mc2_mce = k8_mc2_mce;
1216*4882a593Smuzhiyun break;
1217*4882a593Smuzhiyun
1218*4882a593Smuzhiyun case 0x15:
1219*4882a593Smuzhiyun xec_mask = c->x86_model == 0x60 ? 0x3f : 0x1f;
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun fam_ops.mc0_mce = f15h_mc0_mce;
1222*4882a593Smuzhiyun fam_ops.mc1_mce = f15h_mc1_mce;
1223*4882a593Smuzhiyun fam_ops.mc2_mce = f15h_mc2_mce;
1224*4882a593Smuzhiyun break;
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun case 0x16:
1227*4882a593Smuzhiyun xec_mask = 0x1f;
1228*4882a593Smuzhiyun fam_ops.mc0_mce = cat_mc0_mce;
1229*4882a593Smuzhiyun fam_ops.mc1_mce = cat_mc1_mce;
1230*4882a593Smuzhiyun fam_ops.mc2_mce = f16h_mc2_mce;
1231*4882a593Smuzhiyun break;
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun case 0x17:
1234*4882a593Smuzhiyun case 0x18:
1235*4882a593Smuzhiyun pr_warn_once("Decoding supported only on Scalable MCA processors.\n");
1236*4882a593Smuzhiyun return -EINVAL;
1237*4882a593Smuzhiyun
1238*4882a593Smuzhiyun default:
1239*4882a593Smuzhiyun printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86);
1240*4882a593Smuzhiyun return -EINVAL;
1241*4882a593Smuzhiyun }
1242*4882a593Smuzhiyun
1243*4882a593Smuzhiyun out:
1244*4882a593Smuzhiyun pr_info("MCE: In-kernel MCE decoding enabled.\n");
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun mce_register_decode_chain(&amd_mce_dec_nb);
1247*4882a593Smuzhiyun
1248*4882a593Smuzhiyun return 0;
1249*4882a593Smuzhiyun }
1250*4882a593Smuzhiyun early_initcall(mce_amd_init);
1251*4882a593Smuzhiyun
1252*4882a593Smuzhiyun #ifdef MODULE
mce_amd_exit(void)1253*4882a593Smuzhiyun static void __exit mce_amd_exit(void)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun mce_unregister_decode_chain(&amd_mce_dec_nb);
1256*4882a593Smuzhiyun }
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun MODULE_DESCRIPTION("AMD MCE decoder");
1259*4882a593Smuzhiyun MODULE_ALIAS("edac-mce-amd");
1260*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1261*4882a593Smuzhiyun module_exit(mce_amd_exit);
1262*4882a593Smuzhiyun #endif
1263