From nobody Thu Apr 16 08:39:36 2026 Received: from out28-197.mail.aliyun.com (out28-197.mail.aliyun.com [115.124.28.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B4B0922A4F1 for ; Sun, 1 Mar 2026 14:13:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772374416; cv=none; b=dDeFMwCxusG42V4SgmY1H/MROklFmKrU+PKOldpjBBUFrrvO/66mQGB6JJmdxcR4oY+GnjYmn41yu92LZBGF5TTwrnFAxzX8tBRQhDso9aaB9d3WXhyZZK9cNdvVqYu1Styf/2JBcKb+u5o2FZw5UjJajmj1NXMiecCrxtzaCSI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772374416; c=relaxed/simple; bh=5VwHe6byTaPa2BXSIBaSlDc9uq5H2sUQC5s8VM2ljsc=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=l9PYkqCcX98yHVBJyiF1T/sxsTqaPyvlES4HJjWukQHFuzKl7VONHmjUWOjauuIWquf2sZw7SlI5Dh85uRS59dmEi4H3CkMqbwNWlvyoPvp83zyPMFV5C+Qt44grnMw1qUsyXTaqH3Cy0M/Qv6dHdl4EfWHD83wGP/V9xxm1cVM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=115.124.28.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.ghxJvB7_1772374394 cluster:ay29) by smtp.aliyun-inc.com; Sun, 01 Mar 2026 22:13:23 +0800 From: Aichun Shi To: yazen.ghannam@amd.com Cc: tglx@kernel.org, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [PATCH] x86/topology: Fix Hygon logical_die_id by mapping from amd_node_id Date: Sun, 1 Mar 2026 22:11:56 +0800 Message-ID: <20260301141157.241770-1-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" On Hygon CPUs, for some cases such as EDAC error decoding, contiguous die IDs are required. cpuinfo_topology.amd_node_id cannot be used directly as it may be non-contiguous, thus cpuinfo_topology.logical_die_id can be used in such cases. When CPUID leaf 0x80000026 is not available on Hygon CPUs, die (or node) topology is not encoded in APIC ID space. logical_die_id obtained from topology_get_logical_id(apicid, TOPO_DIE_DOMAIN) therefore does not align with die (or node) topology and is incorrect. Fix this by adding a Hygon-only fixup in a new topology_hygon.c: Build a bijective mapping from (logical_pkg_id, amd_node_id) to a contiguous logical_die_id. Leave the original APIC-based path unchanged when CPUID leaf 0x80000026 is available. Signed-off-by: Aichun Shi --- arch/x86/kernel/cpu/Makefile | 2 +- arch/x86/kernel/cpu/topology.h | 5 ++ arch/x86/kernel/cpu/topology_common.c | 3 + arch/x86/kernel/cpu/topology_hygon.c | 86 +++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 arch/x86/kernel/cpu/topology_hygon.c diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 2f8a58ef690e..4e80d0a5d0c9 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -38,10 +38,10 @@ obj-y +=3D intel.o tsx.o obj-$(CONFIG_PM) +=3D intel_epb.o endif obj-$(CONFIG_CPU_SUP_AMD) +=3D amd.o +obj-$(CONFIG_CPU_SUP_HYGON) +=3D hygon.o topology_hygon.o ifeq ($(CONFIG_AMD_NB)$(CONFIG_SYSFS),yy) obj-y +=3D amd_cache_disable.o endif -obj-$(CONFIG_CPU_SUP_HYGON) +=3D hygon.o obj-$(CONFIG_CPU_SUP_CYRIX_32) +=3D cyrix.o obj-$(CONFIG_CPU_SUP_CENTAUR) +=3D centaur.o obj-$(CONFIG_CPU_SUP_TRANSMETA_32) +=3D transmeta.o diff --git a/arch/x86/kernel/cpu/topology.h b/arch/x86/kernel/cpu/topology.h index 37326297f80c..7203ff0457a4 100644 --- a/arch/x86/kernel/cpu/topology.h +++ b/arch/x86/kernel/cpu/topology.h @@ -22,6 +22,11 @@ void topology_set_dom(struct topo_scan *tscan, enum x86_= topology_domains dom, bool cpu_parse_topology_ext(struct topo_scan *tscan); void cpu_parse_topology_amd(struct topo_scan *tscan); void cpu_topology_fixup_amd(struct topo_scan *tscan); +#ifdef CONFIG_CPU_SUP_HYGON +void cpu_topology_fixup_hygon(struct topo_scan *tscan); +#else +static inline void cpu_topology_fixup_hygon(struct topo_scan *tscan) { } +#endif =20 static inline u32 topo_shift_apicid(u32 apicid, enum x86_topology_domains = dom) { diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/to= pology_common.c index 71625795d711..82803744bd0e 100644 --- a/arch/x86/kernel/cpu/topology_common.c +++ b/arch/x86/kernel/cpu/topology_common.c @@ -199,6 +199,9 @@ static void topo_set_ids(struct topo_scan *tscan, bool = early) =20 if (c->x86_vendor =3D=3D X86_VENDOR_AMD) cpu_topology_fixup_amd(tscan); + + if (c->x86_vendor =3D=3D X86_VENDOR_HYGON && !early) + cpu_topology_fixup_hygon(tscan); } =20 void cpu_parse_topology(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/topology_hygon.c b/arch/x86/kernel/cpu/top= ology_hygon.c new file mode 100644 index 000000000000..645c30524da6 --- /dev/null +++ b/arch/x86/kernel/cpu/topology_hygon.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +#include + +#include "topology.h" + +/* (logical_pkg_id, amd_node_id) -> logical_die_id mapping. */ +struct hygon_die_map_entry { + u32 logical_pkg_id; + u32 amd_node_id; + u32 logical_die_id; +}; + +static DEFINE_SPINLOCK(hygon_die_map_lock); +static struct hygon_die_map_entry hygon_die_map[NR_CPUS]; +static u32 hygon_next_logical_die_id; +static unsigned int hygon_die_map_nr; + +/* + * Build a bijective mapping from (logical_pkg_id, amd_node_id) to a conti= guous + * logical_die_id for Hygon CPUs. + * + * Returns logical_die_id (>=3D 0) on success, or -EINVAL on error. + */ +static int hygon_get_logical_die_id(struct topo_scan *tscan) +{ + struct cpuinfo_x86 *c =3D tscan->c; + unsigned long flags; + int logical_die_id; + unsigned int i; + int logical_pkg_id =3D c->topo.logical_pkg_id; + + if (c->x86_vendor !=3D X86_VENDOR_HYGON) + return -EINVAL; + + if (logical_pkg_id < 0) + return -EINVAL; + + spin_lock_irqsave(&hygon_die_map_lock, flags); + + /* Look up existing (logical_pkg_id, amd_node_id) -> logical_die_id. */ + for (i =3D 0; i < hygon_die_map_nr; i++) { + if (hygon_die_map[i].logical_pkg_id =3D=3D logical_pkg_id && + hygon_die_map[i].amd_node_id =3D=3D tscan->amd_node_id) { + logical_die_id =3D hygon_die_map[i].logical_die_id; + goto out_unlock; + } + } + + if (hygon_die_map_nr >=3D ARRAY_SIZE(hygon_die_map)) { + pr_warn_once("CPU topo: Hygon die map exhausted\n"); + logical_die_id =3D -EINVAL; + goto out_unlock; + } + + /* Allocate new contiguous logical_die_id. */ + logical_die_id =3D hygon_next_logical_die_id++; + hygon_die_map[hygon_die_map_nr++] =3D (struct hygon_die_map_entry) { + .logical_pkg_id =3D logical_pkg_id, + .amd_node_id =3D tscan->amd_node_id, + .logical_die_id =3D logical_die_id, + }; + +out_unlock: + spin_unlock_irqrestore(&hygon_die_map_lock, flags); + return logical_die_id; +} + +void cpu_topology_fixup_hygon(struct topo_scan *tscan) +{ + /* Skip the fixup if CPUID leaf 0x80000026 is available. */ + if (tscan->c->extended_cpuid_level >=3D 0x80000026) + return; + + /* When CPUID leaf 0x80000026 is not available, die (node) topology is + * not encoded in APIC ID space. logical_die_id from the DIE domain is + * incorrect, so fix it up. + */ + int logical_die_id =3D hygon_get_logical_die_id(tscan); + + if (logical_die_id >=3D 0) + tscan->c->topo.logical_die_id =3D logical_die_id; +} --=20 2.47.3