From: Yazen Ghannam <yazen.ghannam@amd.com>
Date: Thu, 28 Oct 2021 17:56:58 +0000
Subject: EDAC/amd64: Allow for DF Indirect Broadcast reads
Git-commit: 448c3d6085b71aad58cd515469560ee76c982007
Patch-mainline: v5.17-rc1
References: jsc#PED-7615
The DF Indirect Access method allows for "Broadcast" accesses in which
case no specific instance is targeted. Add support using a reserved
instance ID of 0xFF to indicate a broadcast access. Set the FICAA
register appropriately.
Define helpers functions for instance and broadcast reads and use them
where appropriate.
Drop the "amd_" prefix since these functions are all static.
Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20211028175728.121452-4-yazen.ghannam@amd.com
Acked-by: Nikolay Borisov <nik.borisov@suse.com>
---
arch/x86/include/asm/amd_nb.h | 12 ++++++++++++
arch/x86/kernel/amd_nb.c | 2 +-
arch/x86/kernel/cpu/mce/amd.c | 12 ++++++------
3 files changed, 19 insertions(+), 7 deletions(-)
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -6,6 +6,8 @@
#include <linux/pci.h>
#include <linux/refcount.h>
+#define DF_BROADCAST 0xFF
+
struct amd_nb_bus_dev_range {
u8 bus;
u8 dev_base;
@@ -26,6 +28,16 @@ extern int amd_smn_read(u16 node, u32 ad
extern int amd_smn_write(u16 node, u32 address, u32 value);
extern int amd_df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo);
+static inline int df_indirect_read_instance(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo)
+{
+ return amd_df_indirect_read(node, func, reg, instance_id, lo);
+}
+
+static inline int df_indirect_read_broadcast(u16 node, u8 func, u16 reg, u32 *lo)
+{
+ return amd_df_indirect_read(node, func, reg, DF_BROADCAST, lo);
+}
+
struct amd_l3_cache {
unsigned indices;
u8 subcaches[4];
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -205,7 +205,7 @@ int amd_df_indirect_read(u16 node, u8 fu
if (!F4)
goto out;
- ficaa = 1;
+ ficaa = (instance_id == DF_BROADCAST) ? 0 : 1;
ficaa |= reg & 0x3FC;
ficaa |= (func & 0x7) << 11;
ficaa |= instance_id << 16;
--- a/arch/x86/kernel/cpu/mce/amd.c
+++ b/arch/x86/kernel/cpu/mce/amd.c
@@ -706,7 +706,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
bool hash_enabled = false;
/* Read D18F0x1B4 (DramOffset), check if base 1 is used. */
- if (amd_df_indirect_read(nid, 0, 0x1B4, umc, &tmp))
+ if (df_indirect_read_instance(nid, 0, 0x1B4, umc, &tmp))
goto out_err;
/* Remove HiAddrOffset from normalized address, if enabled: */
@@ -720,7 +720,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
}
/* Read D18F0x110 (DramBaseAddress). */
- if (amd_df_indirect_read(nid, 0, 0x110 + (8 * base), umc, &tmp))
+ if (df_indirect_read_instance(nid, 0, 0x110 + (8 * base), umc, &tmp))
goto out_err;
/* Check if address range is valid. */
@@ -743,7 +743,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
}
/* Read D18F0x114 (DramLimitAddress). */
- if (amd_df_indirect_read(nid, 0, 0x114 + (8 * base), umc, &tmp))
+ if (df_indirect_read_instance(nid, 0, 0x114 + (8 * base), umc, &tmp))
goto out_err;
intlv_num_sockets = (tmp >> 8) & 0x1;
@@ -799,7 +799,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
* umc/channel# as instance id of the coherent slave
* for FICAA.
*/
- if (amd_df_indirect_read(nid, 0, 0x50, umc, &tmp))
+ if (df_indirect_read_instance(nid, 0, 0x50, umc, &tmp))
goto out_err;
cs_fabric_id = (tmp >> 8) & 0xFF;
@@ -816,7 +816,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
/* Read D18F1x208 (SystemFabricIdMask). */
if (intlv_num_dies || intlv_num_sockets)
- if (amd_df_indirect_read(nid, 1, 0x208, umc, &tmp))
+ if (df_indirect_read_broadcast(nid, 1, 0x208, &tmp))
goto out_err;
/* If interleaved over more than 1 die. */
@@ -855,7 +855,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
/* If legacy MMIO hole enabled */
if (lgcy_mmio_hole_en) {
- if (amd_df_indirect_read(nid, 0, 0x104, umc, &tmp))
+ if (df_indirect_read_broadcast(nid, 0, 0x104, &tmp))
goto out_err;
dram_hole_base = tmp & GENMASK(31, 24);