diff options
author | Timothy Pearson <tpearson@raptorengineeringinc.com> | 2016-04-06 13:25:09 -0500 |
---|---|---|
committer | Timothy Pearson <tpearson@raptorengineeringinc.com> | 2016-04-08 16:43:53 +0200 |
commit | 1d9370b3a58ddfcadda0692500e970109bcbb29f (patch) | |
tree | 2ad94543d07dba585e222e0b310dec036db22219 | |
parent | 49e917bffdb4d43caa418b9712235d174272a664 (diff) | |
download | coreboot-1d9370b3a58ddfcadda0692500e970109bcbb29f.tar.xz |
nb/amd/mct_ddr3: Add MCE reporting logic
When a fatal error and subsequent sync flood / reset occurs,
the MCA status registers may contain valuable information on
the cause of the fatal error. Add functions to report MCEs and
reset the MCA status registers early in the boot process.
Change-Id: Icde1051ac22f93688de1330f5e2c9ce28b14b59a
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
Reviewed-on: https://review.coreboot.org/14265
Tested-by: build bot (Jenkins)
Tested-by: Raptor Engineering Automated Test Stand <noreply@raptorengineeringinc.com>
Reviewed-by: Martin Roth <martinroth@google.com>
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 23 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mct_d.h | 1 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c | 2 |
3 files changed, 25 insertions, 1 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c index f31fb3c7e6..bb12746a5c 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c @@ -2944,6 +2944,29 @@ fatalexit: die("mct_d: fatalexit"); } +void initialize_mca(uint8_t bsp, uint8_t suppress_errors) { + uint8_t node; + uint32_t mc4_status_high; + uint32_t mc4_status_low; + + for (node = 0; node < MAX_NODES_SUPPORTED; node++) { + if (bsp && (node > 0)) + break; + + mc4_status_high = pci_read_config32(PCI_DEV(0, 0x18 + node, 3), 0x4c); + mc4_status_low = pci_read_config32(PCI_DEV(0, 0x18 + node, 3), 0x48); + if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) { + if (!suppress_errors) + printk(BIOS_WARNING, "WARNING: MC4 Machine Check Exception detected on node %d!\n" + "Signature: %08x%08x\n", node, mc4_status_high, mc4_status_low); + + /* Clear MC4 error status */ + pci_write_config32(PCI_DEV(0, 0x18 + node, 3), 0x48, 0x0); + pci_write_config32(PCI_DEV(0, 0x18 + node, 3), 0x4c, 0x0); + } + } +} + static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) { diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h index a3a94393ad..bb6c72351b 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h @@ -992,6 +992,7 @@ u32 SetupDqsPattern_1PassA(u8 Pass); u32 SetupDqsPattern_1PassB(u8 Pass); u8 mct_Get_Start_RcvrEnDly_1Pass(u8 Pass); u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, u16 RcvrEnDlyLimit, u8 Channel, u8 Receiver, u8 Pass); +void initialize_mca(uint8_t bsp, uint8_t suppress_errors); void CPUMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); uint64_t mctGetLogicalCPUID(u32 Node); diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c index 1077cb8f89..65de0f8c6a 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c @@ -256,7 +256,7 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) if ((val & 0x3) == 0x3) { /* Node has dram populated */ uint32_t mc4_status_high = pci_read_config32(pDCTstat->dev_nbmisc, 0x4c); uint32_t mc4_status_low = pci_read_config32(pDCTstat->dev_nbmisc, 0x48); - if (mc4_status_high != 0) { + if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) { printk(BIOS_WARNING, "WARNING: MC4 Machine Check Exception detected!\n" "Signature: %08x%08x\n", mc4_status_high, mc4_status_low); } |