blob: 158cd5fa2146389259fffec1fe1449777ae0a89b [file] [log] [blame]
Borislav Petkovb70ef012009-06-25 19:32:38 +02001#include <linux/module.h>
Borislav Petkov888ab8e2010-08-18 15:11:35 +02002#include <linux/slab.h>
3
Borislav Petkov47ca08a2010-09-27 15:30:39 +02004#include "mce_amd.h"
Doug Thompsonb52401ce2009-05-06 17:57:20 +02005
Borislav Petkov888ab8e2010-08-18 15:11:35 +02006static struct amd_decoder_ops *fam_ops;
7
Borislav Petkov2be64bf2010-09-17 19:11:47 +02008static u8 xec_mask = 0xf;
Borislav Petkov5ce88f62010-08-31 18:28:08 +02009static u8 nb_err_cpumask = 0xf;
10
Borislav Petkov549d0422009-07-24 13:51:42 +020011static bool report_gart_errors;
Borislav Petkov7cfd4a82010-09-01 14:45:20 +020012static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
Borislav Petkov549d0422009-07-24 13:51:42 +020013
14void amd_report_gart_errors(bool v)
15{
16 report_gart_errors = v;
17}
18EXPORT_SYMBOL_GPL(amd_report_gart_errors);
19
Borislav Petkov7cfd4a82010-09-01 14:45:20 +020020void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
Borislav Petkov549d0422009-07-24 13:51:42 +020021{
22 nb_bus_decoder = f;
23}
24EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
25
Borislav Petkov7cfd4a82010-09-01 14:45:20 +020026void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
Borislav Petkov549d0422009-07-24 13:51:42 +020027{
28 if (nb_bus_decoder) {
29 WARN_ON(nb_bus_decoder != f);
30
31 nb_bus_decoder = NULL;
32 }
33}
34EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
35
Doug Thompsonb52401ce2009-05-06 17:57:20 +020036/*
37 * string representation for the different MCA reported error types, see F3x48
38 * or MSR0000_0411.
39 */
Borislav Petkov63375832010-09-06 18:13:39 +020040
41/* transaction type */
42const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020043EXPORT_SYMBOL_GPL(tt_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020044
Borislav Petkov63375832010-09-06 18:13:39 +020045/* cache level */
46const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020047EXPORT_SYMBOL_GPL(ll_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020048
Borislav Petkov63375832010-09-06 18:13:39 +020049/* memory transaction type */
Doug Thompsonb52401ce2009-05-06 17:57:20 +020050const char *rrrr_msgs[] = {
Borislav Petkov63375832010-09-06 18:13:39 +020051 "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
Doug Thompsonb52401ce2009-05-06 17:57:20 +020052};
Borislav Petkovb70ef012009-06-25 19:32:38 +020053EXPORT_SYMBOL_GPL(rrrr_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020054
Borislav Petkov63375832010-09-06 18:13:39 +020055/* participating processor */
56const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020057EXPORT_SYMBOL_GPL(pp_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020058
Borislav Petkov63375832010-09-06 18:13:39 +020059/* request timeout */
60const char *to_msgs[] = { "no timeout", "timed out" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020061EXPORT_SYMBOL_GPL(to_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020062
Borislav Petkov63375832010-09-06 18:13:39 +020063/* memory or i/o */
64const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020065EXPORT_SYMBOL_GPL(ii_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020066
Borislav Petkov5ce88f62010-08-31 18:28:08 +020067static const char *f10h_nb_mce_desc[] = {
68 "HT link data error",
69 "Protocol error (link, L3, probe filter, etc.)",
70 "Parity error in NB-internal arrays",
71 "Link Retry due to IO link transmission error",
72 "L3 ECC data cache error",
73 "ECC error in L3 cache tag",
74 "L3 LRU parity bits error",
75 "ECC Error in the Probe Filter directory"
Doug Thompsonb52401ce2009-05-06 17:57:20 +020076};
Borislav Petkov549d0422009-07-24 13:51:42 +020077
Borislav Petkov86039cd2010-11-08 15:03:35 +010078static const char * const f15h_ic_mce_desc[] = {
79 "UC during a demand linefill from L2",
80 "Parity error during data load from IC",
81 "Parity error for IC valid bit",
82 "Main tag parity error",
83 "Parity error in prediction queue",
84 "PFB data/address parity error",
85 "Parity error in the branch status reg",
86 "PFB promotion address error",
87 "Tag error during probe/victimization",
88 "Parity error for IC probe tag valid bit",
89 "PFB non-cacheable bit parity error",
90 "PFB valid bit parity error", /* xec = 0xd */
91 "patch RAM", /* xec = 010 */
92 "uop queue",
93 "insn buffer",
94 "predecode buffer",
95 "fetch address FIFO"
96};
97
Borislav Petkov25a4f8b2010-09-17 19:22:34 +020098static bool f12h_dc_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +020099{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200100 bool ret = false;
101
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200102 if (MEM_ERROR(ec)) {
103 u8 ll = ec & 0x3;
104 ret = true;
105
106 if (ll == LL_L2)
107 pr_cont("during L1 linefill from L2.\n");
108 else if (ll == LL_L1)
109 pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec));
110 else
111 ret = false;
112 }
113 return ret;
114}
115
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200116static bool f10h_dc_mce(u16 ec, u8 xec)
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200117{
118 u8 r4 = (ec >> 4) & 0xf;
119 u8 ll = ec & 0x3;
120
121 if (r4 == R4_GEN && ll == LL_L1) {
122 pr_cont("during data scrub.\n");
123 return true;
124 }
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200125 return f12h_dc_mce(ec, xec);
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200126}
127
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200128static bool k8_dc_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200129{
130 if (BUS_ERROR(ec)) {
131 pr_cont("during system linefill.\n");
132 return true;
133 }
134
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200135 return f10h_dc_mce(ec, xec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200136}
137
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200138static bool f14h_dc_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200139{
140 u8 r4 = (ec >> 4) & 0xf;
141 u8 ll = ec & 0x3;
142 u8 tt = (ec >> 2) & 0x3;
143 u8 ii = tt;
144 bool ret = true;
145
146 if (MEM_ERROR(ec)) {
147
148 if (tt != TT_DATA || ll != LL_L1)
149 return false;
150
151 switch (r4) {
152 case R4_DRD:
153 case R4_DWR:
154 pr_cont("Data/Tag parity error due to %s.\n",
155 (r4 == R4_DRD ? "load/hw prf" : "store"));
156 break;
157 case R4_EVICT:
158 pr_cont("Copyback parity error on a tag miss.\n");
159 break;
160 case R4_SNOOP:
161 pr_cont("Tag parity error during snoop.\n");
162 break;
163 default:
164 ret = false;
165 }
166 } else if (BUS_ERROR(ec)) {
167
168 if ((ii != II_MEM && ii != II_IO) || ll != LL_LG)
169 return false;
170
171 pr_cont("System read data error on a ");
172
173 switch (r4) {
174 case R4_RD:
175 pr_cont("TLB reload.\n");
176 break;
177 case R4_DWR:
178 pr_cont("store.\n");
179 break;
180 case R4_DRD:
181 pr_cont("load.\n");
182 break;
183 default:
184 ret = false;
185 }
186 } else {
187 ret = false;
188 }
189
190 return ret;
191}
192
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200193static bool f15h_dc_mce(u16 ec, u8 xec)
194{
195 bool ret = true;
196
197 if (MEM_ERROR(ec)) {
198
199 switch (xec) {
200 case 0x0:
201 pr_cont("Data Array access error.\n");
202 break;
203
204 case 0x1:
205 pr_cont("UC error during a linefill from L2/NB.\n");
206 break;
207
208 case 0x2:
209 case 0x11:
210 pr_cont("STQ access error.\n");
211 break;
212
213 case 0x3:
214 pr_cont("SCB access error.\n");
215 break;
216
217 case 0x10:
218 pr_cont("Tag error.\n");
219 break;
220
221 case 0x12:
222 pr_cont("LDQ access error.\n");
223 break;
224
225 default:
226 ret = false;
227 }
228 } else if (BUS_ERROR(ec)) {
229
230 if (!xec)
231 pr_cont("during system linefill.\n");
232 else
233 pr_cont(" Internal %s condition.\n",
234 ((xec == 1) ? "livelock" : "deadlock"));
235 } else
236 ret = false;
237
238 return ret;
239}
240
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200241static void amd_decode_dc_mce(struct mce *m)
Borislav Petkov51966242009-07-28 13:50:43 +0200242{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200243 u16 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200244 u8 xec = (m->status >> 16) & xec_mask;
Borislav Petkov51966242009-07-28 13:50:43 +0200245
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200246 pr_emerg(HW_ERR "Data Cache Error: ");
Borislav Petkov51966242009-07-28 13:50:43 +0200247
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200248 /* TLB error signatures are the same across families */
249 if (TLB_ERROR(ec)) {
250 u8 tt = (ec >> 2) & 0x3;
Borislav Petkov51966242009-07-28 13:50:43 +0200251
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200252 if (tt == TT_DATA) {
253 pr_cont("%s TLB %s.\n", LL_MSG(ec),
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200254 ((xec == 2) ? "locked miss"
255 : (xec ? "multimatch" : "parity")));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200256 return;
257 }
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200258 } else if (fam_ops->dc_mce(ec, xec))
259 ;
260 else
261 pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
Borislav Petkov51966242009-07-28 13:50:43 +0200262}
263
Borislav Petkov86039cd2010-11-08 15:03:35 +0100264static bool k8_ic_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200265{
266 u8 ll = ec & 0x3;
267 u8 r4 = (ec >> 4) & 0xf;
268 bool ret = true;
269
270 if (!MEM_ERROR(ec))
271 return false;
272
273 if (ll == 0x2)
274 pr_cont("during a linefill from L2.\n");
275 else if (ll == 0x1) {
276 switch (r4) {
277 case R4_IRD:
278 pr_cont("Parity error during data load.\n");
279 break;
280
281 case R4_EVICT:
282 pr_cont("Copyback Parity/Victim error.\n");
283 break;
284
285 case R4_SNOOP:
286 pr_cont("Tag Snoop error.\n");
287 break;
288
289 default:
290 ret = false;
291 break;
292 }
293 } else
294 ret = false;
295
296 return ret;
297}
298
Borislav Petkov86039cd2010-11-08 15:03:35 +0100299static bool f14h_ic_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200300{
301 u8 ll = ec & 0x3;
302 u8 tt = (ec >> 2) & 0x3;
303 u8 r4 = (ec >> 4) & 0xf;
304 bool ret = true;
305
306 if (MEM_ERROR(ec)) {
307 if (tt != 0 || ll != 1)
308 ret = false;
309
310 if (r4 == R4_IRD)
311 pr_cont("Data/tag array parity error for a tag hit.\n");
312 else if (r4 == R4_SNOOP)
313 pr_cont("Tag error during snoop/victimization.\n");
314 else
315 ret = false;
316 }
317 return ret;
318}
319
Borislav Petkov86039cd2010-11-08 15:03:35 +0100320static bool f15h_ic_mce(u16 ec, u8 xec)
321{
322 bool ret = true;
323
324 if (!MEM_ERROR(ec))
325 return false;
326
327 switch (xec) {
328 case 0x0 ... 0xa:
329 pr_cont("%s.\n", f15h_ic_mce_desc[xec]);
330 break;
331
332 case 0xd:
333 pr_cont("%s.\n", f15h_ic_mce_desc[xec-2]);
334 break;
335
336 case 0x10 ... 0x14:
337 pr_cont("Decoder %s parity error.\n", f15h_ic_mce_desc[xec-4]);
338 break;
339
340 default:
341 ret = false;
342 }
343 return ret;
344}
345
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200346static void amd_decode_ic_mce(struct mce *m)
Borislav Petkovab5535e2009-07-28 14:06:26 +0200347{
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200348 u16 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200349 u8 xec = (m->status >> 16) & xec_mask;
Borislav Petkovab5535e2009-07-28 14:06:26 +0200350
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200351 pr_emerg(HW_ERR "Instruction Cache Error: ");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200352
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200353 if (TLB_ERROR(ec))
354 pr_cont("%s TLB %s.\n", LL_MSG(ec),
355 (xec ? "multimatch" : "parity error"));
356 else if (BUS_ERROR(ec)) {
Borislav Petkov525906b2010-10-15 15:27:02 +0200357 bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
Borislav Petkovab5535e2009-07-28 14:06:26 +0200358
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200359 pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
Borislav Petkov86039cd2010-11-08 15:03:35 +0100360 } else if (fam_ops->ic_mce(ec, xec))
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200361 ;
362 else
363 pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200364}
365
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200366static void amd_decode_bu_mce(struct mce *m)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200367{
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200368 u32 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200369 u32 xec = (m->status >> 16) & xec_mask;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200370
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200371 pr_emerg(HW_ERR "Bus Unit Error");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200372
373 if (xec == 0x1)
374 pr_cont(" in the write data buffers.\n");
375 else if (xec == 0x3)
376 pr_cont(" in the victim data buffers.\n");
377 else if (xec == 0x2 && MEM_ERROR(ec))
378 pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
379 else if (xec == 0x0) {
380 if (TLB_ERROR(ec))
381 pr_cont(": %s error in a Page Descriptor Cache or "
382 "Guest TLB.\n", TT_MSG(ec));
383 else if (BUS_ERROR(ec))
384 pr_cont(": %s/ECC error in data read from NB: %s.\n",
385 RRRR_MSG(ec), PP_MSG(ec));
386 else if (MEM_ERROR(ec)) {
387 u8 rrrr = (ec >> 4) & 0xf;
388
389 if (rrrr >= 0x7)
390 pr_cont(": %s error during data copyback.\n",
391 RRRR_MSG(ec));
392 else if (rrrr <= 0x1)
393 pr_cont(": %s parity/ECC error during data "
394 "access from L2.\n", RRRR_MSG(ec));
395 else
396 goto wrong_bu_mce;
397 } else
398 goto wrong_bu_mce;
399 } else
400 goto wrong_bu_mce;
401
402 return;
403
404wrong_bu_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200405 pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200406}
407
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200408static void amd_decode_ls_mce(struct mce *m)
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200409{
Borislav Petkovded50622010-08-27 17:03:34 +0200410 u16 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200411 u8 xec = (m->status >> 16) & xec_mask;
Borislav Petkovded50622010-08-27 17:03:34 +0200412
413 if (boot_cpu_data.x86 == 0x14) {
414 pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
415 " please report on LKML.\n");
416 return;
417 }
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200418
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200419 pr_emerg(HW_ERR "Load Store Error");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200420
421 if (xec == 0x0) {
Borislav Petkovded50622010-08-27 17:03:34 +0200422 u8 r4 = (ec >> 4) & 0xf;
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200423
Borislav Petkovded50622010-08-27 17:03:34 +0200424 if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200425 goto wrong_ls_mce;
426
427 pr_cont(" during %s.\n", RRRR_MSG(ec));
Borislav Petkovded50622010-08-27 17:03:34 +0200428 } else
429 goto wrong_ls_mce;
430
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200431 return;
432
433wrong_ls_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200434 pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200435}
436
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200437static bool k8_nb_mce(u16 ec, u8 xec)
438{
439 bool ret = true;
440
441 switch (xec) {
442 case 0x1:
443 pr_cont("CRC error detected on HT link.\n");
444 break;
445
446 case 0x5:
447 pr_cont("Invalid GART PTE entry during GART table walk.\n");
448 break;
449
450 case 0x6:
451 pr_cont("Unsupported atomic RMW received from an IO link.\n");
452 break;
453
454 case 0x0:
455 case 0x8:
Borislav Petkovf0157b32010-10-05 19:07:16 +0200456 if (boot_cpu_data.x86 == 0x11)
457 return false;
458
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200459 pr_cont("DRAM ECC error detected on the NB.\n");
460 break;
461
462 case 0xd:
463 pr_cont("Parity error on the DRAM addr/ctl signals.\n");
464 break;
465
466 default:
467 ret = false;
468 break;
469 }
470
471 return ret;
472}
473
474static bool f10h_nb_mce(u16 ec, u8 xec)
475{
476 bool ret = true;
477 u8 offset = 0;
478
479 if (k8_nb_mce(ec, xec))
480 return true;
481
482 switch(xec) {
483 case 0xa ... 0xc:
484 offset = 10;
485 break;
486
487 case 0xe:
488 offset = 11;
489 break;
490
491 case 0xf:
492 if (TLB_ERROR(ec))
493 pr_cont("GART Table Walk data error.\n");
494 else if (BUS_ERROR(ec))
495 pr_cont("DMA Exclusion Vector Table Walk error.\n");
496 else
497 ret = false;
498
499 goto out;
500 break;
501
502 case 0x1c ... 0x1f:
503 offset = 24;
504 break;
505
506 default:
507 ret = false;
508
509 goto out;
510 break;
511 }
512
513 pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
514
515out:
516 return ret;
517}
518
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200519static bool nb_noop_mce(u16 ec, u8 xec)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200520{
521 return false;
522}
523
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200524void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
Borislav Petkov549d0422009-07-24 13:51:42 +0200525{
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200526 u8 xec = (m->status >> 16) & 0x1f;
527 u16 ec = m->status & 0xffff;
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200528 u32 nbsh = (u32)(m->status >> 32);
Borislav Petkov549d0422009-07-24 13:51:42 +0200529
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200530 pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id);
Borislav Petkov549d0422009-07-24 13:51:42 +0200531
532 /*
533 * F10h, revD can disable ErrCpu[3:0] so check that first and also the
534 * value encoding has changed so interpret those differently
535 */
536 if ((boot_cpu_data.x86 == 0x10) &&
Borislav Petkovcec79242009-10-27 19:12:02 +0100537 (boot_cpu_data.x86_model > 7)) {
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200538 if (nbsh & K8_NBSH_ERR_CPU_VAL)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200539 pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
Borislav Petkov549d0422009-07-24 13:51:42 +0200540 } else {
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200541 u8 assoc_cpus = nbsh & nb_err_cpumask;
Borislav Petkov5b89d2f2010-03-09 20:38:48 +0100542
543 if (assoc_cpus > 0)
544 pr_cont(", core: %d", fls(assoc_cpus) - 1);
Borislav Petkov549d0422009-07-24 13:51:42 +0200545 }
546
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200547 switch (xec) {
548 case 0x2:
549 pr_cont("Sync error (sync packets on HT link detected).\n");
550 return;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200551
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200552 case 0x3:
553 pr_cont("HT Master abort.\n");
554 return;
555
556 case 0x4:
557 pr_cont("HT Target abort.\n");
558 return;
559
560 case 0x7:
561 pr_cont("NB Watchdog timeout.\n");
562 return;
563
564 case 0x9:
565 pr_cont("SVM DMA Exclusion Vector error.\n");
566 return;
567
568 default:
569 break;
570 }
571
572 if (!fam_ops->nb_mce(ec, xec))
573 goto wrong_nb_mce;
574
575 if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
576 if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
577 nb_bus_decoder(node_id, m, nbcfg);
578
579 return;
580
581wrong_nb_mce:
582 pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
Borislav Petkovd93cc222009-07-28 10:56:15 +0200583}
584EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
585
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200586static void amd_decode_fr_mce(struct mce *m)
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200587{
Borislav Petkovf0157b32010-10-05 19:07:16 +0200588 if (boot_cpu_data.x86 == 0xf ||
589 boot_cpu_data.x86 == 0x11)
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200590 goto wrong_fr_mce;
591
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200592 /* we have only one error signature so match all fields at once. */
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200593 if ((m->status & 0xffff) == 0x0f0f) {
594 pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
595 return;
596 }
597
598wrong_fr_mce:
599 pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200600}
601
Borislav Petkov63375832010-09-06 18:13:39 +0200602static inline void amd_decode_err_code(u16 ec)
Borislav Petkovd93cc222009-07-28 10:56:15 +0200603{
Borislav Petkov549d0422009-07-24 13:51:42 +0200604 if (TLB_ERROR(ec)) {
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200605 pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200606 TT_MSG(ec), LL_MSG(ec));
607 } else if (MEM_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200608 pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200609 RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
610 } else if (BUS_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200611 pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
Borislav Petkovd93cc222009-07-28 10:56:15 +0200612 "Participating Processor: %s\n",
613 RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
614 PP_MSG(ec));
615 } else
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200616 pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
Borislav Petkov549d0422009-07-24 13:51:42 +0200617}
Borislav Petkov549d0422009-07-24 13:51:42 +0200618
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200619/*
620 * Filter out unwanted MCE signatures here.
621 */
622static bool amd_filter_mce(struct mce *m)
623{
624 u8 xec = (m->status >> 16) & 0x1f;
625
626 /*
627 * NB GART TLB error reporting is disabled by default.
628 */
629 if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
630 return true;
631
632 return false;
633}
634
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200635int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
Borislav Petkov549d0422009-07-24 13:51:42 +0200636{
Borislav Petkovfb253192009-10-07 13:20:38 +0200637 struct mce *m = (struct mce *)data;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200638 int node, ecc;
Borislav Petkov549d0422009-07-24 13:51:42 +0200639
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200640 if (amd_filter_mce(m))
641 return NOTIFY_STOP;
642
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200643 pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
Borislav Petkov549d0422009-07-24 13:51:42 +0200644
Borislav Petkov37b73702010-08-24 18:21:42 +0200645 pr_cont("%sorrected error, other errors lost: %s, "
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200646 "CPU context corrupt: %s",
647 ((m->status & MCI_STATUS_UC) ? "Unc" : "C"),
Borislav Petkov37b73702010-08-24 18:21:42 +0200648 ((m->status & MCI_STATUS_OVER) ? "yes" : "no"),
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200649 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
Borislav Petkov549d0422009-07-24 13:51:42 +0200650
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200651 /* do the two bits[14:13] together */
Borislav Petkov35d824b2010-04-30 15:19:02 +0200652 ecc = (m->status >> 45) & 0x3;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200653 if (ecc)
654 pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
655
656 pr_cont("\n");
657
Borislav Petkov51966242009-07-28 13:50:43 +0200658 switch (m->bank) {
659 case 0:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200660 amd_decode_dc_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200661 break;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200662
Borislav Petkovab5535e2009-07-28 14:06:26 +0200663 case 1:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200664 amd_decode_ic_mce(m);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200665 break;
666
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200667 case 2:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200668 amd_decode_bu_mce(m);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200669 break;
670
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200671 case 3:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200672 amd_decode_ls_mce(m);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200673 break;
674
Borislav Petkov51966242009-07-28 13:50:43 +0200675 case 4:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200676 node = amd_get_nb_id(m->extcpu);
677 amd_decode_nb_mce(node, m, 0);
Borislav Petkov51966242009-07-28 13:50:43 +0200678 break;
679
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200680 case 5:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200681 amd_decode_fr_mce(m);
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200682 break;
683
Borislav Petkov51966242009-07-28 13:50:43 +0200684 default:
685 break;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200686 }
Borislav Petkov51966242009-07-28 13:50:43 +0200687
688 amd_decode_err_code(m->status & 0xffff);
Borislav Petkovfb253192009-10-07 13:20:38 +0200689
690 return NOTIFY_STOP;
Borislav Petkov549d0422009-07-24 13:51:42 +0200691}
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200692EXPORT_SYMBOL_GPL(amd_decode_mce);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200693
Borislav Petkovfb253192009-10-07 13:20:38 +0200694static struct notifier_block amd_mce_dec_nb = {
695 .notifier_call = amd_decode_mce,
696};
697
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200698static int __init mce_amd_init(void)
699{
Borislav Petkove045c292010-08-06 18:55:45 +0200700 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
701 return 0;
702
Borislav Petkovfda75612010-09-22 16:12:03 +0200703 if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) &&
Borislav Petkov9530d602010-09-06 15:05:45 +0200704 (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf))
Borislav Petkove045c292010-08-06 18:55:45 +0200705 return 0;
706
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200707 fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
708 if (!fam_ops)
709 return -ENOMEM;
710
711 switch (boot_cpu_data.x86) {
712 case 0xf:
713 fam_ops->dc_mce = k8_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200714 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200715 fam_ops->nb_mce = k8_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200716 break;
717
718 case 0x10:
719 fam_ops->dc_mce = f10h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200720 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200721 fam_ops->nb_mce = f10h_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200722 break;
723
Borislav Petkovf0157b32010-10-05 19:07:16 +0200724 case 0x11:
725 fam_ops->dc_mce = k8_dc_mce;
726 fam_ops->ic_mce = k8_ic_mce;
727 fam_ops->nb_mce = f10h_nb_mce;
728 break;
729
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200730 case 0x12:
731 fam_ops->dc_mce = f12h_dc_mce;
Borislav Petkove7281eb2010-09-16 16:45:22 +0200732 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200733 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200734 break;
735
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200736 case 0x14:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200737 nb_err_cpumask = 0x3;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200738 fam_ops->dc_mce = f14h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200739 fam_ops->ic_mce = f14h_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200740 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200741 break;
742
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200743 case 0x15:
744 xec_mask = 0x1f;
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200745 fam_ops->dc_mce = f15h_dc_mce;
Borislav Petkov86039cd2010-11-08 15:03:35 +0100746 fam_ops->ic_mce = f15h_ic_mce;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200747 break;
748
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200749 default:
750 printk(KERN_WARNING "Huh? What family is that: %d?!\n",
751 boot_cpu_data.x86);
752 kfree(fam_ops);
753 return -EINVAL;
754 }
755
Borislav Petkov9530d602010-09-06 15:05:45 +0200756 pr_info("MCE: In-kernel MCE decoding enabled.\n");
757
Borislav Petkove045c292010-08-06 18:55:45 +0200758 atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200759
760 return 0;
761}
762early_initcall(mce_amd_init);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200763
764#ifdef MODULE
765static void __exit mce_amd_exit(void)
766{
Borislav Petkovfb253192009-10-07 13:20:38 +0200767 atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200768 kfree(fam_ops);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200769}
770
771MODULE_DESCRIPTION("AMD MCE decoder");
772MODULE_ALIAS("edac-mce-amd");
773MODULE_LICENSE("GPL");
774module_exit(mce_amd_exit);
775#endif