[tip: x86/urgent] x86/topo: Add topology_num_nodes_per_package()

From: tip-bot2 for Peter Zijlstra

Date: Wed Mar 04 2026 - 10:50:11 EST


The following commit has been merged into the x86/urgent branch of tip:

Commit-ID: ae6730ff42b3a13d94b405edeb5e40108b6d21b6
Gitweb: https://git.kernel.org/tip/ae6730ff42b3a13d94b405edeb5e40108b6d21b6
Author: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
AuthorDate: Tue, 03 Mar 2026 11:55:41 +01:00
Committer: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
CommitterDate: Wed, 04 Mar 2026 16:35:08 +01:00

x86/topo: Add topology_num_nodes_per_package()

Use the MADT and SRAT table data to compute __num_nodes_per_package.

Specifically, SRAT has already been parsed in x86_numa_init(), which is called
before acpi_boot_init() which parses MADT. So both are available in
topology_init_possible_cpus().

This number is useful to divinate the various Intel CoD/SNC and AMD NPS modes,
since the platforms are failing to provide this otherwise.

Doing it this way is independent of the number of online CPUs and
other such shenanigans.

Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Reviewed-by: Ingo Molnar <mingo@xxxxxxxxxx>
Tested-by: Tony Luck <tony.luck@xxxxxxxxx>
Tested-by: K Prateek Nayak <kprateek.nayak@xxxxxxx>
Tested-by: Zhang Rui <rui.zhang@xxxxxxxxx>
Tested-by: Chen Yu <yu.c.chen@xxxxxxxxx>
Tested-by: Kyle Meyer <kyle.meyer@xxxxxxx>
Link: https://patch.msgid.link/20260303110100.004091624@xxxxxxxxxxxxx
---
arch/x86/include/asm/topology.h | 6 ++++++
arch/x86/kernel/cpu/common.c | 3 +++
arch/x86/kernel/cpu/topology.c | 13 +++++++++++--
3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index 1fadf0c..0ba9bdb 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -155,6 +155,7 @@ extern unsigned int __max_logical_packages;
extern unsigned int __max_threads_per_core;
extern unsigned int __num_threads_per_package;
extern unsigned int __num_cores_per_package;
+extern unsigned int __num_nodes_per_package;

const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c);
enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c);
@@ -179,6 +180,11 @@ static inline unsigned int topology_num_threads_per_package(void)
return __num_threads_per_package;
}

+static inline unsigned int topology_num_nodes_per_package(void)
+{
+ return __num_nodes_per_package;
+}
+
#ifdef CONFIG_X86_LOCAL_APIC
int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level);
#else
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 1c3261c..a8ff437 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -95,6 +95,9 @@ EXPORT_SYMBOL(__max_dies_per_package);
unsigned int __max_logical_packages __ro_after_init = 1;
EXPORT_SYMBOL(__max_logical_packages);

+unsigned int __num_nodes_per_package __ro_after_init = 1;
+EXPORT_SYMBOL(__num_nodes_per_package);
+
unsigned int __num_cores_per_package __ro_after_init = 1;
EXPORT_SYMBOL(__num_cores_per_package);

diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c
index 23190a7..eafcb1f 100644
--- a/arch/x86/kernel/cpu/topology.c
+++ b/arch/x86/kernel/cpu/topology.c
@@ -31,6 +31,7 @@
#include <asm/mpspec.h>
#include <asm/msr.h>
#include <asm/smp.h>
+#include <asm/numa.h>

#include "cpu.h"

@@ -492,11 +493,19 @@ void __init topology_init_possible_cpus(void)
set_nr_cpu_ids(allowed);

cnta = domain_weight(TOPO_PKG_DOMAIN);
- cntb = domain_weight(TOPO_DIE_DOMAIN);
__max_logical_packages = cnta;
+
+ pr_info("Max. logical packages: %3u\n", __max_logical_packages);
+
+ cntb = num_phys_nodes();
+ __num_nodes_per_package = DIV_ROUND_UP(cntb, cnta);
+
+ pr_info("Max. logical nodes: %3u\n", cntb);
+ pr_info("Num. nodes per package:%3u\n", __num_nodes_per_package);
+
+ cntb = domain_weight(TOPO_DIE_DOMAIN);
__max_dies_per_package = 1U << (get_count_order(cntb) - get_count_order(cnta));

- pr_info("Max. logical packages: %3u\n", cnta);
pr_info("Max. logical dies: %3u\n", cntb);
pr_info("Max. dies per package: %3u\n", __max_dies_per_package);