[PATCH RFC 3/3] riscv: topology: Expose explicit CPU die topology

From: Troy Mitchell

Date: Sat Sep 19 2026 - 23:20:01 EST


RISC-V uses the generic CPU topology model but does not provide die
topology accessors. The generic sysfs topology code consequently cannot
expose die identifiers or die sibling masks when firmware describes them.

Simply adding the accessors would create die_id, die_cpus, and
die_cpus_list on every RISC-V CPU. That would also expose -1 and a
single-CPU mask when neither DT nor ACPI supplied a die hierarchy.

Add an architecture-selectable visibility predicate for the die sysfs
attributes. Its default preserves the existing sysfs ABI on architectures
that already expose die topology. Make RISC-V expose the attributes only
when the generic topology parser recorded a non-negative die ID.

Legacy DTs, the current ACPI path, and the fallback topology leave die_id
at -1, so RISC-V does not create die sysfs files for them.

Signed-off-by: Troy Mitchell <troy.mitchell@xxxxxxxxx>
---
arch/riscv/include/asm/topology.h | 4 ++++
drivers/base/topology.c | 28 +++++++++++++++++++++++++++-
include/linux/topology.h | 3 +++
3 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/topology.h b/arch/riscv/include/asm/topology.h
index fe1a8bf6902d9..5d99cb39f2819 100644
--- a/arch/riscv/include/asm/topology.h
+++ b/arch/riscv/include/asm/topology.h
@@ -8,6 +8,10 @@
#include <asm/numa.h>
#endif

+#define topology_die_id(cpu) (cpu_topology[cpu].die_id)
+#define topology_die_cpumask(cpu) (&cpu_topology[cpu].die_sibling)
+#define topology_die_sysfs_visible(cpu) (topology_die_id(cpu) >= 0)
+
/* Replace task scheduler's default frequency-invariant accounting */
#define arch_scale_freq_tick topology_scale_freq_tick
#define arch_set_freq_scale topology_set_freq_scale
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index c890e2a5b4280..74d5bb979b1b8 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -171,16 +171,42 @@ static struct attribute *default_attrs[] = {
static umode_t topology_is_visible(struct kobject *kobj,
struct attribute *attr, int unused)
{
- if (attr == &dev_attr_ppin.attr && !topology_ppin(kobj_to_dev(kobj)->id))
+ unsigned int cpu = kobj_to_dev(kobj)->id;
+
+#ifdef TOPOLOGY_DIE_SYSFS
+ if (attr == &dev_attr_die_id.attr &&
+ !topology_die_sysfs_visible(cpu))
+ return 0;
+#endif
+
+ if (attr == &dev_attr_ppin.attr && !topology_ppin(cpu))
return 0;

return attr->mode;
}

+#ifdef TOPOLOGY_DIE_SYSFS
+static umode_t topology_bin_is_visible(struct kobject *kobj,
+ const struct bin_attribute *attr, int unused)
+{
+ unsigned int cpu = kobj_to_dev(kobj)->id;
+
+ if ((attr == &bin_attr_die_cpus ||
+ attr == &bin_attr_die_cpus_list) &&
+ !topology_die_sysfs_visible(cpu))
+ return 0;
+
+ return attr->attr.mode;
+}
+#endif
+
static const struct attribute_group topology_attr_group = {
.attrs = default_attrs,
.bin_attrs = bin_attrs,
.is_visible = topology_is_visible,
+#ifdef TOPOLOGY_DIE_SYSFS
+ .is_bin_visible = topology_bin_is_visible,
+#endif
.name = "topology"
};

diff --git a/include/linux/topology.h b/include/linux/topology.h
index 709a2dcf4c738..9c2c9096aff36 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -179,6 +179,9 @@ static inline int cpu_to_mem(int cpu)

#if defined(topology_die_id) && defined(topology_die_cpumask)
#define TOPOLOGY_DIE_SYSFS
+#ifndef topology_die_sysfs_visible
+#define topology_die_sysfs_visible(cpu) ((void)(cpu), true)
+#endif
#endif
#if defined(topology_cluster_id) && defined(topology_cluster_cpumask)
#define TOPOLOGY_CLUSTER_SYSFS

--
2.55.0