blob: 83b7b5fcee7fa8bf062d0f5af6edd41cee670ecf [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 Petkov888ab8e2010-08-18 15:11:35 +020077static bool f10h_dc_mce(u16 ec)
78{
79 u8 r4 = (ec >> 4) & 0xf;
80 bool ret = false;
81
82 if (r4 == R4_GEN) {
83 pr_cont("during data scrub.\n");
84 return true;
85 }
86
87 if (MEM_ERROR(ec)) {
88 u8 ll = ec & 0x3;
89 ret = true;
90
91 if (ll == LL_L2)
92 pr_cont("during L1 linefill from L2.\n");
93 else if (ll == LL_L1)
94 pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec));
95 else
96 ret = false;
97 }
98 return ret;
99}
100
101static bool k8_dc_mce(u16 ec)
102{
103 if (BUS_ERROR(ec)) {
104 pr_cont("during system linefill.\n");
105 return true;
106 }
107
108 return f10h_dc_mce(ec);
109}
110
111static bool f14h_dc_mce(u16 ec)
112{
113 u8 r4 = (ec >> 4) & 0xf;
114 u8 ll = ec & 0x3;
115 u8 tt = (ec >> 2) & 0x3;
116 u8 ii = tt;
117 bool ret = true;
118
119 if (MEM_ERROR(ec)) {
120
121 if (tt != TT_DATA || ll != LL_L1)
122 return false;
123
124 switch (r4) {
125 case R4_DRD:
126 case R4_DWR:
127 pr_cont("Data/Tag parity error due to %s.\n",
128 (r4 == R4_DRD ? "load/hw prf" : "store"));
129 break;
130 case R4_EVICT:
131 pr_cont("Copyback parity error on a tag miss.\n");
132 break;
133 case R4_SNOOP:
134 pr_cont("Tag parity error during snoop.\n");
135 break;
136 default:
137 ret = false;
138 }
139 } else if (BUS_ERROR(ec)) {
140
141 if ((ii != II_MEM && ii != II_IO) || ll != LL_LG)
142 return false;
143
144 pr_cont("System read data error on a ");
145
146 switch (r4) {
147 case R4_RD:
148 pr_cont("TLB reload.\n");
149 break;
150 case R4_DWR:
151 pr_cont("store.\n");
152 break;
153 case R4_DRD:
154 pr_cont("load.\n");
155 break;
156 default:
157 ret = false;
158 }
159 } else {
160 ret = false;
161 }
162
163 return ret;
164}
165
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200166static void amd_decode_dc_mce(struct mce *m)
Borislav Petkov51966242009-07-28 13:50:43 +0200167{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200168 u16 ec = m->status & 0xffff;
169 u8 xec = (m->status >> 16) & 0xf;
Borislav Petkov51966242009-07-28 13:50:43 +0200170
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200171 pr_emerg(HW_ERR "Data Cache Error: ");
Borislav Petkov51966242009-07-28 13:50:43 +0200172
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200173 /* TLB error signatures are the same across families */
174 if (TLB_ERROR(ec)) {
175 u8 tt = (ec >> 2) & 0x3;
Borislav Petkov51966242009-07-28 13:50:43 +0200176
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200177 if (tt == TT_DATA) {
178 pr_cont("%s TLB %s.\n", LL_MSG(ec),
179 (xec ? "multimatch" : "parity error"));
180 return;
181 }
Borislav Petkov51966242009-07-28 13:50:43 +0200182 else
183 goto wrong_dc_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200184 }
185
186 if (!fam_ops->dc_mce(ec))
Borislav Petkov51966242009-07-28 13:50:43 +0200187 goto wrong_dc_mce;
188
189 return;
190
191wrong_dc_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200192 pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
Borislav Petkov51966242009-07-28 13:50:43 +0200193}
194
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200195static bool k8_ic_mce(u16 ec)
196{
197 u8 ll = ec & 0x3;
198 u8 r4 = (ec >> 4) & 0xf;
199 bool ret = true;
200
201 if (!MEM_ERROR(ec))
202 return false;
203
204 if (ll == 0x2)
205 pr_cont("during a linefill from L2.\n");
206 else if (ll == 0x1) {
207 switch (r4) {
208 case R4_IRD:
209 pr_cont("Parity error during data load.\n");
210 break;
211
212 case R4_EVICT:
213 pr_cont("Copyback Parity/Victim error.\n");
214 break;
215
216 case R4_SNOOP:
217 pr_cont("Tag Snoop error.\n");
218 break;
219
220 default:
221 ret = false;
222 break;
223 }
224 } else
225 ret = false;
226
227 return ret;
228}
229
230static bool f14h_ic_mce(u16 ec)
231{
232 u8 ll = ec & 0x3;
233 u8 tt = (ec >> 2) & 0x3;
234 u8 r4 = (ec >> 4) & 0xf;
235 bool ret = true;
236
237 if (MEM_ERROR(ec)) {
238 if (tt != 0 || ll != 1)
239 ret = false;
240
241 if (r4 == R4_IRD)
242 pr_cont("Data/tag array parity error for a tag hit.\n");
243 else if (r4 == R4_SNOOP)
244 pr_cont("Tag error during snoop/victimization.\n");
245 else
246 ret = false;
247 }
248 return ret;
249}
250
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200251static void amd_decode_ic_mce(struct mce *m)
Borislav Petkovab5535e2009-07-28 14:06:26 +0200252{
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200253 u16 ec = m->status & 0xffff;
254 u8 xec = (m->status >> 16) & 0xf;
Borislav Petkovab5535e2009-07-28 14:06:26 +0200255
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200256 pr_emerg(HW_ERR "Instruction Cache Error: ");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200257
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200258 if (TLB_ERROR(ec))
259 pr_cont("%s TLB %s.\n", LL_MSG(ec),
260 (xec ? "multimatch" : "parity error"));
261 else if (BUS_ERROR(ec)) {
262 bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT(58)));
Borislav Petkovab5535e2009-07-28 14:06:26 +0200263
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200264 pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
265 } else if (fam_ops->ic_mce(ec))
266 ;
267 else
268 pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200269}
270
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200271static void amd_decode_bu_mce(struct mce *m)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200272{
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200273 u32 ec = m->status & 0xffff;
274 u32 xec = (m->status >> 16) & 0xf;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200275
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200276 pr_emerg(HW_ERR "Bus Unit Error");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200277
278 if (xec == 0x1)
279 pr_cont(" in the write data buffers.\n");
280 else if (xec == 0x3)
281 pr_cont(" in the victim data buffers.\n");
282 else if (xec == 0x2 && MEM_ERROR(ec))
283 pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
284 else if (xec == 0x0) {
285 if (TLB_ERROR(ec))
286 pr_cont(": %s error in a Page Descriptor Cache or "
287 "Guest TLB.\n", TT_MSG(ec));
288 else if (BUS_ERROR(ec))
289 pr_cont(": %s/ECC error in data read from NB: %s.\n",
290 RRRR_MSG(ec), PP_MSG(ec));
291 else if (MEM_ERROR(ec)) {
292 u8 rrrr = (ec >> 4) & 0xf;
293
294 if (rrrr >= 0x7)
295 pr_cont(": %s error during data copyback.\n",
296 RRRR_MSG(ec));
297 else if (rrrr <= 0x1)
298 pr_cont(": %s parity/ECC error during data "
299 "access from L2.\n", RRRR_MSG(ec));
300 else
301 goto wrong_bu_mce;
302 } else
303 goto wrong_bu_mce;
304 } else
305 goto wrong_bu_mce;
306
307 return;
308
309wrong_bu_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200310 pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200311}
312
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200313static void amd_decode_ls_mce(struct mce *m)
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200314{
Borislav Petkovded50622010-08-27 17:03:34 +0200315 u16 ec = m->status & 0xffff;
316 u8 xec = (m->status >> 16) & 0xf;
317
318 if (boot_cpu_data.x86 == 0x14) {
319 pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
320 " please report on LKML.\n");
321 return;
322 }
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200323
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200324 pr_emerg(HW_ERR "Load Store Error");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200325
326 if (xec == 0x0) {
Borislav Petkovded50622010-08-27 17:03:34 +0200327 u8 r4 = (ec >> 4) & 0xf;
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200328
Borislav Petkovded50622010-08-27 17:03:34 +0200329 if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200330 goto wrong_ls_mce;
331
332 pr_cont(" during %s.\n", RRRR_MSG(ec));
Borislav Petkovded50622010-08-27 17:03:34 +0200333 } else
334 goto wrong_ls_mce;
335
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200336 return;
337
338wrong_ls_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200339 pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200340}
341
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200342static bool k8_nb_mce(u16 ec, u8 xec)
343{
344 bool ret = true;
345
346 switch (xec) {
347 case 0x1:
348 pr_cont("CRC error detected on HT link.\n");
349 break;
350
351 case 0x5:
352 pr_cont("Invalid GART PTE entry during GART table walk.\n");
353 break;
354
355 case 0x6:
356 pr_cont("Unsupported atomic RMW received from an IO link.\n");
357 break;
358
359 case 0x0:
360 case 0x8:
361 pr_cont("DRAM ECC error detected on the NB.\n");
362 break;
363
364 case 0xd:
365 pr_cont("Parity error on the DRAM addr/ctl signals.\n");
366 break;
367
368 default:
369 ret = false;
370 break;
371 }
372
373 return ret;
374}
375
376static bool f10h_nb_mce(u16 ec, u8 xec)
377{
378 bool ret = true;
379 u8 offset = 0;
380
381 if (k8_nb_mce(ec, xec))
382 return true;
383
384 switch(xec) {
385 case 0xa ... 0xc:
386 offset = 10;
387 break;
388
389 case 0xe:
390 offset = 11;
391 break;
392
393 case 0xf:
394 if (TLB_ERROR(ec))
395 pr_cont("GART Table Walk data error.\n");
396 else if (BUS_ERROR(ec))
397 pr_cont("DMA Exclusion Vector Table Walk error.\n");
398 else
399 ret = false;
400
401 goto out;
402 break;
403
404 case 0x1c ... 0x1f:
405 offset = 24;
406 break;
407
408 default:
409 ret = false;
410
411 goto out;
412 break;
413 }
414
415 pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
416
417out:
418 return ret;
419}
420
421static bool f14h_nb_mce(u16 ec, u8 xec)
422{
423 return false;
424}
425
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200426void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
Borislav Petkov549d0422009-07-24 13:51:42 +0200427{
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200428 u8 xec = (m->status >> 16) & 0x1f;
429 u16 ec = m->status & 0xffff;
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200430 u32 nbsh = (u32)(m->status >> 32);
Borislav Petkov549d0422009-07-24 13:51:42 +0200431
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200432 pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id);
Borislav Petkov549d0422009-07-24 13:51:42 +0200433
434 /*
435 * F10h, revD can disable ErrCpu[3:0] so check that first and also the
436 * value encoding has changed so interpret those differently
437 */
438 if ((boot_cpu_data.x86 == 0x10) &&
Borislav Petkovcec79242009-10-27 19:12:02 +0100439 (boot_cpu_data.x86_model > 7)) {
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200440 if (nbsh & K8_NBSH_ERR_CPU_VAL)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200441 pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
Borislav Petkov549d0422009-07-24 13:51:42 +0200442 } else {
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200443 u8 assoc_cpus = nbsh & nb_err_cpumask;
Borislav Petkov5b89d2f2010-03-09 20:38:48 +0100444
445 if (assoc_cpus > 0)
446 pr_cont(", core: %d", fls(assoc_cpus) - 1);
Borislav Petkov549d0422009-07-24 13:51:42 +0200447 }
448
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200449 switch (xec) {
450 case 0x2:
451 pr_cont("Sync error (sync packets on HT link detected).\n");
452 return;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200453
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200454 case 0x3:
455 pr_cont("HT Master abort.\n");
456 return;
457
458 case 0x4:
459 pr_cont("HT Target abort.\n");
460 return;
461
462 case 0x7:
463 pr_cont("NB Watchdog timeout.\n");
464 return;
465
466 case 0x9:
467 pr_cont("SVM DMA Exclusion Vector error.\n");
468 return;
469
470 default:
471 break;
472 }
473
474 if (!fam_ops->nb_mce(ec, xec))
475 goto wrong_nb_mce;
476
477 if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
478 if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
479 nb_bus_decoder(node_id, m, nbcfg);
480
481 return;
482
483wrong_nb_mce:
484 pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
Borislav Petkovd93cc222009-07-28 10:56:15 +0200485}
486EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
487
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200488static void amd_decode_fr_mce(struct mce *m)
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200489{
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200490 if (boot_cpu_data.x86 == 0xf)
491 goto wrong_fr_mce;
492
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200493 /* we have only one error signature so match all fields at once. */
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200494 if ((m->status & 0xffff) == 0x0f0f) {
495 pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
496 return;
497 }
498
499wrong_fr_mce:
500 pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200501}
502
Borislav Petkov63375832010-09-06 18:13:39 +0200503static inline void amd_decode_err_code(u16 ec)
Borislav Petkovd93cc222009-07-28 10:56:15 +0200504{
Borislav Petkov549d0422009-07-24 13:51:42 +0200505 if (TLB_ERROR(ec)) {
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200506 pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200507 TT_MSG(ec), LL_MSG(ec));
508 } else if (MEM_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200509 pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200510 RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
511 } else if (BUS_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200512 pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
Borislav Petkovd93cc222009-07-28 10:56:15 +0200513 "Participating Processor: %s\n",
514 RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
515 PP_MSG(ec));
516 } else
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200517 pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
Borislav Petkov549d0422009-07-24 13:51:42 +0200518}
Borislav Petkov549d0422009-07-24 13:51:42 +0200519
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200520/*
521 * Filter out unwanted MCE signatures here.
522 */
523static bool amd_filter_mce(struct mce *m)
524{
525 u8 xec = (m->status >> 16) & 0x1f;
526
527 /*
528 * NB GART TLB error reporting is disabled by default.
529 */
530 if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
531 return true;
532
533 return false;
534}
535
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200536int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
Borislav Petkov549d0422009-07-24 13:51:42 +0200537{
Borislav Petkovfb253192009-10-07 13:20:38 +0200538 struct mce *m = (struct mce *)data;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200539 int node, ecc;
Borislav Petkov549d0422009-07-24 13:51:42 +0200540
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200541 if (amd_filter_mce(m))
542 return NOTIFY_STOP;
543
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200544 pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
Borislav Petkov549d0422009-07-24 13:51:42 +0200545
Borislav Petkov37b73702010-08-24 18:21:42 +0200546 pr_cont("%sorrected error, other errors lost: %s, "
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200547 "CPU context corrupt: %s",
548 ((m->status & MCI_STATUS_UC) ? "Unc" : "C"),
Borislav Petkov37b73702010-08-24 18:21:42 +0200549 ((m->status & MCI_STATUS_OVER) ? "yes" : "no"),
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200550 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
Borislav Petkov549d0422009-07-24 13:51:42 +0200551
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200552 /* do the two bits[14:13] together */
Borislav Petkov35d824b2010-04-30 15:19:02 +0200553 ecc = (m->status >> 45) & 0x3;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200554 if (ecc)
555 pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
556
557 pr_cont("\n");
558
Borislav Petkov51966242009-07-28 13:50:43 +0200559 switch (m->bank) {
560 case 0:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200561 amd_decode_dc_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200562 break;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200563
Borislav Petkovab5535e2009-07-28 14:06:26 +0200564 case 1:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200565 amd_decode_ic_mce(m);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200566 break;
567
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200568 case 2:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200569 amd_decode_bu_mce(m);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200570 break;
571
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200572 case 3:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200573 amd_decode_ls_mce(m);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200574 break;
575
Borislav Petkov51966242009-07-28 13:50:43 +0200576 case 4:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200577 node = amd_get_nb_id(m->extcpu);
578 amd_decode_nb_mce(node, m, 0);
Borislav Petkov51966242009-07-28 13:50:43 +0200579 break;
580
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200581 case 5:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200582 amd_decode_fr_mce(m);
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200583 break;
584
Borislav Petkov51966242009-07-28 13:50:43 +0200585 default:
586 break;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200587 }
Borislav Petkov51966242009-07-28 13:50:43 +0200588
589 amd_decode_err_code(m->status & 0xffff);
Borislav Petkovfb253192009-10-07 13:20:38 +0200590
591 return NOTIFY_STOP;
Borislav Petkov549d0422009-07-24 13:51:42 +0200592}
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200593EXPORT_SYMBOL_GPL(amd_decode_mce);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200594
Borislav Petkovfb253192009-10-07 13:20:38 +0200595static struct notifier_block amd_mce_dec_nb = {
596 .notifier_call = amd_decode_mce,
597};
598
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200599static int __init mce_amd_init(void)
600{
601 /*
Borislav Petkove045c292010-08-06 18:55:45 +0200602 * We can decode MCEs for K8, F10h and F11h CPUs:
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200603 */
Borislav Petkove045c292010-08-06 18:55:45 +0200604 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
605 return 0;
606
607 if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
608 return 0;
609
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200610 fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
611 if (!fam_ops)
612 return -ENOMEM;
613
614 switch (boot_cpu_data.x86) {
615 case 0xf:
616 fam_ops->dc_mce = k8_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200617 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200618 fam_ops->nb_mce = k8_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200619 break;
620
621 case 0x10:
622 fam_ops->dc_mce = f10h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200623 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200624 fam_ops->nb_mce = f10h_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200625 break;
626
627 case 0x14:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200628 nb_err_cpumask = 0x3;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200629 fam_ops->dc_mce = f14h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200630 fam_ops->ic_mce = f14h_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200631 fam_ops->nb_mce = f14h_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200632 break;
633
634 default:
635 printk(KERN_WARNING "Huh? What family is that: %d?!\n",
636 boot_cpu_data.x86);
637 kfree(fam_ops);
638 return -EINVAL;
639 }
640
Borislav Petkove045c292010-08-06 18:55:45 +0200641 atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200642
643 return 0;
644}
645early_initcall(mce_amd_init);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200646
647#ifdef MODULE
648static void __exit mce_amd_exit(void)
649{
Borislav Petkovfb253192009-10-07 13:20:38 +0200650 atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200651 kfree(fam_ops);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200652}
653
654MODULE_DESCRIPTION("AMD MCE decoder");
655MODULE_ALIAS("edac-mce-amd");
656MODULE_LICENSE("GPL");
657module_exit(mce_amd_exit);
658#endif