Skip to content

Commit

Permalink
amd64_edac: Erratum #637 workaround
Browse files Browse the repository at this point in the history
F15h CPUs may report a non-DRAM address when reporting an error address
belonging to a CC6 state save area. Add a workaround to detect this
condition and compute the actual DRAM address of the error as documented
in the Revision Guide for AMD Family 15h Models 00h-0Fh Processors.

Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
  • Loading branch information
Borislav Petkov committed Apr 26, 2011
1 parent f08e457 commit c1ae683
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
52 changes: 50 additions & 2 deletions drivers/edac/amd64_edac.c
Expand Up @@ -931,15 +931,63 @@ static int k8_early_channel_count(struct amd64_pvt *pvt)
/* On F10h and later ErrAddr is MC4_ADDR[47:1] */
static u64 get_error_address(struct mce *m)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
u64 addr;
u8 start_bit = 1;
u8 end_bit = 47;

if (boot_cpu_data.x86 == 0xf) {
if (c->x86 == 0xf) {
start_bit = 3;
end_bit = 39;
}

return m->addr & GENMASK(start_bit, end_bit);
addr = m->addr & GENMASK(start_bit, end_bit);

/*
* Erratum 637 workaround
*/
if (c->x86 == 0x15) {
struct amd64_pvt *pvt;
u64 cc6_base, tmp_addr;
u32 tmp;
u8 mce_nid, intlv_en;

if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7)
return addr;

mce_nid = amd_get_nb_id(m->extcpu);
pvt = mcis[mce_nid]->pvt_info;

amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_LIM, &tmp);
intlv_en = tmp >> 21 & 0x7;

/* add [47:27] + 3 trailing bits */
cc6_base = (tmp & GENMASK(0, 20)) << 3;

/* reverse and add DramIntlvEn */
cc6_base |= intlv_en ^ 0x7;

/* pin at [47:24] */
cc6_base <<= 24;

if (!intlv_en)
return cc6_base | (addr & GENMASK(0, 23));

amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_BASE, &tmp);

/* faster log2 */
tmp_addr = (addr & GENMASK(12, 23)) << __fls(intlv_en + 1);

/* OR DramIntlvSel into bits [14:12] */
tmp_addr |= (tmp & GENMASK(21, 23)) >> 9;

/* add remaining [11:0] bits from original MC4_ADDR */
tmp_addr |= addr & GENMASK(0, 11);

return cc6_base | tmp_addr;
}

return addr;
}

static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
Expand Down
1 change: 1 addition & 0 deletions drivers/edac/amd64_edac.h
Expand Up @@ -196,6 +196,7 @@

#define DCT_CFG_SEL 0x10C

#define DRAM_LOCAL_NODE_BASE 0x120
#define DRAM_LOCAL_NODE_LIM 0x124

#define DRAM_BASE_HI 0x140
Expand Down

0 comments on commit c1ae683

Please sign in to comment.