Blame view
drivers/edac/mce_amd.c
17.1 KB
b70ef0101 EDAC: move MCE er... |
1 |
#include <linux/module.h> |
888ab8e6e EDAC, MCE: Adjust... |
2 |
#include <linux/slab.h> |
47ca08a40 EDAC, MCE: Rename... |
3 |
#include "mce_amd.h" |
b52401cec amd64_edac: add M... |
4 |
|
888ab8e6e EDAC, MCE: Adjust... |
5 |
static struct amd_decoder_ops *fam_ops; |
2be64bfac EDAC, MCE: Select... |
6 |
static u8 xec_mask = 0xf; |
5ce88f6ea EDAC, MCE: Comple... |
7 |
static u8 nb_err_cpumask = 0xf; |
549d042df x86, mce: pass mc... |
8 |
static bool report_gart_errors; |
b0b07a2bd EDAC, MCE, AMD: S... |
9 |
static void (*nb_bus_decoder)(int node_id, struct mce *m); |
549d042df x86, mce: pass mc... |
10 11 12 13 14 15 |
void amd_report_gart_errors(bool v) { report_gart_errors = v; } EXPORT_SYMBOL_GPL(amd_report_gart_errors); |
b0b07a2bd EDAC, MCE, AMD: S... |
16 |
void amd_register_ecc_decoder(void (*f)(int, struct mce *)) |
549d042df x86, mce: pass mc... |
17 18 19 20 |
{ nb_bus_decoder = f; } EXPORT_SYMBOL_GPL(amd_register_ecc_decoder); |
b0b07a2bd EDAC, MCE, AMD: S... |
21 |
void amd_unregister_ecc_decoder(void (*f)(int, struct mce *)) |
549d042df x86, mce: pass mc... |
22 23 24 25 26 27 28 29 |
{ if (nb_bus_decoder) { WARN_ON(nb_bus_decoder != f); nb_bus_decoder = NULL; } } EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder); |
b52401cec amd64_edac: add M... |
30 31 32 33 |
/* * string representation for the different MCA reported error types, see F3x48 * or MSR0000_0411. */ |
6337583d7 EDAC, MCE: Saniti... |
34 35 36 |
/* transaction type */ const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" }; |
b70ef0101 EDAC: move MCE er... |
37 |
EXPORT_SYMBOL_GPL(tt_msgs); |
b52401cec amd64_edac: add M... |
38 |
|
6337583d7 EDAC, MCE: Saniti... |
39 40 |
/* cache level */ const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" }; |
b70ef0101 EDAC: move MCE er... |
41 |
EXPORT_SYMBOL_GPL(ll_msgs); |
b52401cec amd64_edac: add M... |
42 |
|
6337583d7 EDAC, MCE: Saniti... |
43 |
/* memory transaction type */ |
b52401cec amd64_edac: add M... |
44 |
const char *rrrr_msgs[] = { |
6337583d7 EDAC, MCE: Saniti... |
45 |
"GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP" |
b52401cec amd64_edac: add M... |
46 |
}; |
b70ef0101 EDAC: move MCE er... |
47 |
EXPORT_SYMBOL_GPL(rrrr_msgs); |
b52401cec amd64_edac: add M... |
48 |
|
6337583d7 EDAC, MCE: Saniti... |
49 50 |
/* participating processor */ const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" }; |
b70ef0101 EDAC: move MCE er... |
51 |
EXPORT_SYMBOL_GPL(pp_msgs); |
b52401cec amd64_edac: add M... |
52 |
|
6337583d7 EDAC, MCE: Saniti... |
53 54 |
/* request timeout */ const char *to_msgs[] = { "no timeout", "timed out" }; |
b70ef0101 EDAC: move MCE er... |
55 |
EXPORT_SYMBOL_GPL(to_msgs); |
b52401cec amd64_edac: add M... |
56 |
|
6337583d7 EDAC, MCE: Saniti... |
57 58 |
/* memory or i/o */ const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" }; |
b70ef0101 EDAC: move MCE er... |
59 |
EXPORT_SYMBOL_GPL(ii_msgs); |
b52401cec amd64_edac: add M... |
60 |
|
5ce88f6ea EDAC, MCE: Comple... |
61 62 63 64 65 66 67 68 69 |
static const char *f10h_nb_mce_desc[] = { "HT link data error", "Protocol error (link, L3, probe filter, etc.)", "Parity error in NB-internal arrays", "Link Retry due to IO link transmission error", "L3 ECC data cache error", "ECC error in L3 cache tag", "L3 LRU parity bits error", "ECC Error in the Probe Filter directory" |
b52401cec amd64_edac: add M... |
70 |
}; |
549d042df x86, mce: pass mc... |
71 |
|
86039cd40 EDAC, MCE: Add F1... |
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
static const char * const f15h_ic_mce_desc[] = { "UC during a demand linefill from L2", "Parity error during data load from IC", "Parity error for IC valid bit", "Main tag parity error", "Parity error in prediction queue", "PFB data/address parity error", "Parity error in the branch status reg", "PFB promotion address error", "Tag error during probe/victimization", "Parity error for IC probe tag valid bit", "PFB non-cacheable bit parity error", "PFB valid bit parity error", /* xec = 0xd */ "patch RAM", /* xec = 010 */ "uop queue", "insn buffer", "predecode buffer", "fetch address FIFO" }; |
70fdb494a EDAC, MCE: Add F1... |
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
static const char * const f15h_cu_mce_desc[] = { "Fill ECC error on data fills", /* xec = 0x4 */ "Fill parity error on insn fills", "Prefetcher request FIFO parity error", "PRQ address parity error", "PRQ data parity error", "WCC Tag ECC error", "WCC Data ECC error", "WCB Data parity error", "VB Data/ECC error", "L2 Tag ECC error", /* xec = 0x10 */ "Hard L2 Tag ECC error", "Multiple hits on L2 tag", "XAB parity error", "PRB address parity error" }; |
8259a7e57 EDAC, MCE: Add F1... |
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
static const char * const fr_ex_mce_desc[] = { "CPU Watchdog timer expire", "Wakeup array dest tag", "AG payload array", "EX payload array", "IDRF array", "Retire dispatch queue", "Mapper checkpoint array", "Physical register file EX0 port", "Physical register file EX1 port", "Physical register file AG0 port", "Physical register file AG1 port", "Flag register file", "DE correctable error could not be corrected" }; |
25a4f8b05 EDAC, MCE: Add F1... |
122 |
static bool f12h_dc_mce(u16 ec, u8 xec) |
519662413 EDAC, AMD: decode... |
123 |
{ |
888ab8e6e EDAC, MCE: Adjust... |
124 |
bool ret = false; |
519662413 EDAC, AMD: decode... |
125 |
|
888ab8e6e EDAC, MCE: Adjust... |
126 |
if (MEM_ERROR(ec)) { |
624528823 EDAC, MCE: Overha... |
127 |
u8 ll = LL(ec); |
888ab8e6e EDAC, MCE: Adjust... |
128 |
ret = true; |
519662413 EDAC, AMD: decode... |
129 |
|
888ab8e6e EDAC, MCE: Adjust... |
130 131 132 133 |
if (ll == LL_L2) pr_cont("during L1 linefill from L2. "); else if (ll == LL_L1) |
624528823 EDAC, MCE: Overha... |
134 135 |
pr_cont("Data/Tag %s error. ", R4_MSG(ec)); |
888ab8e6e EDAC, MCE: Adjust... |
136 137 138 139 140 |
else ret = false; } return ret; } |
519662413 EDAC, AMD: decode... |
141 |
|
25a4f8b05 EDAC, MCE: Add F1... |
142 |
static bool f10h_dc_mce(u16 ec, u8 xec) |
9be0bb107 EDAC, MCE: Add F1... |
143 |
{ |
624528823 EDAC, MCE: Overha... |
144 |
if (R4(ec) == R4_GEN && LL(ec) == LL_L1) { |
9be0bb107 EDAC, MCE: Add F1... |
145 146 147 148 |
pr_cont("during data scrub. "); return true; } |
25a4f8b05 EDAC, MCE: Add F1... |
149 |
return f12h_dc_mce(ec, xec); |
9be0bb107 EDAC, MCE: Add F1... |
150 |
} |
25a4f8b05 EDAC, MCE: Add F1... |
151 |
static bool k8_dc_mce(u16 ec, u8 xec) |
888ab8e6e EDAC, MCE: Adjust... |
152 153 154 155 156 157 |
{ if (BUS_ERROR(ec)) { pr_cont("during system linefill. "); return true; } |
519662413 EDAC, AMD: decode... |
158 |
|
25a4f8b05 EDAC, MCE: Add F1... |
159 |
return f10h_dc_mce(ec, xec); |
888ab8e6e EDAC, MCE: Adjust... |
160 |
} |
25a4f8b05 EDAC, MCE: Add F1... |
161 |
static bool f14h_dc_mce(u16 ec, u8 xec) |
888ab8e6e EDAC, MCE: Adjust... |
162 |
{ |
624528823 EDAC, MCE: Overha... |
163 |
u8 r4 = R4(ec); |
888ab8e6e EDAC, MCE: Adjust... |
164 165 166 |
bool ret = true; if (MEM_ERROR(ec)) { |
624528823 EDAC, MCE: Overha... |
167 |
if (TT(ec) != TT_DATA || LL(ec) != LL_L1) |
888ab8e6e EDAC, MCE: Adjust... |
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
return false; switch (r4) { case R4_DRD: case R4_DWR: pr_cont("Data/Tag parity error due to %s. ", (r4 == R4_DRD ? "load/hw prf" : "store")); break; case R4_EVICT: pr_cont("Copyback parity error on a tag miss. "); break; case R4_SNOOP: pr_cont("Tag parity error during snoop. "); break; default: ret = false; } } else if (BUS_ERROR(ec)) { |
624528823 EDAC, MCE: Overha... |
189 |
if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG) |
888ab8e6e EDAC, MCE: Adjust... |
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
return false; pr_cont("System read data error on a "); switch (r4) { case R4_RD: pr_cont("TLB reload. "); break; case R4_DWR: pr_cont("store. "); break; case R4_DRD: pr_cont("load. "); break; default: ret = false; } } else { ret = false; } return ret; } |
25a4f8b05 EDAC, MCE: Add F1... |
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
static bool f15h_dc_mce(u16 ec, u8 xec) { bool ret = true; if (MEM_ERROR(ec)) { switch (xec) { case 0x0: pr_cont("Data Array access error. "); break; case 0x1: pr_cont("UC error during a linefill from L2/NB. "); break; case 0x2: case 0x11: pr_cont("STQ access error. "); break; case 0x3: pr_cont("SCB access error. "); break; case 0x10: pr_cont("Tag error. "); break; case 0x12: pr_cont("LDQ access error. "); break; default: ret = false; } } else if (BUS_ERROR(ec)) { if (!xec) pr_cont("during system linefill. "); else pr_cont(" Internal %s condition. ", ((xec == 1) ? "livelock" : "deadlock")); } else ret = false; return ret; } |
888ab8e6e EDAC, MCE: Adjust... |
271 272 |
static void amd_decode_dc_mce(struct mce *m) { |
624528823 EDAC, MCE: Overha... |
273 274 |
u16 ec = EC(m->status); u8 xec = XEC(m->status, xec_mask); |
888ab8e6e EDAC, MCE: Adjust... |
275 276 277 278 279 |
pr_emerg(HW_ERR "Data Cache Error: "); /* TLB error signatures are the same across families */ if (TLB_ERROR(ec)) { |
624528823 EDAC, MCE: Overha... |
280 |
if (TT(ec) == TT_DATA) { |
888ab8e6e EDAC, MCE: Adjust... |
281 282 |
pr_cont("%s TLB %s. ", LL_MSG(ec), |
25a4f8b05 EDAC, MCE: Add F1... |
283 284 |
((xec == 2) ? "locked miss" : (xec ? "multimatch" : "parity"))); |
888ab8e6e EDAC, MCE: Adjust... |
285 286 |
return; } |
25a4f8b05 EDAC, MCE: Add F1... |
287 288 289 290 291 |
} else if (fam_ops->dc_mce(ec, xec)) ; else pr_emerg(HW_ERR "Corrupted DC MCE info? "); |
519662413 EDAC, AMD: decode... |
292 |
} |
86039cd40 EDAC, MCE: Add F1... |
293 |
static bool k8_ic_mce(u16 ec, u8 xec) |
ab5535e70 EDAC, AMD: decode... |
294 |
{ |
624528823 EDAC, MCE: Overha... |
295 |
u8 ll = LL(ec); |
dd53bce4e EDAC, MCE: Adjust... |
296 |
bool ret = true; |
ab5535e70 EDAC, AMD: decode... |
297 |
|
dd53bce4e EDAC, MCE: Adjust... |
298 299 |
if (!MEM_ERROR(ec)) return false; |
ab5535e70 EDAC, AMD: decode... |
300 |
|
dd53bce4e EDAC, MCE: Adjust... |
301 302 303 304 |
if (ll == 0x2) pr_cont("during a linefill from L2. "); else if (ll == 0x1) { |
624528823 EDAC, MCE: Overha... |
305 |
switch (R4(ec)) { |
dd53bce4e EDAC, MCE: Adjust... |
306 307 308 309 |
case R4_IRD: pr_cont("Parity error during data load. "); break; |
ab5535e70 EDAC, AMD: decode... |
310 |
|
dd53bce4e EDAC, MCE: Adjust... |
311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
case R4_EVICT: pr_cont("Copyback Parity/Victim error. "); break; case R4_SNOOP: pr_cont("Tag Snoop error. "); break; default: ret = false; break; } |
ab5535e70 EDAC, AMD: decode... |
325 |
} else |
dd53bce4e EDAC, MCE: Adjust... |
326 |
ret = false; |
ab5535e70 EDAC, AMD: decode... |
327 |
|
dd53bce4e EDAC, MCE: Adjust... |
328 329 |
return ret; } |
86039cd40 EDAC, MCE: Add F1... |
330 |
static bool f14h_ic_mce(u16 ec, u8 xec) |
dd53bce4e EDAC, MCE: Adjust... |
331 |
{ |
624528823 EDAC, MCE: Overha... |
332 |
u8 r4 = R4(ec); |
dd53bce4e EDAC, MCE: Adjust... |
333 |
bool ret = true; |
ab5535e70 EDAC, AMD: decode... |
334 |
|
dd53bce4e EDAC, MCE: Adjust... |
335 |
if (MEM_ERROR(ec)) { |
624528823 EDAC, MCE: Overha... |
336 |
if (TT(ec) != 0 || LL(ec) != 1) |
dd53bce4e EDAC, MCE: Adjust... |
337 338 339 340 341 342 343 344 345 346 347 348 349 |
ret = false; if (r4 == R4_IRD) pr_cont("Data/tag array parity error for a tag hit. "); else if (r4 == R4_SNOOP) pr_cont("Tag error during snoop/victimization. "); else ret = false; } return ret; } |
86039cd40 EDAC, MCE: Add F1... |
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
static bool f15h_ic_mce(u16 ec, u8 xec) { bool ret = true; if (!MEM_ERROR(ec)) return false; switch (xec) { case 0x0 ... 0xa: pr_cont("%s. ", f15h_ic_mce_desc[xec]); break; case 0xd: pr_cont("%s. ", f15h_ic_mce_desc[xec-2]); break; case 0x10 ... 0x14: pr_cont("Decoder %s parity error. ", f15h_ic_mce_desc[xec-4]); break; default: ret = false; } return ret; } |
dd53bce4e EDAC, MCE: Adjust... |
378 379 |
static void amd_decode_ic_mce(struct mce *m) { |
624528823 EDAC, MCE: Overha... |
380 381 |
u16 ec = EC(m->status); u8 xec = XEC(m->status, xec_mask); |
dd53bce4e EDAC, MCE: Adjust... |
382 383 384 385 386 387 388 389 |
pr_emerg(HW_ERR "Instruction Cache Error: "); if (TLB_ERROR(ec)) pr_cont("%s TLB %s. ", LL_MSG(ec), (xec ? "multimatch" : "parity error")); else if (BUS_ERROR(ec)) { |
525906bc8 EDAC, MCE: Fix sh... |
390 |
bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58))); |
dd53bce4e EDAC, MCE: Adjust... |
391 392 393 |
pr_cont("during %s. ", (k8 ? "system linefill" : "NB data read")); |
86039cd40 EDAC, MCE: Add F1... |
394 |
} else if (fam_ops->ic_mce(ec, xec)) |
dd53bce4e EDAC, MCE: Adjust... |
395 396 397 398 |
; else pr_emerg(HW_ERR "Corrupted IC MCE info? "); |
ab5535e70 EDAC, AMD: decode... |
399 |
} |
7cfd4a874 EDAC, MCE: Pass c... |
400 |
static void amd_decode_bu_mce(struct mce *m) |
56cad2d6f EDAC, AMD: decode... |
401 |
{ |
624528823 EDAC, MCE: Overha... |
402 403 |
u16 ec = EC(m->status); u8 xec = XEC(m->status, xec_mask); |
56cad2d6f EDAC, AMD: decode... |
404 |
|
c9f281fd9 EDAC, MCE: Add HW... |
405 |
pr_emerg(HW_ERR "Bus Unit Error"); |
56cad2d6f EDAC, AMD: decode... |
406 407 408 409 410 411 412 413 |
if (xec == 0x1) pr_cont(" in the write data buffers. "); else if (xec == 0x3) pr_cont(" in the victim data buffers. "); else if (xec == 0x2 && MEM_ERROR(ec)) |
624528823 EDAC, MCE: Overha... |
414 415 |
pr_cont(": %s error in the L2 cache tags. ", R4_MSG(ec)); |
56cad2d6f EDAC, AMD: decode... |
416 417 418 419 420 421 422 423 |
else if (xec == 0x0) { if (TLB_ERROR(ec)) pr_cont(": %s error in a Page Descriptor Cache or " "Guest TLB. ", TT_MSG(ec)); else if (BUS_ERROR(ec)) pr_cont(": %s/ECC error in data read from NB: %s. ", |
624528823 EDAC, MCE: Overha... |
424 |
R4_MSG(ec), PP_MSG(ec)); |
56cad2d6f EDAC, AMD: decode... |
425 |
else if (MEM_ERROR(ec)) { |
624528823 EDAC, MCE: Overha... |
426 |
u8 r4 = R4(ec); |
56cad2d6f EDAC, AMD: decode... |
427 |
|
624528823 EDAC, MCE: Overha... |
428 |
if (r4 >= 0x7) |
56cad2d6f EDAC, AMD: decode... |
429 430 |
pr_cont(": %s error during data copyback. ", |
624528823 EDAC, MCE: Overha... |
431 432 |
R4_MSG(ec)); else if (r4 <= 0x1) |
56cad2d6f EDAC, AMD: decode... |
433 |
pr_cont(": %s parity/ECC error during data " |
624528823 EDAC, MCE: Overha... |
434 435 |
"access from L2. ", R4_MSG(ec)); |
56cad2d6f EDAC, AMD: decode... |
436 437 438 439 440 441 442 443 444 445 |
else goto wrong_bu_mce; } else goto wrong_bu_mce; } else goto wrong_bu_mce; return; wrong_bu_mce: |
c9f281fd9 EDAC, MCE: Add HW... |
446 447 |
pr_emerg(HW_ERR "Corrupted BU MCE info? "); |
56cad2d6f EDAC, AMD: decode... |
448 |
} |
70fdb494a EDAC, MCE: Add F1... |
449 450 |
static void amd_decode_cu_mce(struct mce *m) { |
624528823 EDAC, MCE: Overha... |
451 452 |
u16 ec = EC(m->status); u8 xec = XEC(m->status, xec_mask); |
70fdb494a EDAC, MCE: Add F1... |
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 |
pr_emerg(HW_ERR "Combined Unit Error: "); if (TLB_ERROR(ec)) { if (xec == 0x0) pr_cont("Data parity TLB read error. "); else if (xec == 0x1) pr_cont("Poison data provided for TLB fill. "); else goto wrong_cu_mce; } else if (BUS_ERROR(ec)) { if (xec > 2) goto wrong_cu_mce; pr_cont("Error during attempted NB data read. "); } else if (MEM_ERROR(ec)) { switch (xec) { case 0x4 ... 0xc: pr_cont("%s. ", f15h_cu_mce_desc[xec - 0x4]); break; case 0x10 ... 0x14: pr_cont("%s. ", f15h_cu_mce_desc[xec - 0x7]); break; default: goto wrong_cu_mce; } } return; wrong_cu_mce: pr_emerg(HW_ERR "Corrupted CU MCE info? "); } |
7cfd4a874 EDAC, MCE: Pass c... |
494 |
static void amd_decode_ls_mce(struct mce *m) |
f9350efd6 EDAC, AMD: decode... |
495 |
{ |
624528823 EDAC, MCE: Overha... |
496 497 |
u16 ec = EC(m->status); u8 xec = XEC(m->status, xec_mask); |
ded506232 EDAC, MCE: Warn a... |
498 |
|
b18434cad EDAC, MCE: No F15... |
499 |
if (boot_cpu_data.x86 >= 0x14) { |
ded506232 EDAC, MCE: Warn a... |
500 501 502 503 504 |
pr_emerg("You shouldn't be seeing an LS MCE on this cpu family," " please report on LKML. "); return; } |
f9350efd6 EDAC, AMD: decode... |
505 |
|
c9f281fd9 EDAC, MCE: Add HW... |
506 |
pr_emerg(HW_ERR "Load Store Error"); |
f9350efd6 EDAC, AMD: decode... |
507 508 |
if (xec == 0x0) { |
624528823 EDAC, MCE: Overha... |
509 |
u8 r4 = R4(ec); |
f9350efd6 EDAC, AMD: decode... |
510 |
|
ded506232 EDAC, MCE: Warn a... |
511 |
if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR)) |
f9350efd6 EDAC, AMD: decode... |
512 |
goto wrong_ls_mce; |
624528823 EDAC, MCE: Overha... |
513 514 |
pr_cont(" during %s. ", R4_MSG(ec)); |
ded506232 EDAC, MCE: Warn a... |
515 516 |
} else goto wrong_ls_mce; |
f9350efd6 EDAC, AMD: decode... |
517 518 519 |
return; wrong_ls_mce: |
c9f281fd9 EDAC, MCE: Add HW... |
520 521 |
pr_emerg(HW_ERR "Corrupted LS MCE info? "); |
f9350efd6 EDAC, AMD: decode... |
522 |
} |
5ce88f6ea EDAC, MCE: Comple... |
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 |
static bool k8_nb_mce(u16 ec, u8 xec) { bool ret = true; switch (xec) { case 0x1: pr_cont("CRC error detected on HT link. "); break; case 0x5: pr_cont("Invalid GART PTE entry during GART table walk. "); break; case 0x6: pr_cont("Unsupported atomic RMW received from an IO link. "); break; case 0x0: case 0x8: |
f0157b3af EDAC, MCE: Add su... |
545 546 |
if (boot_cpu_data.x86 == 0x11) return false; |
5ce88f6ea EDAC, MCE: Comple... |
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 |
pr_cont("DRAM ECC error detected on the NB. "); break; case 0xd: pr_cont("Parity error on the DRAM addr/ctl signals. "); break; default: ret = false; break; } return ret; } static bool f10h_nb_mce(u16 ec, u8 xec) { bool ret = true; u8 offset = 0; if (k8_nb_mce(ec, xec)) return true; switch(xec) { case 0xa ... 0xc: offset = 10; break; case 0xe: offset = 11; break; case 0xf: if (TLB_ERROR(ec)) pr_cont("GART Table Walk data error. "); else if (BUS_ERROR(ec)) pr_cont("DMA Exclusion Vector Table Walk error. "); else ret = false; goto out; break; |
05cd667d6 EDAC, MCE: Add an... |
593 594 595 596 597 598 599 600 601 |
case 0x19: if (boot_cpu_data.x86 == 0x15) pr_cont("Compute Unit Data Error. "); else ret = false; goto out; break; |
5ce88f6ea EDAC, MCE: Comple... |
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 |
case 0x1c ... 0x1f: offset = 24; break; default: ret = false; goto out; break; } pr_cont("%s. ", f10h_nb_mce_desc[xec - offset]); out: return ret; } |
cb9d5ecdf EDAC, MCE: Add F1... |
619 |
static bool nb_noop_mce(u16 ec, u8 xec) |
5ce88f6ea EDAC, MCE: Comple... |
620 621 622 |
{ return false; } |
b0b07a2bd EDAC, MCE, AMD: S... |
623 |
void amd_decode_nb_mce(struct mce *m) |
549d042df x86, mce: pass mc... |
624 |
{ |
df71a0532 amd64_edac: Enabl... |
625 |
struct cpuinfo_x86 *c = &boot_cpu_data; |
b0b07a2bd EDAC, MCE, AMD: S... |
626 627 628 |
int node_id = amd_get_nb_id(m->extcpu); u16 ec = EC(m->status); u8 xec = XEC(m->status, 0x1f); |
256f7276a edac, mce, amd: s... |
629 |
|
295d8cda2 EDAC, MCE, AMD: D... |
630 |
pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id); |
6d5db4668 EDAC, MCE: Fix NB... |
631 |
|
5ce88f6ea EDAC, MCE: Comple... |
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 |
switch (xec) { case 0x2: pr_cont("Sync error (sync packets on HT link detected). "); return; case 0x3: pr_cont("HT Master abort. "); return; case 0x4: pr_cont("HT Target abort. "); return; case 0x7: pr_cont("NB Watchdog timeout. "); return; case 0x9: pr_cont("SVM DMA Exclusion Vector error. "); return; default: break; |
549d042df x86, mce: pass mc... |
660 |
} |
5ce88f6ea EDAC, MCE: Comple... |
661 662 |
if (!fam_ops->nb_mce(ec, xec)) goto wrong_nb_mce; |
df71a0532 amd64_edac: Enabl... |
663 |
if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15) |
5ce88f6ea EDAC, MCE: Comple... |
664 |
if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder) |
b0b07a2bd EDAC, MCE, AMD: S... |
665 |
nb_bus_decoder(node_id, m); |
d93cc222a EDAC, AMD: carve ... |
666 |
|
5ce88f6ea EDAC, MCE: Comple... |
667 668 669 670 671 |
return; wrong_nb_mce: pr_emerg(HW_ERR "Corrupted NB MCE info? "); |
d93cc222a EDAC, AMD: carve ... |
672 673 |
} EXPORT_SYMBOL_GPL(amd_decode_nb_mce); |
7cfd4a874 EDAC, MCE: Pass c... |
674 |
static void amd_decode_fr_mce(struct mce *m) |
53bd5fedc EDAC, AMD: decode... |
675 |
{ |
8259a7e57 EDAC, MCE: Add F1... |
676 |
struct cpuinfo_x86 *c = &boot_cpu_data; |
624528823 EDAC, MCE: Overha... |
677 |
u8 xec = XEC(m->status, xec_mask); |
8259a7e57 EDAC, MCE: Add F1... |
678 679 |
if (c->x86 == 0xf || c->x86 == 0x11) |
fe4ea2623 EDAC, MCE: Fix FR... |
680 |
goto wrong_fr_mce; |
8259a7e57 EDAC, MCE: Add F1... |
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 |
if (c->x86 != 0x15 && xec != 0x0) goto wrong_fr_mce; pr_emerg(HW_ERR "%s Error: ", (c->x86 == 0x15 ? "Execution Unit" : "FIROB")); if (xec == 0x0 || xec == 0xc) pr_cont("%s. ", fr_ex_mce_desc[xec]); else if (xec < 0xd) pr_cont("%s parity error. ", fr_ex_mce_desc[xec]); else goto wrong_fr_mce; return; |
fe4ea2623 EDAC, MCE: Fix FR... |
697 698 699 700 |
wrong_fr_mce: pr_emerg(HW_ERR "Corrupted FR MCE info? "); |
53bd5fedc EDAC, AMD: decode... |
701 |
} |
b8f85c477 EDAC, MCE: Add F1... |
702 703 |
static void amd_decode_fp_mce(struct mce *m) { |
624528823 EDAC, MCE: Overha... |
704 |
u8 xec = XEC(m->status, xec_mask); |
b8f85c477 EDAC, MCE: Add F1... |
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 |
pr_emerg(HW_ERR "Floating Point Unit Error: "); switch (xec) { case 0x1: pr_cont("Free List"); break; case 0x2: pr_cont("Physical Register File"); break; case 0x3: pr_cont("Retire Queue"); break; case 0x4: pr_cont("Scheduler table"); break; case 0x5: pr_cont("Status Register File"); break; default: goto wrong_fp_mce; break; } pr_cont(" parity error. "); return; wrong_fp_mce: pr_emerg(HW_ERR "Corrupted FP MCE info? "); } |
6337583d7 EDAC, MCE: Saniti... |
743 |
static inline void amd_decode_err_code(u16 ec) |
d93cc222a EDAC, AMD: carve ... |
744 |
{ |
fa7ae8cc8 EDAC, MCE: Shorte... |
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 |
pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec)); if (BUS_ERROR(ec)) pr_cont(", mem/io: %s", II_MSG(ec)); else pr_cont(", tx: %s", TT_MSG(ec)); if (MEM_ERROR(ec) || BUS_ERROR(ec)) { pr_cont(", mem-tx: %s", R4_MSG(ec)); if (BUS_ERROR(ec)) pr_cont(", part-proc: %s (%s)", PP_MSG(ec), TO_MSG(ec)); } pr_cont(" "); |
549d042df x86, mce: pass mc... |
762 |
} |
549d042df x86, mce: pass mc... |
763 |
|
5ce88f6ea EDAC, MCE: Comple... |
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 |
/* * Filter out unwanted MCE signatures here. */ static bool amd_filter_mce(struct mce *m) { u8 xec = (m->status >> 16) & 0x1f; /* * NB GART TLB error reporting is disabled by default. */ if (m->bank == 4 && xec == 0x5 && !report_gart_errors) return true; return false; } |
9cdeb404a EDAC, MCE: Rework... |
779 |
int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) |
549d042df x86, mce: pass mc... |
780 |
{ |
fb2531953 mce, edac: Use an... |
781 |
struct mce *m = (struct mce *)data; |
fa7ae8cc8 EDAC, MCE: Shorte... |
782 |
struct cpuinfo_x86 *c = &boot_cpu_data; |
b0b07a2bd EDAC, MCE, AMD: S... |
783 |
int ecc; |
549d042df x86, mce: pass mc... |
784 |
|
5ce88f6ea EDAC, MCE: Comple... |
785 786 |
if (amd_filter_mce(m)) return NOTIFY_STOP; |
086be786c EDAC, MCE, AMD: P... |
787 |
pr_emerg(HW_ERR "CPU:%d\tMC%d_STATUS[%s|%s|%s|%s|%s", |
bff7b8124 EDAC, MCE, AMD: P... |
788 |
m->extcpu, m->bank, |
fa7ae8cc8 EDAC, MCE: Shorte... |
789 790 791 792 793 |
((m->status & MCI_STATUS_OVER) ? "Over" : "-"), ((m->status & MCI_STATUS_UC) ? "UE" : "CE"), ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"), ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"), ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-")); |
549d042df x86, mce: pass mc... |
794 |
|
fa7ae8cc8 EDAC, MCE: Shorte... |
795 796 |
if (c->x86 == 0x15) pr_cont("|%s|%s", |
50adbbd8a EDAC, MCE: Use BI... |
797 798 |
((m->status & BIT_64(44)) ? "Deferred" : "-"), ((m->status & BIT_64(43)) ? "Poison" : "-")); |
549d042df x86, mce: pass mc... |
799 |
|
b69b29de6 EDAC, AMD: carve ... |
800 |
/* do the two bits[14:13] together */ |
35d824b28 edac, mce: Fix wr... |
801 |
ecc = (m->status >> 45) & 0x3; |
b69b29de6 EDAC, AMD: carve ... |
802 |
if (ecc) |
fa7ae8cc8 EDAC, MCE: Shorte... |
803 804 805 806 |
pr_cont("|%sECC", ((ecc == 2) ? "C" : "U")); pr_cont("]: 0x%016llx ", m->status); |
b69b29de6 EDAC, AMD: carve ... |
807 |
|
086be786c EDAC, MCE, AMD: P... |
808 809 810 |
if (m->status & MCI_STATUS_ADDRV) pr_emerg(HW_ERR "\tMC%d_ADDR: 0x%016llx ", m->bank, m->addr); |
b69b29de6 EDAC, AMD: carve ... |
811 |
|
519662413 EDAC, AMD: decode... |
812 813 |
switch (m->bank) { case 0: |
7cfd4a874 EDAC, MCE: Pass c... |
814 |
amd_decode_dc_mce(m); |
519662413 EDAC, AMD: decode... |
815 |
break; |
d93cc222a EDAC, AMD: carve ... |
816 |
|
ab5535e70 EDAC, AMD: decode... |
817 |
case 1: |
7cfd4a874 EDAC, MCE: Pass c... |
818 |
amd_decode_ic_mce(m); |
ab5535e70 EDAC, AMD: decode... |
819 |
break; |
56cad2d6f EDAC, AMD: decode... |
820 |
case 2: |
fa7ae8cc8 EDAC, MCE: Shorte... |
821 |
if (c->x86 == 0x15) |
70fdb494a EDAC, MCE: Add F1... |
822 823 824 |
amd_decode_cu_mce(m); else amd_decode_bu_mce(m); |
56cad2d6f EDAC, AMD: decode... |
825 |
break; |
f9350efd6 EDAC, AMD: decode... |
826 |
case 3: |
7cfd4a874 EDAC, MCE: Pass c... |
827 |
amd_decode_ls_mce(m); |
f9350efd6 EDAC, AMD: decode... |
828 |
break; |
519662413 EDAC, AMD: decode... |
829 |
case 4: |
b0b07a2bd EDAC, MCE, AMD: S... |
830 |
amd_decode_nb_mce(m); |
519662413 EDAC, AMD: decode... |
831 |
break; |
53bd5fedc EDAC, AMD: decode... |
832 |
case 5: |
7cfd4a874 EDAC, MCE: Pass c... |
833 |
amd_decode_fr_mce(m); |
53bd5fedc EDAC, AMD: decode... |
834 |
break; |
b8f85c477 EDAC, MCE: Add F1... |
835 836 837 |
case 6: amd_decode_fp_mce(m); break; |
519662413 EDAC, AMD: decode... |
838 839 |
default: break; |
b69b29de6 EDAC, AMD: carve ... |
840 |
} |
519662413 EDAC, AMD: decode... |
841 842 |
amd_decode_err_code(m->status & 0xffff); |
fb2531953 mce, edac: Use an... |
843 844 |
return NOTIFY_STOP; |
549d042df x86, mce: pass mc... |
845 |
} |
9cdeb404a EDAC, MCE: Rework... |
846 |
EXPORT_SYMBOL_GPL(amd_decode_mce); |
f436f8bb7 x86: EDAC: MCE: F... |
847 |
|
fb2531953 mce, edac: Use an... |
848 849 850 |
static struct notifier_block amd_mce_dec_nb = { .notifier_call = amd_decode_mce, }; |
f436f8bb7 x86: EDAC: MCE: F... |
851 852 |
static int __init mce_amd_init(void) { |
bad11e031 EDAC, MCE: Enable... |
853 854 855 |
struct cpuinfo_x86 *c = &boot_cpu_data; if (c->x86_vendor != X86_VENDOR_AMD) |
e045c2912 MCE, AMD: Limit M... |
856 |
return 0; |
bad11e031 EDAC, MCE: Enable... |
857 858 859 |
if ((c->x86 < 0xf || c->x86 > 0x12) && (c->x86 != 0x14 || c->x86_model > 0xf) && (c->x86 != 0x15 || c->x86_model > 0xf)) |
e045c2912 MCE, AMD: Limit M... |
860 |
return 0; |
888ab8e6e EDAC, MCE: Adjust... |
861 862 863 |
fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL); if (!fam_ops) return -ENOMEM; |
bad11e031 EDAC, MCE: Enable... |
864 |
switch (c->x86) { |
888ab8e6e EDAC, MCE: Adjust... |
865 866 |
case 0xf: fam_ops->dc_mce = k8_dc_mce; |
dd53bce4e EDAC, MCE: Adjust... |
867 |
fam_ops->ic_mce = k8_ic_mce; |
5ce88f6ea EDAC, MCE: Comple... |
868 |
fam_ops->nb_mce = k8_nb_mce; |
888ab8e6e EDAC, MCE: Adjust... |
869 870 871 872 |
break; case 0x10: fam_ops->dc_mce = f10h_dc_mce; |
dd53bce4e EDAC, MCE: Adjust... |
873 |
fam_ops->ic_mce = k8_ic_mce; |
5ce88f6ea EDAC, MCE: Comple... |
874 |
fam_ops->nb_mce = f10h_nb_mce; |
888ab8e6e EDAC, MCE: Adjust... |
875 |
break; |
f0157b3af EDAC, MCE: Add su... |
876 877 878 879 880 |
case 0x11: fam_ops->dc_mce = k8_dc_mce; fam_ops->ic_mce = k8_ic_mce; fam_ops->nb_mce = f10h_nb_mce; break; |
9be0bb107 EDAC, MCE: Add F1... |
881 882 |
case 0x12: fam_ops->dc_mce = f12h_dc_mce; |
e7281eb37 EDAC, MCE: Add F1... |
883 |
fam_ops->ic_mce = k8_ic_mce; |
cb9d5ecdf EDAC, MCE: Add F1... |
884 |
fam_ops->nb_mce = nb_noop_mce; |
9be0bb107 EDAC, MCE: Add F1... |
885 |
break; |
888ab8e6e EDAC, MCE: Adjust... |
886 |
case 0x14: |
5ce88f6ea EDAC, MCE: Comple... |
887 |
nb_err_cpumask = 0x3; |
888ab8e6e EDAC, MCE: Adjust... |
888 |
fam_ops->dc_mce = f14h_dc_mce; |
dd53bce4e EDAC, MCE: Adjust... |
889 |
fam_ops->ic_mce = f14h_ic_mce; |
cb9d5ecdf EDAC, MCE: Add F1... |
890 |
fam_ops->nb_mce = nb_noop_mce; |
888ab8e6e EDAC, MCE: Adjust... |
891 |
break; |
2be64bfac EDAC, MCE: Select... |
892 893 |
case 0x15: xec_mask = 0x1f; |
25a4f8b05 EDAC, MCE: Add F1... |
894 |
fam_ops->dc_mce = f15h_dc_mce; |
86039cd40 EDAC, MCE: Add F1... |
895 |
fam_ops->ic_mce = f15h_ic_mce; |
05cd667d6 EDAC, MCE: Add an... |
896 |
fam_ops->nb_mce = f10h_nb_mce; |
2be64bfac EDAC, MCE: Select... |
897 |
break; |
888ab8e6e EDAC, MCE: Adjust... |
898 |
default: |
bad11e031 EDAC, MCE: Enable... |
899 900 |
printk(KERN_WARNING "Huh? What family is that: %d?! ", c->x86); |
888ab8e6e EDAC, MCE: Adjust... |
901 902 903 |
kfree(fam_ops); return -EINVAL; } |
9530d608e EDAC, MCE: Enable... |
904 905 |
pr_info("MCE: In-kernel MCE decoding enabled. "); |
3653ada5d x86, mce: Add wra... |
906 |
mce_register_decode_chain(&amd_mce_dec_nb); |
f436f8bb7 x86: EDAC: MCE: F... |
907 908 909 910 |
return 0; } early_initcall(mce_amd_init); |
0d18b2e34 x86: EDAC: carve ... |
911 912 913 914 |
#ifdef MODULE static void __exit mce_amd_exit(void) { |
3653ada5d x86, mce: Add wra... |
915 |
mce_unregister_decode_chain(&amd_mce_dec_nb); |
888ab8e6e EDAC, MCE: Adjust... |
916 |
kfree(fam_ops); |
0d18b2e34 x86: EDAC: carve ... |
917 918 919 920 921 922 923 |
} MODULE_DESCRIPTION("AMD MCE decoder"); MODULE_ALIAS("edac-mce-amd"); MODULE_LICENSE("GPL"); module_exit(mce_amd_exit); #endif |