[PATCH v3 3/3] cpupower: do not count incomplete topology entries as physical cores
From: Ali Ahmet Memis
Date: Thu Aug 06 2026 - 13:57:02 EST
The physical core count is derived by sorting core_info by core_cpu_list
and counting how many distinct lists there are. The loop seeds the count
with entry 0 unconditionally:
last_cpu_list = cpu_top->core_info[0].core_cpu_list;
cpu_top->cores = 1;
A CPU whose topology could not be read is still a member of the array,
carrying pkg and core of -1 and a core_cpu_list of "-1". That sorts ahead
of any real cpu list, so after the qsort it is entry 0 and it seeds the
count as if it were a core. The pkg check inside the loop only guards the
entries that follow, never the one the count started from.
An offline CPU is enough to reach this. The topology attribute group is
added and removed by a CPU hotplug callback in drivers/base/topology.c, so
physical_package_id and core_id are absent while a CPU is offline and both
reads fail.
Skip entries without complete topology data and count from zero, so only
CPUs with a package and a core contribute.
Fixes: f89cb9cba7a2 ("cpupower: Implement CPU physical core querying")
Signed-off-by: Ali Ahmet Memis <ali@xxxxxxxxxxxxxx>
---
tools/power/cpupower/lib/cpupower.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/tools/power/cpupower/lib/cpupower.c b/tools/power/cpupower/lib/cpupower.c
index 3d7e22ed1fd7..7784eb499435 100644
--- a/tools/power/cpupower/lib/cpupower.c
+++ b/tools/power/cpupower/lib/cpupower.c
@@ -212,11 +212,16 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
__compare_core_cpu_list);
- last_cpu_list = cpu_top->core_info[0].core_cpu_list;
- cpu_top->cores = 1;
- for (cpu = 1; cpu < cpus; cpu++) {
- if (strcmp(cpu_top->core_info[cpu].core_cpu_list, last_cpu_list) != 0 &&
- cpu_top->core_info[cpu].pkg != -1) {
+ last_cpu_list = NULL;
+ cpu_top->cores = 0;
+ for (cpu = 0; cpu < cpus; cpu++) {
+ if (cpu_top->core_info[cpu].pkg == -1 ||
+ cpu_top->core_info[cpu].core == -1)
+ continue;
+
+ if (!last_cpu_list ||
+ strcmp(cpu_top->core_info[cpu].core_cpu_list,
+ last_cpu_list) != 0) {
last_cpu_list = cpu_top->core_info[cpu].core_cpu_list;
cpu_top->cores++;
}
--
2.55.0