Skip to content

Commit

Permalink
Merge branch 'pm-tools'
Browse files Browse the repository at this point in the history
Merge cpupower utility updates for 6.14:

 - Fix TSC MHz calculation in cpupower (He Rongguang).

 - Add install and uninstall options to bindings Makefile and add header
   changes for cpufreq.h to SWIG bindings in cpupower (John B. Wyatt IV).

 - Add missing residency header changes in cpuidle.h to SWIG bindings in
   cpupower (John B. Wyatt IV).

 - Add output files to .gitignore and clean them up in "make clean" in
   selftests/cpufreq (Li Zhijian).

 - Fix cross-compilation in cpupower Makefile (Peng Fan).

 - Revise the is_valid flag handling for idle_monitor in the cpupower
   utility (wangfushuai).

 - Extend and clean up AMD processors support in cpupower (Mario
   Limonciello).

* pm-tools:
  pm: cpupower: Add missing residency header changes in cpuidle.h to SWIG
  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 20, 2025
2 parents eddd376 + 166eb23 commit 1c91c99
Show file tree
Hide file tree
Showing 14 changed files with 139 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
5 changes: 5 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 All @@ -160,6 +163,8 @@ int cpuidle_state_disable(unsigned int cpu, unsigned int idlestate,
unsigned int disable);
unsigned long cpuidle_state_latency(unsigned int cpu,
unsigned int idlestate);
unsigned long cpuidle_state_residency(unsigned int cpu,
unsigned int idlestate);
unsigned long cpuidle_state_usage(unsigned int cpu,
unsigned int idlestate);
unsigned long long cpuidle_state_time(unsigned int cpu,
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
Loading

0 comments on commit 1c91c99

Please sign in to comment.