blob: 30f7309446a68e8786fa8c26dccc66684880cd43 [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",
Aravind Gopalakrishnanaad19e52013-06-05 15:50:03 -0500137 "DE error occurred",
138 "Retire status queue"
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200139};
140
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200141static bool f12h_mc0_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200142{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200143 bool ret = false;
144
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200145 if (MEM_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200146 u8 ll = LL(ec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200147 ret = true;
148
149 if (ll == LL_L2)
150 pr_cont("during L1 linefill from L2.\n");
151 else if (ll == LL_L1)
Borislav Petkov62452882010-09-22 16:08:37 +0200152 pr_cont("Data/Tag %s error.\n", R4_MSG(ec));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200153 else
154 ret = false;
155 }
156 return ret;
157}
158
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200159static bool f10h_mc0_mce(u16 ec, u8 xec)
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200160{
Borislav Petkov62452882010-09-22 16:08:37 +0200161 if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200162 pr_cont("during data scrub.\n");
163 return true;
164 }
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200165 return f12h_mc0_mce(ec, xec);
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200166}
167
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200168static bool k8_mc0_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200169{
170 if (BUS_ERROR(ec)) {
171 pr_cont("during system linefill.\n");
172 return true;
173 }
174
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200175 return f10h_mc0_mce(ec, xec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200176}
177
Jacob Shin980eec82012-12-18 15:06:11 -0600178static bool cat_mc0_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200179{
Borislav Petkov62452882010-09-22 16:08:37 +0200180 u8 r4 = R4(ec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200181 bool ret = true;
182
183 if (MEM_ERROR(ec)) {
184
Borislav Petkov62452882010-09-22 16:08:37 +0200185 if (TT(ec) != TT_DATA || LL(ec) != LL_L1)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200186 return false;
187
188 switch (r4) {
189 case R4_DRD:
190 case R4_DWR:
191 pr_cont("Data/Tag parity error due to %s.\n",
192 (r4 == R4_DRD ? "load/hw prf" : "store"));
193 break;
194 case R4_EVICT:
195 pr_cont("Copyback parity error on a tag miss.\n");
196 break;
197 case R4_SNOOP:
198 pr_cont("Tag parity error during snoop.\n");
199 break;
200 default:
201 ret = false;
202 }
203 } else if (BUS_ERROR(ec)) {
204
Borislav Petkov62452882010-09-22 16:08:37 +0200205 if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200206 return false;
207
208 pr_cont("System read data error on a ");
209
210 switch (r4) {
211 case R4_RD:
212 pr_cont("TLB reload.\n");
213 break;
214 case R4_DWR:
215 pr_cont("store.\n");
216 break;
217 case R4_DRD:
218 pr_cont("load.\n");
219 break;
220 default:
221 ret = false;
222 }
223 } else {
224 ret = false;
225 }
226
227 return ret;
228}
229
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200230static bool f15h_mc0_mce(u16 ec, u8 xec)
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200231{
232 bool ret = true;
233
234 if (MEM_ERROR(ec)) {
235
236 switch (xec) {
237 case 0x0:
238 pr_cont("Data Array access error.\n");
239 break;
240
241 case 0x1:
242 pr_cont("UC error during a linefill from L2/NB.\n");
243 break;
244
245 case 0x2:
246 case 0x11:
247 pr_cont("STQ access error.\n");
248 break;
249
250 case 0x3:
251 pr_cont("SCB access error.\n");
252 break;
253
254 case 0x10:
255 pr_cont("Tag error.\n");
256 break;
257
258 case 0x12:
259 pr_cont("LDQ access error.\n");
260 break;
261
262 default:
263 ret = false;
264 }
265 } else if (BUS_ERROR(ec)) {
266
267 if (!xec)
Borislav Petkov344f0a02011-11-15 17:10:58 +0100268 pr_cont("System Read Data Error.\n");
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200269 else
Borislav Petkov344f0a02011-11-15 17:10:58 +0100270 pr_cont(" Internal error condition type %d.\n", xec);
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200271 } else
272 ret = false;
273
274 return ret;
275}
276
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200277static void decode_mc0_mce(struct mce *m)
Borislav Petkov51966242009-07-28 13:50:43 +0200278{
Borislav Petkov62452882010-09-22 16:08:37 +0200279 u16 ec = EC(m->status);
280 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov51966242009-07-28 13:50:43 +0200281
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200282 pr_emerg(HW_ERR "MC0 Error: ");
Borislav Petkov51966242009-07-28 13:50:43 +0200283
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200284 /* TLB error signatures are the same across families */
285 if (TLB_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200286 if (TT(ec) == TT_DATA) {
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200287 pr_cont("%s TLB %s.\n", LL_MSG(ec),
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200288 ((xec == 2) ? "locked miss"
289 : (xec ? "multimatch" : "parity")));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200290 return;
291 }
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200292 } else if (fam_ops->mc0_mce(ec, xec))
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200293 ;
294 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200295 pr_emerg(HW_ERR "Corrupted MC0 MCE info?\n");
Borislav Petkov51966242009-07-28 13:50:43 +0200296}
297
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200298static bool k8_mc1_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200299{
Borislav Petkov62452882010-09-22 16:08:37 +0200300 u8 ll = LL(ec);
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200301 bool ret = true;
302
303 if (!MEM_ERROR(ec))
304 return false;
305
306 if (ll == 0x2)
307 pr_cont("during a linefill from L2.\n");
308 else if (ll == 0x1) {
Borislav Petkov62452882010-09-22 16:08:37 +0200309 switch (R4(ec)) {
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200310 case R4_IRD:
311 pr_cont("Parity error during data load.\n");
312 break;
313
314 case R4_EVICT:
315 pr_cont("Copyback Parity/Victim error.\n");
316 break;
317
318 case R4_SNOOP:
319 pr_cont("Tag Snoop error.\n");
320 break;
321
322 default:
323 ret = false;
324 break;
325 }
326 } else
327 ret = false;
328
329 return ret;
330}
331
Jacob Shin980eec82012-12-18 15:06:11 -0600332static bool cat_mc1_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200333{
Borislav Petkov62452882010-09-22 16:08:37 +0200334 u8 r4 = R4(ec);
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200335 bool ret = true;
336
Jacob Shin980eec82012-12-18 15:06:11 -0600337 if (!MEM_ERROR(ec))
338 return false;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200339
Jacob Shin980eec82012-12-18 15:06:11 -0600340 if (TT(ec) != TT_INSTR)
341 return false;
342
343 if (r4 == R4_IRD)
344 pr_cont("Data/tag array parity error for a tag hit.\n");
345 else if (r4 == R4_SNOOP)
346 pr_cont("Tag error during snoop/victimization.\n");
347 else if (xec == 0x0)
348 pr_cont("Tag parity error from victim castout.\n");
349 else if (xec == 0x2)
350 pr_cont("Microcode patch RAM parity error.\n");
351 else
352 ret = false;
353
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200354 return ret;
355}
356
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200357static bool f15h_mc1_mce(u16 ec, u8 xec)
Borislav Petkov86039cd2010-11-08 15:03:35 +0100358{
359 bool ret = true;
360
361 if (!MEM_ERROR(ec))
362 return false;
363
364 switch (xec) {
365 case 0x0 ... 0xa:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200366 pr_cont("%s.\n", f15h_mc1_mce_desc[xec]);
Borislav Petkov86039cd2010-11-08 15:03:35 +0100367 break;
368
369 case 0xd:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200370 pr_cont("%s.\n", f15h_mc1_mce_desc[xec-2]);
Borislav Petkov86039cd2010-11-08 15:03:35 +0100371 break;
372
Borislav Petkov6c1173a2011-11-21 19:45:34 +0100373 case 0x10:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200374 pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
Borislav Petkov6c1173a2011-11-21 19:45:34 +0100375 break;
376
377 case 0x11 ... 0x14:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200378 pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
Borislav Petkov86039cd2010-11-08 15:03:35 +0100379 break;
380
381 default:
382 ret = false;
383 }
384 return ret;
385}
386
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200387static void decode_mc1_mce(struct mce *m)
Borislav Petkovab5535e2009-07-28 14:06:26 +0200388{
Borislav Petkov62452882010-09-22 16:08:37 +0200389 u16 ec = EC(m->status);
390 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200391
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200392 pr_emerg(HW_ERR "MC1 Error: ");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200393
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200394 if (TLB_ERROR(ec))
395 pr_cont("%s TLB %s.\n", LL_MSG(ec),
396 (xec ? "multimatch" : "parity error"));
397 else if (BUS_ERROR(ec)) {
Borislav Petkov525906b2010-10-15 15:27:02 +0200398 bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
Borislav Petkovab5535e2009-07-28 14:06:26 +0200399
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200400 pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200401 } else if (fam_ops->mc1_mce(ec, xec))
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200402 ;
403 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200404 pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200405}
406
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600407static bool k8_mc2_mce(u16 ec, u8 xec)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200408{
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600409 bool ret = true;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200410
411 if (xec == 0x1)
412 pr_cont(" in the write data buffers.\n");
413 else if (xec == 0x3)
414 pr_cont(" in the victim data buffers.\n");
415 else if (xec == 0x2 && MEM_ERROR(ec))
Borislav Petkov62452882010-09-22 16:08:37 +0200416 pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200417 else if (xec == 0x0) {
418 if (TLB_ERROR(ec))
419 pr_cont(": %s error in a Page Descriptor Cache or "
420 "Guest TLB.\n", TT_MSG(ec));
421 else if (BUS_ERROR(ec))
422 pr_cont(": %s/ECC error in data read from NB: %s.\n",
Borislav Petkov62452882010-09-22 16:08:37 +0200423 R4_MSG(ec), PP_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200424 else if (MEM_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200425 u8 r4 = R4(ec);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200426
Borislav Petkov62452882010-09-22 16:08:37 +0200427 if (r4 >= 0x7)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200428 pr_cont(": %s error during data copyback.\n",
Borislav Petkov62452882010-09-22 16:08:37 +0200429 R4_MSG(ec));
430 else if (r4 <= 0x1)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200431 pr_cont(": %s parity/ECC error during data "
Borislav Petkov62452882010-09-22 16:08:37 +0200432 "access from L2.\n", R4_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200433 else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600434 ret = false;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200435 } else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600436 ret = false;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200437 } else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600438 ret = false;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200439
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600440 return ret;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200441}
442
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600443static bool f15h_mc2_mce(u16 ec, u8 xec)
Borislav Petkov70fdb492010-09-21 20:45:10 +0200444{
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600445 bool ret = true;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200446
447 if (TLB_ERROR(ec)) {
448 if (xec == 0x0)
449 pr_cont("Data parity TLB read error.\n");
450 else if (xec == 0x1)
451 pr_cont("Poison data provided for TLB fill.\n");
452 else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600453 ret = false;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200454 } else if (BUS_ERROR(ec)) {
455 if (xec > 2)
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600456 ret = false;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200457
458 pr_cont("Error during attempted NB data read.\n");
459 } else if (MEM_ERROR(ec)) {
460 switch (xec) {
461 case 0x4 ... 0xc:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200462 pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x4]);
Borislav Petkov70fdb492010-09-21 20:45:10 +0200463 break;
464
465 case 0x10 ... 0x14:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200466 pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x7]);
Borislav Petkov70fdb492010-09-21 20:45:10 +0200467 break;
468
469 default:
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600470 ret = false;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200471 }
472 }
473
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600474 return ret;
475}
Borislav Petkov70fdb492010-09-21 20:45:10 +0200476
Jacob Shin980eec82012-12-18 15:06:11 -0600477static bool f16h_mc2_mce(u16 ec, u8 xec)
478{
479 u8 r4 = R4(ec);
480
481 if (!MEM_ERROR(ec))
482 return false;
483
484 switch (xec) {
485 case 0x04 ... 0x05:
486 pr_cont("%cBUFF parity error.\n", (r4 == R4_RD) ? 'I' : 'O');
487 break;
488
489 case 0x09 ... 0x0b:
490 case 0x0d ... 0x0f:
491 pr_cont("ECC error in L2 tag (%s).\n",
492 ((r4 == R4_GEN) ? "BankReq" :
493 ((r4 == R4_SNOOP) ? "Prb" : "Fill")));
494 break;
495
496 case 0x10 ... 0x19:
497 case 0x1b:
498 pr_cont("ECC error in L2 data array (%s).\n",
499 (((r4 == R4_RD) && !(xec & 0x3)) ? "Hit" :
500 ((r4 == R4_GEN) ? "Attr" :
501 ((r4 == R4_EVICT) ? "Vict" : "Fill"))));
502 break;
503
504 case 0x1c ... 0x1d:
505 case 0x1f:
506 pr_cont("Parity error in L2 attribute bits (%s).\n",
507 ((r4 == R4_RD) ? "Hit" :
508 ((r4 == R4_GEN) ? "Attr" : "Fill")));
509 break;
510
511 default:
512 return false;
513 }
514
515 return true;
516}
517
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600518static void decode_mc2_mce(struct mce *m)
519{
520 u16 ec = EC(m->status);
521 u8 xec = XEC(m->status, xec_mask);
522
523 pr_emerg(HW_ERR "MC2 Error: ");
524
525 if (!fam_ops->mc2_mce(ec, xec))
526 pr_cont(HW_ERR "Corrupted MC2 MCE info?\n");
Borislav Petkov70fdb492010-09-21 20:45:10 +0200527}
528
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200529static void decode_mc3_mce(struct mce *m)
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200530{
Borislav Petkov62452882010-09-22 16:08:37 +0200531 u16 ec = EC(m->status);
532 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovded50622010-08-27 17:03:34 +0200533
Borislav Petkovb18434c2010-09-22 11:53:32 +0200534 if (boot_cpu_data.x86 >= 0x14) {
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200535 pr_emerg("You shouldn't be seeing MC3 MCE on this cpu family,"
Borislav Petkovded50622010-08-27 17:03:34 +0200536 " please report on LKML.\n");
537 return;
538 }
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200539
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200540 pr_emerg(HW_ERR "MC3 Error");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200541
542 if (xec == 0x0) {
Borislav Petkov62452882010-09-22 16:08:37 +0200543 u8 r4 = R4(ec);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200544
Borislav Petkovded50622010-08-27 17:03:34 +0200545 if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200546 goto wrong_mc3_mce;
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200547
Borislav Petkov62452882010-09-22 16:08:37 +0200548 pr_cont(" during %s.\n", R4_MSG(ec));
Borislav Petkovded50622010-08-27 17:03:34 +0200549 } else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200550 goto wrong_mc3_mce;
Borislav Petkovded50622010-08-27 17:03:34 +0200551
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200552 return;
553
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200554 wrong_mc3_mce:
555 pr_emerg(HW_ERR "Corrupted MC3 MCE info?\n");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200556}
557
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200558static void decode_mc4_mce(struct mce *m)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200559{
Borislav Petkov68782672011-11-24 21:29:57 +0100560 struct cpuinfo_x86 *c = &boot_cpu_data;
561 int node_id = amd_get_nb_id(m->extcpu);
562 u16 ec = EC(m->status);
563 u8 xec = XEC(m->status, 0x1f);
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200564 u8 offset = 0;
565
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200566 pr_emerg(HW_ERR "MC4 Error (node %d): ", node_id);
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200567
Borislav Petkov68782672011-11-24 21:29:57 +0100568 switch (xec) {
569 case 0x0 ... 0xe:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200570
Borislav Petkov68782672011-11-24 21:29:57 +0100571 /* special handling for DRAM ECCs */
572 if (xec == 0x0 || xec == 0x8) {
573 /* no ECCs on F11h */
574 if (c->x86 == 0x11)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200575 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100576
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200577 pr_cont("%s.\n", mc4_mce_desc[xec]);
Borislav Petkov68782672011-11-24 21:29:57 +0100578
579 if (nb_bus_decoder)
580 nb_bus_decoder(node_id, m);
581 return;
582 }
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200583 break;
584
585 case 0xf:
586 if (TLB_ERROR(ec))
587 pr_cont("GART Table Walk data error.\n");
588 else if (BUS_ERROR(ec))
589 pr_cont("DMA Exclusion Vector Table Walk error.\n");
590 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200591 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100592 return;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200593
Borislav Petkov05cd6672010-09-22 15:06:24 +0200594 case 0x19:
Jacob Shin980eec82012-12-18 15:06:11 -0600595 if (boot_cpu_data.x86 == 0x15 || boot_cpu_data.x86 == 0x16)
Borislav Petkov05cd6672010-09-22 15:06:24 +0200596 pr_cont("Compute Unit Data Error.\n");
597 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200598 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100599 return;
Borislav Petkov05cd6672010-09-22 15:06:24 +0200600
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200601 case 0x1c ... 0x1f:
Borislav Petkov68782672011-11-24 21:29:57 +0100602 offset = 13;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200603 break;
604
605 default:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200606 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100607 }
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200608
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200609 pr_cont("%s.\n", mc4_mce_desc[xec - offset]);
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200610 return;
611
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200612 wrong_mc4_mce:
613 pr_emerg(HW_ERR "Corrupted MC4 MCE info?\n");
Borislav Petkovd93cc222009-07-28 10:56:15 +0200614}
Borislav Petkovd93cc222009-07-28 10:56:15 +0200615
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200616static void decode_mc5_mce(struct mce *m)
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200617{
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200618 struct cpuinfo_x86 *c = &boot_cpu_data;
Borislav Petkov62452882010-09-22 16:08:37 +0200619 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200620
621 if (c->x86 == 0xf || c->x86 == 0x11)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200622 goto wrong_mc5_mce;
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200623
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200624 pr_emerg(HW_ERR "MC5 Error: ");
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200625
626 if (xec == 0x0 || xec == 0xc)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200627 pr_cont("%s.\n", mc5_mce_desc[xec]);
Aravind Gopalakrishnanaad19e52013-06-05 15:50:03 -0500628 else if (xec <= 0xd)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200629 pr_cont("%s parity error.\n", mc5_mce_desc[xec]);
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200630 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200631 goto wrong_mc5_mce;
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200632
633 return;
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200634
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200635 wrong_mc5_mce:
636 pr_emerg(HW_ERR "Corrupted MC5 MCE info?\n");
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200637}
638
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200639static void decode_mc6_mce(struct mce *m)
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200640{
Borislav Petkov62452882010-09-22 16:08:37 +0200641 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200642
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200643 pr_emerg(HW_ERR "MC6 Error: ");
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200644
645 switch (xec) {
646 case 0x1:
647 pr_cont("Free List");
648 break;
649
650 case 0x2:
651 pr_cont("Physical Register File");
652 break;
653
654 case 0x3:
655 pr_cont("Retire Queue");
656 break;
657
658 case 0x4:
659 pr_cont("Scheduler table");
660 break;
661
662 case 0x5:
663 pr_cont("Status Register File");
664 break;
665
666 default:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200667 goto wrong_mc6_mce;
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200668 break;
669 }
670
671 pr_cont(" parity error.\n");
672
673 return;
674
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200675 wrong_mc6_mce:
676 pr_emerg(HW_ERR "Corrupted MC6 MCE info?\n");
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200677}
678
Borislav Petkov63375832010-09-06 18:13:39 +0200679static inline void amd_decode_err_code(u16 ec)
Borislav Petkovd93cc222009-07-28 10:56:15 +0200680{
Jacob Shin980eec82012-12-18 15:06:11 -0600681 if (INT_ERROR(ec)) {
682 pr_emerg(HW_ERR "internal: %s\n", UU_MSG(ec));
683 return;
684 }
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200685
686 pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec));
687
688 if (BUS_ERROR(ec))
689 pr_cont(", mem/io: %s", II_MSG(ec));
690 else
691 pr_cont(", tx: %s", TT_MSG(ec));
692
693 if (MEM_ERROR(ec) || BUS_ERROR(ec)) {
694 pr_cont(", mem-tx: %s", R4_MSG(ec));
695
696 if (BUS_ERROR(ec))
697 pr_cont(", part-proc: %s (%s)", PP_MSG(ec), TO_MSG(ec));
698 }
699
700 pr_cont("\n");
Borislav Petkov549d0422009-07-24 13:51:42 +0200701}
Borislav Petkov549d0422009-07-24 13:51:42 +0200702
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200703/*
704 * Filter out unwanted MCE signatures here.
705 */
706static bool amd_filter_mce(struct mce *m)
707{
708 u8 xec = (m->status >> 16) & 0x1f;
709
710 /*
711 * NB GART TLB error reporting is disabled by default.
712 */
713 if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
714 return true;
715
716 return false;
717}
718
Borislav Petkovd5c67702012-09-14 20:25:37 +0200719static const char *decode_error_status(struct mce *m)
720{
721 if (m->status & MCI_STATUS_UC) {
722 if (m->status & MCI_STATUS_PCC)
723 return "System Fatal error.";
724 if (m->mcgstatus & MCG_STATUS_RIPV)
725 return "Uncorrected, software restartable error.";
726 return "Uncorrected, software containable error.";
727 }
728
729 if (m->status & MCI_STATUS_DEFERRED)
730 return "Deferred error.";
731
732 return "Corrected error, no action required.";
733}
734
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200735int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
Borislav Petkov549d0422009-07-24 13:51:42 +0200736{
Borislav Petkovfb253192009-10-07 13:20:38 +0200737 struct mce *m = (struct mce *)data;
Borislav Petkovf89f8382012-09-13 15:14:22 +0200738 struct cpuinfo_x86 *c = &cpu_data(m->extcpu);
Borislav Petkovb0b07a22011-08-24 18:44:22 +0200739 int ecc;
Borislav Petkov549d0422009-07-24 13:51:42 +0200740
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200741 if (amd_filter_mce(m))
742 return NOTIFY_STOP;
743
Borislav Petkov51966242009-07-28 13:50:43 +0200744 switch (m->bank) {
745 case 0:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200746 decode_mc0_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200747 break;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200748
Borislav Petkovab5535e2009-07-28 14:06:26 +0200749 case 1:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200750 decode_mc1_mce(m);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200751 break;
752
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200753 case 2:
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600754 decode_mc2_mce(m);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200755 break;
756
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200757 case 3:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200758 decode_mc3_mce(m);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200759 break;
760
Borislav Petkov51966242009-07-28 13:50:43 +0200761 case 4:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200762 decode_mc4_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200763 break;
764
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200765 case 5:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200766 decode_mc5_mce(m);
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200767 break;
768
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200769 case 6:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200770 decode_mc6_mce(m);
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200771 break;
772
Borislav Petkov51966242009-07-28 13:50:43 +0200773 default:
774 break;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200775 }
Borislav Petkov51966242009-07-28 13:50:43 +0200776
Borislav Petkovd5c67702012-09-14 20:25:37 +0200777 pr_emerg(HW_ERR "Error Status: %s\n", decode_error_status(m));
778
Borislav Petkovd824c772012-09-14 20:10:59 +0200779 pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
780 m->extcpu,
781 c->x86, c->x86_model, c->x86_mask,
782 m->bank,
783 ((m->status & MCI_STATUS_OVER) ? "Over" : "-"),
784 ((m->status & MCI_STATUS_UC) ? "UE" : "CE"),
785 ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
786 ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"),
787 ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
788
Jacob Shin980eec82012-12-18 15:06:11 -0600789 if (c->x86 == 0x15 || c->x86 == 0x16)
Borislav Petkovd824c772012-09-14 20:10:59 +0200790 pr_cont("|%s|%s",
Borislav Petkovd5c67702012-09-14 20:25:37 +0200791 ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
792 ((m->status & MCI_STATUS_POISON) ? "Poison" : "-"));
Borislav Petkovd824c772012-09-14 20:10:59 +0200793
794 /* do the two bits[14:13] together */
795 ecc = (m->status >> 45) & 0x3;
796 if (ecc)
797 pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
798
799 pr_cont("]: 0x%016llx\n", m->status);
800
801 if (m->status & MCI_STATUS_ADDRV)
802 pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
803
Borislav Petkov51966242009-07-28 13:50:43 +0200804 amd_decode_err_code(m->status & 0xffff);
Borislav Petkovfb253192009-10-07 13:20:38 +0200805
806 return NOTIFY_STOP;
Borislav Petkov549d0422009-07-24 13:51:42 +0200807}
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200808EXPORT_SYMBOL_GPL(amd_decode_mce);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200809
Borislav Petkovfb253192009-10-07 13:20:38 +0200810static struct notifier_block amd_mce_dec_nb = {
811 .notifier_call = amd_decode_mce,
812};
813
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200814static int __init mce_amd_init(void)
815{
Borislav Petkovbad11e02010-09-22 17:44:51 +0200816 struct cpuinfo_x86 *c = &boot_cpu_data;
817
818 if (c->x86_vendor != X86_VENDOR_AMD)
Borislav Petkove045c292010-08-06 18:55:45 +0200819 return 0;
820
Jacob Shin980eec82012-12-18 15:06:11 -0600821 if (c->x86 < 0xf || c->x86 > 0x16)
Borislav Petkove045c292010-08-06 18:55:45 +0200822 return 0;
823
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200824 fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
825 if (!fam_ops)
826 return -ENOMEM;
827
Borislav Petkovbad11e02010-09-22 17:44:51 +0200828 switch (c->x86) {
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200829 case 0xf:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200830 fam_ops->mc0_mce = k8_mc0_mce;
831 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600832 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200833 break;
834
835 case 0x10:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200836 fam_ops->mc0_mce = f10h_mc0_mce;
837 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600838 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200839 break;
840
Borislav Petkovf0157b32010-10-05 19:07:16 +0200841 case 0x11:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200842 fam_ops->mc0_mce = k8_mc0_mce;
843 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600844 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkovf0157b32010-10-05 19:07:16 +0200845 break;
846
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200847 case 0x12:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200848 fam_ops->mc0_mce = f12h_mc0_mce;
849 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600850 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200851 break;
852
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200853 case 0x14:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200854 nb_err_cpumask = 0x3;
Jacob Shin980eec82012-12-18 15:06:11 -0600855 fam_ops->mc0_mce = cat_mc0_mce;
856 fam_ops->mc1_mce = cat_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600857 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200858 break;
859
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200860 case 0x15:
861 xec_mask = 0x1f;
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200862 fam_ops->mc0_mce = f15h_mc0_mce;
863 fam_ops->mc1_mce = f15h_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600864 fam_ops->mc2_mce = f15h_mc2_mce;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200865 break;
866
Jacob Shin980eec82012-12-18 15:06:11 -0600867 case 0x16:
868 xec_mask = 0x1f;
869 fam_ops->mc0_mce = cat_mc0_mce;
870 fam_ops->mc1_mce = cat_mc1_mce;
871 fam_ops->mc2_mce = f16h_mc2_mce;
872 break;
873
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200874 default:
Borislav Petkovec3e82d2012-04-04 14:21:02 +0200875 printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200876 kfree(fam_ops);
877 return -EINVAL;
878 }
879
Borislav Petkov9530d602010-09-06 15:05:45 +0200880 pr_info("MCE: In-kernel MCE decoding enabled.\n");
881
Borislav Petkov3653ada2011-12-04 15:12:09 +0100882 mce_register_decode_chain(&amd_mce_dec_nb);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200883
884 return 0;
885}
886early_initcall(mce_amd_init);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200887
888#ifdef MODULE
889static void __exit mce_amd_exit(void)
890{
Borislav Petkov3653ada2011-12-04 15:12:09 +0100891 mce_unregister_decode_chain(&amd_mce_dec_nb);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200892 kfree(fam_ops);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200893}
894
895MODULE_DESCRIPTION("AMD MCE decoder");
896MODULE_ALIAS("edac-mce-amd");
897MODULE_LICENSE("GPL");
898module_exit(mce_amd_exit);
899#endif