Skip to content

Commit a9a82a7

Browse files
committed
linux/cpukinds/freq: use acpi_cppc/nominal_freq when available
cpufreq/base_frequency is only available on Intel so far, and works well. acpi_cppc/nominal_freq is already available on AMD (and ARM or soon), so it's likely good for the future. However it reports incorrect values on Intel SPR and MTL at least. Hence try cpufreq/base_frequency first, then fallback to acpi_cppc/nominal_freq. Refs #690 Signed-off-by: Brice Goglin <[email protected]> (cherry picked from commit 2292110)
1 parent 64a3f86 commit a9a82a7

File tree

3 files changed

+26
-6
lines changed

3 files changed

+26
-6
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ bug fixes (and other actions) for each version of hwloc since version
2020
Version 2.11.2
2121
--------------
2222
* Add missing CPU info attrs on aarch64 on Linux.
23+
* Use ACPI CPPC on Linux to get better information about cpukinds,
24+
at least on AMD CPUs.
2325
* Fix crash when manipulating cpukinds after topology
2426
duplication, thanks to Hadrien Grasland for the report.
2527
* Fix missing input target checks in memattr functions,

doc/hwloc.doxy

+3-2
Original file line numberDiff line numberDiff line change
@@ -2457,8 +2457,9 @@ These CPU kinds may be annotated with the following native attributes:
24572457
as reported by <tt>cpufreq</tt> drivers on Linux.
24582458
</dd>
24592459
<dt>FrequencyBaseMHz (Linux)</dt>
2460-
<dd>The base operating frequency of the core,
2461-
as reported by some <tt>cpufreq</tt> drivers on Linux (e.g. <tt>intel_pstate</tt>).
2460+
<dd>The base/nominal operating frequency of the core,
2461+
as reported by some <tt>cpufreq</tt> or ACPI drivers on Linux
2462+
(e.g. <tt>cpufreq_cppc</tt> or <tt>intel_pstate</tt>).
24622463
</dd>
24632464
<dt>CoreType (x86)</dt>
24642465
<dd>A string describing the kind of core,

hwloc/topology-linux.c

+21-4
Original file line numberDiff line numberDiff line change
@@ -4474,8 +4474,8 @@ look_sysfsnode(struct hwloc_topology *topology,
44744474

44754475
struct hwloc_linux_cpukinds_by_pu {
44764476
unsigned pu;
4477-
unsigned long max_freq;
4478-
unsigned long base_freq;
4477+
unsigned long max_freq; /* kHz */
4478+
unsigned long base_freq; /* kHz */
44794479
unsigned long capacity;
44804480
int done; /* temporary bit to identify PU that were processed by the current algorithm
44814481
* (only hwloc_linux_cpukinds_adjust_maxfreqs() for now)
@@ -4714,6 +4714,7 @@ look_sysfscpukinds(struct hwloc_topology *topology,
47144714
char *env;
47154715
hwloc_bitmap_t atom_pmu_set, core_pmu_set;
47164716
int maxfreq_enabled = -1; /* -1 means adjust (default), 0 means ignore, 1 means enforce */
4717+
int use_cppc_nominal_freq = -1; /* -1 means try, 0 no, 1 yes */
47174718
unsigned adjust_max = 10;
47184719
int force_homogeneous;
47194720
const char *info;
@@ -4753,10 +4754,26 @@ look_sysfscpukinds(struct hwloc_topology *topology,
47534754
sprintf(str, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", i);
47544755
if (hwloc_read_path_as_uint(str, &maxfreq, data->root_fd) >= 0)
47554756
by_pu[i].max_freq = maxfreq;
4756-
/* base_frequency is intel_pstate specific */
4757+
/* base_frequency is in intel_pstate and works fine */
47574758
sprintf(str, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", i);
4758-
if (hwloc_read_path_as_uint(str, &basefreq, data->root_fd) >= 0)
4759+
if (hwloc_read_path_as_uint(str, &basefreq, data->root_fd) >= 0) {
47594760
by_pu[i].base_freq = basefreq;
4761+
use_cppc_nominal_freq = 0;
4762+
}
4763+
/* try acpi_cppc/nominal_freq only if cpufreq/base_frequency failed
4764+
* acpi_cppc/nominal_freq is widely available, but it returns 0 on some Intel SPR,
4765+
* same freq for all cores on RPL,
4766+
* maxfreq for E-cores and LP-E-cores but basefreq for P-cores on MTL.
4767+
*/
4768+
if (use_cppc_nominal_freq != 0) {
4769+
sprintf(str, "/sys/devices/system/cpu/cpu%d/acpi_cppc/nominal_freq", i);
4770+
if (hwloc_read_path_as_uint(str, &basefreq, data->root_fd) >= 0 && basefreq > 0) {
4771+
by_pu[i].base_freq = basefreq * 1000; /* nominal_freq is already in MHz */
4772+
use_cppc_nominal_freq = 1;
4773+
} else {
4774+
use_cppc_nominal_freq = 0;
4775+
}
4776+
}
47604777
if (maxfreq && !basefreq)
47614778
max_without_basefreq = 1;
47624779
/* capacity */

0 commit comments

Comments
 (0)