blob: 795cfbc0bf50ff39b3f3911b6596d3353f90d4ef [file] [log] [blame]
Borislav Petkovb70ef012009-06-25 19:32:38 +02001#include <linux/module.h>
Borislav Petkov888ab8e2010-08-18 15:11:35 +02002#include <linux/slab.h>
3
Borislav Petkov47ca08a2010-09-27 15:30:39 +02004#include "mce_amd.h"
Doug Thompsonb52401ce2009-05-06 17:57:20 +02005
Borislav Petkov888ab8e2010-08-18 15:11:35 +02006static struct amd_decoder_ops *fam_ops;
7
Borislav Petkov2be64bf2010-09-17 19:11:47 +02008static u8 xec_mask = 0xf;
Borislav Petkov5ce88f62010-08-31 18:28:08 +02009static u8 nb_err_cpumask = 0xf;
10
Borislav Petkov549d0422009-07-24 13:51:42 +020011static bool report_gart_errors;
Borislav Petkov7cfd4a82010-09-01 14:45:20 +020012static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
Borislav Petkov549d0422009-07-24 13:51:42 +020013
14void amd_report_gart_errors(bool v)
15{
16 report_gart_errors = v;
17}
18EXPORT_SYMBOL_GPL(amd_report_gart_errors);
19
Borislav Petkov7cfd4a82010-09-01 14:45:20 +020020void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
Borislav Petkov549d0422009-07-24 13:51:42 +020021{
22 nb_bus_decoder = f;
23}
24EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
25
Borislav Petkov7cfd4a82010-09-01 14:45:20 +020026void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
Borislav Petkov549d0422009-07-24 13:51:42 +020027{
28 if (nb_bus_decoder) {
29 WARN_ON(nb_bus_decoder != f);
30
31 nb_bus_decoder = NULL;
32 }
33}
34EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
35
Doug Thompsonb52401ce2009-05-06 17:57:20 +020036/*
37 * string representation for the different MCA reported error types, see F3x48
38 * or MSR0000_0411.
39 */
Borislav Petkov63375832010-09-06 18:13:39 +020040
41/* transaction type */
42const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020043EXPORT_SYMBOL_GPL(tt_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020044
Borislav Petkov63375832010-09-06 18:13:39 +020045/* cache level */
46const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020047EXPORT_SYMBOL_GPL(ll_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020048
Borislav Petkov63375832010-09-06 18:13:39 +020049/* memory transaction type */
Doug Thompsonb52401ce2009-05-06 17:57:20 +020050const char *rrrr_msgs[] = {
Borislav Petkov63375832010-09-06 18:13:39 +020051 "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
Doug Thompsonb52401ce2009-05-06 17:57:20 +020052};
Borislav Petkovb70ef012009-06-25 19:32:38 +020053EXPORT_SYMBOL_GPL(rrrr_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020054
Borislav Petkov63375832010-09-06 18:13:39 +020055/* participating processor */
56const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020057EXPORT_SYMBOL_GPL(pp_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020058
Borislav Petkov63375832010-09-06 18:13:39 +020059/* request timeout */
60const char *to_msgs[] = { "no timeout", "timed out" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020061EXPORT_SYMBOL_GPL(to_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020062
Borislav Petkov63375832010-09-06 18:13:39 +020063/* memory or i/o */
64const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020065EXPORT_SYMBOL_GPL(ii_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020066
Borislav Petkov5ce88f62010-08-31 18:28:08 +020067static const char *f10h_nb_mce_desc[] = {
68 "HT link data error",
69 "Protocol error (link, L3, probe filter, etc.)",
70 "Parity error in NB-internal arrays",
71 "Link Retry due to IO link transmission error",
72 "L3 ECC data cache error",
73 "ECC error in L3 cache tag",
74 "L3 LRU parity bits error",
75 "ECC Error in the Probe Filter directory"
Doug Thompsonb52401ce2009-05-06 17:57:20 +020076};
Borislav Petkov549d0422009-07-24 13:51:42 +020077
Borislav Petkov86039cd2010-11-08 15:03:35 +010078static const char * const f15h_ic_mce_desc[] = {
79 "UC during a demand linefill from L2",
80 "Parity error during data load from IC",
81 "Parity error for IC valid bit",
82 "Main tag parity error",
83 "Parity error in prediction queue",
84 "PFB data/address parity error",
85 "Parity error in the branch status reg",
86 "PFB promotion address error",
87 "Tag error during probe/victimization",
88 "Parity error for IC probe tag valid bit",
89 "PFB non-cacheable bit parity error",
90 "PFB valid bit parity error", /* xec = 0xd */
91 "patch RAM", /* xec = 010 */
92 "uop queue",
93 "insn buffer",
94 "predecode buffer",
95 "fetch address FIFO"
96};
97
Borislav Petkov70fdb492010-09-21 20:45:10 +020098static const char * const f15h_cu_mce_desc[] = {
99 "Fill ECC error on data fills", /* xec = 0x4 */
100 "Fill parity error on insn fills",
101 "Prefetcher request FIFO parity error",
102 "PRQ address parity error",
103 "PRQ data parity error",
104 "WCC Tag ECC error",
105 "WCC Data ECC error",
106 "WCB Data parity error",
107 "VB Data/ECC error",
108 "L2 Tag ECC error", /* xec = 0x10 */
109 "Hard L2 Tag ECC error",
110 "Multiple hits on L2 tag",
111 "XAB parity error",
112 "PRB address parity error"
113};
114
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200115static const char * const fr_ex_mce_desc[] = {
116 "CPU Watchdog timer expire",
117 "Wakeup array dest tag",
118 "AG payload array",
119 "EX payload array",
120 "IDRF array",
121 "Retire dispatch queue",
122 "Mapper checkpoint array",
123 "Physical register file EX0 port",
124 "Physical register file EX1 port",
125 "Physical register file AG0 port",
126 "Physical register file AG1 port",
127 "Flag register file",
128 "DE correctable error could not be corrected"
129};
130
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200131static bool f12h_dc_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200132{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200133 bool ret = false;
134
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200135 if (MEM_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200136 u8 ll = LL(ec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200137 ret = true;
138
139 if (ll == LL_L2)
140 pr_cont("during L1 linefill from L2.\n");
141 else if (ll == LL_L1)
Borislav Petkov62452882010-09-22 16:08:37 +0200142 pr_cont("Data/Tag %s error.\n", R4_MSG(ec));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200143 else
144 ret = false;
145 }
146 return ret;
147}
148
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200149static bool f10h_dc_mce(u16 ec, u8 xec)
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200150{
Borislav Petkov62452882010-09-22 16:08:37 +0200151 if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200152 pr_cont("during data scrub.\n");
153 return true;
154 }
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200155 return f12h_dc_mce(ec, xec);
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200156}
157
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200158static bool k8_dc_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200159{
160 if (BUS_ERROR(ec)) {
161 pr_cont("during system linefill.\n");
162 return true;
163 }
164
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200165 return f10h_dc_mce(ec, xec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200166}
167
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200168static bool f14h_dc_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200169{
Borislav Petkov62452882010-09-22 16:08:37 +0200170 u8 r4 = R4(ec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200171 bool ret = true;
172
173 if (MEM_ERROR(ec)) {
174
Borislav Petkov62452882010-09-22 16:08:37 +0200175 if (TT(ec) != TT_DATA || LL(ec) != LL_L1)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200176 return false;
177
178 switch (r4) {
179 case R4_DRD:
180 case R4_DWR:
181 pr_cont("Data/Tag parity error due to %s.\n",
182 (r4 == R4_DRD ? "load/hw prf" : "store"));
183 break;
184 case R4_EVICT:
185 pr_cont("Copyback parity error on a tag miss.\n");
186 break;
187 case R4_SNOOP:
188 pr_cont("Tag parity error during snoop.\n");
189 break;
190 default:
191 ret = false;
192 }
193 } else if (BUS_ERROR(ec)) {
194
Borislav Petkov62452882010-09-22 16:08:37 +0200195 if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200196 return false;
197
198 pr_cont("System read data error on a ");
199
200 switch (r4) {
201 case R4_RD:
202 pr_cont("TLB reload.\n");
203 break;
204 case R4_DWR:
205 pr_cont("store.\n");
206 break;
207 case R4_DRD:
208 pr_cont("load.\n");
209 break;
210 default:
211 ret = false;
212 }
213 } else {
214 ret = false;
215 }
216
217 return ret;
218}
219
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200220static bool f15h_dc_mce(u16 ec, u8 xec)
221{
222 bool ret = true;
223
224 if (MEM_ERROR(ec)) {
225
226 switch (xec) {
227 case 0x0:
228 pr_cont("Data Array access error.\n");
229 break;
230
231 case 0x1:
232 pr_cont("UC error during a linefill from L2/NB.\n");
233 break;
234
235 case 0x2:
236 case 0x11:
237 pr_cont("STQ access error.\n");
238 break;
239
240 case 0x3:
241 pr_cont("SCB access error.\n");
242 break;
243
244 case 0x10:
245 pr_cont("Tag error.\n");
246 break;
247
248 case 0x12:
249 pr_cont("LDQ access error.\n");
250 break;
251
252 default:
253 ret = false;
254 }
255 } else if (BUS_ERROR(ec)) {
256
257 if (!xec)
258 pr_cont("during system linefill.\n");
259 else
260 pr_cont(" Internal %s condition.\n",
261 ((xec == 1) ? "livelock" : "deadlock"));
262 } else
263 ret = false;
264
265 return ret;
266}
267
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200268static void amd_decode_dc_mce(struct mce *m)
Borislav Petkov51966242009-07-28 13:50:43 +0200269{
Borislav Petkov62452882010-09-22 16:08:37 +0200270 u16 ec = EC(m->status);
271 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov51966242009-07-28 13:50:43 +0200272
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200273 pr_emerg(HW_ERR "Data Cache Error: ");
Borislav Petkov51966242009-07-28 13:50:43 +0200274
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200275 /* TLB error signatures are the same across families */
276 if (TLB_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200277 if (TT(ec) == TT_DATA) {
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200278 pr_cont("%s TLB %s.\n", LL_MSG(ec),
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200279 ((xec == 2) ? "locked miss"
280 : (xec ? "multimatch" : "parity")));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200281 return;
282 }
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200283 } else if (fam_ops->dc_mce(ec, xec))
284 ;
285 else
286 pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
Borislav Petkov51966242009-07-28 13:50:43 +0200287}
288
Borislav Petkov86039cd2010-11-08 15:03:35 +0100289static bool k8_ic_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200290{
Borislav Petkov62452882010-09-22 16:08:37 +0200291 u8 ll = LL(ec);
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200292 bool ret = true;
293
294 if (!MEM_ERROR(ec))
295 return false;
296
297 if (ll == 0x2)
298 pr_cont("during a linefill from L2.\n");
299 else if (ll == 0x1) {
Borislav Petkov62452882010-09-22 16:08:37 +0200300 switch (R4(ec)) {
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200301 case R4_IRD:
302 pr_cont("Parity error during data load.\n");
303 break;
304
305 case R4_EVICT:
306 pr_cont("Copyback Parity/Victim error.\n");
307 break;
308
309 case R4_SNOOP:
310 pr_cont("Tag Snoop error.\n");
311 break;
312
313 default:
314 ret = false;
315 break;
316 }
317 } else
318 ret = false;
319
320 return ret;
321}
322
Borislav Petkov86039cd2010-11-08 15:03:35 +0100323static bool f14h_ic_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200324{
Borislav Petkov62452882010-09-22 16:08:37 +0200325 u8 r4 = R4(ec);
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200326 bool ret = true;
327
328 if (MEM_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200329 if (TT(ec) != 0 || LL(ec) != 1)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200330 ret = false;
331
332 if (r4 == R4_IRD)
333 pr_cont("Data/tag array parity error for a tag hit.\n");
334 else if (r4 == R4_SNOOP)
335 pr_cont("Tag error during snoop/victimization.\n");
336 else
337 ret = false;
338 }
339 return ret;
340}
341
Borislav Petkov86039cd2010-11-08 15:03:35 +0100342static bool f15h_ic_mce(u16 ec, u8 xec)
343{
344 bool ret = true;
345
346 if (!MEM_ERROR(ec))
347 return false;
348
349 switch (xec) {
350 case 0x0 ... 0xa:
351 pr_cont("%s.\n", f15h_ic_mce_desc[xec]);
352 break;
353
354 case 0xd:
355 pr_cont("%s.\n", f15h_ic_mce_desc[xec-2]);
356 break;
357
358 case 0x10 ... 0x14:
359 pr_cont("Decoder %s parity error.\n", f15h_ic_mce_desc[xec-4]);
360 break;
361
362 default:
363 ret = false;
364 }
365 return ret;
366}
367
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200368static void amd_decode_ic_mce(struct mce *m)
Borislav Petkovab5535e2009-07-28 14:06:26 +0200369{
Borislav Petkov62452882010-09-22 16:08:37 +0200370 u16 ec = EC(m->status);
371 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200372
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200373 pr_emerg(HW_ERR "Instruction Cache Error: ");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200374
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200375 if (TLB_ERROR(ec))
376 pr_cont("%s TLB %s.\n", LL_MSG(ec),
377 (xec ? "multimatch" : "parity error"));
378 else if (BUS_ERROR(ec)) {
Borislav Petkov525906b2010-10-15 15:27:02 +0200379 bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
Borislav Petkovab5535e2009-07-28 14:06:26 +0200380
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200381 pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
Borislav Petkov86039cd2010-11-08 15:03:35 +0100382 } else if (fam_ops->ic_mce(ec, xec))
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200383 ;
384 else
385 pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200386}
387
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200388static void amd_decode_bu_mce(struct mce *m)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200389{
Borislav Petkov62452882010-09-22 16:08:37 +0200390 u16 ec = EC(m->status);
391 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200392
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200393 pr_emerg(HW_ERR "Bus Unit Error");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200394
395 if (xec == 0x1)
396 pr_cont(" in the write data buffers.\n");
397 else if (xec == 0x3)
398 pr_cont(" in the victim data buffers.\n");
399 else if (xec == 0x2 && MEM_ERROR(ec))
Borislav Petkov62452882010-09-22 16:08:37 +0200400 pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200401 else if (xec == 0x0) {
402 if (TLB_ERROR(ec))
403 pr_cont(": %s error in a Page Descriptor Cache or "
404 "Guest TLB.\n", TT_MSG(ec));
405 else if (BUS_ERROR(ec))
406 pr_cont(": %s/ECC error in data read from NB: %s.\n",
Borislav Petkov62452882010-09-22 16:08:37 +0200407 R4_MSG(ec), PP_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200408 else if (MEM_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200409 u8 r4 = R4(ec);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200410
Borislav Petkov62452882010-09-22 16:08:37 +0200411 if (r4 >= 0x7)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200412 pr_cont(": %s error during data copyback.\n",
Borislav Petkov62452882010-09-22 16:08:37 +0200413 R4_MSG(ec));
414 else if (r4 <= 0x1)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200415 pr_cont(": %s parity/ECC error during data "
Borislav Petkov62452882010-09-22 16:08:37 +0200416 "access from L2.\n", R4_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200417 else
418 goto wrong_bu_mce;
419 } else
420 goto wrong_bu_mce;
421 } else
422 goto wrong_bu_mce;
423
424 return;
425
426wrong_bu_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200427 pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200428}
429
Borislav Petkov70fdb492010-09-21 20:45:10 +0200430static void amd_decode_cu_mce(struct mce *m)
431{
Borislav Petkov62452882010-09-22 16:08:37 +0200432 u16 ec = EC(m->status);
433 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov70fdb492010-09-21 20:45:10 +0200434
435 pr_emerg(HW_ERR "Combined Unit Error: ");
436
437 if (TLB_ERROR(ec)) {
438 if (xec == 0x0)
439 pr_cont("Data parity TLB read error.\n");
440 else if (xec == 0x1)
441 pr_cont("Poison data provided for TLB fill.\n");
442 else
443 goto wrong_cu_mce;
444 } else if (BUS_ERROR(ec)) {
445 if (xec > 2)
446 goto wrong_cu_mce;
447
448 pr_cont("Error during attempted NB data read.\n");
449 } else if (MEM_ERROR(ec)) {
450 switch (xec) {
451 case 0x4 ... 0xc:
452 pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x4]);
453 break;
454
455 case 0x10 ... 0x14:
456 pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x7]);
457 break;
458
459 default:
460 goto wrong_cu_mce;
461 }
462 }
463
464 return;
465
466wrong_cu_mce:
467 pr_emerg(HW_ERR "Corrupted CU MCE info?\n");
468}
469
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200470static void amd_decode_ls_mce(struct mce *m)
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200471{
Borislav Petkov62452882010-09-22 16:08:37 +0200472 u16 ec = EC(m->status);
473 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovded50622010-08-27 17:03:34 +0200474
Borislav Petkovb18434c2010-09-22 11:53:32 +0200475 if (boot_cpu_data.x86 >= 0x14) {
Borislav Petkovded50622010-08-27 17:03:34 +0200476 pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
477 " please report on LKML.\n");
478 return;
479 }
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200480
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200481 pr_emerg(HW_ERR "Load Store Error");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200482
483 if (xec == 0x0) {
Borislav Petkov62452882010-09-22 16:08:37 +0200484 u8 r4 = R4(ec);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200485
Borislav Petkovded50622010-08-27 17:03:34 +0200486 if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200487 goto wrong_ls_mce;
488
Borislav Petkov62452882010-09-22 16:08:37 +0200489 pr_cont(" during %s.\n", R4_MSG(ec));
Borislav Petkovded50622010-08-27 17:03:34 +0200490 } else
491 goto wrong_ls_mce;
492
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200493 return;
494
495wrong_ls_mce:
Borislav Petkovc9f281f2010-08-18 18:21:42 +0200496 pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200497}
498
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200499static bool k8_nb_mce(u16 ec, u8 xec)
500{
501 bool ret = true;
502
503 switch (xec) {
504 case 0x1:
505 pr_cont("CRC error detected on HT link.\n");
506 break;
507
508 case 0x5:
509 pr_cont("Invalid GART PTE entry during GART table walk.\n");
510 break;
511
512 case 0x6:
513 pr_cont("Unsupported atomic RMW received from an IO link.\n");
514 break;
515
516 case 0x0:
517 case 0x8:
Borislav Petkovf0157b32010-10-05 19:07:16 +0200518 if (boot_cpu_data.x86 == 0x11)
519 return false;
520
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200521 pr_cont("DRAM ECC error detected on the NB.\n");
522 break;
523
524 case 0xd:
525 pr_cont("Parity error on the DRAM addr/ctl signals.\n");
526 break;
527
528 default:
529 ret = false;
530 break;
531 }
532
533 return ret;
534}
535
536static bool f10h_nb_mce(u16 ec, u8 xec)
537{
538 bool ret = true;
539 u8 offset = 0;
540
541 if (k8_nb_mce(ec, xec))
542 return true;
543
544 switch(xec) {
545 case 0xa ... 0xc:
546 offset = 10;
547 break;
548
549 case 0xe:
550 offset = 11;
551 break;
552
553 case 0xf:
554 if (TLB_ERROR(ec))
555 pr_cont("GART Table Walk data error.\n");
556 else if (BUS_ERROR(ec))
557 pr_cont("DMA Exclusion Vector Table Walk error.\n");
558 else
559 ret = false;
560
561 goto out;
562 break;
563
Borislav Petkov05cd6672010-09-22 15:06:24 +0200564 case 0x19:
565 if (boot_cpu_data.x86 == 0x15)
566 pr_cont("Compute Unit Data Error.\n");
567 else
568 ret = false;
569
570 goto out;
571 break;
572
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200573 case 0x1c ... 0x1f:
574 offset = 24;
575 break;
576
577 default:
578 ret = false;
579
580 goto out;
581 break;
582 }
583
584 pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
585
586out:
587 return ret;
588}
589
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200590static bool nb_noop_mce(u16 ec, u8 xec)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200591{
592 return false;
593}
594
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200595void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
Borislav Petkov549d0422009-07-24 13:51:42 +0200596{
Borislav Petkovdf71a052011-01-19 18:15:10 +0100597 struct cpuinfo_x86 *c = &boot_cpu_data;
Borislav Petkov62452882010-09-22 16:08:37 +0200598 u16 ec = EC(m->status);
599 u8 xec = XEC(m->status, 0x1f);
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200600 u32 nbsh = (u32)(m->status >> 32);
Borislav Petkov6d5db462010-11-25 15:40:27 +0100601 int core = -1;
Borislav Petkov549d0422009-07-24 13:51:42 +0200602
Borislav Petkov6d5db462010-11-25 15:40:27 +0100603 pr_emerg(HW_ERR "Northbridge Error (node %d", node_id);
Borislav Petkov549d0422009-07-24 13:51:42 +0200604
Borislav Petkov6d5db462010-11-25 15:40:27 +0100605 /* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */
Borislav Petkovdf71a052011-01-19 18:15:10 +0100606 if (c->x86 == 0x10 && c->x86_model > 7) {
Borislav Petkovbcd781f2011-01-07 16:17:46 +0100607 if (nbsh & NBSH_ERR_CPU_VAL)
Borislav Petkov6d5db462010-11-25 15:40:27 +0100608 core = nbsh & nb_err_cpumask;
Borislav Petkov549d0422009-07-24 13:51:42 +0200609 } else {
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200610 u8 assoc_cpus = nbsh & nb_err_cpumask;
Borislav Petkov5b89d2f2010-03-09 20:38:48 +0100611
612 if (assoc_cpus > 0)
Borislav Petkov6d5db462010-11-25 15:40:27 +0100613 core = fls(assoc_cpus) - 1;
Borislav Petkov549d0422009-07-24 13:51:42 +0200614 }
615
Borislav Petkov6d5db462010-11-25 15:40:27 +0100616 if (core >= 0)
617 pr_cont(", core %d): ", core);
618 else
619 pr_cont("): ");
620
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200621 switch (xec) {
622 case 0x2:
623 pr_cont("Sync error (sync packets on HT link detected).\n");
624 return;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200625
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200626 case 0x3:
627 pr_cont("HT Master abort.\n");
628 return;
629
630 case 0x4:
631 pr_cont("HT Target abort.\n");
632 return;
633
634 case 0x7:
635 pr_cont("NB Watchdog timeout.\n");
636 return;
637
638 case 0x9:
639 pr_cont("SVM DMA Exclusion Vector error.\n");
640 return;
641
642 default:
643 break;
644 }
645
646 if (!fam_ops->nb_mce(ec, xec))
647 goto wrong_nb_mce;
648
Borislav Petkovdf71a052011-01-19 18:15:10 +0100649 if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200650 if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
651 nb_bus_decoder(node_id, m, nbcfg);
652
653 return;
654
655wrong_nb_mce:
656 pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
Borislav Petkovd93cc222009-07-28 10:56:15 +0200657}
658EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
659
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200660static void amd_decode_fr_mce(struct mce *m)
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200661{
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200662 struct cpuinfo_x86 *c = &boot_cpu_data;
Borislav Petkov62452882010-09-22 16:08:37 +0200663 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200664
665 if (c->x86 == 0xf || c->x86 == 0x11)
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200666 goto wrong_fr_mce;
667
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200668 if (c->x86 != 0x15 && xec != 0x0)
669 goto wrong_fr_mce;
670
671 pr_emerg(HW_ERR "%s Error: ",
672 (c->x86 == 0x15 ? "Execution Unit" : "FIROB"));
673
674 if (xec == 0x0 || xec == 0xc)
675 pr_cont("%s.\n", fr_ex_mce_desc[xec]);
676 else if (xec < 0xd)
677 pr_cont("%s parity error.\n", fr_ex_mce_desc[xec]);
678 else
679 goto wrong_fr_mce;
680
681 return;
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200682
683wrong_fr_mce:
684 pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200685}
686
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200687static void amd_decode_fp_mce(struct mce *m)
688{
Borislav Petkov62452882010-09-22 16:08:37 +0200689 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200690
691 pr_emerg(HW_ERR "Floating Point Unit Error: ");
692
693 switch (xec) {
694 case 0x1:
695 pr_cont("Free List");
696 break;
697
698 case 0x2:
699 pr_cont("Physical Register File");
700 break;
701
702 case 0x3:
703 pr_cont("Retire Queue");
704 break;
705
706 case 0x4:
707 pr_cont("Scheduler table");
708 break;
709
710 case 0x5:
711 pr_cont("Status Register File");
712 break;
713
714 default:
715 goto wrong_fp_mce;
716 break;
717 }
718
719 pr_cont(" parity error.\n");
720
721 return;
722
723wrong_fp_mce:
724 pr_emerg(HW_ERR "Corrupted FP MCE info?\n");
725}
726
Borislav Petkov63375832010-09-06 18:13:39 +0200727static inline void amd_decode_err_code(u16 ec)
Borislav Petkovd93cc222009-07-28 10:56:15 +0200728{
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200729
730 pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec));
731
732 if (BUS_ERROR(ec))
733 pr_cont(", mem/io: %s", II_MSG(ec));
734 else
735 pr_cont(", tx: %s", TT_MSG(ec));
736
737 if (MEM_ERROR(ec) || BUS_ERROR(ec)) {
738 pr_cont(", mem-tx: %s", R4_MSG(ec));
739
740 if (BUS_ERROR(ec))
741 pr_cont(", part-proc: %s (%s)", PP_MSG(ec), TO_MSG(ec));
742 }
743
744 pr_cont("\n");
Borislav Petkov549d0422009-07-24 13:51:42 +0200745}
Borislav Petkov549d0422009-07-24 13:51:42 +0200746
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200747/*
748 * Filter out unwanted MCE signatures here.
749 */
750static bool amd_filter_mce(struct mce *m)
751{
752 u8 xec = (m->status >> 16) & 0x1f;
753
754 /*
755 * NB GART TLB error reporting is disabled by default.
756 */
757 if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
758 return true;
759
760 return false;
761}
762
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200763int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
Borislav Petkov549d0422009-07-24 13:51:42 +0200764{
Borislav Petkovfb253192009-10-07 13:20:38 +0200765 struct mce *m = (struct mce *)data;
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200766 struct cpuinfo_x86 *c = &boot_cpu_data;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200767 int node, ecc;
Borislav Petkov549d0422009-07-24 13:51:42 +0200768
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200769 if (amd_filter_mce(m))
770 return NOTIFY_STOP;
771
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200772 pr_emerg(HW_ERR "MC%d_STATUS[%s|%s|%s|%s|%s",
773 m->bank,
774 ((m->status & MCI_STATUS_OVER) ? "Over" : "-"),
775 ((m->status & MCI_STATUS_UC) ? "UE" : "CE"),
776 ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
777 ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"),
778 ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
Borislav Petkov549d0422009-07-24 13:51:42 +0200779
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200780 if (c->x86 == 0x15)
781 pr_cont("|%s|%s",
Randy Dunlap50adbbd2010-11-13 11:44:26 -0500782 ((m->status & BIT_64(44)) ? "Deferred" : "-"),
783 ((m->status & BIT_64(43)) ? "Poison" : "-"));
Borislav Petkov549d0422009-07-24 13:51:42 +0200784
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200785 /* do the two bits[14:13] together */
Borislav Petkov35d824b2010-04-30 15:19:02 +0200786 ecc = (m->status >> 45) & 0x3;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200787 if (ecc)
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200788 pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200789
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200790 pr_cont("]: 0x%016llx\n", m->status);
791
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200792
Borislav Petkov51966242009-07-28 13:50:43 +0200793 switch (m->bank) {
794 case 0:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200795 amd_decode_dc_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200796 break;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200797
Borislav Petkovab5535e2009-07-28 14:06:26 +0200798 case 1:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200799 amd_decode_ic_mce(m);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200800 break;
801
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200802 case 2:
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200803 if (c->x86 == 0x15)
Borislav Petkov70fdb492010-09-21 20:45:10 +0200804 amd_decode_cu_mce(m);
805 else
806 amd_decode_bu_mce(m);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200807 break;
808
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200809 case 3:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200810 amd_decode_ls_mce(m);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200811 break;
812
Borislav Petkov51966242009-07-28 13:50:43 +0200813 case 4:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200814 node = amd_get_nb_id(m->extcpu);
815 amd_decode_nb_mce(node, m, 0);
Borislav Petkov51966242009-07-28 13:50:43 +0200816 break;
817
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200818 case 5:
Borislav Petkov7cfd4a82010-09-01 14:45:20 +0200819 amd_decode_fr_mce(m);
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200820 break;
821
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200822 case 6:
823 amd_decode_fp_mce(m);
824 break;
825
Borislav Petkov51966242009-07-28 13:50:43 +0200826 default:
827 break;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200828 }
Borislav Petkov51966242009-07-28 13:50:43 +0200829
830 amd_decode_err_code(m->status & 0xffff);
Borislav Petkovfb253192009-10-07 13:20:38 +0200831
832 return NOTIFY_STOP;
Borislav Petkov549d0422009-07-24 13:51:42 +0200833}
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200834EXPORT_SYMBOL_GPL(amd_decode_mce);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200835
Borislav Petkovfb253192009-10-07 13:20:38 +0200836static struct notifier_block amd_mce_dec_nb = {
837 .notifier_call = amd_decode_mce,
838};
839
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200840static int __init mce_amd_init(void)
841{
Borislav Petkovbad11e02010-09-22 17:44:51 +0200842 struct cpuinfo_x86 *c = &boot_cpu_data;
843
844 if (c->x86_vendor != X86_VENDOR_AMD)
Borislav Petkove045c292010-08-06 18:55:45 +0200845 return 0;
846
Borislav Petkovbad11e02010-09-22 17:44:51 +0200847 if ((c->x86 < 0xf || c->x86 > 0x12) &&
848 (c->x86 != 0x14 || c->x86_model > 0xf) &&
849 (c->x86 != 0x15 || c->x86_model > 0xf))
Borislav Petkove045c292010-08-06 18:55:45 +0200850 return 0;
851
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200852 fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
853 if (!fam_ops)
854 return -ENOMEM;
855
Borislav Petkovbad11e02010-09-22 17:44:51 +0200856 switch (c->x86) {
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200857 case 0xf:
858 fam_ops->dc_mce = k8_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200859 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200860 fam_ops->nb_mce = k8_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200861 break;
862
863 case 0x10:
864 fam_ops->dc_mce = f10h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200865 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200866 fam_ops->nb_mce = f10h_nb_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200867 break;
868
Borislav Petkovf0157b32010-10-05 19:07:16 +0200869 case 0x11:
870 fam_ops->dc_mce = k8_dc_mce;
871 fam_ops->ic_mce = k8_ic_mce;
872 fam_ops->nb_mce = f10h_nb_mce;
873 break;
874
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200875 case 0x12:
876 fam_ops->dc_mce = f12h_dc_mce;
Borislav Petkove7281eb2010-09-16 16:45:22 +0200877 fam_ops->ic_mce = k8_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200878 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200879 break;
880
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200881 case 0x14:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200882 nb_err_cpumask = 0x3;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200883 fam_ops->dc_mce = f14h_dc_mce;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200884 fam_ops->ic_mce = f14h_ic_mce;
Borislav Petkovcb9d5ec2010-09-16 17:36:12 +0200885 fam_ops->nb_mce = nb_noop_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200886 break;
887
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200888 case 0x15:
889 xec_mask = 0x1f;
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200890 fam_ops->dc_mce = f15h_dc_mce;
Borislav Petkov86039cd2010-11-08 15:03:35 +0100891 fam_ops->ic_mce = f15h_ic_mce;
Borislav Petkov05cd6672010-09-22 15:06:24 +0200892 fam_ops->nb_mce = f10h_nb_mce;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200893 break;
894
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200895 default:
Borislav Petkovbad11e02010-09-22 17:44:51 +0200896 printk(KERN_WARNING "Huh? What family is that: %d?!\n", c->x86);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200897 kfree(fam_ops);
898 return -EINVAL;
899 }
900
Borislav Petkov9530d602010-09-06 15:05:45 +0200901 pr_info("MCE: In-kernel MCE decoding enabled.\n");
902
Borislav Petkove045c292010-08-06 18:55:45 +0200903 atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200904
905 return 0;
906}
907early_initcall(mce_amd_init);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200908
909#ifdef MODULE
910static void __exit mce_amd_exit(void)
911{
Borislav Petkovfb253192009-10-07 13:20:38 +0200912 atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200913 kfree(fam_ops);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200914}
915
916MODULE_DESCRIPTION("AMD MCE decoder");
917MODULE_ALIAS("edac-mce-amd");
918MODULE_LICENSE("GPL");
919module_exit(mce_amd_exit);
920#endif