power utilities 2026.10.31

turbostat 2026.10.31
 
 	Fix --cpu option to work more than once.
 	Fix --Joules option to work with --show power.
 	Remove hard-coded 8192-CPU limit.
 	Decode Uncore Frequency Agent Types.
 	Dump RDT (Resource Director Technology) config.
 	Dump RP (Resource Priority) config.
 	Recognize Rugged Panther Lake.
 	Fix PMT mmap size, bounds check, and mask computation.
 	Misc cleanups and minor fixes.
 
 x86_energy_perf_policy 2026.10.31
 
 	Harden input parsing and bounds checks.
 	Fix optarg keyword matching.
 	Rewrite MSR device path discovery.
 	Misc cleanups and minor fixes.
 -----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCgAyFiEE67dNfPFP+XUaA73mB9BFOha3NhcFAmrmJyQUHGxlbi5icm93
 bkBpbnRlbC5jb20ACgkQB9BFOha3Nhfugg//QCJbYp/aOZ1k9siqw1pE/z9HJlIr
 2T6vgEadOEqY1Z/ObCeH/E/pgAnrSxbCkX8AOlhdqVBysD6JVn/rvsOo6yLfpI5V
 A7QcYzZfOi9tOP4m6hHC3gmAjkYC8b1vCHMiq+F4QOW1sq7zFIZ5SHPJFUZNrHvK
 54UrRCJ6BfJGw1W/cGozgwYVCJW7yXVHd2845nEhj8SGrkeZZVilkbrDiwFTxvWJ
 PC6QpsScLLq0lKFkr7fIFb/QGr1Zz0dwqCsDzO5z4wHqvvAZ+yAGSYLw3MG/6LBL
 PzFRivNETn7jwNcaQOp0H7teThC3s+WDioFLQjIrp2VNv5/yQeG1FZjh/EnlRBOi
 WcelJfwzWMrkmXfHE1UGrn9Y6HLFddRSxjdpyEQ+QGpH2NAyUxwFDauz9JZl3Tdd
 E/3T6F+BRvDOm/sHg3zMOCewUsbEdbxwLs+g6RNH7QkapcofOtUwzuNGUfD3ETF5
 qbTN+4P1T3FDxeI9GK6yLUZD6DsgIFwGEWOrD2VIp0XZaTNGGLHSwU0vQFEN3Tlq
 sKMkGdtnThTp4nRnWwbDqAQpWVEX+62HsUlOuPYL25CDAyyPfFIBGnCGDqyPLUEp
 Mlp/CMg8jA1VsFzzNX4aMGSjvszfJG+wVtHd/yluid4aqJFofl6Uza3FA5brCAF4
 hp0PVFWnJF907Z4=
 =fZ/K
 -----END PGP SIGNATURE-----

Merge tag 'power-utilities-2026.10.31' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux

Pull x86 power utilities updates from Len Brown:
 "Turbostat:
   - Fix --cpu option to work more than once
   - Fix --Joules option to work with --show power
   - Remove hard-coded 8192-CPU limit
   - Decode Uncore Frequency Agent Types
   - Dump RDT (Resource Director Technology) config
   - Dump RP (Resource Priority) config
   - Recognize Rugged Panther Lake
   - Fix PMT mmap size, bounds check, and mask computation
   - Misc cleanups and minor fixes

  x86_energy_perf_policy:
   - Harden input parsing and bounds checks
   - Fix optarg keyword matching
   - Rewrite MSR device path discovery
   - Misc cleanups and minor fixes"

* tag 'power-utilities-2026.10.31' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux: (42 commits)
  tools/power x86_energy_perf_policy: Version 2026.10.31
  tools/power turbostat: Version 2026.10.31
  tools/power turbostat: Fix PMT mmap size and bounds check
  tools/power turbostat: Fix undefined behavior in pmt_gen_value_mask()
  tools/power turbostat: Fix --Joules when used with --show power
  MAINTAINERS: Add x86_energy_perf_policy
  x86_energy_perf_policy: Simplify write_sysfs() return type
  x86_energy_perf_policy: Use calloc to initialize string buffer
  x86_energy_perf_policy: Cleanup: Constify read only parameters
  x86_energy_perf_policy: Cleanup: Drop unused signal.h
  x86_energy_perf_policy: Document MSRHEADER
  x86_energy_perf_policy: Cleanup: Check fseek() in VM path
  x86_energy_perf_policy: Cleanup: Define BCLK_MHZ
  x86_energy_perf_policy: Cleanup: Define HWP_WINDOW_MAX_USEC
  x86_energy_perf_policy: Bound package iteration
  x86_energy_perf_policy: Harden against potential ratio overflow
  x86_energy_perf_policy: Fix optarg keyword matching
  x86_energy_perf_policy: Cleanup: Use snprintf() for platform-profile
  x86_energy_perf_policy: Harden with strtol()
  x86_energy_perf_policy: Harden update_cpufreq_scaling_freq()
  ...
This commit is contained in:
Linus Torvalds 2026-10-31 15:05:17 -07:00
commit cbbddb6b08
4 changed files with 589 additions and 482 deletions

View File

@ -30303,6 +30303,15 @@ W: https://x86-cpuid.org
F: arch/x86/include/asm/cpuid/leaf_types.h
F: tools/arch/x86/kcpuid/
X86 ENERGY PERF POLICY UTILITY
M: Len Brown <lenb@kernel.org>
L: linux-pm@vger.kernel.org
S: Supported
Q: https://patchwork.kernel.org/project/linux-pm/list/
B: https://bugzilla.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git x86_energy_perf_policy
F: tools/power/x86/x86_energy_perf_policy/
X86 ENTRY CODE
M: Andy Lutomirski <luto@kernel.org>
L: linux-kernel@vger.kernel.org

View File

@ -92,7 +92,7 @@ name as necessary to disambiguate it from others is necessary. Note that option
'%x' hex identifier of the PMT MMIO region.
.fi
.PP
\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. If cpu-set is the string "core", then the system summary plus the first CPU in each core are printed -- eg. subsequent HT siblings are not printed. Or if cpu-set is the string "package", then the system summary plus the first CPU in each package is printed. Otherwise, the system summary plus the specified set of CPUs are printed. The cpu-set is ordered from low to high, comma delimited with ".." and "-" permitted to denote a range. eg. 1,2,8,14..17,21-44
\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. If cpu-set is the string "core", then the system summary plus the first CPU in each core are printed -- eg. subsequent HT siblings are not printed. Or if cpu-set is the string "package", then the system summary plus the first CPU in each package is printed. Otherwise, the system summary plus the specified set of CPUs are printed. The cpu-set is ordered from low to high, comma delimited with ".." and "-" permitted to denote a range. eg. 1,2,8,14..17,21-44 Multiple invocations of --cpu are OR'd together.
.PP
\fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names.
.PP
@ -269,7 +269,7 @@ Periodic output goes to stdout, by default, unless --out is used to specify an o
The 5-second interval can be changed with the "-i sec" option.
.nf
sudo turbostat --quiet --show CPU,frequency
Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMhz
Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMHz
- - 524 12.48 4198 3096 74.53 3800
0 0 4 0.09 4081 3096 98.88 3800
0 4 1 0.02 4063 3096
@ -279,7 +279,7 @@ sudo turbostat --quiet --show CPU,frequency
2 6 3 0.08 4159 3096
3 3 1 0.04 4046 3096 99.66
3 7 0 0.01 3989 3096
Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMhz
Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMHz
- - 525 12.52 4198 3096 74.54 3800
0 0 4 0.10 4051 3096 99.49 3800
0 4 2 0.04 3993 3096

File diff suppressed because it is too large Load Diff

View File

@ -9,17 +9,22 @@
*/
#define _GNU_SOURCE
#include MSRHEADER
/*
* MSRHEADER macro should be defined by the build system to include the
* appropriate MSR definitions header file. Typical usage:
* gcc -DMSRHEADER=\"msr-index.h\" or similar platform-specific MSR header
*/
#include MSRHEADER /* e.g., msr-index.h with MSR_* constant definitions */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sched.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <getopt.h>
#include <err.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <limits.h>
#include <stdlib.h>
@ -33,6 +38,13 @@
#define OPTARG_BALANCE_PERFORMANCE (INT_MAX - 4)
#define OPTARG_PERFORMANCE (INT_MAX - 5)
/* Maximum HWP activity window duration in microseconds */
#define HWP_WINDOW_MAX_USEC 1270000000U
/* Nominal bus clock frequency in MHz - assumed for all HWP systems */
#define BCLK_MHZ 100
#define KHZ_PER_MHZ 1000
struct msr_hwp_cap {
unsigned char highest;
unsigned char guaranteed;
@ -98,6 +110,7 @@ unsigned char update_platform_profile;
int soc_slider_balance;
int soc_slider_offset;
char platform_profile[64];
char msr_path[64];
#define PATH_TO_CPU "/sys/devices/system/cpu/"
#define SYSFS_PATH_MAX 255
@ -139,11 +152,13 @@ void usage(void)
int ratio_2_msr_perf(int ratio)
{
int msr_perf;
unsigned long long temp;
if (!bdx_highest_ratio)
return ratio;
msr_perf = ratio * 255 / bdx_highest_ratio;
temp = (unsigned long long)ratio * 255;
msr_perf = temp / bdx_highest_ratio;
if (debug)
fprintf(stderr, "%d = ratio_to_msr_perf(%d)\n", msr_perf, ratio);
@ -189,7 +204,7 @@ int parse_cmdline_epb(int i)
return ENERGY_PERF_BIAS_PERFORMANCE;
}
if (i < 0 || i > ENERGY_PERF_BIAS_POWERSAVE)
errx(1, "--epb must be from 0 to 15");
errx(1, "--epb must be 0 through 15");
return i;
}
@ -255,7 +270,7 @@ int parse_cmdline_hwp_desired(int i)
return i;
}
int parse_cmdline_hwp_window(int i)
unsigned int parse_cmdline_hwp_window(unsigned int i)
{
unsigned int exponent;
@ -269,13 +284,13 @@ int parse_cmdline_hwp_window(int i)
case OPTARG_PERFORMANCE:
return 0;
}
if (i < 0 || i > 1270000000) {
fprintf(stderr, "--hwp-window: 0 for auto; 1 - 1270000000 usec for window duration\n");
if (i > HWP_WINDOW_MAX_USEC) {
fprintf(stderr, "--hwp-window: 0 for auto; 1 - %u usec for window duration\n", HWP_WINDOW_MAX_USEC);
usage();
}
for (exponent = 0;; ++exponent) {
if (debug)
printf("%d 10^%d\n", i, exponent);
printf("%u 10^%d\n", i, exponent);
if (i <= 127)
break;
@ -283,7 +298,7 @@ int parse_cmdline_hwp_window(int i)
i = i / 10;
}
if (debug)
fprintf(stderr, "%d*10^%d: 0x%x\n", i, exponent, (exponent << 7) | i);
fprintf(stderr, "%u*10^%d: 0x%x\n", i, exponent, (exponent << 7) | i);
return (exponent << 7) | i;
}
@ -303,8 +318,8 @@ int parse_cmdline_hwp_epp(int i)
case OPTARG_PERFORMANCE:
return HWP_EPP_PERFORMANCE;
}
if (i < 0 || i > 0xff) {
fprintf(stderr, "--hwp-epp must be from 0 to 0xff\n");
if (i < 0 || i > 255) {
fprintf(stderr, "--hwp-epp must be 0 through 255\n");
usage();
}
return i;
@ -330,42 +345,36 @@ int parse_cmdline_turbo(int i)
return i;
}
int parse_optarg_string(char *s)
long parse_optarg_string(const char *s)
{
int i;
long i;
char *endptr;
if (!strncmp(s, "default", 7))
if (strcmp(s, "default") == 0)
return OPTARG_NORMAL;
if (!strncmp(s, "normal", 6))
if (strcmp(s, "normal") == 0)
return OPTARG_NORMAL;
if (!strncmp(s, "power", 9))
if (strcmp(s, "power") == 0)
return OPTARG_POWER;
if (!strncmp(s, "balance-power", 17))
if (strcmp(s, "balance-power") == 0)
return OPTARG_BALANCE_POWER;
if (!strncmp(s, "balance-performance", 19))
if (strcmp(s, "balance-performance") == 0)
return OPTARG_BALANCE_PERFORMANCE;
if (!strncmp(s, "performance", 11))
if (strcmp(s, "performance") == 0)
return OPTARG_PERFORMANCE;
errno = 0;
i = strtol(s, &endptr, 0);
if (s == endptr) {
fprintf(stderr, "no digits in \"%s\"\n", s);
if (endptr == s || errno == ERANGE || i < 0 || i > 255) {
warnx("bad value \"%s\"", s);
usage();
}
if (i == LONG_MIN || i == LONG_MAX)
errx(-1, "%s", s);
if (i > 0xFF)
errx(-1, "%d (0x%x) must be < 256", i, i);
if (i < 0)
errx(-1, "%d (0x%x) must be >= 0", i, i);
return i;
}
@ -422,9 +431,10 @@ void parse_cmdline_cpu(char *s)
int end_cpu;
startp++;
errno = 0;
end_cpu = strtol(startp, &endp, 10);
if (startp == endp)
continue;
if (startp == endp || errno == ERANGE)
errx(1, "Confused by end_cpu '%s'", startp);
while (cpu <= end_cpu) {
if (cpu > max_cpu_num)
@ -467,11 +477,11 @@ void parse_cmdline_cpu(char *s)
break;
}
errno = 0;
cpu = strtol(startp, &endp, 10);
if (startp == endp)
if (startp == endp || errno == ERANGE || cpu < 0 || cpu > max_cpu_num)
errx(1, "--cpu cpu-set: confused by '%s'", startp);
if (cpu > max_cpu_num)
errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num);
CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
startp = endp;
}
@ -502,14 +512,15 @@ void parse_cmdline_pkg(char *s)
int end_pkg;
startp++;
errno = 0;
end_pkg = strtol(startp, &endp, 10);
if (startp == endp)
continue;
if (startp == endp || errno == ERANGE)
errx(1, "Confused by end_pkg '%s'", startp);
while (pkg <= end_pkg) {
if (pkg > max_pkg_num)
errx(1, "Requested pkg%d exceeds max pkg%d", pkg, max_pkg_num);
pkg_selected_set |= 1 << pkg;
pkg_selected_set |= 1ULL << pkg;
pkg++;
}
startp = endp;
@ -521,10 +532,12 @@ void parse_cmdline_pkg(char *s)
return;
}
errno = 0;
pkg = strtol(startp, &endp, 10);
if (pkg > max_pkg_num)
errx(1, "Requested pkg%d Exceeds max pkg%d", pkg, max_pkg_num);
pkg_selected_set |= 1 << pkg;
if (startp == endp || errno == ERANGE || pkg < 0 || pkg > max_pkg_num)
errx(1, "Confused by pkg '%s'", startp);
pkg_selected_set |= 1ULL << pkg;
startp = endp;
}
}
@ -533,8 +546,8 @@ void for_packages(unsigned long long pkg_set, int (func) (int))
{
int pkg_num;
for (pkg_num = 0; pkg_num <= max_pkg_num; ++pkg_num) {
if (pkg_set & (1UL << pkg_num))
for (pkg_num = 0; pkg_num <= max_pkg_num && pkg_num < MAX_PACKAGES; ++pkg_num) {
if (pkg_set & (1ULL << pkg_num))
func(pkg_num);
}
}
@ -544,6 +557,7 @@ static int parse_cmdline_int(const char *s, int *out)
char *endp;
long val;
errno = 0;
val = strtol(s, &endp, 0);
if (endp == s || errno == ERANGE)
return -1;
@ -558,7 +572,7 @@ static int parse_cmdline_int(const char *s, int *out)
void print_version(void)
{
printf("x86_energy_perf_policy 2026.04.25 Len Brown <lenb@kernel.org>\n");
printf("x86_energy_perf_policy 2026.10.31 Len Brown <lenb@kernel.org>\n");
}
static int platform_profile_access(int mode)
@ -572,7 +586,7 @@ static int platform_profile_access(int mode)
return 1;
}
static int platform_profile_name_is(char *name)
static int platform_profile_name_is(const char *name)
{
char buf[64];
@ -677,7 +691,7 @@ void cmdline(int argc, char **argv)
errx(1, "--platform-profile: value too long");
if (!platform_profile_access(W_OK))
errx(1, "Can not update platform-profile in '%s'", PATH_PLATFORM_PROFILE);
strcpy(platform_profile, optarg);
snprintf(platform_profile, sizeof(platform_profile), "%s", optarg);
update_platform_profile = 1;
break;
case 'm':
@ -712,13 +726,19 @@ void cmdline(int argc, char **argv)
case 't':
turbo_update_value = parse_cmdline_turbo(parse_optarg_string(optarg));
break;
case 'u':
update_hwp_use_pkg++;
if (atoi(optarg) == 0)
req_update.hwp_use_pkg = 0;
else
req_update.hwp_use_pkg = 1;
break;
case 'u': {
char *endp;
long val;
update_hwp_use_pkg++;
errno = 0;
val = strtol(optarg, &endp, 10);
if (endp == optarg || errno == ERANGE || val < 0 || val > 1)
errx(1, "--hwp-use-pkg: must be 0 or 1");
req_update.hwp_use_pkg = val;
break;
}
case 'v':
print_version();
exit(0);
@ -764,10 +784,10 @@ void err_on_hypervisor(void)
/* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */
cpuinfo = fopen_or_die("/proc/cpuinfo", "r");
buffer = malloc(4096);
buffer = calloc(4096, 1);
if (!buffer) {
fclose(cpuinfo);
err(-ENOMEM, "buffer malloc fail");
err(-ENOMEM, "buffer calloc fail");
}
if (!fread(buffer, 1024, 1, cpuinfo)) {
@ -783,7 +803,11 @@ void err_on_hypervisor(void)
err(1, "Failed to find 'flags' in /proc/cpuinfo");
}
rewind(cpuinfo);
fseek(cpuinfo, flags - buffer, SEEK_SET);
if (fseek(cpuinfo, flags - buffer, SEEK_SET) != 0) {
fclose(cpuinfo);
free(buffer);
err(1, "Failed to seek in /proc/cpuinfo");
}
if (!fgets(buffer, 4096, cpuinfo)) {
fclose(cpuinfo);
free(buffer);
@ -792,28 +816,38 @@ void err_on_hypervisor(void)
fclose(cpuinfo);
hypervisor = strstr(buffer, "hypervisor");
free(buffer);
if (hypervisor)
err(-1, "not supported on this virtual machine");
free(buffer);
}
/*
* if (use_android_msr_path)
* msr_path = /dev/msr%d // Android
* else
* msr_path = /dev/cpu/%d/msr // Linux
*/
static void set_msr_path(int cpu)
{
if (snprintf(msr_path, sizeof(msr_path), use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu) >= (int)sizeof(msr_path))
err(-1, "MSR path buffer overflow for cpu%d", cpu);
}
int get_msr(int cpu, int offset, unsigned long long *msr)
{
int retval;
char pathname[32];
int fd;
sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu);
fd = open(pathname, O_RDONLY);
set_msr_path(cpu);
fd = open(msr_path, O_RDONLY);
if (fd < 0)
err(-1, "%s open failed, try chown or chmod +r %s, or run as root", pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr");
err(-1, "%s open failed, try chown or chmod +r, or run as root", msr_path);
retval = pread(fd, msr, sizeof(*msr), offset);
if (retval != sizeof(*msr)) {
err_on_hypervisor();
err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
err(-1, "%s offset 0x%llx read failed", msr_path, (unsigned long long)offset);
}
if (debug > 1)
@ -825,14 +859,13 @@ int get_msr(int cpu, int offset, unsigned long long *msr)
int put_msr(int cpu, int offset, unsigned long long new_msr)
{
char pathname[32];
int retval;
int fd;
sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu);
fd = open(pathname, O_RDWR);
set_msr_path(cpu);
fd = open(msr_path, O_RDWR);
if (fd < 0)
err(-1, "%s open failed, try chown or chmod +r %s, or run as root", pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr");
err(-1, "%s open failed, try chown or chmod +w, or run as root", msr_path);
retval = pwrite(fd, &new_msr, sizeof(new_msr), offset);
if (retval != sizeof(new_msr))
@ -867,14 +900,14 @@ static unsigned int read_sysfs(const char *path, char *buf, size_t buflen)
return (unsigned int)numread;
}
static unsigned int write_sysfs(const char *path, char *buf, size_t buflen)
static int write_sysfs(const char *path, char *buf, size_t buflen)
{
ssize_t numwritten;
int fd;
fd = open(path, O_WRONLY);
if (fd == -1)
return 0;
return -1;
numwritten = write(fd, buf, buflen - 1);
if (numwritten < 1) {
@ -886,7 +919,7 @@ static unsigned int write_sysfs(const char *path, char *buf, size_t buflen)
close(fd);
return (unsigned int)numwritten;
return 0;
}
static int sysfs_read_string(const char *path, char *buf, size_t buflen)
@ -911,7 +944,7 @@ static int sysfs_write_string(const char *path, const char *buf)
len = snprintf(tmp, sizeof(tmp), "%s\n", buf);
if (len < 0 || len >= (int)sizeof(tmp))
return -1;
return write_sysfs(path, tmp, (size_t)len + 1) ? 0 : -1;
return write_sysfs(path, tmp, (size_t)len + 1);
}
void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str)
@ -934,7 +967,7 @@ void read_hwp_cap(int cpu, struct msr_hwp_cap *cap, unsigned int msr_offset)
cap->lowest = msr_perf_2_ratio(HWP_LOWEST_PERF(msr));
}
void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str)
void print_hwp_request(int cpu, struct msr_hwp_request *h, const char *str)
{
if (cpu != -1)
printf("cpu%d: ", cpu);
@ -946,7 +979,7 @@ void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str)
h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp, h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7, h->hwp_use_pkg);
}
void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, char *str)
void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, const char *str)
{
printf("pkg%d: ", pkg);
@ -1004,8 +1037,9 @@ static int get_epb_sysfs(int cpu)
if (!read_sysfs(path, linebuf, 3))
return -1;
errno = 0;
val = strtol(linebuf, &endp, 0);
if (endp == linebuf || errno == ERANGE)
if (endp == linebuf || errno == ERANGE || val < 0 || val > 15)
return -1;
return (int)val;
@ -1016,7 +1050,6 @@ static int set_epb_sysfs(int cpu, int val)
char path[SYSFS_PATH_MAX];
char linebuf[3];
char *endp;
int ret;
if (!has_epb)
return -1;
@ -1024,12 +1057,12 @@ static int set_epb_sysfs(int cpu, int val)
snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
snprintf(linebuf, sizeof(linebuf), "%d", val);
ret = write_sysfs(path, linebuf, 3);
if (ret <= 0)
if (write_sysfs(path, linebuf, 3))
return -1;
errno = 0;
val = strtol(linebuf, &endp, 0);
if (endp == linebuf || errno == ERANGE)
if (endp == linebuf || errno == ERANGE || val < 0 || val > 15)
return -1;
return (int)val;
@ -1139,7 +1172,7 @@ int print_pkg_msrs(int pkg)
*/
int ratio_2_sysfs_khz(int ratio)
{
int bclk_khz = 100 * 1000; /* 100,000 KHz = 100 MHz */
int bclk_khz = BCLK_MHZ * KHZ_PER_MHZ; /* Convert MHz to KHz */
return ratio * bclk_khz;
}
@ -1155,12 +1188,12 @@ int ratio_2_sysfs_khz(int ratio)
*/
void update_cpufreq_scaling_freq(int is_max, int cpu, unsigned int ratio)
{
char pathname[64];
char pathname[96];
FILE *fp;
int retval;
int khz;
sprintf(pathname, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq", cpu, is_max ? "max" : "min");
snprintf(pathname, sizeof(pathname), "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq", cpu, is_max ? "max" : "min");
fp = fopen(pathname, "w");
if (!fp) {
@ -1601,32 +1634,41 @@ void set_base_cpu(void)
err(-ENODEV, "No valid cpus found");
}
static void probe_android_msr_path(void)
/* return 0 if path exists */
static int check_msr_path(void)
{
struct stat sb;
char test_path[32];
sprintf(test_path, "/dev/msr%d", base_cpu);
if (stat(test_path, &sb) == 0)
use_android_msr_path = 1;
return stat(msr_path, &sb);
}
/*
* Check Linux MSR path
* If it fails, try modprobe and check it again
* If still no joy, enable Android path and try again
*/
void probe_dev_msr(void)
{
struct stat sb;
char pathname[32];
int retval;
probe_android_msr_path();
use_android_msr_path = 0;
set_msr_path(base_cpu);
if (check_msr_path() == 0)
return;
sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", base_cpu);
if (stat(pathname, &sb)) {
if (system("/sbin/modprobe msr > /dev/null 2>&1")) {
if (use_android_msr_path)
err(-5, "no /dev/msr0, Try \"# modprobe msr\" ");
else
err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
}
}
retval = system("/sbin/modprobe msr > /dev/null 2>&1");
if (check_msr_path() == 0)
return;
use_android_msr_path = 1;
set_msr_path(base_cpu);
if (check_msr_path() == 0)
return;
if (WIFEXITED(retval))
retval = WEXITSTATUS(retval);
errx(-1, "\"msr\" driver support required, modprobe msr returned %d", retval);
}
static void get_cpuid_or_exit(unsigned int leaf, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)