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. |
