blob: c0181093b4901ea90dd0381fcdfcfdc91c1bb4c3 [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 Petkov5ce88f62010-08-31 18:28:08 +02008static u8 nb_err_cpumask = 0xf;
9
Borislav Petkov549d0422009-07-24 13:51:42 +020010static bool report_gart_errors;
Borislav Petkov7cfd4a82010-09-01 14:45:20 +020011static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
Borislav Petkov549d0422009-07-24 13:51:42 +020012
13void amd_report_gart_errors(bool v)
14{
15 report_gart_errors = v;
16}
17EXPORT_SYMBOL_GPL(amd_report_gart_errors);
18
Borislav Petkov7cfd4a82010-09-01 14:45:20 +020019void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
Borislav Petkov549d0422009-07-24 13:51:42 +020020{
21 nb_bus_decoder = f;
22}
23EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
24
Borislav Petkov7cfd4a82010-09-01 14:45:20 +020025void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
Borislav Petkov549d0422009-07-24 13:51:42 +020026{
27 if (nb_bus_decoder) {
28 WARN_ON(nb_bus_decoder != f);
29
30 nb_bus_decoder = NULL;
31 }
32}
33EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
34
Doug Thompsonb52401ce2009-05-06 17:57:20 +020035/*
36 * string representation for the different MCA reported error types, see F3x48
37 * or MSR0000_0411.
38 */
Borislav Petkov63375832010-09-06 18:13:39 +020039
40/* transaction type */
41const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020042EXPORT_SYMBOL_GPL(tt_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020043
Borislav Petkov63375832010-09-06 18:13:39 +020044/* cache level */
45const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020046EXPORT_SYMBOL_GPL(ll_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020047
Borislav Petkov63375832010-09-06 18:13:39 +020048/* memory transaction type */
Doug Thompsonb52401ce2009-05-06 17:57:20 +020049const char *rrrr_msgs[] = {
Borislav Petkov63375832010-09-06 18:13:39 +020050 "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
Doug Thompsonb52401ce2009-05-06 17:57:20 +020051};
Borislav Petkovb70ef012009-06-25 19:32:38 +020052EXPORT_SYMBOL_GPL(rrrr_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020053
Borislav Petkov63375832010-09-06 18:13:39 +020054/* participating processor */
55const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020056EXPORT_SYMBOL_GPL(pp_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020057
Borislav Petkov63375832010-09-06 18:13:39 +020058/* request timeout */
59const char *to_msgs[] = { "no timeout", "timed out" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020060EXPORT_SYMBOL_GPL(to_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020061
Borislav Petkov63375832010-09-06 18:13:39 +020062/* memory or i/o */
63const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020064EXPORT_SYMBOL_GPL(ii_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020065
Borislav Petkov5ce88f62010-08-31 18:28:08 +020066static const char *f10h_nb_mce_desc[] = {
67 "HT link data error",
68 "Protocol error (link, L3, probe filter, etc.)",
69 "Parity error in NB-internal arrays",
70 "Link Retry due to IO link transmission error",
71 "L3 ECC data cache error",
72 "ECC error in L3 cache tag",
73 "L3 LRU parity bits error",
74 "ECC Error in the Probe Filter directory"
Doug Thompsonb52401ce2009-05-06 17:57:20 +020075};
Borislav Petkov549d0422009-07-24 13:51:42 +020076
Borislav Petkov9be0bb12010-09-16 15:08:14 +020077static bool f12h_dc_mce(u16 ec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +020078{
Borislav Petkov888ab8e2010-08-18 15:11:35 +020079 bool ret = false;
80
Borislav Petkov888ab8e2010-08-18 15:11:35 +020081 if (MEM_ERROR(ec)) {
82 u8 ll = ec & 0x3;
83 ret = true;
84
85 if (ll == LL_L2)
86 pr_cont("during L1 linefill from L2.\n");
87 else if (ll == LL_L1)
88 pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec));
89 else
90 ret = false;
91 }
92 return ret;
93}
94
Borislav Petkov9be0bb12010-09-16 15:08:14 +020095static bool f10h_dc_mce(u16 ec)
96{
97 u8 r4 = (ec >> 4) & 0xf;
98 u8 ll = ec & 0x3;
99
100 if (r4 == R4_GEN && ll == LL_L1) {
101 pr_cont("during data scrub.\n");
102 return true;
103 }
104 return f12h_dc_mce(ec);
105}
106
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200107static bool k8_dc_mce(u16 ec)
108{
109 if (BUS_ERROR(ec)) {
110 pr_cont("during system linefill.\n");
111 return true;
112 }
113
114 return f10h_dc_mce(ec);
115}
116
117static bool f14h_dc_mce(u16 ec)
118{
119 u8 r4 = (ec >> 4) & 0xf;
120 u8 ll = ec & 0x3;
121 u8 tt = (ec >> 2) & 0x3;
122 u8 ii = tt;
123 bool ret = true;
124
125 if (MEM_ERROR(ec)) {
126
127 if (tt != TT_DATA || ll != LL_L1)
128 return false;
129
130 switch (r4) {
131 case R4_DRD:
132 case R4_DWR:
133 pr_cont("Data/Tag parity error due to %s.\n",
134 (r4 == R4_DRD ? "load/hw prf" : "store"));
135 break;
136 case R4_EVICT:
137 pr_cont("Copyback parity error on a tag miss.\n");
138 break;
139 case R4_SNOOP:
140 pr_cont("Tag parity error during snoop.\n");
141 break;
142 default:
143 ret = false;
144 }
145 } else if (BUS_ERROR(ec)) {
146
147 if ((ii != II_MEM && ii != II_IO) || ll != LL_LG)
148 return false;
149
150 pr_cont("System read data error on a ");
151
152 switch (r4) {
153 case R4_RD:
154 pr_cont("TLB reload.\n");
155 break;
156 case R4_DWR:
157 pr_cont("store.\n");
158 break;
159 case R4_DRD:
160 pr_cont("load.\n");
161 break;
162 default:
163 ret = false;
164 }
165 } else {
166 ret = false;
167 }
168
169 return ret;
170}
171
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200172static void amd_decode_dc_mce(struct mce *m)
Borislav Petkov51966242009-07-28 13:50:43 +0200173{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200174 u16 ec = m->status & 0xffff;
175 u8 xec = (m->status >> 16) & 0xf;
Borislav Petkov51966242009-07-28 13:50:43 +0200176
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200177 pr_emerg(HW_ERR "Data Cache Error: ");
Borislav Petkov51966242009-07-28 13:50:43 +0200178
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200179 /* TLB error signatures are the same across families */
180 if (TLB_ERROR(ec)) {
181 u8 tt = (ec >> 2) & 0x3;
Borislav Petkov51966242009-07-28 13:50:43 +0200182
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200183 if (tt == TT_DATA) {
184 pr_cont("%s TLB %s.\n", LL_MSG(ec),
185 (xec ? "multimatch" : "parity error"));
186 return;
187 }
Borislav Petkov51966242009-07-28 13:50:43 +0200188 else
189 goto wrong_dc_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200190 }
191
192 if (!fam_ops->dc_mce(ec))
Borislav Petkov51966242009-07-28 13:50:43 +0200193 goto wrong_dc_mce;
194
195 return;
196
197wrong_dc_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200198 pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
Borislav Petkov51966242009-07-28 13:50:43 +0200199}
200
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200201static bool k8_ic_mce(u16 ec)
202{
203 u8 ll = ec & 0x3;
204 u8 r4 = (ec >> 4) & 0xf;
205 bool ret = true;
206
207 if (!MEM_ERROR(ec))
208 return false;
209
210 if (ll == 0x2)
211 pr_cont("during a linefill from L2.\n");
212 else if (ll == 0x1) {
213 switch (r4) {
214 case R4_IRD:
215 pr_cont("Parity error during data load.\n");
216 break;
217
218 case R4_EVICT:
219 pr_cont("Copyback Parity/Victim error.\n");
220 break;
221
222 case R4_SNOOP:
223 pr_cont("Tag Snoop error.\n");
224 break;
225
226 default:
227 ret = false;
228 break;
229 }
230 } else
231 ret = false;
232
233 return ret;
234}
235
236static bool f14h_ic_mce(u16 ec)
237{
238 u8 ll = ec & 0x3;
239 u8 tt = (ec >> 2) & 0x3;
240 u8 r4 = (ec >> 4) & 0xf;
241 bool ret = true;
242
243 if (MEM_ERROR(ec)) {
244 if (tt != 0 || ll != 1)
245 ret = false;
246
247 if (r4 == R4_IRD)
248 pr_cont("Data/tag array parity error for a tag hit.\n");
249 else if (r4 == R4_SNOOP)
250 pr_cont("Tag error during snoop/victimization.\n");
251 else
252 ret = false;
253 }
254 return ret;
255}
256
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200257static void amd_decode_ic_mce(struct mce *m)
Borislav Petkovab5535e2009-07-28 14:06:26 +0200258{
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200259 u16 ec = m->status & 0xffff;
260 u8 xec = (m->status >> 16) & 0xf;
Borislav Petkovab5535e2009-07-28 14:06:26 +0200261
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200262 pr_emerg(HW_ERR "Instruction Cache Error: ");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200263
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200264 if (TLB_ERROR(ec))
265 pr_cont("%s TLB %s.\n", LL_MSG(ec),
266 (xec ? "multimatch" : "parity error"));
267 else if (BUS_ERROR(ec)) {
Borislav Petkov525906b2010-10-15 15:27:02 +0200268 bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
Borislav Petkovab5535e2009-07-28 14:06:26 +0200269
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200270 pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
271 } else if (fam_ops->ic_mce(ec))
272 ;
273 else
274 pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200275}
276
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200277static void amd_decode_bu_mce(struct mce *m)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200278{
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200279 u32 ec = m->status & 0xffff;
280 u32 xec = (m->status >> 16) & 0xf;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200281
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200282 pr_emerg(HW_ERR "Bus Unit Error");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200283
284 if (xec == 0x1)
285 pr_cont(" in the write data buffers.\n");
286 else if (xec == 0x3)
287 pr_cont(" in the victim data buffers.\n");
288 else if (xec == 0x2 && MEM_ERROR(ec))
289 pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
290 else if (xec == 0x0) {
291 if (TLB_ERROR(ec))
292 pr_cont(": %s error in a Page Descriptor Cache or "
293 "Guest TLB.\n", TT_MSG(ec));
294 else if (BUS_ERROR(ec))
295 pr_cont(": %s/ECC error in data read from NB: %s.\n",
296 RRRR_MSG(ec), PP_MSG(ec));
297 else if (MEM_ERROR(ec)) {
298 u8 rrrr = (ec >> 4) & 0xf;
299
300 if (rrrr >= 0x7)
301 pr_cont(": %s error during data copyback.\n",
302 RRRR_MSG(ec));
303 else if (rrrr <= 0x1)
304 pr_cont(": %s parity/ECC error during data "
305 "access from L2.\n", RRRR_MSG(ec));
306 else
307 goto wrong_bu_mce;
308 } else
309 goto wrong_bu_mce;
310 } else
311 goto wrong_bu_mce;
312
313 return;
314
315wrong_bu_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200316 pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200317}
318
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200319static void amd_decode_ls_mce(struct mce *m)
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200320{
Borislav Petkovded50622010-08-27 17:03:34 +0200321 u16 ec = m->status & 0xffff;
322 u8 xec = (m->status >> 16) & 0xf;
323
324 if (boot_cpu_data.x86 == 0x14) {
325 pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
326 " please report on LKML.\n");
327 return;
328 }
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200329
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200330 pr_emerg(HW_ERR "Load Store Error");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200331
332 if (xec == 0x0) {
Borislav Petkovded50622010-08-27 17:03:34 +0200333 u8 r4 = (ec >> 4) & 0xf;
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200334
Borislav Petkovded50622010-08-27 17:03:34 +0200335 if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200336 goto wrong_ls_mce;
337
338 pr_cont(" during %s.\n", RRRR_MSG(ec));
Borislav Petkovded50622010-08-27 17:03:34 +0200339 } else
340 goto wrong_ls_mce;
341
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200342 return;
343
344wrong_ls_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200345 pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200346}
347
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200348static bool k8_nb_mce(u16 ec, u8 xec)
349{
350 bool ret = true;
351
352 switch (xec) {
353 case 0x1:
354 pr_cont("CRC error detected on HT link.\n");
355 break;
356
357 case 0x5:
358 pr_cont("Invalid GART PTE entry during GART table walk.\n");
359 break;
360
361 case 0x6:
362 pr_cont("Unsupported atomic RMW received from an IO link.\n");
363 break;
364
365 case 0x0:
366 case 0x8:
Borislav Petkovf0157b32010-10-05 19:07:16 +0200367 if (boot_cpu_data.x86 == 0x11)
368 return false;
369
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200370 pr_cont("DRAM ECC error detected on the NB.\n");
371 break;
372
373 case 0xd:
374 pr_cont("Parity error on the DRAM addr/ctl signals.\n");
375 break;
376
377 default:
378 ret = false;
379 break;
380 }
381
382 return ret;
383}
384
385static bool f10h_nb_mce(u16 ec, u8 xec)
386{
387 bool ret = true;
388 u8 offset = 0;
389
390 if (k8_nb_mce(ec, xec))
391 return true;
392
393 switch(xec) {
394 case 0xa ... 0xc:
395 offset = 10;
396 break;
397
398 case 0xe:
399 offset = 11;
400 break;
401
402 case 0xf:
403 if (TLB_ERROR(ec))
404 pr_cont("GART Table Walk data error.\n");
405 else if (BUS_ERROR(ec))
406 pr_cont("DMA Exclusion Vector Table Walk error.\n");
407 else
408 ret = false;
409
410 goto out;
411 break;
412
413 case 0x1c ... 0x1f:
414 offset = 24;
415 break;
416
417 default:
418 ret = false;
419
420 goto out;
421 break;
422 }
423
424 pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
425
426out:
427 return ret;
428}
429
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200430static bool nb_noop_mce(u16 ec, u8 xec)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200431{
432 return false;
433}
434
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200435void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
Borislav Petkov549d0422009-07-24 13:51:42 +0200436{
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200437 u8 xec = (m->status >> 16) & 0x1f;
438 u16 ec = m->status & 0xffff;
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200439 u32 nbsh = (u32)(m->status >> 32);
Borislav Petkov549d0422009-07-24 13:51:42 +0200440
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200441 pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id);
Borislav Petkov549d0422009-07-24 13:51:42 +0200442
443 /*
444 * F10h, revD can disable ErrCpu[3:0] so check that first and also the
445 * value encoding has changed so interpret those differently
446 */
447 if ((boot_cpu_data.x86 == 0x10) &&
Borislav Petkovcec79242009-10-27 19:12:02 +0100448 (boot_cpu_data.x86_model > 7)) {
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200449 if (nbsh & K8_NBSH_ERR_CPU_VAL)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200450 pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
Borislav Petkov549d0422009-07-24 13:51:42 +0200451 } else {
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200452 u8 assoc_cpus = nbsh & nb_err_cpumask;
Borislav Petkov5b89d2f2010-03-09 20:38:48 +0100453
454 if (assoc_cpus > 0)
455 pr_cont(", core: %d", fls(assoc_cpus) - 1);
Borislav Petkov549d0422009-07-24 13:51:42 +0200456 }
457
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200458 switch (xec) {
459 case 0x2:
460 pr_cont("Sync error (sync packets on HT link detected).\n");
461 return;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200462
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200463 case 0x3:
464 pr_cont("HT Master abort.\n");
465 return;
466
467 case 0x4:
468 pr_cont("HT Target abort.\n");
469 return;
470
471 case 0x7:
472 pr_cont("NB Watchdog timeout.\n");
473 return;
474
475 case 0x9:
476 pr_cont("SVM DMA Exclusion Vector error.\n");
477 return;
478
479 default:
480 break;
481 }
482
483 if (!fam_ops->nb_mce(ec, xec))
484 goto wrong_nb_mce;
485
486 if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
487 if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
488 nb_bus_decoder(node_id, m, nbcfg);
489
490 return;
491
492wrong_nb_mce:
493 pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
Borislav Petkovd93cc222009-07-28 10:56:15 +0200494}
495EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
496
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200497static void amd_decode_fr_mce(struct mce *m)
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200498{
Borislav Petkovf0157b32010-10-05 19:07:16 +0200499 if (boot_cpu_data.x86 == 0xf ||
500 boot_cpu_data.x86 == 0x11)
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200501 goto wrong_fr_mce;
502
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200503 /* we have only one error signature so match all fields at once. */
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200504 if ((m->status & 0xffff) == 0x0f0f) {
505 pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
506 return;
507 }
508
509wrong_fr_mce:
510 pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200511}
512
Borislav Petkov63375832010-09-06 18:13:39 +0200513static inline void amd_decode_err_code(u16 ec)
Borislav Petkovd93cc222009-07-28 10:56:15 +0200514{
Borislav Petkov549d0422009-07-24 13:51:42 +0200515 if (TLB_ERROR(ec)) {
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200516 pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200517 TT_MSG(ec), LL_MSG(ec));
518 } else if (MEM_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200519 pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200520 RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
521 } else if (BUS_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200522 pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
Borislav Petkovd93cc222009-07-28 10:56:15 +0200523 "Participating Processor: %s\n",
524 RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
525 PP_MSG(ec));
526 } else
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200527 pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
Borislav Petkov549d0422009-07-24 13:51:42 +0200528}
Borislav Petkov549d0422009-07-24 13:51:42 +0200529
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200530/*
531 * Filter out unwanted MCE signatures here.
532 */
533static bool amd_filter_mce(struct mce *m)
534{
535 u8 xec = (m->status >> 16) & 0x1f;
536
537 /*
538 * NB GART TLB error reporting is disabled by default.
539 */
540 if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
541 return true;
542
543 return false;
544}
545
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200546int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
Borislav Petkov549d0422009-07-24 13:51:42 +0200547{
Borislav Petkovfb253192009-10-07 13:20:38 +0200548 struct mce *m = (struct mce *)data;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200549 int node, ecc;
Borislav Petkov549d0422009-07-24 13:51:42 +0200550
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200551 if (amd_filter_mce(m))
552 return NOTIFY_STOP;
553
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200554 pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
Borislav Petkov549d0422009-07-24 13:51:42 +0200555
Borislav Petkov37b73702010-08-24 18:21:42 +0200556 pr_cont("%sorrected error, other errors lost: %s, "
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200557 "CPU context corrupt: %s",
558 ((m->status & MCI_STATUS_UC) ? "Unc" : "C"),
Borislav Petkov37b73702010-08-24 18:21:42 +0200559 ((m->status & MCI_STATUS_OVER) ? "yes" : "no"),
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200560 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
Borislav Petkov549d0422009-07-24 13:51:42 +0200561
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200562 /* do the two bits[14:13] together */
Borislav Petkov35d824b2010-04-30 15:19:02 +0200563 ecc = (m->status >> 45) & 0x3;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200564 if (ecc)
565 pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
566
567 pr_cont("\n");
568
Borislav Petkov51966242009-07-28 13:50:43 +0200569 switch (m->bank) {
570 case 0:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200571 amd_decode_dc_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200572 break;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200573
Borislav Petkovab5535e2009-07-28 14:06:26 +0200574 case 1:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200575 amd_decode_ic_mce(m);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200576 break;
577
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200578 case 2:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200579 amd_decode_bu_mce(m);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200580 break;
581
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200582 case 3:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200583 amd_decode_ls_mce(m);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200584 break;
585
Borislav Petkov51966242009-07-28 13:50:43 +0200586 case 4:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200587 node = amd_get_nb_id(m->extcpu);
588 amd_decode_nb_mce(node, m, 0);
Borislav Petkov51966242009-07-28 13:50:43 +0200589 break;
590
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200591 case 5:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200592 amd_decode_fr_mce(m);
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200593 break;
594
Borislav Petkov51966242009-07-28 13:50:43 +0200595 default:
596 break;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200597 }
Borislav Petkov51966242009-07-28 13:50:43 +0200598
599 amd_decode_err_code(m->status & 0xffff);
Borislav Petkovfb253192009-10-07 13:20:38 +0200600
601 return NOTIFY_STOP;
Borislav Petkov549d0422009-07-24 13:51:42 +0200602}
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200603EXPORT_SYMBOL_GPL(amd_decode_mce);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200604
Borislav Petkovfb253192009-10-07 13:20:38 +0200605static struct notifier_block amd_mce_dec_nb = {
606 .notifier_call = amd_decode_mce,
607};
608
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200609static int __init mce_amd_init(void)
610{
Borislav Petkove045c292010-08-06 18:55:45 +0200611 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
612 return 0;
613
Borislav Petkovfda75612010-09-22 16:12:03 +0200614 if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) &&
Borislav Petkov9530d602010-09-06 15:05:45 +0200615 (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf))
Borislav Petkove045c292010-08-06 18:55:45 +0200616 return 0;
617
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200618 fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
619 if (!fam_ops)
620 return -ENOMEM;
621
622 switch (boot_cpu_data.x86) {
623 case 0xf:
624 fam_ops->dc_mce = k8_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200625 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200626 fam_ops->nb_mce = k8_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200627 break;
628
629 case 0x10:
630 fam_ops->dc_mce = f10h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200631 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200632 fam_ops->nb_mce = f10h_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200633 break;
634
Borislav Petkovf0157b32010-10-05 19:07:16 +0200635 case 0x11:
636 fam_ops->dc_mce = k8_dc_mce;
637 fam_ops->ic_mce = k8_ic_mce;
638 fam_ops->nb_mce = f10h_nb_mce;
639 break;
640
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200641 case 0x12:
642 fam_ops->dc_mce = f12h_dc_mce;
Borislav Petkove7281eb2010-09-16 16:45:22 +0200643 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200644 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200645 break;
646
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200647 case 0x14:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200648 nb_err_cpumask = 0x3;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200649 fam_ops->dc_mce = f14h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200650 fam_ops->ic_mce = f14h_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200651 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200652 break;
653
654 default:
655 printk(KERN_WARNING "Huh? What family is that: %d?!\n",
656 boot_cpu_data.x86);
657 kfree(fam_ops);
658 return -EINVAL;
659 }
660
Borislav Petkov9530d602010-09-06 15:05:45 +0200661 pr_info("MCE: In-kernel MCE decoding enabled.\n");
662
Borislav Petkove045c292010-08-06 18:55:45 +0200663 atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200664
665 return 0;
666}
667early_initcall(mce_amd_init);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200668
669#ifdef MODULE
670static void __exit mce_amd_exit(void)
671{
Borislav Petkovfb253192009-10-07 13:20:38 +0200672 atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200673 kfree(fam_ops);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200674}
675
676MODULE_DESCRIPTION("AMD MCE decoder");
677MODULE_ALIAS("edac-mce-amd");
678MODULE_LICENSE("GPL");
679module_exit(mce_amd_exit);
680#endif