|
@@ -602,111 +602,6 @@ static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr)
|
|
|
return input_addr;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-/*
|
|
|
- * @input_addr is an InputAddr associated with the node represented by mci.
|
|
|
- * Translate @input_addr to a DramAddr and return the result.
|
|
|
- */
|
|
|
-static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr)
|
|
|
-{
|
|
|
- struct amd64_pvt *pvt;
|
|
|
- unsigned node_id, intlv_shift;
|
|
|
- u64 bits, dram_addr;
|
|
|
- u32 intlv_sel;
|
|
|
-
|
|
|
- /*
|
|
|
- * Near the start of section 3.4.4 (p. 70, BKDG #26094, K8, revA-E)
|
|
|
- * shows how to translate a DramAddr to an InputAddr. Here we reverse
|
|
|
- * this procedure. When translating from a DramAddr to an InputAddr, the
|
|
|
- * bits used for node interleaving are discarded. Here we recover these
|
|
|
- * bits from the IntlvSel field of the DRAM Limit register (section
|
|
|
- * 3.4.4.2) for the node that input_addr is associated with.
|
|
|
- */
|
|
|
- pvt = mci->pvt_info;
|
|
|
- node_id = pvt->mc_node_id;
|
|
|
-
|
|
|
- BUG_ON(node_id > 7);
|
|
|
-
|
|
|
- intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0));
|
|
|
- if (intlv_shift == 0) {
|
|
|
- edac_dbg(1, " InputAddr 0x%lx translates to DramAddr of same value\n",
|
|
|
- (unsigned long)input_addr);
|
|
|
-
|
|
|
- return input_addr;
|
|
|
- }
|
|
|
-
|
|
|
- bits = ((input_addr & GENMASK(12, 35)) << intlv_shift) +
|
|
|
- (input_addr & 0xfff);
|
|
|
-
|
|
|
- intlv_sel = dram_intlv_sel(pvt, node_id) & ((1 << intlv_shift) - 1);
|
|
|
- dram_addr = bits + (intlv_sel << 12);
|
|
|
-
|
|
|
- edac_dbg(1, "InputAddr 0x%lx translates to DramAddr 0x%lx (%d node interleave bits)\n",
|
|
|
- (unsigned long)input_addr,
|
|
|
- (unsigned long)dram_addr, intlv_shift);
|
|
|
-
|
|
|
- return dram_addr;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * @dram_addr is a DramAddr that maps to the node represented by mci. Convert
|
|
|
- * @dram_addr to a SysAddr.
|
|
|
- */
|
|
|
-static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr)
|
|
|
-{
|
|
|
- struct amd64_pvt *pvt = mci->pvt_info;
|
|
|
- u64 hole_base, hole_offset, hole_size, base, sys_addr;
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
- ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
|
|
|
- &hole_size);
|
|
|
- if (!ret) {
|
|
|
- if ((dram_addr >= hole_base) &&
|
|
|
- (dram_addr < (hole_base + hole_size))) {
|
|
|
- sys_addr = dram_addr + hole_offset;
|
|
|
-
|
|
|
- edac_dbg(1, "using DHAR to translate DramAddr 0x%lx to SysAddr 0x%lx\n",
|
|
|
- (unsigned long)dram_addr,
|
|
|
- (unsigned long)sys_addr);
|
|
|
-
|
|
|
- return sys_addr;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- base = get_dram_base(pvt, pvt->mc_node_id);
|
|
|
- sys_addr = dram_addr + base;
|
|
|
-
|
|
|
- /*
|
|
|
- * The sys_addr we have computed up to this point is a 40-bit value
|
|
|
- * because the k8 deals with 40-bit values. However, the value we are
|
|
|
- * supposed to return is a full 64-bit physical address. The AMD
|
|
|
- * x86-64 architecture specifies that the most significant implemented
|
|
|
- * address bit through bit 63 of a physical address must be either all
|
|
|
- * 0s or all 1s. Therefore we sign-extend the 40-bit sys_addr to a
|
|
|
- * 64-bit value below. See section 3.4.2 of AMD publication 24592:
|
|
|
- * AMD x86-64 Architecture Programmer's Manual Volume 1 Application
|
|
|
- * Programming.
|
|
|
- */
|
|
|
- sys_addr |= ~((sys_addr & (1ull << 39)) - 1);
|
|
|
-
|
|
|
- edac_dbg(1, " Node %d, DramAddr 0x%lx to SysAddr 0x%lx\n",
|
|
|
- pvt->mc_node_id, (unsigned long)dram_addr,
|
|
|
- (unsigned long)sys_addr);
|
|
|
-
|
|
|
- return sys_addr;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * @input_addr is an InputAddr associated with the node given by mci. Translate
|
|
|
- * @input_addr to a SysAddr.
|
|
|
- */
|
|
|
-static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci,
|
|
|
- u64 input_addr)
|
|
|
-{
|
|
|
- return dram_addr_to_sys_addr(mci,
|
|
|
- input_addr_to_dram_addr(mci, input_addr));
|
|
|
-}
|
|
|
-
|
|
|
/* Map the Error address to a PAGE and PAGE OFFSET. */
|
|
|
static inline void error_address_to_page_and_offset(u64 error_address,
|
|
|
struct err_info *err)
|