Coregroup support is currently disabled for shared LPARs even when the
associativity hierarchy contains the information required to identify
the coregroup level.

The associativity hierarchy differs between shared and dedicated LPARs.
For dedicated LPARs, the hierarchy must extend beyond
primary_domain_index + 1 to contain a coregroup level. Shared LPARs have
one fewer level, so a coregroup is available when the hierarchy extends
beyond primary_domain_index.

Remove the unconditional exclusion of shared processors from coregroup
support and use the appropriate hierarchy when detecting a coregroup
level. Read the coregroup ID from the associativity level immediately
following the primary NUMA domain. If no distinct coregroup ID is
available, fall back to the core ID.

The processor sharing mode is not known when NUMA properties are
initially parsed and is determined later in pSeries_setup_arch().
Therefore, initially process CPU associativity using the existing
dedicated-LPAR interpretation and reprocess it after shared processor
mode is known. During the second pass, only reevaluate coregroup
information and avoid repeating NUMA node and distance initialization.

This allows coregroup topology to be enabled on shared LPARs when the
required associativity information is available.

Signed-off-by: Srikar Dronamraju <[email protected]>
---
 arch/powerpc/include/asm/topology.h    |  2 ++
 arch/powerpc/kernel/smp.c              |  4 ----
 arch/powerpc/mm/numa.c                 | 28 +++++++++++++++++---------
 arch/powerpc/platforms/pseries/setup.c |  6 ++++++
 4 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/include/asm/topology.h 
b/arch/powerpc/include/asm/topology.h
index 02c3c9ab3ea9..35230011ef84 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -67,6 +67,7 @@ int of_drconf_to_nid_single(struct drmem_lmb *lmb);
 void update_numa_distance(struct device_node *node);
 
 extern void map_cpu_to_node(int cpu, int node);
+void process_cpu_associativity(bool first_pass);
 #ifdef CONFIG_HOTPLUG_CPU
 extern void unmap_cpu_from_node(unsigned long cpu);
 #endif /* CONFIG_HOTPLUG_CPU */
@@ -104,6 +105,7 @@ static inline void update_numa_distance(struct device_node 
*node) {}
 
 #ifdef CONFIG_SMP
 static inline void map_cpu_to_node(int cpu, int node) {}
+static inline void process_cpu_associativity(bool first_pass) {}
 #ifdef CONFIG_HOTPLUG_CPU
 static inline void unmap_cpu_from_node(unsigned long cpu) {}
 #endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 6a5a5469aaae..0213ef8d855a 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -1052,10 +1052,6 @@ struct cpumask *cpu_coregroup_mask(int cpu)
 
 static bool has_coregroup_support(void)
 {
-       /* Coregroup identification not available on shared systems */
-       if (is_shared_processor())
-               return 0;
-
        return coregroup_enabled;
 }
 
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index fde79f34340e..2a5d94550dc0 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -890,12 +890,15 @@ static int __init numa_setup_drmem_lmb(struct drmem_lmb 
*lmb,
 }
 
 /*
- * Coregroup info is present in associativity property just after
- * primary_domain_index. In dedicated LPARs, coregroup info is present only
- * if primary_domain_index is third from the last or earlier.
+ * Coregroup information follows the primary NUMA domain in the
+ * associativity hierarchy. Shared LPARs have one fewer associativity
+ * level than dedicated LPARs.
  */
 static bool has_coregroup_level(int index)
 {
+       if (is_shared_processor())
+               return index > primary_domain_index;
+
        return index > primary_domain_index + 1;
 }
 
@@ -918,7 +921,7 @@ static int detect_and_enable_coregroup(const __be32 
*associativity, int index)
        return -1;
 }
 
-static void process_cpu_associativity(void)
+void process_cpu_associativity(bool first_pass)
 {
        bool vphn = firmware_has_feature(FW_FEATURE_VPHN);
        unsigned long i;
@@ -947,15 +950,17 @@ static void process_cpu_associativity(void)
                        associativity = of_get_associativity(cpu);
                }
                if (associativity) {
-                       nid = associativity_to_nid(associativity);
-                       initialize_form1_numa_distance(associativity);
+                       if (first_pass) {
+                               nid = associativity_to_nid(associativity);
+                               initialize_form1_numa_distance(associativity);
+                       }
                        index = detect_and_enable_coregroup(associativity, 
index);
                }
                if (cpu)
                        of_node_put(cpu);
 
                /* node_set_online() is an UB if 'nid' is negative */
-               if (likely(nid >= 0) && numa_enabled)
+               if (first_pass && likely(nid >= 0) && numa_enabled)
                        node_set_online(nid);
        }
 }
@@ -990,7 +995,7 @@ static int __init parse_numa_properties(void)
         * init, we need to know the node ids now. This is because
         * each node to be onlined must have NODE_DATA etc backing it.
         */
-       process_cpu_associativity();
+       process_cpu_associativity(true);
 
        if (numa_enabled == 0) {
                pr_warn("disabled by user\n");
@@ -1463,12 +1468,15 @@ int cpu_to_coregroup_id(int cpu)
                goto out;
 
        index = of_read_number(associativity, 1);
-       if (index > primary_domain_index + 1)
-               coregroup_id = of_read_number(&associativity[index - 1], 1);
+       if (has_coregroup_level(index))
+               coregroup_id = 
(int)of_read_number(&associativity[primary_domain_index + 1], 1);
 
 out:
        if (cpunode)
                of_node_put(cpunode);
 
+       if (coregroup_id == -1)
+               return cpu_to_core_id(cpu);
+
        return coregroup_id;
 }
diff --git a/arch/powerpc/platforms/pseries/setup.c 
b/arch/powerpc/platforms/pseries/setup.c
index f29e7547c995..fd8163200b97 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -874,6 +874,12 @@ static void __init pSeries_setup_arch(void)
 
                if (lppaca_shared_proc()) {
                        static_branch_enable(&shared_processor);
+
+                       /*
+                        * Reprocess CPU associativity now that the shared
+                        * LPAR hierarchy can be interpreted correctly.
+                        */
+                       process_cpu_associativity(false);
                        pv_spinlocks_init();
 #ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
                        static_key_slow_inc(&paravirt_steal_enabled);
-- 
2.47.1


Reply via email to