blob: 12bae3b18e3dd912a7c6d738faa067ab76d2fd0b [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 Petkov25a4f8b2010-09-17 19:22:34 +020078static bool f12h_dc_mce(u16 ec, u8 xec)
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 Petkov25a4f8b2010-09-17 19:22:34 +020096static bool f10h_dc_mce(u16 ec, u8 xec)
Borislav Petkov9be0bb12010-09-16 15:08:14 +020097{
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 }
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200105 return f12h_dc_mce(ec, xec);
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200106}
107
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200108static bool k8_dc_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200109{
110 if (BUS_ERROR(ec)) {
111 pr_cont("during system linefill.\n");
112 return true;
113 }
114
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200115 return f10h_dc_mce(ec, xec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200116}
117
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200118static bool f14h_dc_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200119{
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 Petkov25a4f8b2010-09-17 19:22:34 +0200173static bool f15h_dc_mce(u16 ec, u8 xec)
174{
175 bool ret = true;
176
177 if (MEM_ERROR(ec)) {
178
179 switch (xec) {
180 case 0x0:
181 pr_cont("Data Array access error.\n");
182 break;
183
184 case 0x1:
185 pr_cont("UC error during a linefill from L2/NB.\n");
186 break;
187
188 case 0x2:
189 case 0x11:
190 pr_cont("STQ access error.\n");
191 break;
192
193 case 0x3:
194 pr_cont("SCB access error.\n");
195 break;
196
197 case 0x10:
198 pr_cont("Tag error.\n");
199 break;
200
201 case 0x12:
202 pr_cont("LDQ access error.\n");
203 break;
204
205 default:
206 ret = false;
207 }
208 } else if (BUS_ERROR(ec)) {
209
210 if (!xec)
211 pr_cont("during system linefill.\n");
212 else
213 pr_cont(" Internal %s condition.\n",
214 ((xec == 1) ? "livelock" : "deadlock"));
215 } else
216 ret = false;
217
218 return ret;
219}
220
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200221static void amd_decode_dc_mce(struct mce *m)
Borislav Petkov51966242009-07-28 13:50:43 +0200222{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200223 u16 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200224 u8 xec = (m->status >> 16) & xec_mask;
Borislav Petkov51966242009-07-28 13:50:43 +0200225
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200226 pr_emerg(HW_ERR "Data Cache Error: ");
Borislav Petkov51966242009-07-28 13:50:43 +0200227
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200228 /* TLB error signatures are the same across families */
229 if (TLB_ERROR(ec)) {
230 u8 tt = (ec >> 2) & 0x3;
Borislav Petkov51966242009-07-28 13:50:43 +0200231
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200232 if (tt == TT_DATA) {
233 pr_cont("%s TLB %s.\n", LL_MSG(ec),
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200234 ((xec == 2) ? "locked miss"
235 : (xec ? "multimatch" : "parity")));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200236 return;
237 }
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200238 } else if (fam_ops->dc_mce(ec, xec))
239 ;
240 else
241 pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
Borislav Petkov51966242009-07-28 13:50:43 +0200242}
243
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200244static bool k8_ic_mce(u16 ec)
245{
246 u8 ll = ec & 0x3;
247 u8 r4 = (ec >> 4) & 0xf;
248 bool ret = true;
249
250 if (!MEM_ERROR(ec))
251 return false;
252
253 if (ll == 0x2)
254 pr_cont("during a linefill from L2.\n");
255 else if (ll == 0x1) {
256 switch (r4) {
257 case R4_IRD:
258 pr_cont("Parity error during data load.\n");
259 break;
260
261 case R4_EVICT:
262 pr_cont("Copyback Parity/Victim error.\n");
263 break;
264
265 case R4_SNOOP:
266 pr_cont("Tag Snoop error.\n");
267 break;
268
269 default:
270 ret = false;
271 break;
272 }
273 } else
274 ret = false;
275
276 return ret;
277}
278
279static bool f14h_ic_mce(u16 ec)
280{
281 u8 ll = ec & 0x3;
282 u8 tt = (ec >> 2) & 0x3;
283 u8 r4 = (ec >> 4) & 0xf;
284 bool ret = true;
285
286 if (MEM_ERROR(ec)) {
287 if (tt != 0 || ll != 1)
288 ret = false;
289
290 if (r4 == R4_IRD)
291 pr_cont("Data/tag array parity error for a tag hit.\n");
292 else if (r4 == R4_SNOOP)
293 pr_cont("Tag error during snoop/victimization.\n");
294 else
295 ret = false;
296 }
297 return ret;
298}
299
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200300static void amd_decode_ic_mce(struct mce *m)
Borislav Petkovab5535e2009-07-28 14:06:26 +0200301{
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200302 u16 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200303 u8 xec = (m->status >> 16) & xec_mask;
Borislav Petkovab5535e2009-07-28 14:06:26 +0200304
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200305 pr_emerg(HW_ERR "Instruction Cache Error: ");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200306
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200307 if (TLB_ERROR(ec))
308 pr_cont("%s TLB %s.\n", LL_MSG(ec),
309 (xec ? "multimatch" : "parity error"));
310 else if (BUS_ERROR(ec)) {
Borislav Petkov525906b2010-10-15 15:27:02 +0200311 bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
Borislav Petkovab5535e2009-07-28 14:06:26 +0200312
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200313 pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
314 } else if (fam_ops->ic_mce(ec))
315 ;
316 else
317 pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200318}
319
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200320static void amd_decode_bu_mce(struct mce *m)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200321{
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200322 u32 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200323 u32 xec = (m->status >> 16) & xec_mask;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200324
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200325 pr_emerg(HW_ERR "Bus Unit Error");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200326
327 if (xec == 0x1)
328 pr_cont(" in the write data buffers.\n");
329 else if (xec == 0x3)
330 pr_cont(" in the victim data buffers.\n");
331 else if (xec == 0x2 && MEM_ERROR(ec))
332 pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
333 else if (xec == 0x0) {
334 if (TLB_ERROR(ec))
335 pr_cont(": %s error in a Page Descriptor Cache or "
336 "Guest TLB.\n", TT_MSG(ec));
337 else if (BUS_ERROR(ec))
338 pr_cont(": %s/ECC error in data read from NB: %s.\n",
339 RRRR_MSG(ec), PP_MSG(ec));
340 else if (MEM_ERROR(ec)) {
341 u8 rrrr = (ec >> 4) & 0xf;
342
343 if (rrrr >= 0x7)
344 pr_cont(": %s error during data copyback.\n",
345 RRRR_MSG(ec));
346 else if (rrrr <= 0x1)
347 pr_cont(": %s parity/ECC error during data "
348 "access from L2.\n", RRRR_MSG(ec));
349 else
350 goto wrong_bu_mce;
351 } else
352 goto wrong_bu_mce;
353 } else
354 goto wrong_bu_mce;
355
356 return;
357
358wrong_bu_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200359 pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200360}
361
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200362static void amd_decode_ls_mce(struct mce *m)
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200363{
Borislav Petkovded50622010-08-27 17:03:34 +0200364 u16 ec = m->status & 0xffff;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200365 u8 xec = (m->status >> 16) & xec_mask;
Borislav Petkovded50622010-08-27 17:03:34 +0200366
367 if (boot_cpu_data.x86 == 0x14) {
368 pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
369 " please report on LKML.\n");
370 return;
371 }
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200372
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200373 pr_emerg(HW_ERR "Load Store Error");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200374
375 if (xec == 0x0) {
Borislav Petkovded50622010-08-27 17:03:34 +0200376 u8 r4 = (ec >> 4) & 0xf;
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200377
Borislav Petkovded50622010-08-27 17:03:34 +0200378 if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200379 goto wrong_ls_mce;
380
381 pr_cont(" during %s.\n", RRRR_MSG(ec));
Borislav Petkovded50622010-08-27 17:03:34 +0200382 } else
383 goto wrong_ls_mce;
384
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200385 return;
386
387wrong_ls_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200388 pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200389}
390
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200391static bool k8_nb_mce(u16 ec, u8 xec)
392{
393 bool ret = true;
394
395 switch (xec) {
396 case 0x1:
397 pr_cont("CRC error detected on HT link.\n");
398 break;
399
400 case 0x5:
401 pr_cont("Invalid GART PTE entry during GART table walk.\n");
402 break;
403
404 case 0x6:
405 pr_cont("Unsupported atomic RMW received from an IO link.\n");
406 break;
407
408 case 0x0:
409 case 0x8:
Borislav Petkovf0157b32010-10-05 19:07:16 +0200410 if (boot_cpu_data.x86 == 0x11)
411 return false;
412
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200413 pr_cont("DRAM ECC error detected on the NB.\n");
414 break;
415
416 case 0xd:
417 pr_cont("Parity error on the DRAM addr/ctl signals.\n");
418 break;
419
420 default:
421 ret = false;
422 break;
423 }
424
425 return ret;
426}
427
428static bool f10h_nb_mce(u16 ec, u8 xec)
429{
430 bool ret = true;
431 u8 offset = 0;
432
433 if (k8_nb_mce(ec, xec))
434 return true;
435
436 switch(xec) {
437 case 0xa ... 0xc:
438 offset = 10;
439 break;
440
441 case 0xe:
442 offset = 11;
443 break;
444
445 case 0xf:
446 if (TLB_ERROR(ec))
447 pr_cont("GART Table Walk data error.\n");
448 else if (BUS_ERROR(ec))
449 pr_cont("DMA Exclusion Vector Table Walk error.\n");
450 else
451 ret = false;
452
453 goto out;
454 break;
455
456 case 0x1c ... 0x1f:
457 offset = 24;
458 break;
459
460 default:
461 ret = false;
462
463 goto out;
464 break;
465 }
466
467 pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
468
469out:
470 return ret;
471}
472
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200473static bool nb_noop_mce(u16 ec, u8 xec)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200474{
475 return false;
476}
477
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200478void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
Borislav Petkov549d0422009-07-24 13:51:42 +0200479{
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200480 u8 xec = (m->status >> 16) & 0x1f;
481 u16 ec = m->status & 0xffff;
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200482 u32 nbsh = (u32)(m->status >> 32);
Borislav Petkov549d0422009-07-24 13:51:42 +0200483
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200484 pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id);
Borislav Petkov549d0422009-07-24 13:51:42 +0200485
486 /*
487 * F10h, revD can disable ErrCpu[3:0] so check that first and also the
488 * value encoding has changed so interpret those differently
489 */
490 if ((boot_cpu_data.x86 == 0x10) &&
Borislav Petkovcec79242009-10-27 19:12:02 +0100491 (boot_cpu_data.x86_model > 7)) {
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200492 if (nbsh & K8_NBSH_ERR_CPU_VAL)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200493 pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
Borislav Petkov549d0422009-07-24 13:51:42 +0200494 } else {
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200495 u8 assoc_cpus = nbsh & nb_err_cpumask;
Borislav Petkov5b89d2f2010-03-09 20:38:48 +0100496
497 if (assoc_cpus > 0)
498 pr_cont(", core: %d", fls(assoc_cpus) - 1);
Borislav Petkov549d0422009-07-24 13:51:42 +0200499 }
500
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200501 switch (xec) {
502 case 0x2:
503 pr_cont("Sync error (sync packets on HT link detected).\n");
504 return;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200505
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200506 case 0x3:
507 pr_cont("HT Master abort.\n");
508 return;
509
510 case 0x4:
511 pr_cont("HT Target abort.\n");
512 return;
513
514 case 0x7:
515 pr_cont("NB Watchdog timeout.\n");
516 return;
517
518 case 0x9:
519 pr_cont("SVM DMA Exclusion Vector error.\n");
520 return;
521
522 default:
523 break;
524 }
525
526 if (!fam_ops->nb_mce(ec, xec))
527 goto wrong_nb_mce;
528
529 if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
530 if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
531 nb_bus_decoder(node_id, m, nbcfg);
532
533 return;
534
535wrong_nb_mce:
536 pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
Borislav Petkovd93cc222009-07-28 10:56:15 +0200537}
538EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
539
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200540static void amd_decode_fr_mce(struct mce *m)
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200541{
Borislav Petkovf0157b32010-10-05 19:07:16 +0200542 if (boot_cpu_data.x86 == 0xf ||
543 boot_cpu_data.x86 == 0x11)
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200544 goto wrong_fr_mce;
545
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200546 /* we have only one error signature so match all fields at once. */
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200547 if ((m->status & 0xffff) == 0x0f0f) {
548 pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
549 return;
550 }
551
552wrong_fr_mce:
553 pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200554}
555
Borislav Petkov63375832010-09-06 18:13:39 +0200556static inline void amd_decode_err_code(u16 ec)
Borislav Petkovd93cc222009-07-28 10:56:15 +0200557{
Borislav Petkov549d0422009-07-24 13:51:42 +0200558 if (TLB_ERROR(ec)) {
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200559 pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200560 TT_MSG(ec), LL_MSG(ec));
561 } else if (MEM_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200562 pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
Borislav Petkov549d0422009-07-24 13:51:42 +0200563 RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
564 } else if (BUS_ERROR(ec)) {
Borislav Petkov63375832010-09-06 18:13:39 +0200565 pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
Borislav Petkovd93cc222009-07-28 10:56:15 +0200566 "Participating Processor: %s\n",
567 RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
568 PP_MSG(ec));
569 } else
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200570 pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
Borislav Petkov549d0422009-07-24 13:51:42 +0200571}
Borislav Petkov549d0422009-07-24 13:51:42 +0200572
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200573/*
574 * Filter out unwanted MCE signatures here.
575 */
576static bool amd_filter_mce(struct mce *m)
577{
578 u8 xec = (m->status >> 16) & 0x1f;
579
580 /*
581 * NB GART TLB error reporting is disabled by default.
582 */
583 if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
584 return true;
585
586 return false;
587}
588
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200589int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
Borislav Petkov549d0422009-07-24 13:51:42 +0200590{
Borislav Petkovfb253192009-10-07 13:20:38 +0200591 struct mce *m = (struct mce *)data;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200592 int node, ecc;
Borislav Petkov549d0422009-07-24 13:51:42 +0200593
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200594 if (amd_filter_mce(m))
595 return NOTIFY_STOP;
596
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200597 pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
Borislav Petkov549d0422009-07-24 13:51:42 +0200598
Borislav Petkov37b73702010-08-24 18:21:42 +0200599 pr_cont("%sorrected error, other errors lost: %s, "
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200600 "CPU context corrupt: %s",
601 ((m->status & MCI_STATUS_UC) ? "Unc" : "C"),
Borislav Petkov37b73702010-08-24 18:21:42 +0200602 ((m->status & MCI_STATUS_OVER) ? "yes" : "no"),
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200603 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
Borislav Petkov549d0422009-07-24 13:51:42 +0200604
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200605 /* do the two bits[14:13] together */
Borislav Petkov35d824b2010-04-30 15:19:02 +0200606 ecc = (m->status >> 45) & 0x3;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200607 if (ecc)
608 pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
609
610 pr_cont("\n");
611
Borislav Petkov51966242009-07-28 13:50:43 +0200612 switch (m->bank) {
613 case 0:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200614 amd_decode_dc_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200615 break;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200616
Borislav Petkovab5535e2009-07-28 14:06:26 +0200617 case 1:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200618 amd_decode_ic_mce(m);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200619 break;
620
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200621 case 2:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200622 amd_decode_bu_mce(m);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200623 break;
624
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200625 case 3:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200626 amd_decode_ls_mce(m);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200627 break;
628
Borislav Petkov51966242009-07-28 13:50:43 +0200629 case 4:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200630 node = amd_get_nb_id(m->extcpu);
631 amd_decode_nb_mce(node, m, 0);
Borislav Petkov51966242009-07-28 13:50:43 +0200632 break;
633
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200634 case 5:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200635 amd_decode_fr_mce(m);
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200636 break;
637
Borislav Petkov51966242009-07-28 13:50:43 +0200638 default:
639 break;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200640 }
Borislav Petkov51966242009-07-28 13:50:43 +0200641
642 amd_decode_err_code(m->status & 0xffff);
Borislav Petkovfb253192009-10-07 13:20:38 +0200643
644 return NOTIFY_STOP;
Borislav Petkov549d0422009-07-24 13:51:42 +0200645}
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200646EXPORT_SYMBOL_GPL(amd_decode_mce);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200647
Borislav Petkovfb253192009-10-07 13:20:38 +0200648static struct notifier_block amd_mce_dec_nb = {
649 .notifier_call = amd_decode_mce,
650};
651
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200652static int __init mce_amd_init(void)
653{
Borislav Petkove045c292010-08-06 18:55:45 +0200654 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
655 return 0;
656
Borislav Petkovfda75612010-09-22 16:12:03 +0200657 if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) &&
Borislav Petkov9530d602010-09-06 15:05:45 +0200658 (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf))
Borislav Petkove045c292010-08-06 18:55:45 +0200659 return 0;
660
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200661 fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
662 if (!fam_ops)
663 return -ENOMEM;
664
665 switch (boot_cpu_data.x86) {
666 case 0xf:
667 fam_ops->dc_mce = k8_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200668 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200669 fam_ops->nb_mce = k8_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200670 break;
671
672 case 0x10:
673 fam_ops->dc_mce = f10h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200674 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200675 fam_ops->nb_mce = f10h_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200676 break;
677
Borislav Petkovf0157b32010-10-05 19:07:16 +0200678 case 0x11:
679 fam_ops->dc_mce = k8_dc_mce;
680 fam_ops->ic_mce = k8_ic_mce;
681 fam_ops->nb_mce = f10h_nb_mce;
682 break;
683
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200684 case 0x12:
685 fam_ops->dc_mce = f12h_dc_mce;
Borislav Petkove7281eb2010-09-16 16:45:22 +0200686 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200687 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200688 break;
689
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200690 case 0x14:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200691 nb_err_cpumask = 0x3;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200692 fam_ops->dc_mce = f14h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200693 fam_ops->ic_mce = f14h_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200694 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200695 break;
696
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200697 case 0x15:
698 xec_mask = 0x1f;
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200699 fam_ops->dc_mce = f15h_dc_mce;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200700 break;
701
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200702 default:
703 printk(KERN_WARNING "Huh? What family is that: %d?!\n",
704 boot_cpu_data.x86);
705 kfree(fam_ops);
706 return -EINVAL;
707 }
708
Borislav Petkov9530d602010-09-06 15:05:45 +0200709 pr_info("MCE: In-kernel MCE decoding enabled.\n");
710
Borislav Petkove045c292010-08-06 18:55:45 +0200711 atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200712
713 return 0;
714}
715early_initcall(mce_amd_init);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200716
717#ifdef MODULE
718static void __exit mce_amd_exit(void)
719{
Borislav Petkovfb253192009-10-07 13:20:38 +0200720 atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200721 kfree(fam_ops);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200722}
723
724MODULE_DESCRIPTION("AMD MCE decoder");
725MODULE_ALIAS("edac-mce-amd");
726MODULE_LICENSE("GPL");
727module_exit(mce_amd_exit);
728#endif