* [PATCH 1/7] powerpc/numa: Remove redundant coregroup enablement
2026-10-16 11:04 [PATCH 0/7] powerpc/numa: Enable coregroup support for shared LPARs Srikar Dronamraju
@ 2026-10-16 11:04 ` Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 2/7] powerpc/numa: Consolidate VPHN associativity lookup Srikar Dronamraju
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Srikar Dronamraju @ 2026-10-16 11:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Ellerman, Madhavan Srinivasan, chleroy,
Srikar Dronamraju, Nicholas Piggin, Shrikanth Hegde,
Peter Zijlstra, linux-kernel
parse_numa_properties() determines whether the coregroup associativity
level is present and sets coregroup_enabled before find_possible_nodes()
is called.
Therefore, there is no need for find_possible_nodes() to determine the
same information again from the length of the associativity domain
property.
Signed-off-by: Srikar Dronamraju <srikar@linux.ibm.com>
---
arch/powerpc/mm/numa.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index e97b624203ea..09f7e7b2b192 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1124,7 +1124,7 @@ static void __init find_possible_nodes(void)
{
struct device_node *rtas, *root;
const __be32 *domains = NULL;
- int prop_length, max_nodes;
+ int max_nodes;
u32 i;
if (!numa_enabled)
@@ -1145,13 +1145,10 @@ static void __init find_possible_nodes(void)
*/
root = of_find_node_by_path("/");
if (!of_get_property(root, "ibm,migratable-partition", NULL))
- domains = of_get_property(rtas,
- "ibm,current-associativity-domains",
- &prop_length);
+ domains = of_get_property(rtas, "ibm,current-associativity-domains", NULL);
of_node_put(root);
if (!domains) {
- domains = of_get_property(rtas, "ibm,max-associativity-domains",
- &prop_length);
+ domains = of_get_property(rtas, "ibm,max-associativity-domains", NULL);
if (!domains)
goto out;
}
@@ -1164,10 +1161,6 @@ static void __init find_possible_nodes(void)
node_set(i, node_possible_map);
}
- prop_length /= sizeof(int);
- if (prop_length > primary_domain_index + 2)
- coregroup_enabled = 1;
-
out:
of_node_put(rtas);
}
--
2.47.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 2/7] powerpc/numa: Consolidate VPHN associativity lookup
2026-10-16 11:04 [PATCH 0/7] powerpc/numa: Enable coregroup support for shared LPARs Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 1/7] powerpc/numa: Remove redundant coregroup enablement Srikar Dronamraju
@ 2026-10-16 11:04 ` Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 3/7] powerpc/numa: Factor out coregroup availability check Srikar Dronamraju
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Srikar Dronamraju @ 2026-10-16 11:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Ellerman, Madhavan Srinivasan, chleroy,
Srikar Dronamraju, Nicholas Piggin, Shrikanth Hegde,
Peter Zijlstra, linux-kernel
There are two helpers for retrieving the associativity of a virtual
processor using VPHN. The helper used during NUMA initialization also
handles the case where the CPU is not yet mapped to a logical CPU,
while the helper used for topology updates operates on a logical CPU.
Consolidate them by extending the former helper to handle both cases.
If the argument corresponds to a possible CPU, translate it to its
hardware ID; otherwise, treat it as a hardware CPU ID directly.
Rename __vphn_get_associativity() to vphn_get_associativity() and use
it for both NUMA initialization and topology updates. Return the VPHN
hypercall return code instead of converting all failures to -1, and
remove the duplicate implementation.
Signed-off-by: Srikar Dronamraju <srikar@linux.ibm.com>
---
arch/powerpc/mm/numa.c | 54 ++++--------------------------------------
1 file changed, 5 insertions(+), 49 deletions(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 09f7e7b2b192..df3b51a1beb4 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -641,7 +641,7 @@ int of_drconf_to_nid_single(struct drmem_lmb *lmb)
#ifdef CONFIG_PPC_SPLPAR
-static int __vphn_get_associativity(long lcpu, __be32 *associativity)
+static long vphn_get_associativity(unsigned long lcpu, __be32 *associativity)
{
long rc, hwid;
@@ -665,7 +665,7 @@ static int __vphn_get_associativity(long lcpu, __be32 *associativity)
return 0;
}
- return -1;
+ return rc;
}
static int vphn_get_nid(long lcpu)
@@ -673,7 +673,7 @@ static int vphn_get_nid(long lcpu)
__be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
- if (!__vphn_get_associativity(lcpu, associativity))
+ if (!vphn_get_associativity(lcpu, associativity))
return associativity_to_nid(associativity);
return NUMA_NO_NODE;
@@ -681,7 +681,7 @@ static int vphn_get_nid(long lcpu)
}
#else
-static int __vphn_get_associativity(long lcpu, __be32 *associativity)
+static long vphn_get_associativity(unsigned long lcpu, __be32 *associativity)
{
return -1;
}
@@ -951,7 +951,7 @@ static int __init parse_numa_properties(void)
memset(vphn_assoc, 0, VPHN_ASSOC_BUFSIZE * sizeof(__be32));
- if (__vphn_get_associativity(i, vphn_assoc) == 0) {
+ if (vphn_get_associativity(i, vphn_assoc) == 0) {
nid = associativity_to_nid(vphn_assoc);
initialize_form1_numa_distance(vphn_assoc);
index = detect_and_enable_coregroup(vphn_assoc, index);
@@ -1384,43 +1384,6 @@ u64 memory_hotplug_max(void)
#ifdef CONFIG_PPC_SPLPAR
static int topology_inited;
-/*
- * Retrieve the new associativity information for a virtual processor's
- * home node.
- */
-static long vphn_get_associativity(unsigned long cpu,
- __be32 *associativity)
-{
- long rc;
-
- rc = hcall_vphn(get_hard_smp_processor_id(cpu),
- VPHN_FLAG_VCPU, associativity);
-
- switch (rc) {
- case H_SUCCESS:
- pr_debug("VPHN hcall succeeded. Reset polling...\n");
- goto out;
-
- case H_FUNCTION:
- pr_err_ratelimited("VPHN unsupported. Disabling polling...\n");
- break;
- case H_HARDWARE:
- pr_err_ratelimited("hcall_vphn() experienced a hardware fault "
- "preventing VPHN. Disabling polling...\n");
- break;
- case H_PARAMETER:
- pr_err_ratelimited("hcall_vphn() was passed an invalid parameter. "
- "Disabling polling...\n");
- break;
- default:
- pr_err_ratelimited("hcall_vphn() returned %ld. Disabling polling...\n"
- , rc);
- break;
- }
-out:
- return rc;
-}
-
void find_and_update_cpu_nid(int cpu)
{
__be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
@@ -1449,13 +1412,6 @@ static int topology_update_init(void)
return 0;
}
device_initcall(topology_update_init);
-
-#else
-static long vphn_get_associativity(unsigned long cpu,
- __be32 *associativity)
-{
- return -1;
-}
#endif /* CONFIG_PPC_SPLPAR */
int cpu_to_coregroup_id(int cpu)
--
2.47.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 3/7] powerpc/numa: Factor out coregroup availability check
2026-10-16 11:04 [PATCH 0/7] powerpc/numa: Enable coregroup support for shared LPARs Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 1/7] powerpc/numa: Remove redundant coregroup enablement Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 2/7] powerpc/numa: Consolidate VPHN associativity lookup Srikar Dronamraju
@ 2026-10-16 11:04 ` Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 4/7] powerpc/numa: Allow coregroup detection when NUMA is disabled Srikar Dronamraju
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Srikar Dronamraju @ 2026-10-16 11:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Ellerman, Madhavan Srinivasan, chleroy,
Srikar Dronamraju, Nicholas Piggin, Shrikanth Hegde,
Peter Zijlstra, linux-kernel
Coregroup information is present in the associativity hierarchy when
there is an associativity level beyond the primary NUMA domain.
Factor out the check for the presence of the coregroup associativity
level into a helper so that it can be reused when determining
coregroup availability.
No functional change intended.
Signed-off-by: Srikar Dronamraju <srikar@linux.ibm.com>
---
arch/powerpc/mm/numa.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index df3b51a1beb4..7cb37cb0c5db 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -889,6 +889,16 @@ static int __init numa_setup_drmem_lmb(struct drmem_lmb *lmb,
return 0;
}
+/*
+ * 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.
+ */
+static bool has_coregroup_level(int index)
+{
+ return index > primary_domain_index + 1;
+}
+
/*
* If hierarchy extends beyond primary_domain_index + 1, then next
* level corresponds to coregroup.
@@ -899,8 +909,7 @@ static int detect_and_enable_coregroup(const __be32 *associativity, int index)
goto out;
index = of_read_number(associativity, 1);
-
- if (index > primary_domain_index + 1) {
+ if (has_coregroup_level(index)) {
coregroup_enabled = 1;
return index;
}
--
2.47.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 4/7] powerpc/numa: Allow coregroup detection when NUMA is disabled
2026-10-16 11:04 [PATCH 0/7] powerpc/numa: Enable coregroup support for shared LPARs Srikar Dronamraju
` (2 preceding siblings ...)
2026-10-16 11:04 ` [PATCH 3/7] powerpc/numa: Factor out coregroup availability check Srikar Dronamraju
@ 2026-10-16 11:04 ` Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 5/7] powerpc/numa: Consolidate associativity lookup in parse_numa_properties Srikar Dronamraju
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Srikar Dronamraju @ 2026-10-16 11:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Ellerman, Madhavan Srinivasan, chleroy,
Srikar Dronamraju, Nicholas Piggin, Shrikanth Hegde,
Peter Zijlstra, linux-kernel
parse_numa_properties() currently returns immediately when NUMA is
disabled, which also prevents CPU associativity from being parsed for
coregroup information.
Move the numa_enabled check after CPU associativity processing so that
coregroup topology can still be detected. Keep node onlining conditional
on NUMA being enabled and return before processing memory and PCI NUMA
information when NUMA is disabled.
This allows coregroup topology to be initialized independently of NUMA
node topology.
Signed-off-by: Srikar Dronamraju <srikar@linux.ibm.com>
---
arch/powerpc/mm/numa.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 7cb37cb0c5db..ffdb07b995a8 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -925,11 +925,6 @@ static int __init parse_numa_properties(void)
const __be32 *associativity;
unsigned long i;
- if (numa_enabled == 0) {
- pr_warn("disabled by user\n");
- return -1;
- }
-
primary_domain_index = find_primary_domain_index();
if (primary_domain_index < 0) {
@@ -985,10 +980,15 @@ static int __init parse_numa_properties(void)
}
/* node_set_online() is an UB if 'nid' is negative */
- if (likely(nid >= 0))
+ if (likely(nid >= 0) && numa_enabled)
node_set_online(nid);
}
+ if (numa_enabled == 0) {
+ pr_warn("disabled by user\n");
+ return -1;
+ }
+
get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
for_each_node_by_type(memory, "memory") {
--
2.47.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 5/7] powerpc/numa: Consolidate associativity lookup in parse_numa_properties
2026-10-16 11:04 [PATCH 0/7] powerpc/numa: Enable coregroup support for shared LPARs Srikar Dronamraju
` (3 preceding siblings ...)
2026-10-16 11:04 ` [PATCH 4/7] powerpc/numa: Allow coregroup detection when NUMA is disabled Srikar Dronamraju
@ 2026-10-16 11:04 ` Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 6/7] powerpc/numa: Extract CPU associativity processing into separate function Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 7/7] powerpc/numa: Enable coregroup support for shared LPARs Srikar Dronamraju
6 siblings, 0 replies; 8+ messages in thread
From: Srikar Dronamraju @ 2026-10-16 11:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Ellerman, Madhavan Srinivasan, chleroy,
Srikar Dronamraju, Nicholas Piggin, Shrikanth Hegde,
Peter Zijlstra, linux-kernel
Refactor the CPU associativity lookup logic to reduce code nesting and
improve readability. Previously, the code had separate paths for VPHN
and device tree lookups with duplicated processing logic.
Consolidate the lookup into a unified flow:
1. Try VPHN associativity if firmware supports it
2. Fall back to device tree associativity if VPHN fails or unavailable
3. Process the associativity information once, regardless of source
No functional change is intended. Both VPHN and device tree paths
continue to work as before, with the common associativity processing
performed in one place.
Signed-off-by: Srikar Dronamraju <srikar@linux.ibm.com>
---
arch/powerpc/mm/numa.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index ffdb07b995a8..c2aefb60ed5a 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -920,6 +920,7 @@ static int detect_and_enable_coregroup(const __be32 *associativity, int index)
static int __init parse_numa_properties(void)
{
+ bool vphn = firmware_has_feature(FW_FEATURE_VPHN);
struct device_node *memory, *pci;
int default_nid = 0, index = 0;
const __be32 *associativity;
@@ -951,17 +952,16 @@ static int __init parse_numa_properties(void)
*/
for_each_present_cpu(i) {
__be32 vphn_assoc[VPHN_ASSOC_BUFSIZE];
+ struct device_node *cpu = NULL;
int nid = NUMA_NO_NODE;
- memset(vphn_assoc, 0, VPHN_ASSOC_BUFSIZE * sizeof(__be32));
-
- if (vphn_get_associativity(i, vphn_assoc) == 0) {
- nid = associativity_to_nid(vphn_assoc);
- initialize_form1_numa_distance(vphn_assoc);
- index = detect_and_enable_coregroup(vphn_assoc, index);
- } else {
- struct device_node *cpu;
-
+ associativity = NULL;
+ if (vphn) {
+ memset(vphn_assoc, 0, VPHN_ASSOC_BUFSIZE * sizeof(__be32));
+ if (vphn_get_associativity(i, vphn_assoc) == 0)
+ associativity = vphn_assoc;
+ }
+ if (!associativity) {
/*
* Don't fall back to default_nid yet -- we will plug
* cpus into nodes once the memory scan has discovered
@@ -971,13 +971,14 @@ static int __init parse_numa_properties(void)
BUG_ON(!cpu);
associativity = of_get_associativity(cpu);
- if (associativity) {
- nid = associativity_to_nid(associativity);
- index = detect_and_enable_coregroup(associativity, index);
- initialize_form1_numa_distance(associativity);
- }
- of_node_put(cpu);
}
+ if (associativity) {
+ 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)
--
2.47.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 6/7] powerpc/numa: Extract CPU associativity processing into separate function
2026-10-16 11:04 [PATCH 0/7] powerpc/numa: Enable coregroup support for shared LPARs Srikar Dronamraju
` (4 preceding siblings ...)
2026-10-16 11:04 ` [PATCH 5/7] powerpc/numa: Consolidate associativity lookup in parse_numa_properties Srikar Dronamraju
@ 2026-10-16 11:04 ` Srikar Dronamraju
2026-10-16 11:04 ` [PATCH 7/7] powerpc/numa: Enable coregroup support for shared LPARs Srikar Dronamraju
6 siblings, 0 replies; 8+ messages in thread
From: Srikar Dronamraju @ 2026-10-16 11:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Ellerman, Madhavan Srinivasan, chleroy,
Srikar Dronamraju, Nicholas Piggin, Shrikanth Hegde,
Peter Zijlstra, linux-kernel
Move the CPU associativity processing loop from parse_numa_properties()
into a dedicated process_cpu_associativity() function. This improves code
organization by separating concerns:
- parse_numa_properties() handles overall NUMA initialization
- process_cpu_associativity() focuses on CPU associativity processing
This also allows CPU associativity processing to be invoked again after
the processor sharing mode is known.
No functional change in the initialization flow.
Signed-off-by: Srikar Dronamraju <srikar@linux.ibm.com>
---
arch/powerpc/mm/numa.c | 65 +++++++++++++++++++++++-------------------
1 file changed, 36 insertions(+), 29 deletions(-)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index c2aefb60ed5a..fde79f34340e 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -918,44 +918,18 @@ static int detect_and_enable_coregroup(const __be32 *associativity, int index)
return -1;
}
-static int __init parse_numa_properties(void)
+static void process_cpu_associativity(void)
{
bool vphn = firmware_has_feature(FW_FEATURE_VPHN);
- struct device_node *memory, *pci;
- int default_nid = 0, index = 0;
- const __be32 *associativity;
unsigned long i;
+ int index = 0;
- primary_domain_index = find_primary_domain_index();
-
- if (primary_domain_index < 0) {
- /*
- * if we fail to parse primary_domain_index from device tree
- * mark the numa disabled, boot with numa disabled.
- */
- numa_enabled = false;
- return primary_domain_index;
- }
-
- pr_debug("associativity depth for CPU/Memory: %d\n", primary_domain_index);
-
- /*
- * If it is FORM2 initialize the distance table here.
- */
- if (affinity_form == FORM2_AFFINITY)
- initialize_form2_numa_distance_lookup_table();
-
- /*
- * Even though we connect cpus to numa domains later in SMP
- * init, we need to know the node ids now. This is because
- * each node to be onlined must have NODE_DATA etc backing it.
- */
for_each_present_cpu(i) {
+ const __be32 *associativity = NULL;
__be32 vphn_assoc[VPHN_ASSOC_BUFSIZE];
struct device_node *cpu = NULL;
int nid = NUMA_NO_NODE;
- associativity = NULL;
if (vphn) {
memset(vphn_assoc, 0, VPHN_ASSOC_BUFSIZE * sizeof(__be32));
if (vphn_get_associativity(i, vphn_assoc) == 0)
@@ -984,6 +958,39 @@ static int __init parse_numa_properties(void)
if (likely(nid >= 0) && numa_enabled)
node_set_online(nid);
}
+}
+
+static int __init parse_numa_properties(void)
+{
+ struct device_node *memory, *pci;
+ int default_nid = 0;
+ const __be32 *associativity;
+
+ primary_domain_index = find_primary_domain_index();
+
+ if (primary_domain_index < 0) {
+ /*
+ * if we fail to parse primary_domain_index from device tree
+ * mark the numa disabled, boot with numa disabled.
+ */
+ numa_enabled = false;
+ return primary_domain_index;
+ }
+
+ pr_debug("associativity depth for CPU/Memory: %d\n", primary_domain_index);
+
+ /*
+ * If it is FORM2 initialize the distance table here.
+ */
+ if (affinity_form == FORM2_AFFINITY)
+ initialize_form2_numa_distance_lookup_table();
+
+ /*
+ * Even though we connect cpus to numa domains later in SMP
+ * 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();
if (numa_enabled == 0) {
pr_warn("disabled by user\n");
--
2.47.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 7/7] powerpc/numa: Enable coregroup support for shared LPARs
2026-10-16 11:04 [PATCH 0/7] powerpc/numa: Enable coregroup support for shared LPARs Srikar Dronamraju
` (5 preceding siblings ...)
2026-10-16 11:04 ` [PATCH 6/7] powerpc/numa: Extract CPU associativity processing into separate function Srikar Dronamraju
@ 2026-10-16 11:04 ` Srikar Dronamraju
6 siblings, 0 replies; 8+ messages in thread
From: Srikar Dronamraju @ 2026-10-16 11:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Ellerman, Madhavan Srinivasan, chleroy,
Srikar Dronamraju, Nicholas Piggin, Shrikanth Hegde,
Peter Zijlstra, linux-kernel
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 <srikar@linux.ibm.com>
---
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(¶virt_steal_enabled);
--
2.47.1
^ permalink raw reply [flat|nested] 8+ messages in thread