diff options
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 453e9bf90968..cfb16f631d52 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -575,6 +575,37 @@ static void mce_read_aux(struct mce *m, int i) | |||
575 | } | 575 | } |
576 | } | 576 | } |
577 | 577 | ||
578 | static bool memory_error(struct mce *m) | ||
579 | { | ||
580 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
581 | |||
582 | if (c->x86_vendor == X86_VENDOR_AMD) { | ||
583 | /* | ||
584 | * coming soon | ||
585 | */ | ||
586 | return false; | ||
587 | } else if (c->x86_vendor == X86_VENDOR_INTEL) { | ||
588 | /* | ||
589 | * Intel SDM Volume 3B - 15.9.2 Compound Error Codes | ||
590 | * | ||
591 | * Bit 7 of the MCACOD field of IA32_MCi_STATUS is used for | ||
592 | * indicating a memory error. Bit 8 is used for indicating a | ||
593 | * cache hierarchy error. The combination of bit 2 and bit 3 | ||
594 | * is used for indicating a `generic' cache hierarchy error | ||
595 | * But we can't just blindly check the above bits, because if | ||
596 | * bit 11 is set, then it is a bus/interconnect error - and | ||
597 | * either way the above bits just gives more detail on what | ||
598 | * bus/interconnect error happened. Note that bit 12 can be | ||
599 | * ignored, as it's the "filter" bit. | ||
600 | */ | ||
601 | return (m->status & 0xef80) == BIT(7) || | ||
602 | (m->status & 0xef00) == BIT(8) || | ||
603 | (m->status & 0xeffc) == 0xc; | ||
604 | } | ||
605 | |||
606 | return false; | ||
607 | } | ||
608 | |||
578 | DEFINE_PER_CPU(unsigned, mce_poll_count); | 609 | DEFINE_PER_CPU(unsigned, mce_poll_count); |
579 | 610 | ||
580 | /* | 611 | /* |
@@ -595,6 +626,7 @@ DEFINE_PER_CPU(unsigned, mce_poll_count); | |||
595 | void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) | 626 | void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) |
596 | { | 627 | { |
597 | struct mce m; | 628 | struct mce m; |
629 | int severity; | ||
598 | int i; | 630 | int i; |
599 | 631 | ||
600 | this_cpu_inc(mce_poll_count); | 632 | this_cpu_inc(mce_poll_count); |
@@ -630,6 +662,20 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) | |||
630 | 662 | ||
631 | if (!(flags & MCP_TIMESTAMP)) | 663 | if (!(flags & MCP_TIMESTAMP)) |
632 | m.tsc = 0; | 664 | m.tsc = 0; |
665 | |||
666 | severity = mce_severity(&m, mca_cfg.tolerant, NULL, false); | ||
667 | |||
668 | /* | ||
669 | * In the cases where we don't have a valid address after all, | ||
670 | * do not add it into the ring buffer. | ||
671 | */ | ||
672 | if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m)) { | ||
673 | if (m.status & MCI_STATUS_ADDRV) { | ||
674 | mce_ring_add(m.addr >> PAGE_SHIFT); | ||
675 | mce_schedule_work(); | ||
676 | } | ||
677 | } | ||
678 | |||
633 | /* | 679 | /* |
634 | * Don't get the IP here because it's unlikely to | 680 | * Don't get the IP here because it's unlikely to |
635 | * have anything to do with the actual error location. | 681 | * have anything to do with the actual error location. |