diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 1194b20a7cccff89a036f627a043cec56b59f315..57f6ecb117c04b1df3fa43443dd839214ae47d76 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -641,7 +641,12 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) u32 tmp; - u8 die_id_shift, die_id_mask, socket_id_shift, socket_id_mask; + u8 die_id_shift, socket_id_shift; +#ifdef CONFIG_CPU_SUP_HYGON + u16 die_id_mask, socket_id_mask; +#else + u8 die_id_mask, socket_id_mask; +#endif u8 intlv_num_dies, intlv_num_chan, intlv_num_sockets; u8 intlv_addr_sel, intlv_addr_bit; u8 num_intlv_bits, hashed_bit; @@ -650,7 +655,7 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) bool hash_enabled = false; /* Read DramOffset, check if base 1 is used. */ - if (hygon_f18h_m4h() && + if ((hygon_f18h_m4h() || hygon_f18h_m10h()) && amd_df_indirect_read(nid, 0, 0x214, umc, &tmp)) goto out_err; else if (amd_df_indirect_read(nid, 0, 0x1B4, umc, &tmp)) @@ -678,7 +683,7 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) } intlv_num_sockets = 0; - if (hygon_f18h_m4h()) + if (hygon_f18h_m4h() || hygon_f18h_m10h()) intlv_num_sockets = (tmp >> 2) & 0x3; lgcy_mmio_hole_en = tmp & BIT(1); intlv_num_chan = (tmp >> 4) & 0xF; @@ -696,13 +701,20 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) if (amd_df_indirect_read(nid, 0, 0x114 + (8 * base), umc, &tmp)) goto out_err; - if (!hygon_f18h_m4h()) + if (!hygon_f18h_m4h() && !hygon_f18h_m10h()) intlv_num_sockets = (tmp >> 8) & 0x1; intlv_num_dies = (tmp >> 10) & 0x3; dram_limit_addr = ((tmp & GENMASK_ULL(31, 12)) << 16) | GENMASK_ULL(27, 0); intlv_addr_bit = intlv_addr_sel + 8; + if ((hygon_f18h_m4h() && boot_cpu_data.x86_model >= 0x6) || + hygon_f18h_m10h()) { + if (amd_df_indirect_read(nid, 0, 0x60, umc, &tmp)) + goto out_err; + intlv_num_dies = tmp & 0x3; + } + /* Re-use intlv_num_chan by setting it equal to log2(#channels) */ switch (intlv_num_chan) { case 0: intlv_num_chan = 0; break; @@ -746,7 +758,12 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) if (num_intlv_bits > 0) { u64 temp_addr_x, temp_addr_i, temp_addr_y; - u8 die_id_bit, sock_id_bit, cs_fabric_id; + u8 die_id_bit, sock_id_bit; +#ifdef CONFIG_CPU_SUP_HYGON + u16 cs_fabric_id; +#else + u8 cs_fabric_id; +#endif /* * Read FabricBlockInstanceInformation3_CS[BlockFabricID]. @@ -757,7 +774,7 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) if (amd_df_indirect_read(nid, 0, 0x50, umc, &tmp)) goto out_err; - if (hygon_f18h_m4h()) + if (hygon_f18h_m4h() || hygon_f18h_m10h()) cs_fabric_id = (tmp >> 8) & 0x7FF; else cs_fabric_id = (tmp >> 8) & 0xFF; @@ -783,12 +800,14 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) if (hygon_f18h_m4h()) { die_id_shift = (tmp >> 12) & 0xF; die_id_mask = tmp & 0x7FF; + cs_id |= (((cs_fabric_id & die_id_mask) >> die_id_shift) - 4) << + die_id_bit; } else { die_id_shift = (tmp >> 24) & 0xF; die_id_mask = (tmp >> 8) & 0xFF; + cs_id |= ((cs_fabric_id & die_id_mask) >> die_id_shift) << + die_id_bit; } - - cs_id |= ((cs_fabric_id & die_id_mask) >> die_id_shift) << die_id_bit; } /* If interleaved over more than 1 socket. */