When the topology mode is TOPOLOGY_MODE_HW, topology_init_early()
already parses the set of socket present on the system.

Use the socket_info to configure the sparsebitmask (sbm) properties for
the system - namely the number of sockets and maximum threads in a
socket instance.

arch_sbm_cpu_instance_id() traverses all socket instances to find
a matching CPU which is not optimal but instance ID is only checked
when the CPU is coming online. Since this is a rare event, the
inefficiency is tolerable.

Signed-off-by: K Prateek Nayak <[email protected]>
---
Build tested with LKP's s390 randconfig with QEMU cmdline:

  qemu-system-s390x \
  -cpu max \
  -smp 2 \
  -m 2048 \
  -kernel ./arch/s390/boot/vmlinux  \
  -append "console=ttyAMA0 earlycon ignore_loglevel log_buf_len=10M 
print_fatal_signals=1 LOGLEVEL=8 sched_debug" \
  -nographic

Note: Since ctop needs KVM acceleration to emulate TOPOLOGY_MODE_HW, the
actual spasemask setting is only build tested at the moment.

XXX: Any way around this using cross-compile and QEMU?
---
 arch/s390/kernel/topology.c | 52 +++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 1377c6f3f670..80dc51f5ce6f 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/cpu.h>
+#include <linux/sbm.h>
 #include <linux/smp.h>
 #include <linux/mm.h>
 #include <linux/nodemask.h>
@@ -561,6 +562,55 @@ static int __init detect_polarization(union topology_entry 
*tle)
        return tl_core->pp != POLARIZATION_HRZ;
 }
 
+int arch_sbm_cpu_instance_id(int cpu)
+{
+       struct mask_info *info = &socket_info;
+
+       /*
+        * sbm core should not call this if sbm_set_topology() was
+        * skipped below due to lack of topology information.
+        */
+       if (WARN_ON_ONCE(topology_mode != TOPOLOGY_MODE_HW))
+               return -1;
+
+       while (info) {
+               if (cpumask_test_cpu(cpu, &info->mask))
+                       return info->id;
+               info = info->next;
+       }
+
+       pr_warn_once("socket mapping for CPU%d not found! Mapping to ID 0", 
cpu);
+       return 0;
+}
+
+static void __configure_sbm_topology(void)
+{
+       int num_sbm_instances = 0, max_threads_per_instance = -1;
+       struct mask_info *info = &socket_info;
+
+       /*
+        * Consider single package if topology
+        * information is unavailable.
+        *
+        * sbm core will handle the initialization.
+        */
+       if (topology_mode != TOPOLOGY_MODE_HW)
+               return;
+
+       while (info) {
+               num_sbm_instances += 1;
+               max_threads_per_instance = max_t(int,
+                                                cpumask_weight(&info->mask),
+                                                max_threads_per_instance);
+               info = info->next;
+       }
+
+       if (WARN_ON_ONCE(!num_sbm_instances || max_threads_per_instance < 1))
+               return;
+
+       sbm_set_topology(num_sbm_instances, max_threads_per_instance);
+}
+
 void __init topology_init_early(void)
 {
        struct sysinfo_15_1_x *info;
@@ -588,6 +638,8 @@ void __init topology_init_early(void)
        cpumask_set_cpu(0, &cpu_setup_mask);
        __arch_update_cpu_topology();
        __arch_update_dedicated_flag(NULL);
+
+       __configure_sbm_topology();
 }
 
 static inline int topology_get_mode(int enabled)
-- 
2.34.1


Reply via email to