Skip to content

Commit

Permalink
Merge tag 'linux-cpupower-6.14-rc1' of ssh://gitolite.kernel.org/pub/…
Browse files Browse the repository at this point in the history
…scm/linux/kernel/git/shuah/linux

Merge cpupower utility updates for 6.14 from Shuah Khan:

"Several fixes, cleanups and AMD support enhancements:

 - fix TSC MHz calculation
 - Add install and uninstall options to bindings makefile
 - Add header changes for cpufreq.h to SWIG bindings
 - selftests/cpufreq: gitignore output files and clean them in make clean
 - Remove spurious return statement
 - Add support for parsing 'enabled' or 'disabled' strings from table
 - Add support for amd-pstate preferred core rankings
 - Don't try to read frequency from hardware when kernel uses aperf mperf
 - Add support for showing energy performance preference
 - Don't fetch maximum latency when EPP is enabled
 - Adjust whitespace for amd-pstate specific prints
 - Fix cross compilation
 - revise is_valid flag handling for idle_monitor"

* tag 'linux-cpupower-6.14-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/shuah/linux:
  pm: cpupower: Add header changes for cpufreq.h to SWIG bindings
  pm: cpupower: Add install and uninstall options to bindings makefile
  cpupower: Adjust whitespace for amd-pstate specific prints
  cpupower: Don't fetch maximum latency when EPP is enabled
  cpupower: Add support for showing energy performance preference
  cpupower: Don't try to read frequency from hardware when kernel uses aperfmperf
  cpupower: Add support for amd-pstate preferred core rankings
  cpupower: Add support for parsing 'enabled' or 'disabled' strings from table
  cpupower: Remove spurious return statement
  cpupower: fix TSC MHz calculation
  cpupower: revise is_valid flag handling for idle_monitor
  pm: cpupower: Makefile: Fix cross compilation
  selftests/cpufreq: gitignore output files and clean them in make clean
  • Loading branch information
Rafael J. Wysocki committed Jan 10, 2025
2 parents 9d89551 + 8d09744 commit c3a8b2b
Show file tree
Hide file tree
Showing 14 changed files with 137 additions and 19 deletions.
8 changes: 8 additions & 0 deletions tools/power/cpupower/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,19 @@ INSTALL_SCRIPT = ${INSTALL} -m 644
# to something more interesting, like "arm-linux-". If you want
# to compile vs uClibc, that can be done here as well.
CROSS ?= #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
ifneq ($(CROSS), )
CC = $(CROSS)gcc
LD = $(CROSS)gcc
AR = $(CROSS)ar
STRIP = $(CROSS)strip
RANLIB = $(CROSS)ranlib
else
CC ?= $(CROSS)gcc
LD ?= $(CROSS)gcc
AR ?= $(CROSS)ar
STRIP ?= $(CROSS)strip
RANLIB ?= $(CROSS)ranlib
endif
HOSTCC = gcc
MKDIR = mkdir

Expand Down
10 changes: 10 additions & 0 deletions tools/power/cpupower/bindings/python/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ HAVE_PYCONFIG := $(shell if which python-config >/dev/null 2>&1; then echo 1; el
LIB_DIR := ../../lib
PY_INCLUDE = $(firstword $(shell python-config --includes))
OBJECTS_LIB = $(wildcard $(LIB_DIR)/*.o)
INSTALL_DIR = $(shell python3 -c "import site; print(site.getsitepackages()[0])")

all: _raw_pylibcpupower.so

Expand All @@ -28,6 +29,15 @@ else ifeq ($(HAVE_PYCONFIG),0)
endif
swig -python raw_pylibcpupower.swg

# Only installs the Python bindings
install: _raw_pylibcpupower.so
install -D _raw_pylibcpupower.so $(INSTALL_DIR)/_raw_pylibcpupower.so
install -D raw_pylibcpupower.py $(INSTALL_DIR)/raw_pylibcpupower.py

uninstall:
rm -f $(INSTALL_DIR)/_raw_pylibcpupower.so
rm -f $(INSTALL_DIR)/raw_pylibcpupower.py

# Will only clean the bindings folder; will not clean the actual cpupower folder
clean:
rm -f raw_pylibcpupower.py raw_pylibcpupower_wrap.c raw_pylibcpupower_wrap.o _raw_pylibcpupower.so
25 changes: 25 additions & 0 deletions tools/power/cpupower/bindings/python/README
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,31 @@ To run the test script:
$ python test_raw_pylibcpupower.py


developing/using the bindings directly
--------------------------------------

You need to add the Python bindings directory to your $PYTHONPATH.

You would set the path in the Bash terminal or in the Bash profile:

PYTHONPATH=~/linux/tools/power/cpupower/bindings/python:$PYTHONPATH

This allows you to set a specific repo of the bindings to use.


installing/uninstalling
-----------------------

Python uses a system specific site-packages folder to look up modules to import
by default. You do not need to install cpupower to use the SWIG bindings.

You can install and uninstall the bindings to the site-packages with:

sudo make install

sudo make uninstall


credits
-------

Expand Down
3 changes: 3 additions & 0 deletions tools/power/cpupower/bindings/python/raw_pylibcpupower.swg
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ void cpufreq_put_stats(struct cpufreq_stats *stats);

unsigned long cpufreq_get_transitions(unsigned int cpu);

char *cpufreq_get_energy_performance_preference(unsigned int cpu);
void cpufreq_put_energy_performance_preference(char *ptr);

int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);

int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq);
Expand Down
18 changes: 18 additions & 0 deletions tools/power/cpupower/lib/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ unsigned long cpufreq_get_sysfs_value_from_table(unsigned int cpu,
if (len == 0)
return 0;

if (!strcmp(linebuf, "enabled\n"))
return 1;
if (!strcmp(linebuf, "disabled\n"))
return 0;
value = strtoul(linebuf, &endp, 0);

if (endp == linebuf || errno == ERANGE)
Expand All @@ -123,12 +127,14 @@ static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
enum cpufreq_string {
SCALING_DRIVER,
SCALING_GOVERNOR,
ENERGY_PERFORMANCE_PREFERENCE,
MAX_CPUFREQ_STRING_FILES
};

static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
[SCALING_DRIVER] = "scaling_driver",
[SCALING_GOVERNOR] = "scaling_governor",
[ENERGY_PERFORMANCE_PREFERENCE] = "energy_performance_preference",
};


Expand Down Expand Up @@ -203,6 +209,18 @@ unsigned long cpufreq_get_transition_latency(unsigned int cpu)
return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
}

char *cpufreq_get_energy_performance_preference(unsigned int cpu)
{
return sysfs_cpufreq_get_one_string(cpu, ENERGY_PERFORMANCE_PREFERENCE);
}

void cpufreq_put_energy_performance_preference(char *ptr)
{
if (!ptr)
return;
free(ptr);
}

int cpufreq_get_hardware_limits(unsigned int cpu,
unsigned long *min,
unsigned long *max)
Expand Down
8 changes: 8 additions & 0 deletions tools/power/cpupower/lib/cpufreq.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
unsigned long cpufreq_get_transition_latency(unsigned int cpu);


/* determine energy performance preference
*
* returns NULL on failure, else the string that represents the energy performance
* preference requested.
*/
char *cpufreq_get_energy_performance_preference(unsigned int cpu);
void cpufreq_put_energy_performance_preference(char *ptr);

/* determine hardware CPU frequency limits
*
* These may be limited further by thermal, energy or other
Expand Down
36 changes: 33 additions & 3 deletions tools/power/cpupower/utils/cpufreq-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ static void print_duration(unsigned long duration)
} else
printf("%lu ns", duration);
}
return;
}

static int get_boost_mode_x86(unsigned int cpu)
Expand Down Expand Up @@ -255,7 +254,12 @@ static int get_freq_kernel(unsigned int cpu, unsigned int human)

static int get_freq_hardware(unsigned int cpu, unsigned int human)
{
unsigned long freq = cpufreq_get_freq_hardware(cpu);
unsigned long freq;

if (cpupower_cpu_info.caps & CPUPOWER_CAP_APERF)
return -EINVAL;

freq = cpufreq_get_freq_hardware(cpu);
printf(_(" current CPU frequency: "));
if (!freq) {
printf("Unable to call hardware\n");
Expand Down Expand Up @@ -418,12 +422,32 @@ static int get_freq_stats(unsigned int cpu, unsigned int human)
return 0;
}

/* --epp / -z */

static int get_epp(unsigned int cpu, bool interactive)
{
char *epp;

epp = cpufreq_get_energy_performance_preference(cpu);
if (!epp)
return -EINVAL;
if (interactive)
printf(_(" energy performance preference: %s\n"), epp);

cpufreq_put_energy_performance_preference(epp);

return 0;
}

/* --latency / -y */

static int get_latency(unsigned int cpu, unsigned int human)
{
unsigned long latency = cpufreq_get_transition_latency(cpu);

if (!get_epp(cpu, false))
return -EINVAL;

printf(_(" maximum transition latency: "));
if (!latency || latency == UINT_MAX) {
printf(_(" Cannot determine or is not supported.\n"));
Expand Down Expand Up @@ -457,6 +481,7 @@ static void debug_output_one(unsigned int cpu)
get_related_cpus(cpu);
get_affected_cpus(cpu);
get_latency(cpu, 1);
get_epp(cpu, true);
get_hardware_limits(cpu, 1);

freqs = cpufreq_get_available_frequencies(cpu);
Expand Down Expand Up @@ -497,6 +522,7 @@ static struct option info_opts[] = {
{"human", no_argument, NULL, 'm'},
{"no-rounding", no_argument, NULL, 'n'},
{"performance", no_argument, NULL, 'c'},
{"epp", no_argument, NULL, 'z'},
{ },
};

Expand All @@ -510,7 +536,7 @@ int cmd_freq_info(int argc, char **argv)
int output_param = 0;

do {
ret = getopt_long(argc, argv, "oefwldpgrasmybnc", info_opts,
ret = getopt_long(argc, argv, "oefwldpgrasmybncz", info_opts,
NULL);
switch (ret) {
case '?':
Expand All @@ -534,6 +560,7 @@ int cmd_freq_info(int argc, char **argv)
case 's':
case 'y':
case 'c':
case 'z':
if (output_param) {
output_param = -1;
cont = 0;
Expand Down Expand Up @@ -643,6 +670,9 @@ int cmd_freq_info(int argc, char **argv)
case 'c':
ret = get_perf_cap(cpu);
break;
case 'z':
ret = get_epp(cpu, true);
break;
}
if (ret)
return ret;
Expand Down
18 changes: 14 additions & 4 deletions tools/power/cpupower/utils/helpers/amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,17 @@ enum amd_pstate_value {
AMD_PSTATE_HIGHEST_PERF,
AMD_PSTATE_MAX_FREQ,
AMD_PSTATE_LOWEST_NONLINEAR_FREQ,
AMD_PSTATE_HW_PREFCORE,
AMD_PSTATE_PREFCORE_RANKING,
MAX_AMD_PSTATE_VALUE_READ_FILES,
};

static const char *amd_pstate_value_files[MAX_AMD_PSTATE_VALUE_READ_FILES] = {
[AMD_PSTATE_HIGHEST_PERF] = "amd_pstate_highest_perf",
[AMD_PSTATE_MAX_FREQ] = "amd_pstate_max_freq",
[AMD_PSTATE_LOWEST_NONLINEAR_FREQ] = "amd_pstate_lowest_nonlinear_freq",
[AMD_PSTATE_HW_PREFCORE] = "amd_pstate_hw_prefcore",
[AMD_PSTATE_PREFCORE_RANKING] = "amd_pstate_prefcore_ranking",
};

static unsigned long amd_pstate_get_data(unsigned int cpu,
Expand Down Expand Up @@ -215,7 +219,9 @@ void amd_pstate_boost_init(unsigned int cpu, int *support, int *active)

void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding)
{
printf(_(" AMD PSTATE Highest Performance: %lu. Maximum Frequency: "),

printf(_(" amd-pstate limits:\n"));
printf(_(" Highest Performance: %lu. Maximum Frequency: "),
amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF));
/*
* If boost isn't active, the cpuinfo_max doesn't indicate real max
Expand All @@ -224,22 +230,26 @@ void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding)
print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ), no_rounding);
printf(".\n");

printf(_(" AMD PSTATE Nominal Performance: %lu. Nominal Frequency: "),
printf(_(" Nominal Performance: %lu. Nominal Frequency: "),
acpi_cppc_get_data(cpu, NOMINAL_PERF));
print_speed(acpi_cppc_get_data(cpu, NOMINAL_FREQ) * 1000,
no_rounding);
printf(".\n");

printf(_(" AMD PSTATE Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "),
printf(_(" Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "),
acpi_cppc_get_data(cpu, LOWEST_NONLINEAR_PERF));
print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_LOWEST_NONLINEAR_FREQ),
no_rounding);
printf(".\n");

printf(_(" AMD PSTATE Lowest Performance: %lu. Lowest Frequency: "),
printf(_(" Lowest Performance: %lu. Lowest Frequency: "),
acpi_cppc_get_data(cpu, LOWEST_PERF));
print_speed(acpi_cppc_get_data(cpu, LOWEST_FREQ) * 1000, no_rounding);
printf(".\n");

printf(_(" Preferred Core Support: %lu. Preferred Core Ranking: %lu.\n"),
amd_pstate_get_data(cpu, AMD_PSTATE_HW_PREFCORE),
amd_pstate_get_data(cpu, AMD_PSTATE_PREFCORE_RANKING));
}

/* AMD P-State Helper Functions ************************************/
Expand Down
4 changes: 2 additions & 2 deletions tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ static int hsw_ext_start(void)

for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) {
for (cpu = 0; cpu < cpu_count; cpu++) {
hsw_ext_get_count(num, &val, cpu);
is_valid[cpu] = !hsw_ext_get_count(num, &val, cpu);
previous_count[num][cpu] = val;
}
}
Expand All @@ -134,7 +134,7 @@ static int hsw_ext_stop(void)

for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) {
for (cpu = 0; cpu < cpu_count; cpu++) {
is_valid[cpu] = !hsw_ext_get_count(num, &val, cpu);
is_valid[cpu] |= !hsw_ext_get_count(num, &val, cpu);
current_count[num][cpu] = val;
}
}
Expand Down
17 changes: 10 additions & 7 deletions tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static int mperf_get_count_percent(unsigned int self_id, double *percent,
unsigned int cpu);
static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
unsigned int cpu);
static struct timespec time_start, time_end;
static struct timespec *time_start, *time_end;

static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
{
Expand Down Expand Up @@ -148,7 +148,7 @@ static int mperf_measure_stats(unsigned int cpu)
ret = get_aperf_mperf(cpu, &aval, &mval);
aperf_current_count[cpu] = aval;
mperf_current_count[cpu] = mval;
is_valid[cpu] = !ret;
is_valid[cpu] |= !ret;

return 0;
}
Expand All @@ -174,7 +174,7 @@ static int mperf_get_count_percent(unsigned int id, double *percent,
dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
mperf_cstates[id].name, mperf_diff, tsc_diff);
} else if (max_freq_mode == MAX_FREQ_SYSFS) {
timediff = max_frequency * timespec_diff_us(time_start, time_end);
timediff = max_frequency * timespec_diff_us(time_start[cpu], time_end[cpu]);
*percent = 100.0 * mperf_diff / timediff;
dprint("%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n",
mperf_cstates[id].name, mperf_diff, timediff);
Expand Down Expand Up @@ -207,7 +207,7 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
if (max_freq_mode == MAX_FREQ_TSC_REF) {
/* Calculate max_freq from TSC count */
tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
time_diff = timespec_diff_us(time_start, time_end);
time_diff = timespec_diff_us(time_start[cpu], time_end[cpu]);
max_frequency = tsc_diff / time_diff;
}

Expand All @@ -226,9 +226,8 @@ static int mperf_start(void)
{
int cpu;

clock_gettime(CLOCK_REALTIME, &time_start);

for (cpu = 0; cpu < cpu_count; cpu++) {
clock_gettime(CLOCK_REALTIME, &time_start[cpu]);
mperf_get_tsc(&tsc_at_measure_start[cpu]);
mperf_init_stats(cpu);
}
Expand All @@ -243,9 +242,9 @@ static int mperf_stop(void)
for (cpu = 0; cpu < cpu_count; cpu++) {
mperf_measure_stats(cpu);
mperf_get_tsc(&tsc_at_measure_end[cpu]);
clock_gettime(CLOCK_REALTIME, &time_end[cpu]);
}

clock_gettime(CLOCK_REALTIME, &time_end);
return 0;
}

Expand Down Expand Up @@ -349,6 +348,8 @@ struct cpuidle_monitor *mperf_register(void)
aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long));
tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long));
time_start = calloc(cpu_count, sizeof(struct timespec));
time_end = calloc(cpu_count, sizeof(struct timespec));
mperf_monitor.name_len = strlen(mperf_monitor.name);
return &mperf_monitor;
}
Expand All @@ -361,6 +362,8 @@ void mperf_unregister(void)
free(aperf_current_count);
free(tsc_at_measure_start);
free(tsc_at_measure_end);
free(time_start);
free(time_end);
free(is_valid);
}

Expand Down
Loading

0 comments on commit c3a8b2b

Please sign in to comment.