diff options
author | Jacob Shin <jacob.shin@amd.com> | 2012-12-18 16:06:11 -0500 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2013-01-22 16:39:58 -0500 |
commit | 980eec8b20a9093f862a28f0f4bf67e55a9497be (patch) | |
tree | 94511ca5687bd16c3a3cd678fe4891a53c7a3f61 /drivers/edac | |
parent | 4a73d3de63d4c4498e3dbf8614604c6b1dcc1fc2 (diff) |
EDAC, MCE, AMD: Add MCE decoding support for Family 16h
Add MCE decoding logic for AMD Family 16h processors.
Boris:
- drop unneeded uu_msgs export
- exit early in cat_mc1_mce and save us an indentation level
Signed-off-by: Jacob Shin <jacob.shin@amd.com>
Signed-off-by: Borislav Petkov <bp@alien8.de>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/mce_amd.c | 95 | ||||
-rw-r--r-- | drivers/edac/mce_amd.h | 3 |
2 files changed, 81 insertions, 17 deletions
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index e4752bec5023..75441d357d16 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
@@ -64,6 +64,9 @@ EXPORT_SYMBOL_GPL(to_msgs); | |||
64 | const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" }; | 64 | const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" }; |
65 | EXPORT_SYMBOL_GPL(ii_msgs); | 65 | EXPORT_SYMBOL_GPL(ii_msgs); |
66 | 66 | ||
67 | /* internal error type */ | ||
68 | const char * const uu_msgs[] = { "RESV", "RESV", "HWA", "RESV" }; | ||
69 | |||
67 | static const char * const f15h_mc1_mce_desc[] = { | 70 | static const char * const f15h_mc1_mce_desc[] = { |
68 | "UC during a demand linefill from L2", | 71 | "UC during a demand linefill from L2", |
69 | "Parity error during data load from IC", | 72 | "Parity error during data load from IC", |
@@ -176,7 +179,7 @@ static bool k8_mc0_mce(u16 ec, u8 xec) | |||
176 | return f10h_mc0_mce(ec, xec); | 179 | return f10h_mc0_mce(ec, xec); |
177 | } | 180 | } |
178 | 181 | ||
179 | static bool f14h_mc0_mce(u16 ec, u8 xec) | 182 | static bool cat_mc0_mce(u16 ec, u8 xec) |
180 | { | 183 | { |
181 | u8 r4 = R4(ec); | 184 | u8 r4 = R4(ec); |
182 | bool ret = true; | 185 | bool ret = true; |
@@ -330,22 +333,28 @@ static bool k8_mc1_mce(u16 ec, u8 xec) | |||
330 | return ret; | 333 | return ret; |
331 | } | 334 | } |
332 | 335 | ||
333 | static bool f14h_mc1_mce(u16 ec, u8 xec) | 336 | static bool cat_mc1_mce(u16 ec, u8 xec) |
334 | { | 337 | { |
335 | u8 r4 = R4(ec); | 338 | u8 r4 = R4(ec); |
336 | bool ret = true; | 339 | bool ret = true; |
337 | 340 | ||
338 | if (MEM_ERROR(ec)) { | 341 | if (!MEM_ERROR(ec)) |
339 | if (TT(ec) != 0 || LL(ec) != 1) | 342 | return false; |
340 | ret = false; | 343 | |
344 | 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; | ||
341 | 357 | ||
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 | ||
347 | ret = false; | ||
348 | } | ||
349 | return ret; | 358 | return ret; |
350 | } | 359 | } |
351 | 360 | ||
@@ -469,6 +478,47 @@ static bool f15h_mc2_mce(u16 ec, u8 xec) | |||
469 | return ret; | 478 | return ret; |
470 | } | 479 | } |
471 | 480 | ||
481 | static 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 | |||
472 | static void decode_mc2_mce(struct mce *m) | 522 | static void decode_mc2_mce(struct mce *m) |
473 | { | 523 | { |
474 | u16 ec = EC(m->status); | 524 | u16 ec = EC(m->status); |
@@ -546,7 +596,7 @@ static void decode_mc4_mce(struct mce *m) | |||
546 | return; | 596 | return; |
547 | 597 | ||
548 | case 0x19: | 598 | case 0x19: |
549 | if (boot_cpu_data.x86 == 0x15) | 599 | if (boot_cpu_data.x86 == 0x15 || boot_cpu_data.x86 == 0x16) |
550 | pr_cont("Compute Unit Data Error.\n"); | 600 | pr_cont("Compute Unit Data Error.\n"); |
551 | else | 601 | else |
552 | goto wrong_mc4_mce; | 602 | goto wrong_mc4_mce; |
@@ -632,6 +682,10 @@ static void decode_mc6_mce(struct mce *m) | |||
632 | 682 | ||
633 | static inline void amd_decode_err_code(u16 ec) | 683 | static inline void amd_decode_err_code(u16 ec) |
634 | { | 684 | { |
685 | if (INT_ERROR(ec)) { | ||
686 | pr_emerg(HW_ERR "internal: %s\n", UU_MSG(ec)); | ||
687 | return; | ||
688 | } | ||
635 | 689 | ||
636 | pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec)); | 690 | pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec)); |
637 | 691 | ||
@@ -736,7 +790,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
736 | ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"), | 790 | ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"), |
737 | ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-")); | 791 | ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-")); |
738 | 792 | ||
739 | if (c->x86 == 0x15) | 793 | if (c->x86 == 0x15 || c->x86 == 0x16) |
740 | pr_cont("|%s|%s", | 794 | pr_cont("|%s|%s", |
741 | ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"), | 795 | ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"), |
742 | ((m->status & MCI_STATUS_POISON) ? "Poison" : "-")); | 796 | ((m->status & MCI_STATUS_POISON) ? "Poison" : "-")); |
@@ -768,7 +822,7 @@ static int __init mce_amd_init(void) | |||
768 | if (c->x86_vendor != X86_VENDOR_AMD) | 822 | if (c->x86_vendor != X86_VENDOR_AMD) |
769 | return 0; | 823 | return 0; |
770 | 824 | ||
771 | if (c->x86 < 0xf || c->x86 > 0x15) | 825 | if (c->x86 < 0xf || c->x86 > 0x16) |
772 | return 0; | 826 | return 0; |
773 | 827 | ||
774 | fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL); | 828 | fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL); |
@@ -802,8 +856,8 @@ static int __init mce_amd_init(void) | |||
802 | 856 | ||
803 | case 0x14: | 857 | case 0x14: |
804 | nb_err_cpumask = 0x3; | 858 | nb_err_cpumask = 0x3; |
805 | fam_ops->mc0_mce = f14h_mc0_mce; | 859 | fam_ops->mc0_mce = cat_mc0_mce; |
806 | fam_ops->mc1_mce = f14h_mc1_mce; | 860 | fam_ops->mc1_mce = cat_mc1_mce; |
807 | fam_ops->mc2_mce = k8_mc2_mce; | 861 | fam_ops->mc2_mce = k8_mc2_mce; |
808 | break; | 862 | break; |
809 | 863 | ||
@@ -814,6 +868,13 @@ static int __init mce_amd_init(void) | |||
814 | fam_ops->mc2_mce = f15h_mc2_mce; | 868 | fam_ops->mc2_mce = f15h_mc2_mce; |
815 | break; | 869 | break; |
816 | 870 | ||
871 | 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 | |||
817 | default: | 878 | default: |
818 | printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86); | 879 | printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86); |
819 | kfree(fam_ops); | 880 | kfree(fam_ops); |
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 000f6e2c4cbe..28289084017a 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #define TLB_ERROR(x) (((x) & 0xFFF0) == 0x0010) | 14 | #define TLB_ERROR(x) (((x) & 0xFFF0) == 0x0010) |
15 | #define MEM_ERROR(x) (((x) & 0xFF00) == 0x0100) | 15 | #define MEM_ERROR(x) (((x) & 0xFF00) == 0x0100) |
16 | #define BUS_ERROR(x) (((x) & 0xF800) == 0x0800) | 16 | #define BUS_ERROR(x) (((x) & 0xF800) == 0x0800) |
17 | #define INT_ERROR(x) (((x) & 0xF4FF) == 0x0400) | ||
17 | 18 | ||
18 | #define TT(x) (((x) >> 2) & 0x3) | 19 | #define TT(x) (((x) >> 2) & 0x3) |
19 | #define TT_MSG(x) tt_msgs[TT(x)] | 20 | #define TT_MSG(x) tt_msgs[TT(x)] |
@@ -25,6 +26,8 @@ | |||
25 | #define TO_MSG(x) to_msgs[TO(x)] | 26 | #define TO_MSG(x) to_msgs[TO(x)] |
26 | #define PP(x) (((x) >> 9) & 0x3) | 27 | #define PP(x) (((x) >> 9) & 0x3) |
27 | #define PP_MSG(x) pp_msgs[PP(x)] | 28 | #define PP_MSG(x) pp_msgs[PP(x)] |
29 | #define UU(x) (((x) >> 8) & 0x3) | ||
30 | #define UU_MSG(x) uu_msgs[UU(x)] | ||
28 | 31 | ||
29 | #define R4(x) (((x) >> 4) & 0xf) | 32 | #define R4(x) (((x) >> 4) & 0xf) |
30 | #define R4_MSG(x) ((R4(x) < 9) ? rrrr_msgs[R4(x)] : "Wrong R4!") | 33 | #define R4_MSG(x) ((R4(x) < 9) ? rrrr_msgs[R4(x)] : "Wrong R4!") |