blob: 01853eed20194c160ae31c4d075c58c21c663164 [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 Thompsonb52401c2009-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 Thompsonb52401c2009-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 Thompsonb52401c2009-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 Thompsonb52401c2009-05-06 17:57:20 +020048
Borislav Petkov63375832010-09-06 18:13:39 +020049/* memory transaction type */
Doug Thompsonb52401c2009-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 Thompsonb52401c2009-05-06 17:57:20 +020052};
Borislav Petkovb70ef012009-06-25 19:32:38 +020053EXPORT_SYMBOL_GPL(rrrr_msgs);
Doug Thompsonb52401c2009-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 Thompsonb52401c2009-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 Thompsonb52401c2009-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 Thompsonb52401c2009-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 Thompsonb52401c2009-05-06 17:57:20 +020076};
Borislav Petkov549d0422009-07-24 13:51:42 +020077
Borislav Petkov9be0bb12010-09-16 15:08:14 +020078static bool f12h_dc_mce(u16 ec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +020079{
Borislav Petkov888ab8e2010-08-18 15:11:35 +020080 bool ret = false;
81
Borislav Petkov888ab8e2010-08-18 15:11:35 +020082 if (MEM_ERROR(ec)) {
83 u8 ll = ec & 0x3;
84 ret = true;
85
86 if (ll == LL_L2)
87 pr_cont("during L1 linefill from L2.\n");
88 else if (ll == LL_L1)
89 pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec));
90 else
91 ret = false;
92 }
93 return ret;
94}
95
Borislav Petkov9be0bb12010-09-16 15:08:14 +020096static bool f10h_dc_mce(u16 ec)
97{
98 u8 r4 = (ec >> 4) & 0xf;
99 u8 ll = ec & 0x3;
100
101 if (r4 == R4_GEN && ll == LL_L1) {
102 pr_cont("during data scrub.\n");
103 return true;
104 }
105 return f12h_dc_mce(ec);
106}
107
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200108static bool k8_dc_mce(u16 ec)
109{
110 if (BUS_ERROR(ec)) {
111 pr_cont("during system linefill.\n");
112 return true;
113 }
114
115 return f10h_dc_mce(ec);
116}
117
118static bool f14h_dc_mce(u16 ec)
119{
120 u8 r4 = (ec >> 4) & 0xf;
121 u8 ll = ec & 0x3;
122 u8 tt = (ec >> 2) & 0x3;
123 u8 ii = tt;
124 bool ret = true;
125
126 if (MEM_ERROR(ec)) {
127
128 if (tt != TT_DATA || ll != LL_L1)
129 return false;
130
131 switch (r4) {
132 case R4_DRD:
133 case R4_DWR:
134 pr_cont("Data/Tag parity error due to %s.\n",
135 (r4 == R4_DRD ? "load/hw prf" : "store"));
136 break;
137 case R4_EVICT:
138 pr_cont("Copyback parity error on a tag miss.\n");
139 break;
140 case R4_SNOOP:
141 pr_cont("Tag parity error during snoop.\n");
142 break;
143 default:
144 ret = false;
145 }
146 } else if (BUS_ERROR(ec)) {
147
148 if ((ii != II_MEM && ii != II_IO) || ll != LL_LG)
149 return false;
150
151 pr_cont("System read data error on a ");
152
153 switch (r4) {
154 case R4_RD:
155 pr_cont("TLB reload.\n");
156 break;
157 case R4_DWR:
158 pr_cont("store.\n");
159 break;
160 case R4_DRD:
161 pr_cont("load.\n");
162 break;
163 default:
164 ret = false;
165 }
166 } else {
167 ret = false;
168 }
169
170 return ret;
171}
172
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200173static void amd_decode_dc_mce(struct mce *m)
Borislav Petkov51966242009-07-28 13:50:43 +0200174{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200175 u16 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200176 u8 xec = (m->status >> 16) & xec_mask;
Borislav Petkov51966242009-07-28 13:50:43 +0200177
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200178 pr_emerg(HW_ERR "Data Cache Error: ");
Borislav Petkov51966242009-07-28 13:50:43 +0200179
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200180 /* TLB error signatures are the same across families */
181 if (TLB_ERROR(ec)) {
182 u8 tt = (ec >> 2) & 0x3;
Borislav Petkov51966242009-07-28 13:50:43 +0200183
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200184 if (tt == TT_DATA) {
185 pr_cont("%s TLB %s.\n", LL_MSG(ec),
186 (xec ? "multimatch" : "parity error"));
187 return;
188 }
Borislav Petkov51966242009-07-28 13:50:43 +0200189 else
190 goto wrong_dc_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200191 }
192
193 if (!fam_ops->dc_mce(ec))
Borislav Petkov51966242009-07-28 13:50:43 +0200194 goto wrong_dc_mce;
195
196 return;
197
198wrong_dc_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200199 pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
Borislav Petkov51966242009-07-28 13:50:43 +0200200}
201
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200202static bool k8_ic_mce(u16 ec)
203{
204 u8 ll = ec & 0x3;
205 u8 r4 = (ec >> 4) & 0xf;
206 bool ret = true;
207
208 if (!MEM_ERROR(ec))
209 return false;
210
211 if (ll == 0x2)
212 pr_cont("during a linefill from L2.\n");
213 else if (ll == 0x1) {
214 switch (r4) {
215 case R4_IRD:
216 pr_cont("Parity error during data load.\n");
217 break;
218
219 case R4_EVICT:
220 pr_cont("Copyback Parity/Victim error.\n");
221 break;
222
223 case R4_SNOOP:
224 pr_cont("Tag Snoop error.\n");
225 break;
226
227 default:
228 ret = false;
229 break;
230 }
231 } else
232 ret = false;
233
234 return ret;
235}
236
237static bool f14h_ic_mce(u16 ec)
238{
239 u8 ll = ec & 0x3;
240 u8 tt = (ec >> 2) & 0x3;
241 u8 r4 = (ec >> 4) & 0xf;
242 bool ret = true;
243
244 if (MEM_ERROR(ec)) {
245 if (tt != 0 || ll != 1)
246 ret = false;
247
248 if (r4 == R4_IRD)
249 pr_cont("Data/tag array parity error for a tag hit.\n");
250 else if (r4 == R4_SNOOP)
251 pr_cont("Tag error during snoop/victimization.\n");
252 else
253 ret = false;
254 }
255 return ret;
256}
257
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200258static void amd_decode_ic_mce(struct mce *m)
Borislav Petkovab5535e2009-07-28 14:06:26 +0200259{
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200260 u16 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200261 u8 xec = (m->status >> 16) & xec_mask;
Borislav Petkovab5535e2009-07-28 14:06:26 +0200262
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200263 pr_emerg(HW_ERR "Instruction Cache Error: ");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200264
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200265 if (TLB_ERROR(ec))
266 pr_cont("%s TLB %s.\n", LL_MSG(ec),
267 (xec ? "multimatch" : "parity error"));
268 else if (BUS_ERROR(ec)) {
Borislav Petkov525906b2010-10-15 15:27:02 +0200269 bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
Borislav Petkovab5535e2009-07-28 14:06:26 +0200270
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200271 pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
272 } else if (fam_ops->ic_mce(ec))
273 ;
274 else
275 pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200276}
277
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200278static void amd_decode_bu_mce(struct mce *m)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200279{
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200280 u32 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200281 u32 xec = (m->status >> 16) & xec_mask;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200282
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200283 pr_emerg(HW_ERR "Bus Unit Error");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200284
285 if (xec == 0x1)
286 pr_cont(" in the write data buffers.\n");
287 else if (xec == 0x3)
288 pr_cont(" in the victim data buffers.\n");
289 else if (xec == 0x2 && MEM_ERROR(ec))
290 pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
291 else if (xec == 0x0) {
292 if (TLB_ERROR(ec))
293 pr_cont(": %s error in a Page Descriptor Cache or "
294 "Guest TLB.\n", TT_MSG(ec));
295 else if (BUS_ERROR(ec))
296 pr_cont(": %s/ECC error in data read from NB: %s.\n",
297 RRRR_MSG(ec), PP_MSG(ec));
298 else if (MEM_ERROR(ec)) {
299 u8 rrrr = (ec >> 4) & 0xf;
300
301 if (rrrr >= 0x7)
302 pr_cont(": %s error during data copyback.\n",
303 RRRR_MSG(ec));
304 else if (rrrr <= 0x1)
305 pr_cont(": %s parity/ECC error during data "
306 "access from L2.\n", RRRR_MSG(ec));
307 else
308 goto wrong_bu_mce;
309 } else
310 goto wrong_bu_mce;
311 } else
312 goto wrong_bu_mce;
313
314 return;
315
316wrong_bu_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200317 pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200318}
319
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200320static void amd_decode_ls_mce(struct mce *m)
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200321{
Borislav Petkovded50622010-08-27 17:03:34 +0200322 u16 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200323 u8 xec = (m->status >> 16) & xec_mask;
Borislav Petkovded50622010-08-27 17:03:34 +0200324
325 if (boot_cpu_data.x86 == 0x14) {
326 pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
327 " please report on LKML.\n");
328 return;
329 }
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200330
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200331 pr_emerg(HW_ERR "Load Store Error");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200332
333 if (xec == 0x0) {
Borislav Petkovded50622010-08-27 17:03:34 +0200334 u8 r4 = (ec >> 4) & 0xf;
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200335
Borislav Petkovded50622010-08-27 17:03:34 +0200336 if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200337 goto wrong_ls_mce;
338
339 pr_cont(" during %s.\n", RRRR_MSG(ec));
Borislav Petkovded50622010-08-27 17:03:34 +0200340 } else
341 goto wrong_ls_mce;
342
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200343 return;
344
345wrong_ls_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200346 pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200347}
348
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200349static bool k8_nb_mce(u16 ec, u8 xec)
350{
351 bool ret = true;
352
353 switch (xec) {
354 case 0x1:
355 pr_cont("CRC error detected on HT link.\n");
356 break;
357
358 case 0x5:
359 pr_cont("Invalid GART PTE entry during GART table walk.\n");
360 break;
361
362 case 0x6:
363 pr_cont("Unsupported atomic RMW received from an IO link.\n");
364 break;
365
366 case 0x0:
367 case 0x8:
Borislav Petkovf0157b32010-10-05 19:07:16 +0200368 if (boot_cpu_data.x86 == 0x11)
369 return false;
370
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200371 pr_cont("DRAM ECC error detected on the NB.\n");
372 break;
373
374 case 0xd:
375 pr_cont("Parity error on the DRAM addr/ctl signals.\n");
376 break;
377
378 default:
379 ret = false;
380 break;
381 }
382
383 return ret;
384}
385
386static bool f10h_nb_mce(u16 ec, u8 xec)
387{
388 bool ret = true;
389 u8 offset = 0;
390
391 if (k8_nb_mce(ec, xec))
392 return true;
393
394 switch(xec) {
395 case 0xa ... 0xc:
396 offset = 10;
397 break;
398
399 case 0xe:
400 offset = 11;
401 break;
402
403 case 0xf:
404 if (TLB_ERROR(ec))
405 pr_cont("GART Table Walk data error.\n");
406 else if (BUS_ERROR(ec))
407 pr_cont("DMA Exclusion Vector Table Walk error.\n");
408 else
409 ret = false;
410
411 goto out;
412 break;
413
414 case 0x1c ... 0x1f:
415 offset = 24;
416 break;
417
418 default:
419 ret = false;
420
421 goto out;
422 break;
423 }
424
425 pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
426
427out:
428 return ret;
429}
430
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200431static bool nb_noop_mce(u16 ec, u8 xec)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200432{
433 return false;
434}
435
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200436void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
Borislav Petkov549d0422009-07-24 13:51:42 +0200437{
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200438 u8 xec = (m->status >> 16) & 0x1f;
439 u16 ec = m->status & 0xffff;
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200440 u32 nbsh = (u32)(m->status >> 32);
Borislav Petkov549d0422009-07-24 13:51:42 +0200441
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200442 pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id);
Borislav Petkov549d0422009-07-24 13:51:42 +0200443
444 /*
445 * F10h, revD can disable ErrCpu[3:0] so check that first and also the
446 * value encoding has changed so interpret those differently
447 */
448 if ((boot_cpu_data.x86 == 0x10) &&
Borislav Petkovcec79242009-10-27 19:12:02 +0100449 (boot_cpu_data.x86_model > 7)) {
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200450 if (nbsh & K8_NBSH_ERR_CPU_VAL)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200451 pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
Borislav Petkov549d0422009-07-24 13:51:42 +0200452 } else {
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200453 u8 assoc_cpus = nbsh & nb_err_cpumask;
Borislav Petkov5b89d2f2010-03-09 20:38:48 +0100454
455 if (assoc_cpus > 0)
456 pr_cont(", core: %d", fls(assoc_cpus) - 1);
Borislav Petkov549d0422009-07-24 13:51:42 +0200457 }
458
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200459 switch (xec) {
460 case 0x2:
461 pr_cont("Sync error (sync packets on HT link detected).\n");
462 return;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200463
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200464 case 0x3:
465 pr_cont("HT Master abort.\n");
466 return;
467
468 case 0x4:
469 pr_cont("HT Target abort.\n");
470 return;
471
472 case 0x7:
473 pr_cont("NB Watchdog timeout.\n");
474 return;
475
476 case 0x9:
477 pr_cont("SVM DMA Exclusion Vector error.\n");
478 return;
479
480 default:
481 break;
482 }
483
484 if (!fam_ops->nb_mce(ec, xec))
485 goto wrong_nb_mce;
486
487 if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
488 if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
489 nb_bus_decoder(node_id, m, nbcfg);
490
491 return;
492
493wrong_nb_mce:
494 pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
Borislav Petkovd93cc222009-07-28 10:56:15 +0200495}
496EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
497
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200498static void amd_decode_fr_mce(struct mce *m)
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200499{
Borislav Petkovf0157b32010-10-05 19:07:16 +0200500 if (boot_cpu_data.x86 == 0xf ||
501 boot_cpu_data.x86 == 0x11)
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200502 goto wrong_fr_mce;
503
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200504 /* we have only one error signature so match all fields at once. */
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200505 if ((m->status & 0xffff) == 0x0f0f) {
506 pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
507 return;
508 }
509
510wrong_fr_mce:
511 pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200512}
513
Borislav Petkov63375832010-09-06 18:13:39 +0200514static inline void amd_decode_err_code(u16 ec)
Borislav Petkovd93cc222009-07-28 10:56:15 +0200515{
Borislav Petkov549d0422009-07-24 13:51:42 +0200516 if (TLB_ERROR(ec)) {
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200517 pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200518 TT_MSG(ec), LL_MSG(ec));
519 } else if (MEM_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200520 pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200521 RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
522 } else if (BUS_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200523 pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
Borislav Petkovd93cc222009-07-28 10:56:15 +0200524 "Participating Processor: %s\n",
525 RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
526 PP_MSG(ec));
527 } else
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200528 pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
Borislav Petkov549d0422009-07-24 13:51:42 +0200529}
Borislav Petkov549d0422009-07-24 13:51:42 +0200530
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200531/*
532 * Filter out unwanted MCE signatures here.
533 */
534static bool amd_filter_mce(struct mce *m)
535{
536 u8 xec = (m->status >> 16) & 0x1f;
537
538 /*
539 * NB GART TLB error reporting is disabled by default.
540 */
541 if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
542 return true;
543
544 return false;
545}
546
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200547int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
Borislav Petkov549d0422009-07-24 13:51:42 +0200548{
Borislav Petkovfb253192009-10-07 13:20:38 +0200549 struct mce *m = (struct mce *)data;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200550 int node, ecc;
Borislav Petkov549d0422009-07-24 13:51:42 +0200551
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200552 if (amd_filter_mce(m))
553 return NOTIFY_STOP;
554
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200555 pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
Borislav Petkov549d0422009-07-24 13:51:42 +0200556
Borislav Petkov37b73702010-08-24 18:21:42 +0200557 pr_cont("%sorrected error, other errors lost: %s, "
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200558 "CPU context corrupt: %s",
559 ((m->status & MCI_STATUS_UC) ? "Unc" : "C"),
Borislav Petkov37b73702010-08-24 18:21:42 +0200560 ((m->status & MCI_STATUS_OVER) ? "yes" : "no"),
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200561 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
Borislav Petkov549d0422009-07-24 13:51:42 +0200562
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200563 /* do the two bits[14:13] together */
Borislav Petkov35d824b2010-04-30 15:19:02 +0200564 ecc = (m->status >> 45) & 0x3;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200565 if (ecc)
566 pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
567
568 pr_cont("\n");
569
Borislav Petkov51966242009-07-28 13:50:43 +0200570 switch (m->bank) {
571 case 0:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200572 amd_decode_dc_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200573 break;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200574
Borislav Petkovab5535e2009-07-28 14:06:26 +0200575 case 1:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200576 amd_decode_ic_mce(m);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200577 break;
578
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200579 case 2:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200580 amd_decode_bu_mce(m);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200581 break;
582
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200583 case 3:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200584 amd_decode_ls_mce(m);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200585 break;
586
Borislav Petkov51966242009-07-28 13:50:43 +0200587 case 4:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200588 node = amd_get_nb_id(m->extcpu);
589 amd_decode_nb_mce(node, m, 0);
Borislav Petkov51966242009-07-28 13:50:43 +0200590 break;
591
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200592 case 5:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200593 amd_decode_fr_mce(m);
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200594 break;
595
Borislav Petkov51966242009-07-28 13:50:43 +0200596 default:
597 break;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200598 }
Borislav Petkov51966242009-07-28 13:50:43 +0200599
600 amd_decode_err_code(m->status & 0xffff);
Borislav Petkovfb253192009-10-07 13:20:38 +0200601
602 return NOTIFY_STOP;
Borislav Petkov549d0422009-07-24 13:51:42 +0200603}
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200604EXPORT_SYMBOL_GPL(amd_decode_mce);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200605
Borislav Petkovfb253192009-10-07 13:20:38 +0200606static struct notifier_block amd_mce_dec_nb = {
607 .notifier_call = amd_decode_mce,
608};
609
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200610static int __init mce_amd_init(void)
611{
Borislav Petkove045c292010-08-06 18:55:45 +0200612 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
613 return 0;
614
Borislav Petkovfda75612010-09-22 16:12:03 +0200615 if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) &&
Borislav Petkov9530d602010-09-06 15:05:45 +0200616 (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf))
Borislav Petkove045c292010-08-06 18:55:45 +0200617 return 0;
618
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200619 fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
620 if (!fam_ops)
621 return -ENOMEM;
622
623 switch (boot_cpu_data.x86) {
624 case 0xf:
625 fam_ops->dc_mce = k8_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200626 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200627 fam_ops->nb_mce = k8_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200628 break;
629
630 case 0x10:
631 fam_ops->dc_mce = f10h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200632 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200633 fam_ops->nb_mce = f10h_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200634 break;
635
Borislav Petkovf0157b32010-10-05 19:07:16 +0200636 case 0x11:
637 fam_ops->dc_mce = k8_dc_mce;
638 fam_ops->ic_mce = k8_ic_mce;
639 fam_ops->nb_mce = f10h_nb_mce;
640 break;
641
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200642 case 0x12:
643 fam_ops->dc_mce = f12h_dc_mce;
Borislav Petkove7281eb2010-09-16 16:45:22 +0200644 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200645 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200646 break;
647
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200648 case 0x14:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200649 nb_err_cpumask = 0x3;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200650 fam_ops->dc_mce = f14h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200651 fam_ops->ic_mce = f14h_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200652 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200653 break;
654
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200655 case 0x15:
656 xec_mask = 0x1f;
657 break;
658
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200659 default:
660 printk(KERN_WARNING "Huh? What family is that: %d?!\n",
661 boot_cpu_data.x86);
662 kfree(fam_ops);
663 return -EINVAL;
664 }
665
Borislav Petkov9530d602010-09-06 15:05:45 +0200666 pr_info("MCE: In-kernel MCE decoding enabled.\n");
667
Borislav Petkove045c292010-08-06 18:55:45 +0200668 atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200669
670 return 0;
671}
672early_initcall(mce_amd_init);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200673
674#ifdef MODULE
675static void __exit mce_amd_exit(void)
676{
Borislav Petkovfb253192009-10-07 13:20:38 +0200677 atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200678 kfree(fam_ops);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200679}
680
681MODULE_DESCRIPTION("AMD MCE decoder");
682MODULE_ALIAS("edac-mce-amd");
683MODULE_LICENSE("GPL");
684module_exit(mce_amd_exit);
685#endif