[PATCH v8 3/3] powerpc/sysfs: Add topology/smallcore_thread_siblings[_list]

From: Gautham R. Shenoy
Date: Thu Sep 20 2018 - 13:23:11 EST


From: "Gautham R. Shenoy" <ego@xxxxxxxxxxxxxxxxxx>

This patch adds two sysfs attributes named smallcore_thread_siblings
and smallcore_thread_siblings_list to the "topology" attribute group
for each CPU device.

The read-only attributes
/sys/device/system/cpu/cpuN/topology/smallcore_thread_siblings and
/sys/device/system/cpu/cpuN/topology/smallcore_thread_siblings_list
will the online siblings of CPU N that share the L1 cache with it on
big-core configurations in cpumask format and cpu-list format
respectively.

Signed-off-by: Gautham R. Shenoy <ego@xxxxxxxxxxxxxxxxxx>
---
Documentation/ABI/testing/sysfs-devices-system-cpu | 14 ++++
arch/powerpc/kernel/sysfs.c | 88 ++++++++++++++++++++++
2 files changed, 102 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 7331822..2a80dc2 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -511,3 +511,17 @@ Description: Control Symetric Multi Threading (SMT)

If control status is "forceoff" or "notsupported" writes
are rejected.
+
+What: /sys/devices/system/cpu/cpu#/topology/smallcore_thread_siblings
+ /sys/devices/system/cpu/cpu#/topology/smallcore_thread_siblings_list
+Date: Sept 2018
+Contact: Linux for PowerPC mailing list <linuxppc-dev@xxxxxxxxxx>
+Description: CPU topology files that describe the thread siblings of a
+ logical CPU that share the L1-cache with it on POWER9
+ big-core configurations.
+
+ smallcore_thread_siblings: internal kernel map of
+ cpu#'s hardware threads that share L1-cache with cpu#.
+
+ smallcore_thread_siblings_list: human-readable list of
+ cpu#'s hardware threads that share L1-cache with cpu#.
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 755dc98..f9c7d96 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -18,6 +18,7 @@
#include <asm/smp.h>
#include <asm/pmc.h>
#include <asm/firmware.h>
+#include <asm/cputhreads.h>

#include "cacheinfo.h"
#include "setup.h"
@@ -714,6 +715,62 @@ static void sysfs_create_dscr_default(void)
#endif /* HAS_PPC_PMC_PA6T */
#endif /* HAS_PPC_PMC_CLASSIC */

+static ssize_t smallcore_thread_siblings_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int cpu = dev->id;
+
+ return cpumap_print_to_pagebuf(false, buf, cpu_smallcore_mask(cpu));
+}
+static DEVICE_ATTR_RO(smallcore_thread_siblings);
+
+static ssize_t smallcore_thread_siblings_list_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int cpu = dev->id;
+
+ return cpumap_print_to_pagebuf(true, buf, cpu_smallcore_mask(cpu));
+}
+static DEVICE_ATTR_RO(smallcore_thread_siblings_list);
+
+static struct attribute *smallcore_attrs[] = {
+ &dev_attr_smallcore_thread_siblings.attr,
+ &dev_attr_smallcore_thread_siblings_list.attr,
+ NULL
+};
+
+static const struct attribute_group smallcore_attr_group = {
+ .name = "topology",
+ .attrs = smallcore_attrs
+};
+
+static int smallcore_register_cpu_online(unsigned int cpu)
+{
+ int err;
+ struct device *cpu_dev = get_cpu_device(cpu);
+
+ if (!has_big_cores)
+ return 0;
+
+ err = sysfs_merge_group(&cpu_dev->kobj, &smallcore_attr_group);
+
+ return err;
+}
+
+static int smallcore_unregister_cpu_online(unsigned int cpu)
+{
+ struct device *cpu_dev = get_cpu_device(cpu);
+
+ if (!has_big_cores)
+ return 0;
+
+ sysfs_unmerge_group(&cpu_dev->kobj, &smallcore_attr_group);
+
+ return 0;
+}
+
static int register_cpu_online(unsigned int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
@@ -1060,3 +1117,34 @@ static int __init topology_init(void)
return 0;
}
subsys_initcall(topology_init);
+
+/*
+ * NOTE: The smallcore_register_cpu_online
+ * (resp. smallcore_unregister_cpu_online) callback will merge
+ * (resp. unmerge) a couple of additional attributes to the
+ * "topology" attribute group of a CPU device when the CPU comes
+ * online (resp. goes offline).
+ *
+ * Hence, the registration of these callbacks must happen after
+ * topology_sysfs_init() is called so that the topology
+ * attribute group is created before these additional attributes
+ * can be merged/unmerged. We cannot register these callbacks in
+ * topology_init() since this function is called before
+ * topology_sysfs_init(). Hence we define the following
+ * late_initcall for this purpose.
+ */
+static int __init smallcore_topology_init(void)
+{
+ int r;
+
+ if (!has_big_cores)
+ return 0;
+
+ r = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+ "powerpc/topology/smallcore:online",
+ smallcore_register_cpu_online,
+ smallcore_unregister_cpu_online);
+ WARN_ON(r < 0);
+ return 0;
+}
+late_initcall(smallcore_topology_init);
--
1.9.4