From 684f3cadbfed1a9153a9b1b9e28cd5ba90112371 Mon Sep 17 00:00:00 2001 From: Pu Wen Date: Tue, 20 Feb 2024 20:32:33 +0800 Subject: [PATCH 1/4] EDAC/amd64: Revert hi_addr_offset for Hygon family 18h model 4h hygon inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I92H9L CVE: NA --------------------------- The HiAddrOffset is always the top 4 bits of normalized address, so revert the modification in commit 08fdc64fd095 to the original implementation. Fixes: 08fdc64fd095 ("EDAC/amd64: Adjust address translation for Hygon family 18h model 4h") Signed-off-by: Pu Wen --- arch/x86/kernel/cpu/mce/amd.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c index af4a83695970..780a27873249 100644 --- a/arch/x86/kernel/cpu/mce/amd.c +++ b/arch/x86/kernel/cpu/mce/amd.c @@ -660,12 +660,7 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) /* Remove HiAddrOffset from normalized address, if enabled: */ if (tmp & BIT(0)) { - u64 hi_addr_offset; - - if (hygon_f18h_m4h()) - hi_addr_offset = (tmp & GENMASK_ULL(31, 18)) << 8; - else - hi_addr_offset = (tmp & GENMASK_ULL(31, 20)) << 8; + u64 hi_addr_offset = (tmp & GENMASK_ULL(31, 20)) << 8; if (norm_addr >= hi_addr_offset) { ret_addr -= hi_addr_offset; -- Gitee From 7187e73a222dea8211dc2a10fbef0e7262ca27db Mon Sep 17 00:00:00 2001 From: Pu Wen Date: Tue, 20 Feb 2024 20:39:28 +0800 Subject: [PATCH 2/4] EDAC/amd64: Fix intlv_num_chan for Hygon family 18h model 4h hygon inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I92H9L CVE: NA --------------------------- Make the modification in commit 08fdc64fd095 to intlv_num_chan only for Hygon family 18h model 4h. Fixes: 08fdc64fd095 ("EDAC/amd64: Adjust address translation for Hygon family 18h model 4h") Signed-off-by: Pu Wen --- arch/x86/kernel/cpu/mce/amd.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c index 780a27873249..6ae54119205a 100644 --- a/arch/x86/kernel/cpu/mce/amd.c +++ b/arch/x86/kernel/cpu/mce/amd.c @@ -709,10 +709,6 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) switch (intlv_num_chan) { case 0: intlv_num_chan = 0; break; case 1: intlv_num_chan = 1; break; - case 2: - if (hygon_f18h_m4h()) - intlv_num_chan = 2; - break; case 3: intlv_num_chan = 2; break; case 5: intlv_num_chan = 3; break; case 7: intlv_num_chan = 4; break; @@ -721,6 +717,9 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) hash_enabled = true; break; default: + if (hygon_f18h_m4h() && boot_cpu_data.x86_model == 0x4 && + intlv_num_chan == 2) + break; pr_err("%s: Invalid number of interleaved channels %d.\n", __func__, intlv_num_chan); goto out_err; -- Gitee From 9735c0588291aeeac11a70ef5807231f9a29bfdf Mon Sep 17 00:00:00 2001 From: Pu Wen Date: Tue, 20 Feb 2024 20:43:26 +0800 Subject: [PATCH 3/4] x86/amd_nb: Get DF ID from F5 device for Hygon family 18h model 6h hygon inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I92H9L CVE: NA --------------------------- The DF ID should be get from DF F5 device for Hygon family 18h model 6h processor. Fixes: 950b6f3c6ad4 ("x86/amd_nb: Add support for Hygon family 18h model 6h") Signed-off-by: Pu Wen --- arch/x86/kernel/amd_nb.c | 73 +++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 53ab5b75d583..6e6f57b6b16b 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -27,6 +27,7 @@ #define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1 0x1491 #define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1 0x14b1 #define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4 0x14b4 +#define PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5 0x14b5 /* Protect the PCI config register pairs used for SMN and DF indirect access. */ static DEFINE_MUTEX(smn_mutex); @@ -250,43 +251,55 @@ u16 hygon_nb_num(void) } EXPORT_SYMBOL_GPL(hygon_nb_num); -static int get_df1_register(struct pci_dev *misc, int offset, u32 *value) +static int get_df_register(struct pci_dev *misc, u8 func, int offset, u32 *value) { - struct pci_dev *df_f1 = NULL; + struct pci_dev *df_func = NULL; u32 device; int err; - switch (boot_cpu_data.x86_model) { - case 0x4: - device = PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1; - break; - case 0x5: - if (misc->device == PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3) - device = PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1; - else + if (func == 1) { + switch (boot_cpu_data.x86_model) { + case 0x4: device = PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1; - break; - case 0x6: - device = PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1; - break; - default: + break; + case 0x5: + if (misc->device == PCI_DEVICE_ID_HYGON_18H_M05H_DF_F3) + device = PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1; + else + device = PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1; + break; + case 0x6: + device = PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1; + break; + default: + return -ENODEV; + } + } else if (func == 5) { + switch (boot_cpu_data.x86_model) { + case 0x6: + device = PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5; + break; + default: + return -ENODEV; + } + } else { return -ENODEV; } - while ((df_f1 = pci_get_device(misc->vendor, device, df_f1))) - if (pci_domain_nr(df_f1->bus) == pci_domain_nr(misc->bus) && - df_f1->bus->number == misc->bus->number && - PCI_SLOT(df_f1->devfn) == PCI_SLOT(misc->devfn)) + while ((df_func = pci_get_device(misc->vendor, device, df_func))) + if (pci_domain_nr(df_func->bus) == pci_domain_nr(misc->bus) && + df_func->bus->number == misc->bus->number && + PCI_SLOT(df_func->devfn) == PCI_SLOT(misc->devfn)) break; - if (!df_f1) { - pr_warn("Error getting DF F1 device.\n"); + if (!df_func) { + pr_warn("Error getting DF F%d device.\n", func); return -ENODEV; } - err = pci_read_config_dword(df_f1, offset, value); + err = pci_read_config_dword(df_func, offset, value); if (err) - pr_warn("Error reading DF F1 register.\n"); + pr_warn("Error reading DF F%d register.\n", func); return err; } @@ -296,9 +309,15 @@ int get_df_id(struct pci_dev *misc, u8 *id) u32 value; int ret; - /* F1x200[23:20]: DF ID */ - ret = get_df1_register(misc, 0x200, &value); - *id = (value >> 20) & 0xf; + if (boot_cpu_data.x86_model == 0x6) { + /* F5x180[19:16]: DF ID */ + ret = get_df_register(misc, 5, 0x180, &value); + *id = (value >> 16) & 0xf; + } else { + /* F1x200[23:20]: DF ID */ + ret = get_df_register(misc, 1, 0x200, &value); + *id = (value >> 20) & 0xf; + } return ret; } @@ -310,7 +329,7 @@ static u8 get_socket_num(struct pci_dev *misc) int ret; /* F1x200[7:0]: Which socket is present. */ - ret = get_df1_register(misc, 0x200, &value); + ret = get_df_register(misc, 1, 0x200, &value); return ret ? 0 : hweight8(value & 0xff); } -- Gitee From ebbdd648428c85dc97339f86e86d2c3566745dde Mon Sep 17 00:00:00 2001 From: Pu Wen Date: Tue, 20 Feb 2024 20:45:28 +0800 Subject: [PATCH 4/4] EDAC/amd64: Adjust UMC channel for Hygon family 18h model 6h hygon inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I92H9L CVE: NA --------------------------- Hygon family 18h model 6h has 2 cs mapped to 1 umc, so adjust for it. Fixes: 950b6f3c6ad4 ("EDAC/amd64: Add support for Hygon family 18h model 6h") Signed-off-by: Pu Wen --- drivers/edac/amd64_edac.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index ef80e27d5503..663e9b9cd856 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2737,6 +2737,7 @@ static void decode_umc_error(int node_id, struct mce *m) struct amd64_pvt *pvt; struct err_info err; u64 sys_addr; + u8 umc; mci = edac_mc_find(node_id); if (!mci) @@ -2767,7 +2768,12 @@ static void decode_umc_error(int node_id, struct mce *m) err.csrow = m->synd & 0x7; - if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) { + if (hygon_f18h_m4h() && boot_cpu_data.x86_model == 0x6) + umc = err.channel << 1; + else + umc = err.channel; + + if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, umc, &sys_addr)) { err.err_code = ERR_NORM_ADDR; goto log_error; } -- Gitee