Once the CPU topology is parsed, initialize the sparsebitmap (sbm)
topology by counting the number of LLC / NUMA instances in the system
and the maximum number of threads in these instance.

Similar to alloc_irqstack_bootmem(), init_sbm_topology() is done after
setup_arch() has finished mapping the cache, socket, and NUMA IDs for
all the present CPUs.

arch_sbm_cpu_instance_id() uses a combination of cpu_to_node() and
max_cache_id to determine the sparsemask instances.

Signed-off-by: K Prateek Nayak <[email protected]>
---
Tested with sparc64_defconfig with

  qemu-system-sparc64 \
  -M sun4u \
  -m 512 \
  -kernel vmlinux \
  -nographic -append "console=ttyS0"

Similar to some of my previous attempts, I was not able to boot a SMP
configuration with qemu-system-sparc64. For all purposes, sbm
initialization is only build tested.
---
 arch/sparc/kernel/setup_64.c | 45 ++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index 63615f5c99b4..7ab52d17e46f 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -28,6 +28,7 @@
 #include <linux/root_dev.h>
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
+#include <linux/sbm.h>
 #include <linux/initrd.h>
 #include <linux/module.h>
 #include <linux/start_kernel.h>
@@ -53,6 +54,7 @@
 #include <asm/cacheflush.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
+#include <asm/cpudata.h>
 
 #ifdef CONFIG_IP_PNP
 #include <net/ipconfig.h>
@@ -619,6 +621,48 @@ static void __init alloc_irqstack_bootmem(void)
        }
 }
 
+static struct cpumask cpu_sbm_setup_map __initdata;
+static int __node_thread_count[NR_CPUS] __initdata;
+
+int arch_sbm_cpu_instance_id(int cpu)
+{
+       /* Combine the node and cache identifier. */
+       return ((u32)cpu_to_node(cpu) << 16) |
+              cpu_data(cpu).max_cache_id;
+}
+
+static void __init init_sbm_topology(void)
+{
+       int num_sbm_instances, max_threads_per_instance = 1;
+       int i;
+
+       for_each_possible_cpu(i) {
+               bool found = false;
+               int j;
+
+               for_each_cpu(j, &cpu_sbm_setup_map) {
+                       if (cpu_to_node(i) == cpu_to_node(j) &&
+                           cpu_data(i).max_cache_id == 
cpu_data(j).max_cache_id) {
+                               found = true;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       cpumask_set_cpu(i, &cpu_sbm_setup_map);
+                       __node_thread_count[i] = 1;
+                       continue;
+               }
+
+               __node_thread_count[j] += 1;
+               max_threads_per_instance = max(max_threads_per_instance,
+                                              __node_thread_count[j]);
+       }
+
+       num_sbm_instances = cpumask_weight(&cpu_sbm_setup_map);
+       sbm_set_topology(num_sbm_instances, max_threads_per_instance);
+}
+
 void __init setup_arch(char **cmdline_p)
 {
        /* Initialize PROM console and command line. */
@@ -677,6 +721,7 @@ void __init setup_arch(char **cmdline_p)
         * allocate the IRQ stacks.
         */
        alloc_irqstack_bootmem();
+       init_sbm_topology();
 }
 
 extern int stop_a_enabled;
-- 
2.34.1


Reply via email to