diff options
author | Borislav Petkov <borislav.petkov@amd.com> | 2010-08-26 13:05:49 -0400 |
---|---|---|
committer | Borislav Petkov <bp@amd64.org> | 2010-10-21 08:48:01 -0400 |
commit | dd53bce4e8987f6848840d42bbeead5221eff308 (patch) | |
tree | 0aa19cb96710be5c5f978b513a231e85590f6f60 /drivers | |
parent | 888ab8e6eb2e41179cdc8edf5d0abd1cce0f0370 (diff) |
EDAC, MCE: Adjust IC decoders to F14h
Add support for IC MCEs for F14h CPUs. K8 and F10h are almost identical
so use one function for both.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/edac/mce_amd.c | 118 | ||||
-rw-r--r-- | drivers/edac/mce_amd.h | 1 |
2 files changed, 71 insertions, 48 deletions
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index 33985aa61356..60d5d9f4dfee 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
@@ -219,61 +219,80 @@ wrong_dc_mce: | |||
219 | pr_emerg(HW_ERR "Corrupted DC MCE info?\n"); | 219 | pr_emerg(HW_ERR "Corrupted DC MCE info?\n"); |
220 | } | 220 | } |
221 | 221 | ||
222 | static void amd_decode_ic_mce(struct mce *m) | 222 | static bool k8_ic_mce(u16 ec) |
223 | { | 223 | { |
224 | u32 ec = m->status & 0xffff; | 224 | u8 ll = ec & 0x3; |
225 | u32 xec = (m->status >> 16) & 0xf; | 225 | u8 r4 = (ec >> 4) & 0xf; |
226 | bool ret = true; | ||
226 | 227 | ||
227 | pr_emerg(HW_ERR "Instruction Cache Error"); | 228 | if (!MEM_ERROR(ec)) |
229 | return false; | ||
228 | 230 | ||
229 | if (xec == 1 && TLB_ERROR(ec)) | 231 | if (ll == 0x2) |
230 | pr_cont(": %s TLB multimatch.\n", LL_MSG(ec)); | 232 | pr_cont("during a linefill from L2.\n"); |
231 | else if (xec == 0) { | 233 | else if (ll == 0x1) { |
232 | if (TLB_ERROR(ec)) | 234 | switch (r4) { |
233 | pr_cont(": %s TLB Parity error.\n", LL_MSG(ec)); | 235 | case R4_IRD: |
234 | else if (BUS_ERROR(ec)) { | 236 | pr_cont("Parity error during data load.\n"); |
235 | if (boot_cpu_data.x86 == 0xf && | 237 | break; |
236 | (m->status & BIT(58))) | ||
237 | pr_cont(" during system linefill.\n"); | ||
238 | else | ||
239 | pr_cont(" during attempted NB data read.\n"); | ||
240 | } else if (MEM_ERROR(ec)) { | ||
241 | u8 ll = ec & 0x3; | ||
242 | u8 rrrr = (ec >> 4) & 0xf; | ||
243 | 238 | ||
244 | if (ll == 0x2) | 239 | case R4_EVICT: |
245 | pr_cont(" during a linefill from L2.\n"); | 240 | pr_cont("Copyback Parity/Victim error.\n"); |
246 | else if (ll == 0x1) { | 241 | break; |
247 | 242 | ||
248 | switch (rrrr) { | 243 | case R4_SNOOP: |
249 | case 0x5: | 244 | pr_cont("Tag Snoop error.\n"); |
250 | pr_cont(": Parity error during " | 245 | break; |
251 | "data load.\n"); | 246 | |
252 | break; | 247 | default: |
253 | 248 | ret = false; | |
254 | case 0x7: | 249 | break; |
255 | pr_cont(": Copyback Parity/Victim" | 250 | } |
256 | " error.\n"); | ||
257 | break; | ||
258 | |||
259 | case 0x8: | ||
260 | pr_cont(": Tag Snoop error.\n"); | ||
261 | break; | ||
262 | |||
263 | default: | ||
264 | goto wrong_ic_mce; | ||
265 | break; | ||
266 | } | ||
267 | } | ||
268 | } else | ||
269 | goto wrong_ic_mce; | ||
270 | } else | 251 | } else |
271 | goto wrong_ic_mce; | 252 | ret = false; |
272 | 253 | ||
273 | return; | 254 | return ret; |
255 | } | ||
256 | |||
257 | static bool f14h_ic_mce(u16 ec) | ||
258 | { | ||
259 | u8 ll = ec & 0x3; | ||
260 | u8 tt = (ec >> 2) & 0x3; | ||
261 | u8 r4 = (ec >> 4) & 0xf; | ||
262 | bool ret = true; | ||
274 | 263 | ||
275 | wrong_ic_mce: | 264 | if (MEM_ERROR(ec)) { |
276 | pr_emerg(HW_ERR "Corrupted IC MCE info?\n"); | 265 | if (tt != 0 || ll != 1) |
266 | ret = false; | ||
267 | |||
268 | if (r4 == R4_IRD) | ||
269 | pr_cont("Data/tag array parity error for a tag hit.\n"); | ||
270 | else if (r4 == R4_SNOOP) | ||
271 | pr_cont("Tag error during snoop/victimization.\n"); | ||
272 | else | ||
273 | ret = false; | ||
274 | } | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static void amd_decode_ic_mce(struct mce *m) | ||
279 | { | ||
280 | u16 ec = m->status & 0xffff; | ||
281 | u8 xec = (m->status >> 16) & 0xf; | ||
282 | |||
283 | pr_emerg(HW_ERR "Instruction Cache Error: "); | ||
284 | |||
285 | if (TLB_ERROR(ec)) | ||
286 | pr_cont("%s TLB %s.\n", LL_MSG(ec), | ||
287 | (xec ? "multimatch" : "parity error")); | ||
288 | else if (BUS_ERROR(ec)) { | ||
289 | bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT(58))); | ||
290 | |||
291 | pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read")); | ||
292 | } else if (fam_ops->ic_mce(ec)) | ||
293 | ; | ||
294 | else | ||
295 | pr_emerg(HW_ERR "Corrupted IC MCE info?\n"); | ||
277 | } | 296 | } |
278 | 297 | ||
279 | static void amd_decode_bu_mce(struct mce *m) | 298 | static void amd_decode_bu_mce(struct mce *m) |
@@ -481,14 +500,17 @@ static int __init mce_amd_init(void) | |||
481 | switch (boot_cpu_data.x86) { | 500 | switch (boot_cpu_data.x86) { |
482 | case 0xf: | 501 | case 0xf: |
483 | fam_ops->dc_mce = k8_dc_mce; | 502 | fam_ops->dc_mce = k8_dc_mce; |
503 | fam_ops->ic_mce = k8_ic_mce; | ||
484 | break; | 504 | break; |
485 | 505 | ||
486 | case 0x10: | 506 | case 0x10: |
487 | fam_ops->dc_mce = f10h_dc_mce; | 507 | fam_ops->dc_mce = f10h_dc_mce; |
508 | fam_ops->ic_mce = k8_ic_mce; | ||
488 | break; | 509 | break; |
489 | 510 | ||
490 | case 0x14: | 511 | case 0x14: |
491 | fam_ops->dc_mce = f14h_dc_mce; | 512 | fam_ops->dc_mce = f14h_dc_mce; |
513 | fam_ops->ic_mce = f14h_ic_mce; | ||
492 | break; | 514 | break; |
493 | 515 | ||
494 | default: | 516 | default: |
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 85985c225442..dc81dba9364b 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h | |||
@@ -101,6 +101,7 @@ struct err_regs { | |||
101 | */ | 101 | */ |
102 | struct amd_decoder_ops { | 102 | struct amd_decoder_ops { |
103 | bool (*dc_mce)(u16); | 103 | bool (*dc_mce)(u16); |
104 | bool (*ic_mce)(u16); | ||
104 | }; | 105 | }; |
105 | 106 | ||
106 | void amd_report_gart_errors(bool); | 107 | void amd_report_gart_errors(bool); |