[PATCH RFC 1/3] arch_topology: Add a die level to CPU topology

From: Troy Mitchell

Date: Sat Sep 19 2026 - 23:18:43 EST


The generic topology model records packages and clusters but has no
representation for a die between them. Systems with multiple dies in one
package must therefore either report each die as a package or flatten
clusters across all dies. Both choices lose part of the physical hierarchy.

Add a die identifier and sibling mask between the package and cluster
levels. Initialize the identifier to -1 and only build die sibling masks
when firmware supplied a valid identifier. CPU topology paths without die
information, including the current ACPI parser and the fallback topology,
therefore keep the die unknown instead of inventing die 0.

Scope cluster sibling matching to a die so each die can number its
clusters independently, and maintain the new mask across CPU hotplug.

Signed-off-by: Troy Mitchell <troy.mitchell@xxxxxxxxx>
---
drivers/base/arch_topology.c | 20 +++++++++++++++++---
include/linux/arch_topology.h | 2 ++
2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index 8c5e47c28d9a3..ee82827be3351 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -766,6 +766,14 @@ void update_siblings_masks(unsigned int cpuid)
cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);

+ if (cpuid_topo->die_id != cpu_topo->die_id)
+ continue;
+
+ if (cpuid_topo->die_id >= 0) {
+ cpumask_set_cpu(cpu, &cpuid_topo->die_sibling);
+ cpumask_set_cpu(cpuid, &cpu_topo->die_sibling);
+ }
+
if (cpuid_topo->cluster_id != cpu_topo->cluster_id)
continue;

@@ -792,6 +800,9 @@ static void clear_cpu_topology(int cpu)
cpumask_clear(&cpu_topo->cluster_sibling);
cpumask_set_cpu(cpu, &cpu_topo->cluster_sibling);

+ cpumask_clear(&cpu_topo->die_sibling);
+ cpumask_set_cpu(cpu, &cpu_topo->die_sibling);
+
cpumask_clear(&cpu_topo->core_sibling);
cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
cpumask_clear(&cpu_topo->thread_sibling);
@@ -808,6 +819,7 @@ void __init reset_cpu_topology(void)
cpu_topo->thread_id = -1;
cpu_topo->core_id = -1;
cpu_topo->cluster_id = -1;
+ cpu_topo->die_id = -1;
cpu_topo->package_id = -1;

clear_cpu_topology(cpu);
@@ -824,6 +836,8 @@ void remove_cpu_topology(unsigned int cpu)
cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling));
for_each_cpu(sibling, topology_cluster_cpumask(cpu))
cpumask_clear_cpu(cpu, topology_cluster_cpumask(sibling));
+ for_each_cpu(sibling, &cpu_topology[cpu].die_sibling)
+ cpumask_clear_cpu(cpu, &cpu_topology[sibling].die_sibling);
for_each_cpu(sibling, topology_llc_cpumask(cpu))
cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling));

@@ -969,9 +983,9 @@ void store_cpu_topology(unsigned int cpuid)
cpuid_topo->core_id = cpuid;
cpuid_topo->package_id = cpu_to_node(cpuid);

- pr_debug("CPU%u: package %d core %d thread %d\n",
- cpuid, cpuid_topo->package_id, cpuid_topo->core_id,
- cpuid_topo->thread_id);
+ pr_debug("CPU%u: package %d die %d core %d thread %d\n",
+ cpuid, cpuid_topo->package_id, cpuid_topo->die_id,
+ cpuid_topo->core_id, cpuid_topo->thread_id);

topology_populated:
update_siblings_masks(cpuid);
diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h
index ebd7f8935f969..2a5591bb95075 100644
--- a/include/linux/arch_topology.h
+++ b/include/linux/arch_topology.h
@@ -63,10 +63,12 @@ struct cpu_topology {
int thread_id;
int core_id;
int cluster_id;
+ int die_id;
int package_id;
cpumask_t thread_sibling;
cpumask_t core_sibling;
cpumask_t cluster_sibling;
+ cpumask_t die_sibling;
cpumask_t llc_sibling;
};


--
2.55.0