blob: f3f0c930d550ebb34509eb05dec7faf17c579151 [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 Petkovb0b07a22011-08-24 18:44:22 +020012static void (*nb_bus_decoder)(int node_id, struct mce *m);
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 Petkovb0b07a22011-08-24 18:44:22 +020020void amd_register_ecc_decoder(void (*f)(int, struct mce *))
Borislav Petkov549d0422009-07-24 13:51:42 +020021{
22 nb_bus_decoder = f;
23}
24EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
25
Borislav Petkovb0b07a22011-08-24 18:44:22 +020026void amd_unregister_ecc_decoder(void (*f)(int, struct mce *))
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 */
Borislav Petkov0f086692012-12-23 12:40:45 +010042static const char * const tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
Doug Thompsonb52401ce2009-05-06 17:57:20 +020043
Borislav Petkov63375832010-09-06 18:13:39 +020044/* cache level */
Borislav Petkov0f086692012-12-23 12:40:45 +010045static const char * const ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
Doug Thompsonb52401ce2009-05-06 17:57:20 +020046
Borislav Petkov63375832010-09-06 18:13:39 +020047/* memory transaction type */
Borislav Petkov0f086692012-12-23 12:40:45 +010048static const char * const rrrr_msgs[] = {
Borislav Petkov63375832010-09-06 18:13:39 +020049 "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
Doug Thompsonb52401ce2009-05-06 17:57:20 +020050};
51
Borislav Petkov63375832010-09-06 18:13:39 +020052/* participating processor */
Borislav Petkovebe2aea2011-11-29 19:03:25 +010053const char * const pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
Borislav Petkovb70ef012009-06-25 19:32:38 +020054EXPORT_SYMBOL_GPL(pp_msgs);
Doug Thompsonb52401ce2009-05-06 17:57:20 +020055
Borislav Petkov63375832010-09-06 18:13:39 +020056/* request timeout */
Borislav Petkov0f086692012-12-23 12:40:45 +010057static const char * const to_msgs[] = { "no timeout", "timed out" };
Doug Thompsonb52401ce2009-05-06 17:57:20 +020058
Borislav Petkov63375832010-09-06 18:13:39 +020059/* memory or i/o */
Borislav Petkov0f086692012-12-23 12:40:45 +010060static const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
Doug Thompsonb52401ce2009-05-06 17:57:20 +020061
Jacob Shin980eec82012-12-18 15:06:11 -060062/* internal error type */
Borislav Petkov0f086692012-12-23 12:40:45 +010063static const char * const uu_msgs[] = { "RESV", "RESV", "HWA", "RESV" };
Jacob Shin980eec82012-12-18 15:06:11 -060064
Borislav Petkovf05c41a2012-09-11 18:57:43 +020065static const char * const f15h_mc1_mce_desc[] = {
Borislav Petkov86039cd2010-11-08 15:03:35 +010066 "UC during a demand linefill from L2",
67 "Parity error during data load from IC",
68 "Parity error for IC valid bit",
69 "Main tag parity error",
70 "Parity error in prediction queue",
71 "PFB data/address parity error",
72 "Parity error in the branch status reg",
73 "PFB promotion address error",
74 "Tag error during probe/victimization",
75 "Parity error for IC probe tag valid bit",
76 "PFB non-cacheable bit parity error",
77 "PFB valid bit parity error", /* xec = 0xd */
Borislav Petkov6c1173a2011-11-21 19:45:34 +010078 "Microcode Patch Buffer", /* xec = 010 */
Borislav Petkov86039cd2010-11-08 15:03:35 +010079 "uop queue",
80 "insn buffer",
81 "predecode buffer",
82 "fetch address FIFO"
83};
84
Borislav Petkovf05c41a2012-09-11 18:57:43 +020085static const char * const f15h_mc2_mce_desc[] = {
Borislav Petkov70fdb492010-09-21 20:45:10 +020086 "Fill ECC error on data fills", /* xec = 0x4 */
87 "Fill parity error on insn fills",
88 "Prefetcher request FIFO parity error",
89 "PRQ address parity error",
90 "PRQ data parity error",
91 "WCC Tag ECC error",
92 "WCC Data ECC error",
93 "WCB Data parity error",
Borislav Petkovb64a99c2011-11-23 14:50:44 +010094 "VB Data ECC or parity error",
Borislav Petkov70fdb492010-09-21 20:45:10 +020095 "L2 Tag ECC error", /* xec = 0x10 */
96 "Hard L2 Tag ECC error",
97 "Multiple hits on L2 tag",
98 "XAB parity error",
99 "PRB address parity error"
100};
101
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200102static const char * const mc4_mce_desc[] = {
Borislav Petkov68782672011-11-24 21:29:57 +0100103 "DRAM ECC error detected on the NB",
104 "CRC error detected on HT link",
105 "Link-defined sync error packets detected on HT link",
106 "HT Master abort",
107 "HT Target abort",
108 "Invalid GART PTE entry during GART table walk",
109 "Unsupported atomic RMW received from an IO link",
110 "Watchdog timeout due to lack of progress",
111 "DRAM ECC error detected on the NB",
112 "SVM DMA Exclusion Vector error",
113 "HT data error detected on link",
114 "Protocol error (link, L3, probe filter)",
115 "NB internal arrays parity error",
116 "DRAM addr/ctl signals parity error",
117 "IO link transmission error",
118 "L3 data cache ECC error", /* xec = 0x1c */
119 "L3 cache tag error",
120 "L3 LRU parity bits error",
121 "ECC Error in the Probe Filter directory"
122};
123
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200124static const char * const mc5_mce_desc[] = {
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200125 "CPU Watchdog timer expire",
126 "Wakeup array dest tag",
127 "AG payload array",
128 "EX payload array",
129 "IDRF array",
130 "Retire dispatch queue",
131 "Mapper checkpoint array",
132 "Physical register file EX0 port",
133 "Physical register file EX1 port",
134 "Physical register file AG0 port",
135 "Physical register file AG1 port",
136 "Flag register file",
Borislav Petkovae615b42011-11-25 15:42:59 +0100137 "DE error occurred"
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200138};
139
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200140static bool f12h_mc0_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200141{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200142 bool ret = false;
143
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200144 if (MEM_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200145 u8 ll = LL(ec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200146 ret = true;
147
148 if (ll == LL_L2)
149 pr_cont("during L1 linefill from L2.\n");
150 else if (ll == LL_L1)
Borislav Petkov62452882010-09-22 16:08:37 +0200151 pr_cont("Data/Tag %s error.\n", R4_MSG(ec));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200152 else
153 ret = false;
154 }
155 return ret;
156}
157
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200158static bool f10h_mc0_mce(u16 ec, u8 xec)
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200159{
Borislav Petkov62452882010-09-22 16:08:37 +0200160 if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200161 pr_cont("during data scrub.\n");
162 return true;
163 }
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200164 return f12h_mc0_mce(ec, xec);
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200165}
166
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200167static bool k8_mc0_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200168{
169 if (BUS_ERROR(ec)) {
170 pr_cont("during system linefill.\n");
171 return true;
172 }
173
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200174 return f10h_mc0_mce(ec, xec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200175}
176
Jacob Shin980eec82012-12-18 15:06:11 -0600177static bool cat_mc0_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200178{
Borislav Petkov62452882010-09-22 16:08:37 +0200179 u8 r4 = R4(ec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200180 bool ret = true;
181
182 if (MEM_ERROR(ec)) {
183
Borislav Petkov62452882010-09-22 16:08:37 +0200184 if (TT(ec) != TT_DATA || LL(ec) != LL_L1)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200185 return false;
186
187 switch (r4) {
188 case R4_DRD:
189 case R4_DWR:
190 pr_cont("Data/Tag parity error due to %s.\n",
191 (r4 == R4_DRD ? "load/hw prf" : "store"));
192 break;
193 case R4_EVICT:
194 pr_cont("Copyback parity error on a tag miss.\n");
195 break;
196 case R4_SNOOP:
197 pr_cont("Tag parity error during snoop.\n");
198 break;
199 default:
200 ret = false;
201 }
202 } else if (BUS_ERROR(ec)) {
203
Borislav Petkov62452882010-09-22 16:08:37 +0200204 if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200205 return false;
206
207 pr_cont("System read data error on a ");
208
209 switch (r4) {
210 case R4_RD:
211 pr_cont("TLB reload.\n");
212 break;
213 case R4_DWR:
214 pr_cont("store.\n");
215 break;
216 case R4_DRD:
217 pr_cont("load.\n");
218 break;
219 default:
220 ret = false;
221 }
222 } else {
223 ret = false;
224 }
225
226 return ret;
227}
228
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200229static bool f15h_mc0_mce(u16 ec, u8 xec)
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200230{
231 bool ret = true;
232
233 if (MEM_ERROR(ec)) {
234
235 switch (xec) {
236 case 0x0:
237 pr_cont("Data Array access error.\n");
238 break;
239
240 case 0x1:
241 pr_cont("UC error during a linefill from L2/NB.\n");
242 break;
243
244 case 0x2:
245 case 0x11:
246 pr_cont("STQ access error.\n");
247 break;
248
249 case 0x3:
250 pr_cont("SCB access error.\n");
251 break;
252
253 case 0x10:
254 pr_cont("Tag error.\n");
255 break;
256
257 case 0x12:
258 pr_cont("LDQ access error.\n");
259 break;
260
261 default:
262 ret = false;
263 }
264 } else if (BUS_ERROR(ec)) {
265
266 if (!xec)
Borislav Petkov344f0a02011-11-15 17:10:58 +0100267 pr_cont("System Read Data Error.\n");
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200268 else
Borislav Petkov344f0a02011-11-15 17:10:58 +0100269 pr_cont(" Internal error condition type %d.\n", xec);
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200270 } else
271 ret = false;
272
273 return ret;
274}
275
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200276static void decode_mc0_mce(struct mce *m)
Borislav Petkov51966242009-07-28 13:50:43 +0200277{
Borislav Petkov62452882010-09-22 16:08:37 +0200278 u16 ec = EC(m->status);
279 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov51966242009-07-28 13:50:43 +0200280
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200281 pr_emerg(HW_ERR "MC0 Error: ");
Borislav Petkov51966242009-07-28 13:50:43 +0200282
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200283 /* TLB error signatures are the same across families */
284 if (TLB_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200285 if (TT(ec) == TT_DATA) {
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200286 pr_cont("%s TLB %s.\n", LL_MSG(ec),
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200287 ((xec == 2) ? "locked miss"
288 : (xec ? "multimatch" : "parity")));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200289 return;
290 }
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200291 } else if (fam_ops->mc0_mce(ec, xec))
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200292 ;
293 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200294 pr_emerg(HW_ERR "Corrupted MC0 MCE info?\n");
Borislav Petkov51966242009-07-28 13:50:43 +0200295}
296
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200297static bool k8_mc1_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200298{
Borislav Petkov62452882010-09-22 16:08:37 +0200299 u8 ll = LL(ec);
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200300 bool ret = true;
301
302 if (!MEM_ERROR(ec))
303 return false;
304
305 if (ll == 0x2)
306 pr_cont("during a linefill from L2.\n");
307 else if (ll == 0x1) {
Borislav Petkov62452882010-09-22 16:08:37 +0200308 switch (R4(ec)) {
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200309 case R4_IRD:
310 pr_cont("Parity error during data load.\n");
311 break;
312
313 case R4_EVICT:
314 pr_cont("Copyback Parity/Victim error.\n");
315 break;
316
317 case R4_SNOOP:
318 pr_cont("Tag Snoop error.\n");
319 break;
320
321 default:
322 ret = false;
323 break;
324 }
325 } else
326 ret = false;
327
328 return ret;
329}
330
Jacob Shin980eec82012-12-18 15:06:11 -0600331static bool cat_mc1_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200332{
Borislav Petkov62452882010-09-22 16:08:37 +0200333 u8 r4 = R4(ec);
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200334 bool ret = true;
335
Jacob Shin980eec82012-12-18 15:06:11 -0600336 if (!MEM_ERROR(ec))
337 return false;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200338
Jacob Shin980eec82012-12-18 15:06:11 -0600339 if (TT(ec) != TT_INSTR)
340 return false;
341
342 if (r4 == R4_IRD)
343 pr_cont("Data/tag array parity error for a tag hit.\n");
344 else if (r4 == R4_SNOOP)
345 pr_cont("Tag error during snoop/victimization.\n");
346 else if (xec == 0x0)
347 pr_cont("Tag parity error from victim castout.\n");
348 else if (xec == 0x2)
349 pr_cont("Microcode patch RAM parity error.\n");
350 else
351 ret = false;
352
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200353 return ret;
354}
355
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200356static bool f15h_mc1_mce(u16 ec, u8 xec)
Borislav Petkov86039cd2010-11-08 15:03:35 +0100357{
358 bool ret = true;
359
360 if (!MEM_ERROR(ec))
361 return false;
362
363 switch (xec) {
364 case 0x0 ... 0xa:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200365 pr_cont("%s.\n", f15h_mc1_mce_desc[xec]);
Borislav Petkov86039cd2010-11-08 15:03:35 +0100366 break;
367
368 case 0xd:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200369 pr_cont("%s.\n", f15h_mc1_mce_desc[xec-2]);
Borislav Petkov86039cd2010-11-08 15:03:35 +0100370 break;
371
Borislav Petkov6c1173a2011-11-21 19:45:34 +0100372 case 0x10:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200373 pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
Borislav Petkov6c1173a2011-11-21 19:45:34 +0100374 break;
375
376 case 0x11 ... 0x14:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200377 pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
Borislav Petkov86039cd2010-11-08 15:03:35 +0100378 break;
379
380 default:
381 ret = false;
382 }
383 return ret;
384}
385
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200386static void decode_mc1_mce(struct mce *m)
Borislav Petkovab5535e2009-07-28 14:06:26 +0200387{
Borislav Petkov62452882010-09-22 16:08:37 +0200388 u16 ec = EC(m->status);
389 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200390
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200391 pr_emerg(HW_ERR "MC1 Error: ");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200392
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200393 if (TLB_ERROR(ec))
394 pr_cont("%s TLB %s.\n", LL_MSG(ec),
395 (xec ? "multimatch" : "parity error"));
396 else if (BUS_ERROR(ec)) {
Borislav Petkov525906b2010-10-15 15:27:02 +0200397 bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
Borislav Petkovab5535e2009-07-28 14:06:26 +0200398
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200399 pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200400 } else if (fam_ops->mc1_mce(ec, xec))
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200401 ;
402 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200403 pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200404}
405
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600406static bool k8_mc2_mce(u16 ec, u8 xec)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200407{
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600408 bool ret = true;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200409
410 if (xec == 0x1)
411 pr_cont(" in the write data buffers.\n");
412 else if (xec == 0x3)
413 pr_cont(" in the victim data buffers.\n");
414 else if (xec == 0x2 && MEM_ERROR(ec))
Borislav Petkov62452882010-09-22 16:08:37 +0200415 pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200416 else if (xec == 0x0) {
417 if (TLB_ERROR(ec))
418 pr_cont(": %s error in a Page Descriptor Cache or "
419 "Guest TLB.\n", TT_MSG(ec));
420 else if (BUS_ERROR(ec))
421 pr_cont(": %s/ECC error in data read from NB: %s.\n",
Borislav Petkov62452882010-09-22 16:08:37 +0200422 R4_MSG(ec), PP_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200423 else if (MEM_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200424 u8 r4 = R4(ec);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200425
Borislav Petkov62452882010-09-22 16:08:37 +0200426 if (r4 >= 0x7)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200427 pr_cont(": %s error during data copyback.\n",
Borislav Petkov62452882010-09-22 16:08:37 +0200428 R4_MSG(ec));
429 else if (r4 <= 0x1)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200430 pr_cont(": %s parity/ECC error during data "
Borislav Petkov62452882010-09-22 16:08:37 +0200431 "access from L2.\n", R4_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200432 else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600433 ret = false;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200434 } else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600435 ret = false;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200436 } else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600437 ret = false;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200438
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600439 return ret;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200440}
441
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600442static bool f15h_mc2_mce(u16 ec, u8 xec)
Borislav Petkov70fdb492010-09-21 20:45:10 +0200443{
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600444 bool ret = true;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200445
446 if (TLB_ERROR(ec)) {
447 if (xec == 0x0)
448 pr_cont("Data parity TLB read error.\n");
449 else if (xec == 0x1)
450 pr_cont("Poison data provided for TLB fill.\n");
451 else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600452 ret = false;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200453 } else if (BUS_ERROR(ec)) {
454 if (xec > 2)
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600455 ret = false;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200456
457 pr_cont("Error during attempted NB data read.\n");
458 } else if (MEM_ERROR(ec)) {
459 switch (xec) {
460 case 0x4 ... 0xc:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200461 pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x4]);
Borislav Petkov70fdb492010-09-21 20:45:10 +0200462 break;
463
464 case 0x10 ... 0x14:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200465 pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x7]);
Borislav Petkov70fdb492010-09-21 20:45:10 +0200466 break;
467
468 default:
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600469 ret = false;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200470 }
471 }
472
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600473 return ret;
474}
Borislav Petkov70fdb492010-09-21 20:45:10 +0200475
Jacob Shin980eec82012-12-18 15:06:11 -0600476static bool f16h_mc2_mce(u16 ec, u8 xec)
477{
478 u8 r4 = R4(ec);
479
480 if (!MEM_ERROR(ec))
481 return false;
482
483 switch (xec) {
484 case 0x04 ... 0x05:
485 pr_cont("%cBUFF parity error.\n", (r4 == R4_RD) ? 'I' : 'O');
486 break;
487
488 case 0x09 ... 0x0b:
489 case 0x0d ... 0x0f:
490 pr_cont("ECC error in L2 tag (%s).\n",
491 ((r4 == R4_GEN) ? "BankReq" :
492 ((r4 == R4_SNOOP) ? "Prb" : "Fill")));
493 break;
494
495 case 0x10 ... 0x19:
496 case 0x1b:
497 pr_cont("ECC error in L2 data array (%s).\n",
498 (((r4 == R4_RD) && !(xec & 0x3)) ? "Hit" :
499 ((r4 == R4_GEN) ? "Attr" :
500 ((r4 == R4_EVICT) ? "Vict" : "Fill"))));
501 break;
502
503 case 0x1c ... 0x1d:
504 case 0x1f:
505 pr_cont("Parity error in L2 attribute bits (%s).\n",
506 ((r4 == R4_RD) ? "Hit" :
507 ((r4 == R4_GEN) ? "Attr" : "Fill")));
508 break;
509
510 default:
511 return false;
512 }
513
514 return true;
515}
516
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600517static void decode_mc2_mce(struct mce *m)
518{
519 u16 ec = EC(m->status);
520 u8 xec = XEC(m->status, xec_mask);
521
522 pr_emerg(HW_ERR "MC2 Error: ");
523
524 if (!fam_ops->mc2_mce(ec, xec))
525 pr_cont(HW_ERR "Corrupted MC2 MCE info?\n");
Borislav Petkov70fdb492010-09-21 20:45:10 +0200526}
527
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200528static void decode_mc3_mce(struct mce *m)
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200529{
Borislav Petkov62452882010-09-22 16:08:37 +0200530 u16 ec = EC(m->status);
531 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovded50622010-08-27 17:03:34 +0200532
Borislav Petkovb18434c2010-09-22 11:53:32 +0200533 if (boot_cpu_data.x86 >= 0x14) {
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200534 pr_emerg("You shouldn't be seeing MC3 MCE on this cpu family,"
Borislav Petkovded50622010-08-27 17:03:34 +0200535 " please report on LKML.\n");
536 return;
537 }
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200538
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200539 pr_emerg(HW_ERR "MC3 Error");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200540
541 if (xec == 0x0) {
Borislav Petkov62452882010-09-22 16:08:37 +0200542 u8 r4 = R4(ec);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200543
Borislav Petkovded50622010-08-27 17:03:34 +0200544 if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200545 goto wrong_mc3_mce;
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200546
Borislav Petkov62452882010-09-22 16:08:37 +0200547 pr_cont(" during %s.\n", R4_MSG(ec));
Borislav Petkovded50622010-08-27 17:03:34 +0200548 } else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200549 goto wrong_mc3_mce;
Borislav Petkovded50622010-08-27 17:03:34 +0200550
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200551 return;
552
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200553 wrong_mc3_mce:
554 pr_emerg(HW_ERR "Corrupted MC3 MCE info?\n");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200555}
556
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200557static void decode_mc4_mce(struct mce *m)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200558{
Borislav Petkov68782672011-11-24 21:29:57 +0100559 struct cpuinfo_x86 *c = &boot_cpu_data;
560 int node_id = amd_get_nb_id(m->extcpu);
561 u16 ec = EC(m->status);
562 u8 xec = XEC(m->status, 0x1f);
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200563 u8 offset = 0;
564
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200565 pr_emerg(HW_ERR "MC4 Error (node %d): ", node_id);
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200566
Borislav Petkov68782672011-11-24 21:29:57 +0100567 switch (xec) {
568 case 0x0 ... 0xe:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200569
Borislav Petkov68782672011-11-24 21:29:57 +0100570 /* special handling for DRAM ECCs */
571 if (xec == 0x0 || xec == 0x8) {
572 /* no ECCs on F11h */
573 if (c->x86 == 0x11)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200574 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100575
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200576 pr_cont("%s.\n", mc4_mce_desc[xec]);
Borislav Petkov68782672011-11-24 21:29:57 +0100577
578 if (nb_bus_decoder)
579 nb_bus_decoder(node_id, m);
580 return;
581 }
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200582 break;
583
584 case 0xf:
585 if (TLB_ERROR(ec))
586 pr_cont("GART Table Walk data error.\n");
587 else if (BUS_ERROR(ec))
588 pr_cont("DMA Exclusion Vector Table Walk error.\n");
589 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200590 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100591 return;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200592
Borislav Petkov05cd6672010-09-22 15:06:24 +0200593 case 0x19:
Jacob Shin980eec82012-12-18 15:06:11 -0600594 if (boot_cpu_data.x86 == 0x15 || boot_cpu_data.x86 == 0x16)
Borislav Petkov05cd6672010-09-22 15:06:24 +0200595 pr_cont("Compute Unit Data Error.\n");
596 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200597 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100598 return;
Borislav Petkov05cd6672010-09-22 15:06:24 +0200599
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200600 case 0x1c ... 0x1f:
Borislav Petkov68782672011-11-24 21:29:57 +0100601 offset = 13;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200602 break;
603
604 default:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200605 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100606 }
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200607
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200608 pr_cont("%s.\n", mc4_mce_desc[xec - offset]);
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200609 return;
610
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200611 wrong_mc4_mce:
612 pr_emerg(HW_ERR "Corrupted MC4 MCE info?\n");
Borislav Petkovd93cc222009-07-28 10:56:15 +0200613}
Borislav Petkovd93cc222009-07-28 10:56:15 +0200614
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200615static void decode_mc5_mce(struct mce *m)
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200616{
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200617 struct cpuinfo_x86 *c = &boot_cpu_data;
Borislav Petkov62452882010-09-22 16:08:37 +0200618 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200619
620 if (c->x86 == 0xf || c->x86 == 0x11)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200621 goto wrong_mc5_mce;
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200622
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200623 pr_emerg(HW_ERR "MC5 Error: ");
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200624
625 if (xec == 0x0 || xec == 0xc)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200626 pr_cont("%s.\n", mc5_mce_desc[xec]);
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200627 else if (xec < 0xd)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200628 pr_cont("%s parity error.\n", mc5_mce_desc[xec]);
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200629 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200630 goto wrong_mc5_mce;
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200631
632 return;
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200633
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200634 wrong_mc5_mce:
635 pr_emerg(HW_ERR "Corrupted MC5 MCE info?\n");
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200636}
637
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200638static void decode_mc6_mce(struct mce *m)
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200639{
Borislav Petkov62452882010-09-22 16:08:37 +0200640 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200641
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200642 pr_emerg(HW_ERR "MC6 Error: ");
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200643
644 switch (xec) {
645 case 0x1:
646 pr_cont("Free List");
647 break;
648
649 case 0x2:
650 pr_cont("Physical Register File");
651 break;
652
653 case 0x3:
654 pr_cont("Retire Queue");
655 break;
656
657 case 0x4:
658 pr_cont("Scheduler table");
659 break;
660
661 case 0x5:
662 pr_cont("Status Register File");
663 break;
664
665 default:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200666 goto wrong_mc6_mce;
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200667 break;
668 }
669
670 pr_cont(" parity error.\n");
671
672 return;
673
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200674 wrong_mc6_mce:
675 pr_emerg(HW_ERR "Corrupted MC6 MCE info?\n");
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200676}
677
Borislav Petkov63375832010-09-06 18:13:39 +0200678static inline void amd_decode_err_code(u16 ec)
Borislav Petkovd93cc222009-07-28 10:56:15 +0200679{
Jacob Shin980eec82012-12-18 15:06:11 -0600680 if (INT_ERROR(ec)) {
681 pr_emerg(HW_ERR "internal: %s\n", UU_MSG(ec));
682 return;
683 }
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200684
685 pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec));
686
687 if (BUS_ERROR(ec))
688 pr_cont(", mem/io: %s", II_MSG(ec));
689 else
690 pr_cont(", tx: %s", TT_MSG(ec));
691
692 if (MEM_ERROR(ec) || BUS_ERROR(ec)) {
693 pr_cont(", mem-tx: %s", R4_MSG(ec));
694
695 if (BUS_ERROR(ec))
696 pr_cont(", part-proc: %s (%s)", PP_MSG(ec), TO_MSG(ec));
697 }
698
699 pr_cont("\n");
Borislav Petkov549d0422009-07-24 13:51:42 +0200700}
Borislav Petkov549d0422009-07-24 13:51:42 +0200701
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200702/*
703 * Filter out unwanted MCE signatures here.
704 */
705static bool amd_filter_mce(struct mce *m)
706{
707 u8 xec = (m->status >> 16) & 0x1f;
708
709 /*
710 * NB GART TLB error reporting is disabled by default.
711 */
712 if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
713 return true;
714
715 return false;
716}
717
Borislav Petkovd5c67702012-09-14 20:25:37 +0200718static const char *decode_error_status(struct mce *m)
719{
720 if (m->status & MCI_STATUS_UC) {
721 if (m->status & MCI_STATUS_PCC)
722 return "System Fatal error.";
723 if (m->mcgstatus & MCG_STATUS_RIPV)
724 return "Uncorrected, software restartable error.";
725 return "Uncorrected, software containable error.";
726 }
727
728 if (m->status & MCI_STATUS_DEFERRED)
729 return "Deferred error.";
730
731 return "Corrected error, no action required.";
732}
733
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200734int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
Borislav Petkov549d0422009-07-24 13:51:42 +0200735{
Borislav Petkovfb253192009-10-07 13:20:38 +0200736 struct mce *m = (struct mce *)data;
Borislav Petkovf89f8382012-09-13 15:14:22 +0200737 struct cpuinfo_x86 *c = &cpu_data(m->extcpu);
Borislav Petkovb0b07a22011-08-24 18:44:22 +0200738 int ecc;
Borislav Petkov549d0422009-07-24 13:51:42 +0200739
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200740 if (amd_filter_mce(m))
741 return NOTIFY_STOP;
742
Borislav Petkov51966242009-07-28 13:50:43 +0200743 switch (m->bank) {
744 case 0:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200745 decode_mc0_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200746 break;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200747
Borislav Petkovab5535e2009-07-28 14:06:26 +0200748 case 1:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200749 decode_mc1_mce(m);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200750 break;
751
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200752 case 2:
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600753 decode_mc2_mce(m);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200754 break;
755
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200756 case 3:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200757 decode_mc3_mce(m);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200758 break;
759
Borislav Petkov51966242009-07-28 13:50:43 +0200760 case 4:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200761 decode_mc4_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200762 break;
763
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200764 case 5:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200765 decode_mc5_mce(m);
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200766 break;
767
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200768 case 6:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200769 decode_mc6_mce(m);
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200770 break;
771
Borislav Petkov51966242009-07-28 13:50:43 +0200772 default:
773 break;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200774 }
Borislav Petkov51966242009-07-28 13:50:43 +0200775
Borislav Petkovd5c67702012-09-14 20:25:37 +0200776 pr_emerg(HW_ERR "Error Status: %s\n", decode_error_status(m));
777
Borislav Petkovd824c772012-09-14 20:10:59 +0200778 pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
779 m->extcpu,
780 c->x86, c->x86_model, c->x86_mask,
781 m->bank,
782 ((m->status & MCI_STATUS_OVER) ? "Over" : "-"),
783 ((m->status & MCI_STATUS_UC) ? "UE" : "CE"),
784 ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
785 ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"),
786 ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
787
Jacob Shin980eec82012-12-18 15:06:11 -0600788 if (c->x86 == 0x15 || c->x86 == 0x16)
Borislav Petkovd824c772012-09-14 20:10:59 +0200789 pr_cont("|%s|%s",
Borislav Petkovd5c67702012-09-14 20:25:37 +0200790 ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
791 ((m->status & MCI_STATUS_POISON) ? "Poison" : "-"));
Borislav Petkovd824c772012-09-14 20:10:59 +0200792
793 /* do the two bits[14:13] together */
794 ecc = (m->status >> 45) & 0x3;
795 if (ecc)
796 pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
797
798 pr_cont("]: 0x%016llx\n", m->status);
799
800 if (m->status & MCI_STATUS_ADDRV)
801 pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
802
Borislav Petkov51966242009-07-28 13:50:43 +0200803 amd_decode_err_code(m->status & 0xffff);
Borislav Petkovfb253192009-10-07 13:20:38 +0200804
805 return NOTIFY_STOP;
Borislav Petkov549d0422009-07-24 13:51:42 +0200806}
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200807EXPORT_SYMBOL_GPL(amd_decode_mce);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200808
Borislav Petkovfb253192009-10-07 13:20:38 +0200809static struct notifier_block amd_mce_dec_nb = {
810 .notifier_call = amd_decode_mce,
811};
812
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200813static int __init mce_amd_init(void)
814{
Borislav Petkovbad11e02010-09-22 17:44:51 +0200815 struct cpuinfo_x86 *c = &boot_cpu_data;
816
817 if (c->x86_vendor != X86_VENDOR_AMD)
Borislav Petkove045c292010-08-06 18:55:45 +0200818 return 0;
819
Jacob Shin980eec82012-12-18 15:06:11 -0600820 if (c->x86 < 0xf || c->x86 > 0x16)
Borislav Petkove045c292010-08-06 18:55:45 +0200821 return 0;
822
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200823 fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
824 if (!fam_ops)
825 return -ENOMEM;
826
Borislav Petkovbad11e02010-09-22 17:44:51 +0200827 switch (c->x86) {
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200828 case 0xf:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200829 fam_ops->mc0_mce = k8_mc0_mce;
830 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600831 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200832 break;
833
834 case 0x10:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200835 fam_ops->mc0_mce = f10h_mc0_mce;
836 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600837 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200838 break;
839
Borislav Petkovf0157b32010-10-05 19:07:16 +0200840 case 0x11:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200841 fam_ops->mc0_mce = k8_mc0_mce;
842 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600843 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkovf0157b32010-10-05 19:07:16 +0200844 break;
845
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200846 case 0x12:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200847 fam_ops->mc0_mce = f12h_mc0_mce;
848 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600849 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200850 break;
851
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200852 case 0x14:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200853 nb_err_cpumask = 0x3;
Jacob Shin980eec82012-12-18 15:06:11 -0600854 fam_ops->mc0_mce = cat_mc0_mce;
855 fam_ops->mc1_mce = cat_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600856 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200857 break;
858
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200859 case 0x15:
860 xec_mask = 0x1f;
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200861 fam_ops->mc0_mce = f15h_mc0_mce;
862 fam_ops->mc1_mce = f15h_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600863 fam_ops->mc2_mce = f15h_mc2_mce;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200864 break;
865
Jacob Shin980eec82012-12-18 15:06:11 -0600866 case 0x16:
867 xec_mask = 0x1f;
868 fam_ops->mc0_mce = cat_mc0_mce;
869 fam_ops->mc1_mce = cat_mc1_mce;
870 fam_ops->mc2_mce = f16h_mc2_mce;
871 break;
872
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200873 default:
Borislav Petkovec3e82d2012-04-04 14:21:02 +0200874 printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200875 kfree(fam_ops);
876 return -EINVAL;
877 }
878
Borislav Petkov9530d602010-09-06 15:05:45 +0200879 pr_info("MCE: In-kernel MCE decoding enabled.\n");
880
Borislav Petkov3653ada2011-12-04 15:12:09 +0100881 mce_register_decode_chain(&amd_mce_dec_nb);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200882
883 return 0;
884}
885early_initcall(mce_amd_init);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200886
887#ifdef MODULE
888static void __exit mce_amd_exit(void)
889{
Borislav Petkov3653ada2011-12-04 15:12:09 +0100890 mce_unregister_decode_chain(&amd_mce_dec_nb);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200891 kfree(fam_ops);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200892}
893
894MODULE_DESCRIPTION("AMD MCE decoder");
895MODULE_ALIAS("edac-mce-amd");
896MODULE_LICENSE("GPL");
897module_exit(mce_amd_exit);
898#endif