cpupower: Add generic CPPC performance display

Arm64 machines, and possibly others, use the standard ACPI defined CPPC
infrastructure. cpupower has CPPC support, but it's largely written
around the intricacies of AMD processors, using platform MSRs to avoid
shortcomings in the specification.

Add a generic CPPC display that depends only on standardized fields. The
computed frequency values are best effort and rely on the FW providing
optional values that can be used to derive a meaningful frequency at a
given unique performance level.

Link: https://lore.kernel.org/r/20260709221344.1919794-2-jeremy.linton@arm.com
Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
This commit is contained in:
Jeremy Linton
2026-07-09 17:13:42 -05:00
committed by Shuah Khan
parent dc59e4fea9
commit 68f34fad76

View File

@@ -0,0 +1,56 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "helpers/helpers.h"
#include "cpufreq.h"
#include "acpi_cppc.h"
#define cppc_to_frequency(perf) (roundf(slope * (perf) + intercept))
void cppc_show_perf_and_freq(unsigned int cpu, int no_rounding)
{
int64_t nominal = acpi_cppc_get_data(cpu, NOMINAL_PERF);
int64_t nominal_freq = acpi_cppc_get_data(cpu, NOMINAL_FREQ) * 1000;
int64_t lowest = acpi_cppc_get_data(cpu, LOWEST_PERF);
int64_t lowest_freq = acpi_cppc_get_data(cpu, LOWEST_FREQ) * 1000;
unsigned long non_linear = acpi_cppc_get_data(cpu, LOWEST_NONLINEAR_PERF);
unsigned long highest = acpi_cppc_get_data(cpu, HIGHEST_PERF);
float slope, intercept;
/* do the optional freq fields look invalid? */
if (!nominal_freq || !lowest_freq || nominal == lowest)
return;
slope = (float)(nominal_freq - lowest_freq) / (nominal - lowest);
intercept = lowest_freq - slope * lowest;
printf(_(" CPPC limits:\n"));
printf(_(" Highest Performance: %lu. Maximum Frequency: "),
highest);
/*
* If boost isn't active, the cpuinfo_max doesn't indicate real max
* frequency.
*/
print_speed(cppc_to_frequency(highest), no_rounding);
printf(".\n");
printf(_(" Nominal Performance: %lu. Nominal Frequency: "),
acpi_cppc_get_data(cpu, NOMINAL_PERF));
print_speed(nominal_freq, no_rounding);
printf(".\n");
printf(_(" Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "),
non_linear);
print_speed(cppc_to_frequency(non_linear), no_rounding);
printf(".\n");
printf(_(" Lowest Performance: %lu. Lowest Frequency: "),
acpi_cppc_get_data(cpu, LOWEST_PERF));
print_speed(lowest_freq, no_rounding);
printf(".\n");
}