aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen Yucong <slaoub@gmail.com>2014-11-17 21:09:20 -0500
committerTony Luck <tony.luck@intel.com>2014-11-19 13:56:51 -0500
commitfa92c58694268a7e9f7fa2c6881c1482221c2788 (patch)
tree6329a4c117ccc0169a487798cdfddbaaf702130c
parente3480271f59253cb60d030aa5e615bf00b731fea (diff)
x86, mce: Support memory error recovery for both UCNA and Deferred error in machine_check_poll
Uncorrected no action required (UCNA) - is a uncorrected recoverable machine check error that is not signaled via a machine check exception and, instead, is reported to system software as a corrected machine check error. UCNA errors indicate that some data in the system is corrupted, but the data has not been consumed and the processor state is valid and you may continue execution on this processor. UCNA errors require no action from system software to continue execution. Note that UCNA errors are supported by the processor only when IA32_MCG_CAP[24] (MCG_SER_P) is set. -- Intel SDM Volume 3B Deferred errors are errors that cannot be corrected by hardware, but do not cause an immediate interruption in program flow, loss of data integrity, or corruption of processor state. These errors indicate that data has been corrupted but not consumed. Hardware writes information to the status and address registers in the corresponding bank that identifies the source of the error if deferred errors are enabled for logging. Deferred errors are not reported via machine check exceptions; they can be seen by polling the MCi_STATUS registers. -- AMD64 APM Volume 2 Above two items, both UCNA and Deferred errors belong to detected errors, but they can't be corrected by hardware, and this is very similar to Software Recoverable Action Optional (SRAO) errors. Therefore, we can take some actions that have been used for handling SRAO errors to handle UCNA and Deferred errors. Acked-by: Borislav Petkov <bp@suse.de> Signed-off-by: Chen Yucong <slaoub@gmail.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c46
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
578static 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
578DEFINE_PER_CPU(unsigned, mce_poll_count); 609DEFINE_PER_CPU(unsigned, mce_poll_count);
579 610
580/* 611/*
@@ -595,6 +626,7 @@ DEFINE_PER_CPU(unsigned, mce_poll_count);
595void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) 626void 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.