blob: 75441d357d166213f42d91ca9c1bf1532ff2b5b7 [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 Petkovebe2aea2011-11-29 19:03:25 +010042const char * const 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 */
Borislav Petkovebe2aea2011-11-29 19:03:25 +010046const char * const 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 */
Borislav Petkovebe2aea2011-11-29 19:03:25 +010050const char * const 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 */
Borislav Petkovebe2aea2011-11-29 19:03:25 +010056const char * const 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 */
Borislav Petkovebe2aea2011-11-29 19:03:25 +010060const char * const 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 */
Borislav Petkovebe2aea2011-11-29 19:03:25 +010064const char * const 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
Jacob Shin980eec82012-12-18 15:06:11 -060067/* internal error type */
68const char * const uu_msgs[] = { "RESV", "RESV", "HWA", "RESV" };
69
Borislav Petkovf05c41a2012-09-11 18:57:43 +020070static const char * const f15h_mc1_mce_desc[] = {
Borislav Petkov86039cd2010-11-08 15:03:35 +010071 "UC during a demand linefill from L2",
72 "Parity error during data load from IC",
73 "Parity error for IC valid bit",
74 "Main tag parity error",
75 "Parity error in prediction queue",
76 "PFB data/address parity error",
77 "Parity error in the branch status reg",
78 "PFB promotion address error",
79 "Tag error during probe/victimization",
80 "Parity error for IC probe tag valid bit",
81 "PFB non-cacheable bit parity error",
82 "PFB valid bit parity error", /* xec = 0xd */
Borislav Petkov6c1173a2011-11-21 19:45:34 +010083 "Microcode Patch Buffer", /* xec = 010 */
Borislav Petkov86039cd2010-11-08 15:03:35 +010084 "uop queue",
85 "insn buffer",
86 "predecode buffer",
87 "fetch address FIFO"
88};
89
Borislav Petkovf05c41a2012-09-11 18:57:43 +020090static const char * const f15h_mc2_mce_desc[] = {
Borislav Petkov70fdb492010-09-21 20:45:10 +020091 "Fill ECC error on data fills", /* xec = 0x4 */
92 "Fill parity error on insn fills",
93 "Prefetcher request FIFO parity error",
94 "PRQ address parity error",
95 "PRQ data parity error",
96 "WCC Tag ECC error",
97 "WCC Data ECC error",
98 "WCB Data parity error",
Borislav Petkovb64a99c2011-11-23 14:50:44 +010099 "VB Data ECC or parity error",
Borislav Petkov70fdb492010-09-21 20:45:10 +0200100 "L2 Tag ECC error", /* xec = 0x10 */
101 "Hard L2 Tag ECC error",
102 "Multiple hits on L2 tag",
103 "XAB parity error",
104 "PRB address parity error"
105};
106
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200107static const char * const mc4_mce_desc[] = {
Borislav Petkov68782672011-11-24 21:29:57 +0100108 "DRAM ECC error detected on the NB",
109 "CRC error detected on HT link",
110 "Link-defined sync error packets detected on HT link",
111 "HT Master abort",
112 "HT Target abort",
113 "Invalid GART PTE entry during GART table walk",
114 "Unsupported atomic RMW received from an IO link",
115 "Watchdog timeout due to lack of progress",
116 "DRAM ECC error detected on the NB",
117 "SVM DMA Exclusion Vector error",
118 "HT data error detected on link",
119 "Protocol error (link, L3, probe filter)",
120 "NB internal arrays parity error",
121 "DRAM addr/ctl signals parity error",
122 "IO link transmission error",
123 "L3 data cache ECC error", /* xec = 0x1c */
124 "L3 cache tag error",
125 "L3 LRU parity bits error",
126 "ECC Error in the Probe Filter directory"
127};
128
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200129static const char * const mc5_mce_desc[] = {
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200130 "CPU Watchdog timer expire",
131 "Wakeup array dest tag",
132 "AG payload array",
133 "EX payload array",
134 "IDRF array",
135 "Retire dispatch queue",
136 "Mapper checkpoint array",
137 "Physical register file EX0 port",
138 "Physical register file EX1 port",
139 "Physical register file AG0 port",
140 "Physical register file AG1 port",
141 "Flag register file",
Borislav Petkovae615b42011-11-25 15:42:59 +0100142 "DE error occurred"
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200143};
144
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200145static bool f12h_mc0_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200146{
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200147 bool ret = false;
148
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200149 if (MEM_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200150 u8 ll = LL(ec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200151 ret = true;
152
153 if (ll == LL_L2)
154 pr_cont("during L1 linefill from L2.\n");
155 else if (ll == LL_L1)
Borislav Petkov62452882010-09-22 16:08:37 +0200156 pr_cont("Data/Tag %s error.\n", R4_MSG(ec));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200157 else
158 ret = false;
159 }
160 return ret;
161}
162
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200163static bool f10h_mc0_mce(u16 ec, u8 xec)
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200164{
Borislav Petkov62452882010-09-22 16:08:37 +0200165 if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200166 pr_cont("during data scrub.\n");
167 return true;
168 }
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200169 return f12h_mc0_mce(ec, xec);
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200170}
171
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200172static bool k8_mc0_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200173{
174 if (BUS_ERROR(ec)) {
175 pr_cont("during system linefill.\n");
176 return true;
177 }
178
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200179 return f10h_mc0_mce(ec, xec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200180}
181
Jacob Shin980eec82012-12-18 15:06:11 -0600182static bool cat_mc0_mce(u16 ec, u8 xec)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200183{
Borislav Petkov62452882010-09-22 16:08:37 +0200184 u8 r4 = R4(ec);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200185 bool ret = true;
186
187 if (MEM_ERROR(ec)) {
188
Borislav Petkov62452882010-09-22 16:08:37 +0200189 if (TT(ec) != TT_DATA || LL(ec) != LL_L1)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200190 return false;
191
192 switch (r4) {
193 case R4_DRD:
194 case R4_DWR:
195 pr_cont("Data/Tag parity error due to %s.\n",
196 (r4 == R4_DRD ? "load/hw prf" : "store"));
197 break;
198 case R4_EVICT:
199 pr_cont("Copyback parity error on a tag miss.\n");
200 break;
201 case R4_SNOOP:
202 pr_cont("Tag parity error during snoop.\n");
203 break;
204 default:
205 ret = false;
206 }
207 } else if (BUS_ERROR(ec)) {
208
Borislav Petkov62452882010-09-22 16:08:37 +0200209 if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG)
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200210 return false;
211
212 pr_cont("System read data error on a ");
213
214 switch (r4) {
215 case R4_RD:
216 pr_cont("TLB reload.\n");
217 break;
218 case R4_DWR:
219 pr_cont("store.\n");
220 break;
221 case R4_DRD:
222 pr_cont("load.\n");
223 break;
224 default:
225 ret = false;
226 }
227 } else {
228 ret = false;
229 }
230
231 return ret;
232}
233
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200234static bool f15h_mc0_mce(u16 ec, u8 xec)
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200235{
236 bool ret = true;
237
238 if (MEM_ERROR(ec)) {
239
240 switch (xec) {
241 case 0x0:
242 pr_cont("Data Array access error.\n");
243 break;
244
245 case 0x1:
246 pr_cont("UC error during a linefill from L2/NB.\n");
247 break;
248
249 case 0x2:
250 case 0x11:
251 pr_cont("STQ access error.\n");
252 break;
253
254 case 0x3:
255 pr_cont("SCB access error.\n");
256 break;
257
258 case 0x10:
259 pr_cont("Tag error.\n");
260 break;
261
262 case 0x12:
263 pr_cont("LDQ access error.\n");
264 break;
265
266 default:
267 ret = false;
268 }
269 } else if (BUS_ERROR(ec)) {
270
271 if (!xec)
Borislav Petkov344f0a02011-11-15 17:10:58 +0100272 pr_cont("System Read Data Error.\n");
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200273 else
Borislav Petkov344f0a02011-11-15 17:10:58 +0100274 pr_cont(" Internal error condition type %d.\n", xec);
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200275 } else
276 ret = false;
277
278 return ret;
279}
280
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200281static void decode_mc0_mce(struct mce *m)
Borislav Petkov51966242009-07-28 13:50:43 +0200282{
Borislav Petkov62452882010-09-22 16:08:37 +0200283 u16 ec = EC(m->status);
284 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov51966242009-07-28 13:50:43 +0200285
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200286 pr_emerg(HW_ERR "MC0 Error: ");
Borislav Petkov51966242009-07-28 13:50:43 +0200287
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200288 /* TLB error signatures are the same across families */
289 if (TLB_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200290 if (TT(ec) == TT_DATA) {
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200291 pr_cont("%s TLB %s.\n", LL_MSG(ec),
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200292 ((xec == 2) ? "locked miss"
293 : (xec ? "multimatch" : "parity")));
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200294 return;
295 }
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200296 } else if (fam_ops->mc0_mce(ec, xec))
Borislav Petkov25a4f8b2010-09-17 19:22:34 +0200297 ;
298 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200299 pr_emerg(HW_ERR "Corrupted MC0 MCE info?\n");
Borislav Petkov51966242009-07-28 13:50:43 +0200300}
301
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200302static bool k8_mc1_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200303{
Borislav Petkov62452882010-09-22 16:08:37 +0200304 u8 ll = LL(ec);
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200305 bool ret = true;
306
307 if (!MEM_ERROR(ec))
308 return false;
309
310 if (ll == 0x2)
311 pr_cont("during a linefill from L2.\n");
312 else if (ll == 0x1) {
Borislav Petkov62452882010-09-22 16:08:37 +0200313 switch (R4(ec)) {
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200314 case R4_IRD:
315 pr_cont("Parity error during data load.\n");
316 break;
317
318 case R4_EVICT:
319 pr_cont("Copyback Parity/Victim error.\n");
320 break;
321
322 case R4_SNOOP:
323 pr_cont("Tag Snoop error.\n");
324 break;
325
326 default:
327 ret = false;
328 break;
329 }
330 } else
331 ret = false;
332
333 return ret;
334}
335
Jacob Shin980eec82012-12-18 15:06:11 -0600336static bool cat_mc1_mce(u16 ec, u8 xec)
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200337{
Borislav Petkov62452882010-09-22 16:08:37 +0200338 u8 r4 = R4(ec);
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200339 bool ret = true;
340
Jacob Shin980eec82012-12-18 15:06:11 -0600341 if (!MEM_ERROR(ec))
342 return false;
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200343
Jacob Shin980eec82012-12-18 15:06:11 -0600344 if (TT(ec) != TT_INSTR)
345 return false;
346
347 if (r4 == R4_IRD)
348 pr_cont("Data/tag array parity error for a tag hit.\n");
349 else if (r4 == R4_SNOOP)
350 pr_cont("Tag error during snoop/victimization.\n");
351 else if (xec == 0x0)
352 pr_cont("Tag parity error from victim castout.\n");
353 else if (xec == 0x2)
354 pr_cont("Microcode patch RAM parity error.\n");
355 else
356 ret = false;
357
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200358 return ret;
359}
360
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200361static bool f15h_mc1_mce(u16 ec, u8 xec)
Borislav Petkov86039cd2010-11-08 15:03:35 +0100362{
363 bool ret = true;
364
365 if (!MEM_ERROR(ec))
366 return false;
367
368 switch (xec) {
369 case 0x0 ... 0xa:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200370 pr_cont("%s.\n", f15h_mc1_mce_desc[xec]);
Borislav Petkov86039cd2010-11-08 15:03:35 +0100371 break;
372
373 case 0xd:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200374 pr_cont("%s.\n", f15h_mc1_mce_desc[xec-2]);
Borislav Petkov86039cd2010-11-08 15:03:35 +0100375 break;
376
Borislav Petkov6c1173a2011-11-21 19:45:34 +0100377 case 0x10:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200378 pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
Borislav Petkov6c1173a2011-11-21 19:45:34 +0100379 break;
380
381 case 0x11 ... 0x14:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200382 pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
Borislav Petkov86039cd2010-11-08 15:03:35 +0100383 break;
384
385 default:
386 ret = false;
387 }
388 return ret;
389}
390
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200391static void decode_mc1_mce(struct mce *m)
Borislav Petkovab5535e2009-07-28 14:06:26 +0200392{
Borislav Petkov62452882010-09-22 16:08:37 +0200393 u16 ec = EC(m->status);
394 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200395
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200396 pr_emerg(HW_ERR "MC1 Error: ");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200397
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200398 if (TLB_ERROR(ec))
399 pr_cont("%s TLB %s.\n", LL_MSG(ec),
400 (xec ? "multimatch" : "parity error"));
401 else if (BUS_ERROR(ec)) {
Borislav Petkov525906b2010-10-15 15:27:02 +0200402 bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
Borislav Petkovab5535e2009-07-28 14:06:26 +0200403
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200404 pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200405 } else if (fam_ops->mc1_mce(ec, xec))
Borislav Petkovdd53bce2010-08-26 19:05:49 +0200406 ;
407 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200408 pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
Borislav Petkovab5535e2009-07-28 14:06:26 +0200409}
410
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600411static bool k8_mc2_mce(u16 ec, u8 xec)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200412{
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600413 bool ret = true;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200414
415 if (xec == 0x1)
416 pr_cont(" in the write data buffers.\n");
417 else if (xec == 0x3)
418 pr_cont(" in the victim data buffers.\n");
419 else if (xec == 0x2 && MEM_ERROR(ec))
Borislav Petkov62452882010-09-22 16:08:37 +0200420 pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200421 else if (xec == 0x0) {
422 if (TLB_ERROR(ec))
423 pr_cont(": %s error in a Page Descriptor Cache or "
424 "Guest TLB.\n", TT_MSG(ec));
425 else if (BUS_ERROR(ec))
426 pr_cont(": %s/ECC error in data read from NB: %s.\n",
Borislav Petkov62452882010-09-22 16:08:37 +0200427 R4_MSG(ec), PP_MSG(ec));
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200428 else if (MEM_ERROR(ec)) {
Borislav Petkov62452882010-09-22 16:08:37 +0200429 u8 r4 = R4(ec);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200430
Borislav Petkov62452882010-09-22 16:08:37 +0200431 if (r4 >= 0x7)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200432 pr_cont(": %s error during data copyback.\n",
Borislav Petkov62452882010-09-22 16:08:37 +0200433 R4_MSG(ec));
434 else if (r4 <= 0x1)
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200435 pr_cont(": %s parity/ECC error during data "
Borislav Petkov62452882010-09-22 16:08:37 +0200436 "access from L2.\n", R4_MSG(ec));
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 } else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600440 ret = false;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200441 } else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600442 ret = false;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200443
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600444 return ret;
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200445}
446
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600447static bool f15h_mc2_mce(u16 ec, u8 xec)
Borislav Petkov70fdb492010-09-21 20:45:10 +0200448{
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600449 bool ret = true;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200450
451 if (TLB_ERROR(ec)) {
452 if (xec == 0x0)
453 pr_cont("Data parity TLB read error.\n");
454 else if (xec == 0x1)
455 pr_cont("Poison data provided for TLB fill.\n");
456 else
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600457 ret = false;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200458 } else if (BUS_ERROR(ec)) {
459 if (xec > 2)
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600460 ret = false;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200461
462 pr_cont("Error during attempted NB data read.\n");
463 } else if (MEM_ERROR(ec)) {
464 switch (xec) {
465 case 0x4 ... 0xc:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200466 pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x4]);
Borislav Petkov70fdb492010-09-21 20:45:10 +0200467 break;
468
469 case 0x10 ... 0x14:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200470 pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x7]);
Borislav Petkov70fdb492010-09-21 20:45:10 +0200471 break;
472
473 default:
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600474 ret = false;
Borislav Petkov70fdb492010-09-21 20:45:10 +0200475 }
476 }
477
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600478 return ret;
479}
Borislav Petkov70fdb492010-09-21 20:45:10 +0200480
Jacob Shin980eec82012-12-18 15:06:11 -0600481static bool f16h_mc2_mce(u16 ec, u8 xec)
482{
483 u8 r4 = R4(ec);
484
485 if (!MEM_ERROR(ec))
486 return false;
487
488 switch (xec) {
489 case 0x04 ... 0x05:
490 pr_cont("%cBUFF parity error.\n", (r4 == R4_RD) ? 'I' : 'O');
491 break;
492
493 case 0x09 ... 0x0b:
494 case 0x0d ... 0x0f:
495 pr_cont("ECC error in L2 tag (%s).\n",
496 ((r4 == R4_GEN) ? "BankReq" :
497 ((r4 == R4_SNOOP) ? "Prb" : "Fill")));
498 break;
499
500 case 0x10 ... 0x19:
501 case 0x1b:
502 pr_cont("ECC error in L2 data array (%s).\n",
503 (((r4 == R4_RD) && !(xec & 0x3)) ? "Hit" :
504 ((r4 == R4_GEN) ? "Attr" :
505 ((r4 == R4_EVICT) ? "Vict" : "Fill"))));
506 break;
507
508 case 0x1c ... 0x1d:
509 case 0x1f:
510 pr_cont("Parity error in L2 attribute bits (%s).\n",
511 ((r4 == R4_RD) ? "Hit" :
512 ((r4 == R4_GEN) ? "Attr" : "Fill")));
513 break;
514
515 default:
516 return false;
517 }
518
519 return true;
520}
521
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600522static void decode_mc2_mce(struct mce *m)
523{
524 u16 ec = EC(m->status);
525 u8 xec = XEC(m->status, xec_mask);
526
527 pr_emerg(HW_ERR "MC2 Error: ");
528
529 if (!fam_ops->mc2_mce(ec, xec))
530 pr_cont(HW_ERR "Corrupted MC2 MCE info?\n");
Borislav Petkov70fdb492010-09-21 20:45:10 +0200531}
532
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200533static void decode_mc3_mce(struct mce *m)
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200534{
Borislav Petkov62452882010-09-22 16:08:37 +0200535 u16 ec = EC(m->status);
536 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovded50622010-08-27 17:03:34 +0200537
Borislav Petkovb18434c2010-09-22 11:53:32 +0200538 if (boot_cpu_data.x86 >= 0x14) {
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200539 pr_emerg("You shouldn't be seeing MC3 MCE on this cpu family,"
Borislav Petkovded50622010-08-27 17:03:34 +0200540 " please report on LKML.\n");
541 return;
542 }
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200543
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200544 pr_emerg(HW_ERR "MC3 Error");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200545
546 if (xec == 0x0) {
Borislav Petkov62452882010-09-22 16:08:37 +0200547 u8 r4 = R4(ec);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200548
Borislav Petkovded50622010-08-27 17:03:34 +0200549 if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200550 goto wrong_mc3_mce;
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200551
Borislav Petkov62452882010-09-22 16:08:37 +0200552 pr_cont(" during %s.\n", R4_MSG(ec));
Borislav Petkovded50622010-08-27 17:03:34 +0200553 } else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200554 goto wrong_mc3_mce;
Borislav Petkovded50622010-08-27 17:03:34 +0200555
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200556 return;
557
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200558 wrong_mc3_mce:
559 pr_emerg(HW_ERR "Corrupted MC3 MCE info?\n");
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200560}
561
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200562static void decode_mc4_mce(struct mce *m)
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200563{
Borislav Petkov68782672011-11-24 21:29:57 +0100564 struct cpuinfo_x86 *c = &boot_cpu_data;
565 int node_id = amd_get_nb_id(m->extcpu);
566 u16 ec = EC(m->status);
567 u8 xec = XEC(m->status, 0x1f);
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200568 u8 offset = 0;
569
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200570 pr_emerg(HW_ERR "MC4 Error (node %d): ", node_id);
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200571
Borislav Petkov68782672011-11-24 21:29:57 +0100572 switch (xec) {
573 case 0x0 ... 0xe:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200574
Borislav Petkov68782672011-11-24 21:29:57 +0100575 /* special handling for DRAM ECCs */
576 if (xec == 0x0 || xec == 0x8) {
577 /* no ECCs on F11h */
578 if (c->x86 == 0x11)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200579 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100580
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200581 pr_cont("%s.\n", mc4_mce_desc[xec]);
Borislav Petkov68782672011-11-24 21:29:57 +0100582
583 if (nb_bus_decoder)
584 nb_bus_decoder(node_id, m);
585 return;
586 }
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200587 break;
588
589 case 0xf:
590 if (TLB_ERROR(ec))
591 pr_cont("GART Table Walk data error.\n");
592 else if (BUS_ERROR(ec))
593 pr_cont("DMA Exclusion Vector Table Walk error.\n");
594 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200595 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100596 return;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200597
Borislav Petkov05cd6672010-09-22 15:06:24 +0200598 case 0x19:
Jacob Shin980eec82012-12-18 15:06:11 -0600599 if (boot_cpu_data.x86 == 0x15 || boot_cpu_data.x86 == 0x16)
Borislav Petkov05cd6672010-09-22 15:06:24 +0200600 pr_cont("Compute Unit Data Error.\n");
601 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200602 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100603 return;
Borislav Petkov05cd6672010-09-22 15:06:24 +0200604
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200605 case 0x1c ... 0x1f:
Borislav Petkov68782672011-11-24 21:29:57 +0100606 offset = 13;
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200607 break;
608
609 default:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200610 goto wrong_mc4_mce;
Borislav Petkov68782672011-11-24 21:29:57 +0100611 }
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200612
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200613 pr_cont("%s.\n", mc4_mce_desc[xec - offset]);
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200614 return;
615
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200616 wrong_mc4_mce:
617 pr_emerg(HW_ERR "Corrupted MC4 MCE info?\n");
Borislav Petkovd93cc222009-07-28 10:56:15 +0200618}
Borislav Petkovd93cc222009-07-28 10:56:15 +0200619
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200620static void decode_mc5_mce(struct mce *m)
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200621{
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200622 struct cpuinfo_x86 *c = &boot_cpu_data;
Borislav Petkov62452882010-09-22 16:08:37 +0200623 u8 xec = XEC(m->status, xec_mask);
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200624
625 if (c->x86 == 0xf || c->x86 == 0x11)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200626 goto wrong_mc5_mce;
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200627
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200628 pr_emerg(HW_ERR "MC5 Error: ");
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200629
630 if (xec == 0x0 || xec == 0xc)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200631 pr_cont("%s.\n", mc5_mce_desc[xec]);
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200632 else if (xec < 0xd)
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200633 pr_cont("%s parity error.\n", mc5_mce_desc[xec]);
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200634 else
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200635 goto wrong_mc5_mce;
Borislav Petkov8259a7e2010-09-22 15:28:59 +0200636
637 return;
Borislav Petkovfe4ea262010-08-31 18:38:24 +0200638
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200639 wrong_mc5_mce:
640 pr_emerg(HW_ERR "Corrupted MC5 MCE info?\n");
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200641}
642
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200643static void decode_mc6_mce(struct mce *m)
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200644{
Borislav Petkov62452882010-09-22 16:08:37 +0200645 u8 xec = XEC(m->status, xec_mask);
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200646
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200647 pr_emerg(HW_ERR "MC6 Error: ");
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200648
649 switch (xec) {
650 case 0x1:
651 pr_cont("Free List");
652 break;
653
654 case 0x2:
655 pr_cont("Physical Register File");
656 break;
657
658 case 0x3:
659 pr_cont("Retire Queue");
660 break;
661
662 case 0x4:
663 pr_cont("Scheduler table");
664 break;
665
666 case 0x5:
667 pr_cont("Status Register File");
668 break;
669
670 default:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200671 goto wrong_mc6_mce;
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200672 break;
673 }
674
675 pr_cont(" parity error.\n");
676
677 return;
678
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200679 wrong_mc6_mce:
680 pr_emerg(HW_ERR "Corrupted MC6 MCE info?\n");
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200681}
682
Borislav Petkov63375832010-09-06 18:13:39 +0200683static inline void amd_decode_err_code(u16 ec)
Borislav Petkovd93cc222009-07-28 10:56:15 +0200684{
Jacob Shin980eec82012-12-18 15:06:11 -0600685 if (INT_ERROR(ec)) {
686 pr_emerg(HW_ERR "internal: %s\n", UU_MSG(ec));
687 return;
688 }
Borislav Petkovfa7ae8c2010-09-22 17:42:27 +0200689
690 pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec));
691
692 if (BUS_ERROR(ec))
693 pr_cont(", mem/io: %s", II_MSG(ec));
694 else
695 pr_cont(", tx: %s", TT_MSG(ec));
696
697 if (MEM_ERROR(ec) || BUS_ERROR(ec)) {
698 pr_cont(", mem-tx: %s", R4_MSG(ec));
699
700 if (BUS_ERROR(ec))
701 pr_cont(", part-proc: %s (%s)", PP_MSG(ec), TO_MSG(ec));
702 }
703
704 pr_cont("\n");
Borislav Petkov549d0422009-07-24 13:51:42 +0200705}
Borislav Petkov549d0422009-07-24 13:51:42 +0200706
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200707/*
708 * Filter out unwanted MCE signatures here.
709 */
710static bool amd_filter_mce(struct mce *m)
711{
712 u8 xec = (m->status >> 16) & 0x1f;
713
714 /*
715 * NB GART TLB error reporting is disabled by default.
716 */
717 if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
718 return true;
719
720 return false;
721}
722
Borislav Petkovd5c67702012-09-14 20:25:37 +0200723static const char *decode_error_status(struct mce *m)
724{
725 if (m->status & MCI_STATUS_UC) {
726 if (m->status & MCI_STATUS_PCC)
727 return "System Fatal error.";
728 if (m->mcgstatus & MCG_STATUS_RIPV)
729 return "Uncorrected, software restartable error.";
730 return "Uncorrected, software containable error.";
731 }
732
733 if (m->status & MCI_STATUS_DEFERRED)
734 return "Deferred error.";
735
736 return "Corrected error, no action required.";
737}
738
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200739int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
Borislav Petkov549d0422009-07-24 13:51:42 +0200740{
Borislav Petkovfb253192009-10-07 13:20:38 +0200741 struct mce *m = (struct mce *)data;
Borislav Petkovf89f8382012-09-13 15:14:22 +0200742 struct cpuinfo_x86 *c = &cpu_data(m->extcpu);
Borislav Petkovb0b07a22011-08-24 18:44:22 +0200743 int ecc;
Borislav Petkov549d0422009-07-24 13:51:42 +0200744
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200745 if (amd_filter_mce(m))
746 return NOTIFY_STOP;
747
Borislav Petkov51966242009-07-28 13:50:43 +0200748 switch (m->bank) {
749 case 0:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200750 decode_mc0_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200751 break;
Borislav Petkovd93cc222009-07-28 10:56:15 +0200752
Borislav Petkovab5535e2009-07-28 14:06:26 +0200753 case 1:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200754 decode_mc1_mce(m);
Borislav Petkovab5535e2009-07-28 14:06:26 +0200755 break;
756
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200757 case 2:
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600758 decode_mc2_mce(m);
Borislav Petkov56cad2d2009-07-28 14:14:24 +0200759 break;
760
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200761 case 3:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200762 decode_mc3_mce(m);
Borislav Petkovf9350ef2009-07-28 14:17:30 +0200763 break;
764
Borislav Petkov51966242009-07-28 13:50:43 +0200765 case 4:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200766 decode_mc4_mce(m);
Borislav Petkov51966242009-07-28 13:50:43 +0200767 break;
768
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200769 case 5:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200770 decode_mc5_mce(m);
Borislav Petkov53bd5fe2009-07-28 14:20:46 +0200771 break;
772
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200773 case 6:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200774 decode_mc6_mce(m);
Borislav Petkovb8f85c42010-09-22 15:37:58 +0200775 break;
776
Borislav Petkov51966242009-07-28 13:50:43 +0200777 default:
778 break;
Borislav Petkovb69b29d2009-07-27 16:21:14 +0200779 }
Borislav Petkov51966242009-07-28 13:50:43 +0200780
Borislav Petkovd5c67702012-09-14 20:25:37 +0200781 pr_emerg(HW_ERR "Error Status: %s\n", decode_error_status(m));
782
Borislav Petkovd824c772012-09-14 20:10:59 +0200783 pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
784 m->extcpu,
785 c->x86, c->x86_model, c->x86_mask,
786 m->bank,
787 ((m->status & MCI_STATUS_OVER) ? "Over" : "-"),
788 ((m->status & MCI_STATUS_UC) ? "UE" : "CE"),
789 ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
790 ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"),
791 ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
792
Jacob Shin980eec82012-12-18 15:06:11 -0600793 if (c->x86 == 0x15 || c->x86 == 0x16)
Borislav Petkovd824c772012-09-14 20:10:59 +0200794 pr_cont("|%s|%s",
Borislav Petkovd5c67702012-09-14 20:25:37 +0200795 ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
796 ((m->status & MCI_STATUS_POISON) ? "Poison" : "-"));
Borislav Petkovd824c772012-09-14 20:10:59 +0200797
798 /* do the two bits[14:13] together */
799 ecc = (m->status >> 45) & 0x3;
800 if (ecc)
801 pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
802
803 pr_cont("]: 0x%016llx\n", m->status);
804
805 if (m->status & MCI_STATUS_ADDRV)
806 pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
807
Borislav Petkov51966242009-07-28 13:50:43 +0200808 amd_decode_err_code(m->status & 0xffff);
Borislav Petkovfb253192009-10-07 13:20:38 +0200809
810 return NOTIFY_STOP;
Borislav Petkov549d0422009-07-24 13:51:42 +0200811}
Borislav Petkov9cdeb402010-09-02 18:33:24 +0200812EXPORT_SYMBOL_GPL(amd_decode_mce);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200813
Borislav Petkovfb253192009-10-07 13:20:38 +0200814static struct notifier_block amd_mce_dec_nb = {
815 .notifier_call = amd_decode_mce,
816};
817
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200818static int __init mce_amd_init(void)
819{
Borislav Petkovbad11e02010-09-22 17:44:51 +0200820 struct cpuinfo_x86 *c = &boot_cpu_data;
821
822 if (c->x86_vendor != X86_VENDOR_AMD)
Borislav Petkove045c292010-08-06 18:55:45 +0200823 return 0;
824
Jacob Shin980eec82012-12-18 15:06:11 -0600825 if (c->x86 < 0xf || c->x86 > 0x16)
Borislav Petkove045c292010-08-06 18:55:45 +0200826 return 0;
827
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200828 fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
829 if (!fam_ops)
830 return -ENOMEM;
831
Borislav Petkovbad11e02010-09-22 17:44:51 +0200832 switch (c->x86) {
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200833 case 0xf:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200834 fam_ops->mc0_mce = k8_mc0_mce;
835 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600836 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200837 break;
838
839 case 0x10:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200840 fam_ops->mc0_mce = f10h_mc0_mce;
841 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600842 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200843 break;
844
Borislav Petkovf0157b32010-10-05 19:07:16 +0200845 case 0x11:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200846 fam_ops->mc0_mce = k8_mc0_mce;
847 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600848 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkovf0157b32010-10-05 19:07:16 +0200849 break;
850
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200851 case 0x12:
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200852 fam_ops->mc0_mce = f12h_mc0_mce;
853 fam_ops->mc1_mce = k8_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600854 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov9be0bb12010-09-16 15:08:14 +0200855 break;
856
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200857 case 0x14:
Borislav Petkov5ce88f62010-08-31 18:28:08 +0200858 nb_err_cpumask = 0x3;
Jacob Shin980eec82012-12-18 15:06:11 -0600859 fam_ops->mc0_mce = cat_mc0_mce;
860 fam_ops->mc1_mce = cat_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600861 fam_ops->mc2_mce = k8_mc2_mce;
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200862 break;
863
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200864 case 0x15:
865 xec_mask = 0x1f;
Borislav Petkovf05c41a2012-09-11 18:57:43 +0200866 fam_ops->mc0_mce = f15h_mc0_mce;
867 fam_ops->mc1_mce = f15h_mc1_mce;
Jacob Shin4a73d3d2012-12-18 15:06:10 -0600868 fam_ops->mc2_mce = f15h_mc2_mce;
Borislav Petkov2be64bf2010-09-17 19:11:47 +0200869 break;
870
Jacob Shin980eec82012-12-18 15:06:11 -0600871 case 0x16:
872 xec_mask = 0x1f;
873 fam_ops->mc0_mce = cat_mc0_mce;
874 fam_ops->mc1_mce = cat_mc1_mce;
875 fam_ops->mc2_mce = f16h_mc2_mce;
876 break;
877
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200878 default:
Borislav Petkovec3e82d2012-04-04 14:21:02 +0200879 printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200880 kfree(fam_ops);
881 return -EINVAL;
882 }
883
Borislav Petkov9530d602010-09-06 15:05:45 +0200884 pr_info("MCE: In-kernel MCE decoding enabled.\n");
885
Borislav Petkov3653ada2011-12-04 15:12:09 +0100886 mce_register_decode_chain(&amd_mce_dec_nb);
Ingo Molnarf436f8b2009-10-01 16:14:32 +0200887
888 return 0;
889}
890early_initcall(mce_amd_init);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200891
892#ifdef MODULE
893static void __exit mce_amd_exit(void)
894{
Borislav Petkov3653ada2011-12-04 15:12:09 +0100895 mce_unregister_decode_chain(&amd_mce_dec_nb);
Borislav Petkov888ab8e2010-08-18 15:11:35 +0200896 kfree(fam_ops);
Borislav Petkov0d18b2e2009-10-02 15:31:48 +0200897}
898
899MODULE_DESCRIPTION("AMD MCE decoder");
900MODULE_ALIAS("edac-mce-amd");
901MODULE_LICENSE("GPL");
902module_exit(mce_amd_exit);
903#endif