Update Linux to v5.10.109
Sourced from [1]
[1] https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.109.tar.xz
Change-Id: I19bca9fc6762d4e63bcf3e4cba88bbe560d9c76c
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/tools/power/x86/intel-speed-select/.gitignore b/tools/power/x86/intel-speed-select/.gitignore
index f611459..a814f89 100644
--- a/tools/power/x86/intel-speed-select/.gitignore
+++ b/tools/power/x86/intel-speed-select/.gitignore
@@ -1,2 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
include/
intel-speed-select
diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c
index 21fcfe6..ead9e51 100644
--- a/tools/power/x86/intel-speed-select/isst-config.c
+++ b/tools/power/x86/intel-speed-select/isst-config.c
@@ -11,10 +11,11 @@
struct process_cmd_struct {
char *feature;
char *command;
- void (*process_fn)(void);
+ void (*process_fn)(int arg);
+ int arg;
};
-static const char *version_str = "v1.0";
+static const char *version_str = "v1.6";
static const int supported_api_ver = 1;
static struct isst_if_platform_info isst_platform_info;
static char *progname;
@@ -22,8 +23,9 @@
static FILE *outf;
static int cpu_model;
+static int cpu_stepping;
-#define MAX_CPUS_IN_ONE_REQ 64
+#define MAX_CPUS_IN_ONE_REQ 256
static short max_target_cpus;
static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
@@ -39,6 +41,11 @@
static int out_format_json;
static int cmd_help;
static int force_online_offline;
+static int auto_mode;
+static int fact_enable_fail;
+
+static int mbox_delay;
+static int mbox_retries = 3;
/* clos related */
static int current_clos = -1;
@@ -58,6 +65,18 @@
};
struct _cpu_map *cpu_map;
+struct cpu_topology {
+ short cpu;
+ short core_id;
+ short pkg_id;
+ short die_id;
+};
+
+FILE *get_output_file(void)
+{
+ return outf;
+}
+
void debug_printf(const char *format, ...)
{
va_list args;
@@ -70,7 +89,24 @@
va_end(args);
}
-static void update_cpu_model(void)
+
+int is_clx_n_platform(void)
+{
+ if (cpu_model == 0x55)
+ if (cpu_stepping == 0x6 || cpu_stepping == 0x7)
+ return 1;
+ return 0;
+}
+
+int is_skx_based_platform(void)
+{
+ if (cpu_model == 0x55)
+ return 1;
+
+ return 0;
+}
+
+static int update_cpu_model(void)
{
unsigned int ebx, ecx, edx;
unsigned int fms, family;
@@ -80,6 +116,33 @@
cpu_model = (fms >> 4) & 0xf;
if (family == 6 || family == 0xf)
cpu_model += ((fms >> 16) & 0xf) << 4;
+
+ cpu_stepping = fms & 0xf;
+ /* only three CascadeLake-N models are supported */
+ if (is_clx_n_platform()) {
+ FILE *fp;
+ size_t n = 0;
+ char *line = NULL;
+ int ret = 1;
+
+ fp = fopen("/proc/cpuinfo", "r");
+ if (!fp)
+ err(-1, "cannot open /proc/cpuinfo\n");
+
+ while (getline(&line, &n, fp) > 0) {
+ if (strstr(line, "model name")) {
+ if (strstr(line, "6252N") ||
+ strstr(line, "6230N") ||
+ strstr(line, "5218N"))
+ ret = 0;
+ break;
+ }
+ }
+ free(line);
+ fclose(fp);
+ return ret;
+ }
+ return 0;
}
/* Open a file, and exit on failure */
@@ -136,31 +199,150 @@
return out_format_json;
}
+static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id)
+{
+ const char *pathname = "/var/run/isst_cpu_topology.dat";
+ struct cpu_topology cpu_top;
+ FILE *fp;
+ int ret;
+
+ fp = fopen(pathname, "rb");
+ if (!fp)
+ return -1;
+
+ ret = fseek(fp, cpu * sizeof(cpu_top), SEEK_SET);
+ if (ret)
+ goto err_ret;
+
+ ret = fread(&cpu_top, sizeof(cpu_top), 1, fp);
+ if (ret != 1) {
+ ret = -1;
+ goto err_ret;
+ }
+
+ *pkg_id = cpu_top.pkg_id;
+ *core_id = cpu_top.core_id;
+ *die_id = cpu_top.die_id;
+ ret = 0;
+
+err_ret:
+ fclose(fp);
+
+ return ret;
+}
+
+static void store_cpu_topology(void)
+{
+ const char *pathname = "/var/run/isst_cpu_topology.dat";
+ FILE *fp;
+ int i;
+
+ fp = fopen(pathname, "rb");
+ if (fp) {
+ /* Mapping already exists */
+ fclose(fp);
+ return;
+ }
+
+ fp = fopen(pathname, "wb");
+ if (!fp) {
+ fprintf(stderr, "Can't create file:%s\n", pathname);
+ return;
+ }
+
+ fprintf(stderr, "Caching topology information\n");
+
+ for (i = 0; i < topo_max_cpus; ++i) {
+ struct cpu_topology cpu_top;
+
+ cpu_top.core_id = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/core_id", i);
+ if (cpu_top.core_id < 0)
+ cpu_top.core_id = -1;
+
+ cpu_top.pkg_id = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
+ if (cpu_top.pkg_id < 0)
+ cpu_top.pkg_id = -1;
+
+ cpu_top.die_id = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/die_id", i);
+ if (cpu_top.die_id < 0)
+ cpu_top.die_id = -1;
+
+ cpu_top.cpu = i;
+
+ if (fwrite(&cpu_top, sizeof(cpu_top), 1, fp) != 1) {
+ fprintf(stderr, "Can't write to:%s\n", pathname);
+ break;
+ }
+ }
+
+ fclose(fp);
+}
+
int get_physical_package_id(int cpu)
{
- return parse_int_file(
- 0, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
- cpu);
+ int ret;
+
+ ret = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
+ cpu);
+ if (ret < 0) {
+ int core_id, pkg_id, die_id;
+
+ ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
+ if (!ret)
+ return pkg_id;
+ }
+
+ return ret;
}
int get_physical_core_id(int cpu)
{
- return parse_int_file(
- 0, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
+ int ret;
+
+ ret = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/core_id",
+ cpu);
+ if (ret < 0) {
+ int core_id, pkg_id, die_id;
+
+ ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
+ if (!ret)
+ return core_id;
+ }
+
+ return ret;
}
int get_physical_die_id(int cpu)
{
int ret;
- ret = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/topology/die_id",
- cpu);
+ ret = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/die_id",
+ cpu);
+ if (ret < 0) {
+ int core_id, pkg_id, die_id;
+
+ ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
+ if (!ret)
+ return die_id;
+ }
+
if (ret < 0)
ret = 0;
return ret;
}
+int get_cpufreq_base_freq(int cpu)
+{
+ return parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", cpu);
+}
+
int get_topo_max_cpus(void)
{
return topo_max_cpus;
@@ -175,8 +357,14 @@
"/sys/devices/system/cpu/cpu%d/online", cpu);
fd = open(buffer, O_WRONLY);
- if (fd < 0)
+ if (fd < 0) {
+ if (!cpu && state) {
+ fprintf(stderr, "This system is not configured for CPU 0 online/offline\n");
+ fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n");
+ return;
+ }
err(-1, "%s open failed", buffer);
+ }
if (state)
ret = write(fd, "1\n", 2);
@@ -215,7 +403,12 @@
die_id = get_physical_die_id(i);
if (die_id < 0)
die_id = 0;
- pkg_id = get_physical_package_id(i);
+
+ pkg_id = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
+ if (pkg_id < 0)
+ continue;
+
/* Create an unique id for package, die combination to store */
pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
@@ -237,7 +430,7 @@
void (*callback)(int, void *, void *, void *, void *), void *arg1,
void *arg2, void *arg3, void *arg4)
{
- int i;
+ int i, found = 0;
for (i = 0; i < topo_max_cpus; ++i) {
int online;
@@ -251,9 +444,14 @@
online =
1; /* online entry for CPU 0 needs some special configs */
- if (online && callback)
+ if (online && callback) {
callback(i, arg1, arg2, arg3, arg4);
+ found = 1;
+ }
}
+
+ if (!found)
+ fprintf(stderr, "No valid CPU in the list\n");
}
#define BITMASK_SIZE 32
@@ -261,14 +459,27 @@
{
FILE *filep;
unsigned long dummy;
+ int i;
topo_max_cpus = 0;
- filep = fopen_or_exit(
- "/sys/devices/system/cpu/cpu0/topology/thread_siblings", "r");
+ for (i = 0; i < 256; ++i) {
+ char path[256];
+
+ snprintf(path, sizeof(path),
+ "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
+ filep = fopen(path, "r");
+ if (filep)
+ break;
+ }
+
+ if (!filep) {
+ fprintf(stderr, "Can't get max cpu number\n");
+ exit(0);
+ }
+
while (fscanf(filep, "%lx,", &dummy) == 1)
topo_max_cpus += BITMASK_SIZE;
fclose(filep);
- topo_max_cpus--; /* 0 based */
debug_printf("max cpus %d\n", topo_max_cpus);
}
@@ -294,6 +505,7 @@
}
static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
+static long long core_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
static void set_cpu_present_cpu_mask(void)
{
size_t size;
@@ -317,14 +529,41 @@
die_id = 0;
pkg_id = get_physical_package_id(i);
+ if (pkg_id < 0) {
+ fprintf(stderr, "Failed to get package id, CPU %d may be offline\n", i);
+ continue;
+ }
if (pkg_id < MAX_PACKAGE_COUNT &&
- die_id < MAX_DIE_PER_PACKAGE)
+ die_id < MAX_DIE_PER_PACKAGE) {
+ int core_id = get_physical_core_id(i);
+
cpu_cnt[pkg_id][die_id]++;
+ core_mask[pkg_id][die_id] |= (1ULL << core_id);
+ }
}
closedir(dir);
}
}
+int get_max_punit_core_id(int pkg_id, int die_id)
+{
+ int max_id = 0;
+ int i;
+
+ for (i = 0; i < topo_max_cpus; ++i)
+ {
+ if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
+ continue;
+
+ if (cpu_map[i].pkg_id == pkg_id &&
+ cpu_map[i].die_id == die_id &&
+ cpu_map[i].punit_cpu_core > max_id)
+ max_id = cpu_map[i].punit_cpu_core;
+ }
+
+ return max_id;
+}
+
int get_cpu_count(int pkg_id, int die_id)
{
if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
@@ -422,7 +661,7 @@
pkg_id = get_physical_package_id(cpu);
for (i = 0; i < 64; ++i) {
- if (core_mask & BIT(i)) {
+ if (core_mask & BIT_ULL(i)) {
int j;
for (j = 0; j < topo_max_cpus; ++j) {
@@ -477,7 +716,11 @@
}
if (ioctl(fd, cmd, &io_regs) == -1) {
- perror("ISST_IF_IO_CMD");
+ if (errno == ENOTTY) {
+ perror("ISST_IF_IO_COMMAND\n");
+ fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
+ exit(0);
+ }
fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
cpu, reg, write);
} else {
@@ -499,14 +742,15 @@
unsigned int req_data, unsigned int *resp)
{
const char *pathname = "/dev/isst_interface";
- int fd;
+ int fd, retry;
struct isst_if_mbox_cmds mbox_cmds = { 0 };
debug_printf(
"mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
cpu, command, sub_command, parameter, req_data);
- if (isst_platform_info.mmio_supported && command == CONFIG_CLOS) {
+ if (!is_skx_based_platform() && command == CONFIG_CLOS &&
+ sub_command != CLOS_PM_QOS_CONFIG) {
unsigned int value;
int write = 0;
int clos_id, core_id, ret = 0;
@@ -535,12 +779,6 @@
if (!ret && !write)
*resp = value;
break;
- case CLOS_PM_QOS_CONFIG:
- ret = isst_send_mmio_command(cpu, PM_QOS_CONFIG_OFFSET,
- write, &value);
- if (!ret && !write)
- *resp = value;
- break;
case CLOS_STATUS:
break;
default:
@@ -556,24 +794,42 @@
mbox_cmds.mbox_cmd[0].parameter = parameter;
mbox_cmds.mbox_cmd[0].req_data = req_data;
+ if (mbox_delay)
+ usleep(mbox_delay * 1000);
+
fd = open(pathname, O_RDWR);
if (fd < 0)
err(-1, "%s open failed", pathname);
- if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
- perror("ISST_IF_MBOX_COMMAND");
- fprintf(outf,
- "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
- cpu, command, sub_command, parameter, req_data);
- } else {
- *resp = mbox_cmds.mbox_cmd[0].resp_data;
- debug_printf(
- "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
- cpu, command, sub_command, parameter, req_data, *resp);
- }
+ retry = mbox_retries;
+
+ do {
+ if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
+ if (errno == ENOTTY) {
+ perror("ISST_IF_MBOX_COMMAND\n");
+ fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
+ exit(0);
+ }
+ debug_printf(
+ "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
+ cpu, command, sub_command, parameter, req_data, errno);
+ --retry;
+ } else {
+ *resp = mbox_cmds.mbox_cmd[0].resp_data;
+ debug_printf(
+ "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
+ cpu, command, sub_command, parameter, req_data, *resp);
+ break;
+ }
+ } while (retry);
close(fd);
+ if (!retry) {
+ debug_printf("Failed mbox command even after retries\n");
+ return -1;
+
+ }
return 0;
}
@@ -596,7 +852,7 @@
msr_cmds.msr_cmd[0].data = *req_resp;
if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
- perror("ISST_IF_MSR_COMMAD");
+ perror("ISST_IF_MSR_COMMAND");
fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
cpu, msr, write);
} else {
@@ -637,12 +893,85 @@
return 0;
}
+static void isst_print_extended_platform_info(void)
+{
+ int cp_state, cp_cap, fact_support = 0, pbf_support = 0;
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ struct isst_pkg_ctdp pkg_dev;
+ int ret, i, j;
+ FILE *filep;
+
+ for (i = 0; i < 256; ++i) {
+ char path[256];
+
+ snprintf(path, sizeof(path),
+ "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
+ filep = fopen(path, "r");
+ if (filep)
+ break;
+ }
+
+ if (!filep)
+ return;
+
+ fclose(filep);
+
+ ret = isst_get_ctdp_levels(i, &pkg_dev);
+ if (ret)
+ return;
+
+ if (pkg_dev.enabled) {
+ fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n");
+ } else {
+ fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n");
+ fprintf(outf, "Only performance level 0 (base level) is present\n");
+ }
+
+ if (pkg_dev.locked)
+ fprintf(outf, "TDP level change control is locked\n");
+ else
+ fprintf(outf, "TDP level change control is unlocked, max level: %d \n", pkg_dev.levels);
+
+ for (j = 0; j <= pkg_dev.levels; ++j) {
+ ret = isst_get_ctdp_control(i, j, &ctdp_level);
+ if (ret)
+ continue;
+
+ if (!fact_support && ctdp_level.fact_support)
+ fact_support = 1;
+
+ if (!pbf_support && ctdp_level.pbf_support)
+ pbf_support = 1;
+ }
+
+ if (fact_support)
+ fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n");
+ else
+ fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n");
+
+ if (pbf_support)
+ fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n");
+ else
+ fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n");
+
+ ret = isst_read_pm_config(i, &cp_state, &cp_cap);
+ if (cp_cap)
+ fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n");
+ else
+ fprintf(outf, "Intel(R) SST-CP (feature core-power) is not supported\n");
+}
+
static void isst_print_platform_information(void)
{
struct isst_if_platform_info platform_info;
const char *pathname = "/dev/isst_interface";
int fd;
+ if (is_clx_n_platform()) {
+ fprintf(stderr, "\nThis option in not supported on this platform\n");
+ exit(0);
+ }
+
fd = open(pathname, O_RDWR);
if (fd < 0)
err(-1, "%s open failed", pathname);
@@ -658,6 +987,7 @@
platform_info.mbox_supported);
fprintf(outf, "Platform: mmio supported : %d\n",
platform_info.mmio_supported);
+ isst_print_extended_platform_info();
}
close(fd);
@@ -665,6 +995,7 @@
exit(0);
}
+static char *local_str0, *local_str1;
static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
void *arg4)
{
@@ -674,14 +1005,15 @@
fn_ptr = arg1;
ret = fn_ptr(cpu, arg2);
if (ret)
- perror("get_tdp_*");
+ isst_display_error_info_message(1, "get_tdp_* failed", 0, 0);
else
isst_ctdp_display_core_info(cpu, outf, arg3,
- *(unsigned int *)arg4);
+ *(unsigned int *)arg4,
+ local_str0, local_str1);
}
-#define _get_tdp_level(desc, suffix, object, help) \
- static void get_tdp_##object(void) \
+#define _get_tdp_level(desc, suffix, object, help, str0, str1) \
+ static void get_tdp_##object(int arg) \
{ \
struct isst_pkg_ctdp ctdp; \
\
@@ -691,6 +1023,8 @@
help); \
exit(0); \
} \
+ local_str0 = str0; \
+ local_str1 = str1; \
isst_ctdp_display_information_start(outf); \
if (max_target_cpus) \
for_each_online_target_cpu_in_set( \
@@ -704,12 +1038,164 @@
isst_ctdp_display_information_end(outf); \
}
-_get_tdp_level("get-config-levels", levels, levels, "TDP levels");
-_get_tdp_level("get-config-version", levels, version, "TDP version");
-_get_tdp_level("get-config-enabled", levels, enabled, "TDP enable status");
+_get_tdp_level("get-config-levels", levels, levels, "Max TDP level", NULL, NULL);
+_get_tdp_level("get-config-version", levels, version, "TDP version", NULL, NULL);
+_get_tdp_level("get-config-enabled", levels, enabled, "perf-profile enable status", "disabled", "enabled");
_get_tdp_level("get-config-current_level", levels, current_level,
- "Current TDP Level");
-_get_tdp_level("get-lock-status", levels, locked, "TDP lock status");
+ "Current TDP Level", NULL, NULL);
+_get_tdp_level("get-lock-status", levels, locked, "TDP lock status", "unlocked", "locked");
+
+struct isst_pkg_ctdp clx_n_pkg_dev;
+
+static int clx_n_get_base_ratio(void)
+{
+ FILE *fp;
+ char *begin, *end, *line = NULL;
+ char number[5];
+ float value = 0;
+ size_t n = 0;
+
+ fp = fopen("/proc/cpuinfo", "r");
+ if (!fp)
+ err(-1, "cannot open /proc/cpuinfo\n");
+
+ while (getline(&line, &n, fp) > 0) {
+ if (strstr(line, "model name")) {
+ /* this is true for CascadeLake-N */
+ begin = strstr(line, "@ ") + 2;
+ end = strstr(line, "GHz");
+ strncpy(number, begin, end - begin);
+ value = atof(number) * 10;
+ break;
+ }
+ }
+ free(line);
+ fclose(fp);
+
+ return (int)(value);
+}
+
+static int clx_n_config(int cpu)
+{
+ int i, ret, pkg_id, die_id;
+ unsigned long cpu_bf;
+ struct isst_pkg_ctdp_level_info *ctdp_level;
+ struct isst_pbf_info *pbf_info;
+
+ ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
+ pbf_info = &ctdp_level->pbf_info;
+ ctdp_level->core_cpumask_size =
+ alloc_cpu_set(&ctdp_level->core_cpumask);
+
+ /* find the frequency base ratio */
+ ctdp_level->tdp_ratio = clx_n_get_base_ratio();
+ if (ctdp_level->tdp_ratio == 0) {
+ debug_printf("CLX: cn base ratio is zero\n");
+ ret = -1;
+ goto error_ret;
+ }
+
+ /* find the high and low priority frequencies */
+ pbf_info->p1_high = 0;
+ pbf_info->p1_low = ~0;
+
+ pkg_id = get_physical_package_id(cpu);
+ die_id = get_physical_die_id(cpu);
+
+ for (i = 0; i < topo_max_cpus; i++) {
+ if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
+ continue;
+
+ if (pkg_id != get_physical_package_id(i) ||
+ die_id != get_physical_die_id(i))
+ continue;
+
+ CPU_SET_S(i, ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask);
+
+ cpu_bf = parse_int_file(1,
+ "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
+ i);
+ if (cpu_bf > pbf_info->p1_high)
+ pbf_info->p1_high = cpu_bf;
+ if (cpu_bf < pbf_info->p1_low)
+ pbf_info->p1_low = cpu_bf;
+ }
+
+ if (pbf_info->p1_high == ~0UL) {
+ debug_printf("CLX: maximum base frequency not set\n");
+ ret = -1;
+ goto error_ret;
+ }
+
+ if (pbf_info->p1_low == 0) {
+ debug_printf("CLX: minimum base frequency not set\n");
+ ret = -1;
+ goto error_ret;
+ }
+
+ /* convert frequencies back to ratios */
+ pbf_info->p1_high = pbf_info->p1_high / 100000;
+ pbf_info->p1_low = pbf_info->p1_low / 100000;
+
+ /* create high priority cpu mask */
+ pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
+ for (i = 0; i < topo_max_cpus; i++) {
+ if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
+ continue;
+
+ if (pkg_id != get_physical_package_id(i) ||
+ die_id != get_physical_die_id(i))
+ continue;
+
+ cpu_bf = parse_int_file(1,
+ "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
+ i);
+ cpu_bf = cpu_bf / 100000;
+ if (cpu_bf == pbf_info->p1_high)
+ CPU_SET_S(i, pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask);
+ }
+
+ /* extra ctdp & pbf struct parameters */
+ ctdp_level->processed = 1;
+ ctdp_level->pbf_support = 1; /* PBF is always supported and enabled */
+ ctdp_level->pbf_enabled = 1;
+ ctdp_level->fact_support = 0; /* FACT is never supported */
+ ctdp_level->fact_enabled = 0;
+
+ return 0;
+
+error_ret:
+ free_cpu_set(ctdp_level->core_cpumask);
+ return ret;
+}
+
+static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2,
+ void *arg3, void *arg4)
+{
+ int ret;
+
+ if (tdp_level != 0xff && tdp_level != 0) {
+ isst_display_error_info_message(1, "Invalid level", 1, tdp_level);
+ exit(0);
+ }
+
+ ret = clx_n_config(cpu);
+ if (ret) {
+ debug_printf("clx_n_config failed");
+ } else {
+ struct isst_pkg_ctdp_level_info *ctdp_level;
+ struct isst_pbf_info *pbf_info;
+
+ ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
+ pbf_info = &ctdp_level->pbf_info;
+ clx_n_pkg_dev.processed = 1;
+ isst_ctdp_display_information(cpu, outf, tdp_level, &clx_n_pkg_dev);
+ free_cpu_set(ctdp_level->core_cpumask);
+ free_cpu_set(pbf_info->core_cpumask);
+ }
+}
static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2,
void *arg3, void *arg4)
@@ -720,15 +1206,19 @@
memset(&pkg_dev, 0, sizeof(pkg_dev));
ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev);
if (ret) {
- perror("isst_get_process_ctdp");
+ isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, cpu);
+ isst_ctdp_display_information_end(outf);
+ exit(1);
} else {
isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev);
isst_get_process_ctdp_complete(cpu, &pkg_dev);
}
}
-static void dump_isst_config(void)
+static void dump_isst_config(int arg)
{
+ void *fn;
+
if (cmd_help) {
fprintf(stderr,
"Print Intel(R) Speed Select Technology Performance profile configuration\n");
@@ -740,27 +1230,34 @@
exit(0);
}
+ if (!is_clx_n_platform())
+ fn = dump_isst_config_for_cpu;
+ else
+ fn = dump_clx_n_config_for_cpu;
+
isst_ctdp_display_information_start(outf);
if (max_target_cpus)
- for_each_online_target_cpu_in_set(dump_isst_config_for_cpu,
- NULL, NULL, NULL, NULL);
+ for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
else
- for_each_online_package_in_set(dump_isst_config_for_cpu, NULL,
- NULL, NULL, NULL);
+ for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
isst_ctdp_display_information_end(outf);
}
+static void adjust_scaling_max_from_base_freq(int cpu);
+
static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
void *arg4)
{
int ret;
ret = isst_set_tdp_level(cpu, tdp_level);
- if (ret)
- perror("set_tdp_level_for_cpu");
- else {
+ if (ret) {
+ isst_display_error_info_message(1, "Set TDP level failed", 0, 0);
+ isst_ctdp_display_information_end(outf);
+ exit(1);
+ } else {
isst_display_result(cpu, outf, "perf-profile", "set_tdp_level",
ret);
if (force_online_offline) {
@@ -768,10 +1265,17 @@
int pkg_id = get_physical_package_id(cpu);
int die_id = get_physical_die_id(cpu);
+ /* Wait for updated base frequencies */
+ usleep(2000);
+
fprintf(stderr, "Option is set to online/offline\n");
ctdp_level.core_cpumask_size =
alloc_cpu_set(&ctdp_level.core_cpumask);
- isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
+ ret = isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
+ if (ret) {
+ isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
+ return;
+ }
if (ctdp_level.cpu_count) {
int i, max_cpus = get_topo_max_cpus();
for (i = 0; i < max_cpus; ++i) {
@@ -780,6 +1284,7 @@
if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
fprintf(stderr, "online cpu %d\n", i);
set_cpu_online_offline(i, 1);
+ adjust_scaling_max_from_base_freq(i);
} else {
fprintf(stderr, "offline cpu %d\n", i);
set_cpu_online_offline(i, 0);
@@ -790,7 +1295,7 @@
}
}
-static void set_tdp_level(void)
+static void set_tdp_level(int arg)
{
if (cmd_help) {
fprintf(stderr, "Set Config TDP level\n");
@@ -798,11 +1303,13 @@
"\t Arguments: -l|--level : Specify tdp level\n");
fprintf(stderr,
"\t Optional Arguments: -o | online : online/offline for the tdp level\n");
+ fprintf(stderr,
+ "\t online/offline operation has limitations, refer to Linux hotplug documentation\n");
exit(0);
}
if (tdp_level == 0xff) {
- fprintf(outf, "Invalid command: specify tdp_level\n");
+ isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
exit(1);
}
isst_ctdp_display_information_start(outf);
@@ -815,6 +1322,26 @@
isst_ctdp_display_information_end(outf);
}
+static void clx_n_dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2,
+ void *arg3, void *arg4)
+{
+ int ret;
+
+ ret = clx_n_config(cpu);
+ if (ret) {
+ isst_display_error_info_message(1, "clx_n_config failed", 0, 0);
+ } else {
+ struct isst_pkg_ctdp_level_info *ctdp_level;
+ struct isst_pbf_info *pbf_info;
+
+ ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
+ pbf_info = &ctdp_level->pbf_info;
+ isst_pbf_display_information(cpu, outf, tdp_level, pbf_info);
+ free_cpu_set(ctdp_level->core_cpumask);
+ free_cpu_set(pbf_info->core_cpumask);
+ }
+}
+
static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
void *arg4)
{
@@ -823,15 +1350,19 @@
ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info);
if (ret) {
- perror("isst_get_pbf_info");
+ isst_display_error_info_message(1, "Failed to get base-freq info at this level", 1, tdp_level);
+ isst_ctdp_display_information_end(outf);
+ exit(1);
} else {
isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info);
isst_get_pbf_info_complete(&pbf_info);
}
}
-static void dump_pbf_config(void)
+static void dump_pbf_config(int arg)
{
+ void *fn;
+
if (cmd_help) {
fprintf(stderr,
"Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n");
@@ -841,76 +1372,432 @@
}
if (tdp_level == 0xff) {
- fprintf(outf, "Invalid command: specify tdp_level\n");
+ isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
exit(1);
}
- isst_ctdp_display_information_start(outf);
- if (max_target_cpus)
- for_each_online_target_cpu_in_set(dump_pbf_config_for_cpu, NULL,
- NULL, NULL, NULL);
+ if (!is_clx_n_platform())
+ fn = dump_pbf_config_for_cpu;
else
- for_each_online_package_in_set(dump_pbf_config_for_cpu, NULL,
- NULL, NULL, NULL);
+ fn = clx_n_dump_pbf_config_for_cpu;
+
+ isst_ctdp_display_information_start(outf);
+
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
+ else
+ for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
+
isst_ctdp_display_information_end(outf);
}
+static int set_clos_param(int cpu, int clos, int epp, int wt, int min, int max)
+{
+ struct isst_clos_config clos_config;
+ int ret;
+
+ ret = isst_pm_get_clos(cpu, clos, &clos_config);
+ if (ret) {
+ isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
+ return ret;
+ }
+ clos_config.clos_min = min;
+ clos_config.clos_max = max;
+ clos_config.epp = epp;
+ clos_config.clos_prop_prio = wt;
+ ret = isst_set_clos(cpu, clos, &clos_config);
+ if (ret) {
+ isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int set_cpufreq_scaling_min_max(int cpu, int max, int freq)
+{
+ char buffer[128], freq_str[16];
+ int fd, ret, len;
+
+ if (max)
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
+ else
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
+
+ fd = open(buffer, O_WRONLY);
+ if (fd < 0)
+ return fd;
+
+ snprintf(freq_str, sizeof(freq_str), "%d", freq);
+ len = strlen(freq_str);
+ ret = write(fd, freq_str, len);
+ if (ret == -1) {
+ close(fd);
+ return ret;
+ }
+ close(fd);
+
+ return 0;
+}
+
+static int no_turbo(void)
+{
+ return parse_int_file(0, "/sys/devices/system/cpu/intel_pstate/no_turbo");
+}
+
+static void adjust_scaling_max_from_base_freq(int cpu)
+{
+ int base_freq, scaling_max_freq;
+
+ scaling_max_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
+ base_freq = get_cpufreq_base_freq(cpu);
+ if (scaling_max_freq < base_freq || no_turbo())
+ set_cpufreq_scaling_min_max(cpu, 1, base_freq);
+}
+
+static void adjust_scaling_min_from_base_freq(int cpu)
+{
+ int base_freq, scaling_min_freq;
+
+ scaling_min_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
+ base_freq = get_cpufreq_base_freq(cpu);
+ if (scaling_min_freq < base_freq)
+ set_cpufreq_scaling_min_max(cpu, 0, base_freq);
+}
+
+static int set_clx_pbf_cpufreq_scaling_min_max(int cpu)
+{
+ struct isst_pkg_ctdp_level_info *ctdp_level;
+ struct isst_pbf_info *pbf_info;
+ int i, pkg_id, die_id, freq, freq_high, freq_low;
+ int ret;
+
+ ret = clx_n_config(cpu);
+ if (ret) {
+ debug_printf("cpufreq_scaling_min_max failed for CLX");
+ return ret;
+ }
+
+ ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
+ pbf_info = &ctdp_level->pbf_info;
+ freq_high = pbf_info->p1_high * 100000;
+ freq_low = pbf_info->p1_low * 100000;
+
+ pkg_id = get_physical_package_id(cpu);
+ die_id = get_physical_die_id(cpu);
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ if (pkg_id != get_physical_package_id(i) ||
+ die_id != get_physical_die_id(i))
+ continue;
+
+ if (CPU_ISSET_S(i, pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask))
+ freq = freq_high;
+ else
+ freq = freq_low;
+
+ set_cpufreq_scaling_min_max(i, 1, freq);
+ set_cpufreq_scaling_min_max(i, 0, freq);
+ }
+
+ return 0;
+}
+
+static int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, int scaling_max)
+{
+ char buffer[128], min_freq[16];
+ int fd, ret, len;
+
+ if (!CPU_ISSET_S(cpu, present_cpumask_size, present_cpumask))
+ return -1;
+
+ if (cpuinfo_max)
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu);
+ else
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_min_freq", cpu);
+
+ fd = open(buffer, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ len = read(fd, min_freq, sizeof(min_freq));
+ close(fd);
+
+ if (len < 0)
+ return len;
+
+ if (scaling_max)
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
+ else
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
+
+ fd = open(buffer, O_WRONLY);
+ if (fd < 0)
+ return fd;
+
+ len = strlen(min_freq);
+ ret = write(fd, min_freq, len);
+ if (ret == -1) {
+ close(fd);
+ return ret;
+ }
+ close(fd);
+
+ return 0;
+}
+
+static void set_scaling_min_to_cpuinfo_max(int cpu)
+{
+ int i, pkg_id, die_id;
+
+ pkg_id = get_physical_package_id(cpu);
+ die_id = get_physical_die_id(cpu);
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ if (pkg_id != get_physical_package_id(i) ||
+ die_id != get_physical_die_id(i))
+ continue;
+
+ set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0);
+ adjust_scaling_min_from_base_freq(i);
+ }
+}
+
+static void set_scaling_min_to_cpuinfo_min(int cpu)
+{
+ int i, pkg_id, die_id;
+
+ pkg_id = get_physical_package_id(cpu);
+ die_id = get_physical_die_id(cpu);
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ if (pkg_id != get_physical_package_id(i) ||
+ die_id != get_physical_die_id(i))
+ continue;
+
+ set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0);
+ }
+}
+
+static void set_scaling_max_to_cpuinfo_max(int cpu)
+{
+ int i, pkg_id, die_id;
+
+ pkg_id = get_physical_package_id(cpu);
+ die_id = get_physical_die_id(cpu);
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ if (pkg_id != get_physical_package_id(i) ||
+ die_id != get_physical_die_id(i))
+ continue;
+
+ set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1);
+ }
+}
+
+static int set_core_priority_and_min(int cpu, int mask_size,
+ cpu_set_t *cpu_mask, int min_high,
+ int min_low)
+{
+ int pkg_id, die_id, ret, i;
+
+ if (!CPU_COUNT_S(mask_size, cpu_mask))
+ return -1;
+
+ ret = set_clos_param(cpu, 0, 0, 0, min_high, 0xff);
+ if (ret)
+ return ret;
+
+ ret = set_clos_param(cpu, 1, 15, 15, min_low, 0xff);
+ if (ret)
+ return ret;
+
+ ret = set_clos_param(cpu, 2, 15, 15, min_low, 0xff);
+ if (ret)
+ return ret;
+
+ ret = set_clos_param(cpu, 3, 15, 15, min_low, 0xff);
+ if (ret)
+ return ret;
+
+ pkg_id = get_physical_package_id(cpu);
+ die_id = get_physical_die_id(cpu);
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ int clos;
+
+ if (pkg_id != get_physical_package_id(i) ||
+ die_id != get_physical_die_id(i))
+ continue;
+
+ if (CPU_ISSET_S(i, mask_size, cpu_mask))
+ clos = 0;
+ else
+ clos = 3;
+
+ debug_printf("Associate cpu: %d clos: %d\n", i, clos);
+ ret = isst_clos_associate(i, clos);
+ if (ret) {
+ isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int set_pbf_core_power(int cpu)
+{
+ struct isst_pbf_info pbf_info;
+ struct isst_pkg_ctdp pkg_dev;
+ int ret;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret) {
+ debug_printf("isst_get_ctdp_levels failed");
+ return ret;
+ }
+ debug_printf("Current_level: %d\n", pkg_dev.current_level);
+
+ ret = isst_get_pbf_info(cpu, pkg_dev.current_level, &pbf_info);
+ if (ret) {
+ debug_printf("isst_get_pbf_info failed");
+ return ret;
+ }
+ debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high,
+ pbf_info.p1_low);
+
+ ret = set_core_priority_and_min(cpu, pbf_info.core_cpumask_size,
+ pbf_info.core_cpumask,
+ pbf_info.p1_high, pbf_info.p1_low);
+ if (ret) {
+ debug_printf("set_core_priority_and_min failed");
+ return ret;
+ }
+
+ ret = isst_pm_qos_config(cpu, 1, 1);
+ if (ret) {
+ debug_printf("isst_pm_qos_config failed");
+ return ret;
+ }
+
+ return 0;
+}
+
static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
void *arg4)
{
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ struct isst_pkg_ctdp pkg_dev;
int ret;
int status = *(int *)arg4;
+ if (is_clx_n_platform()) {
+ ret = 0;
+ if (status) {
+ set_clx_pbf_cpufreq_scaling_min_max(cpu);
+
+ } else {
+ set_scaling_max_to_cpuinfo_max(cpu);
+ set_scaling_min_to_cpuinfo_min(cpu);
+ }
+ goto disp_result;
+ }
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret) {
+ isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
+ goto disp_result;
+ }
+
+ ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
+ if (ret) {
+ isst_display_error_info_message(1, "Failed to get current level", 0, 0);
+ goto disp_result;
+ }
+
+ if (!ctdp_level.pbf_support) {
+ isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, pkg_dev.current_level);
+ ret = -1;
+ goto disp_result;
+ }
+
+ if (auto_mode && status) {
+ ret = set_pbf_core_power(cpu);
+ if (ret)
+ goto disp_result;
+ }
+
ret = isst_set_pbf_fact_status(cpu, 1, status);
if (ret) {
- perror("isst_set_pbf");
+ debug_printf("isst_set_pbf_fact_status failed");
+ if (auto_mode)
+ isst_pm_qos_config(cpu, 0, 0);
} else {
- if (status)
- isst_display_result(cpu, outf, "base-freq", "enable",
- ret);
- else
- isst_display_result(cpu, outf, "base-freq", "disable",
- ret);
+ if (auto_mode) {
+ if (status)
+ set_scaling_min_to_cpuinfo_max(cpu);
+ else
+ set_scaling_min_to_cpuinfo_min(cpu);
+ }
}
+
+ if (auto_mode && !status)
+ isst_pm_qos_config(cpu, 0, 1);
+
+disp_result:
+ if (status)
+ isst_display_result(cpu, outf, "base-freq", "enable",
+ ret);
+ else
+ isst_display_result(cpu, outf, "base-freq", "disable",
+ ret);
}
-static void set_pbf_enable(void)
+static void set_pbf_enable(int arg)
{
- int status = 1;
+ int enable = arg;
if (cmd_help) {
- fprintf(stderr,
- "Enable Intel Speed Select Technology base frequency feature [No command arguments are required]\n");
+ if (enable) {
+ fprintf(stderr,
+ "Enable Intel Speed Select Technology base frequency feature\n");
+ if (is_clx_n_platform()) {
+ fprintf(stderr,
+ "\tOn this platform this command doesn't enable feature in the hardware.\n");
+ fprintf(stderr,
+ "\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n");
+ exit(0);
+
+ }
+ fprintf(stderr,
+ "\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n");
+ } else {
+
+ if (is_clx_n_platform()) {
+ fprintf(stderr,
+ "\tOn this platform this command doesn't disable feature in the hardware.\n");
+ fprintf(stderr,
+ "\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n");
+ exit(0);
+ }
+ fprintf(stderr,
+ "Disable Intel Speed Select Technology base frequency feature\n");
+ fprintf(stderr,
+ "\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
+ }
exit(0);
}
isst_ctdp_display_information_start(outf);
if (max_target_cpus)
for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
- NULL, &status);
+ NULL, &enable);
else
for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
- NULL, &status);
- isst_ctdp_display_information_end(outf);
-}
-
-static void set_pbf_disable(void)
-{
- int status = 0;
-
- if (cmd_help) {
- fprintf(stderr,
- "Disable Intel Speed Select Technology base frequency feature [No command arguments are required]\n");
- exit(0);
- }
-
- isst_ctdp_display_information_start(outf);
- if (max_target_cpus)
- for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
- NULL, &status);
- else
- for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
- NULL, &status);
+ NULL, &enable);
isst_ctdp_display_information_end(outf);
}
@@ -920,15 +1807,18 @@
struct isst_fact_info fact_info;
int ret;
- ret = isst_get_fact_info(cpu, tdp_level, &fact_info);
- if (ret)
- perror("isst_get_fact_bucket_info");
- else
+ ret = isst_get_fact_info(cpu, tdp_level, fact_bucket, &fact_info);
+ if (ret) {
+ isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level);
+ isst_ctdp_display_information_end(outf);
+ exit(1);
+ } else {
isst_fact_display_information(cpu, outf, tdp_level, fact_bucket,
fact_avx, &fact_info);
+ }
}
-static void dump_fact_config(void)
+static void dump_fact_config(int arg)
{
if (cmd_help) {
fprintf(stderr,
@@ -943,7 +1833,7 @@
}
if (tdp_level == 0xff) {
- fprintf(outf, "Invalid command: specify tdp_level\n");
+ isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0);
exit(1);
}
@@ -960,76 +1850,180 @@
static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
void *arg4)
{
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ struct isst_pkg_ctdp pkg_dev;
int ret;
int status = *(int *)arg4;
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret) {
+ isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
+ goto disp_results;
+ }
+
+ ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
+ if (ret) {
+ isst_display_error_info_message(1, "Failed to get current level", 0, 0);
+ goto disp_results;
+ }
+
+ if (!ctdp_level.fact_support) {
+ isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, pkg_dev.current_level);
+ ret = -1;
+ goto disp_results;
+ }
+
+ if (status) {
+ ret = isst_pm_qos_config(cpu, 1, 1);
+ if (ret)
+ goto disp_results;
+ }
+
ret = isst_set_pbf_fact_status(cpu, 0, status);
- if (ret)
- perror("isst_set_fact");
- else {
- if (status) {
- struct isst_pkg_ctdp pkg_dev;
+ if (ret) {
+ debug_printf("isst_set_pbf_fact_status failed");
+ if (auto_mode)
+ isst_pm_qos_config(cpu, 0, 0);
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
- if (ret) {
- isst_display_result(cpu, outf, "turbo-freq",
- "enable", ret);
- return;
- }
+ goto disp_results;
+ }
+
+ /* Set TRL */
+ if (status) {
+ struct isst_pkg_ctdp pkg_dev;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (!ret)
ret = isst_set_trl(cpu, fact_trl);
- isst_display_result(cpu, outf, "turbo-freq", "enable",
- ret);
+ if (ret && auto_mode)
+ isst_pm_qos_config(cpu, 0, 0);
+ } else {
+ if (auto_mode)
+ isst_pm_qos_config(cpu, 0, 0);
+ }
+
+disp_results:
+ if (status) {
+ isst_display_result(cpu, outf, "turbo-freq", "enable", ret);
+ if (ret)
+ fact_enable_fail = ret;
+ } else {
+ /* Since we modified TRL during Fact enable, restore it */
+ isst_set_trl_from_current_tdp(cpu, fact_trl);
+ isst_display_result(cpu, outf, "turbo-freq", "disable", ret);
+ }
+}
+
+static void set_fact_enable(int arg)
+{
+ int i, ret, enable = arg;
+
+ if (cmd_help) {
+ if (enable) {
+ fprintf(stderr,
+ "Enable Intel Speed Select Technology Turbo frequency feature\n");
+ fprintf(stderr,
+ "Optional: -t|--trl : Specify turbo ratio limit\n");
+ fprintf(stderr,
+ "\tOptional Arguments: -a|--auto : Designate specified target CPUs with");
+ fprintf(stderr,
+ "-C|--cpu option as as high priority using core-power feature\n");
} else {
- /* Since we modified TRL during Fact enable, restore it */
- isst_set_trl_from_current_tdp(cpu, fact_trl);
- isst_display_result(cpu, outf, "turbo-freq", "disable",
- ret);
+ fprintf(stderr,
+ "Disable Intel Speed Select Technology turbo frequency feature\n");
+ fprintf(stderr,
+ "Optional: -t|--trl : Specify turbo ratio limit\n");
+ fprintf(stderr,
+ "\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
}
- }
-}
-
-static void set_fact_enable(void)
-{
- int status = 1;
-
- if (cmd_help) {
- fprintf(stderr,
- "Enable Intel Speed Select Technology Turbo frequency feature\n");
- fprintf(stderr,
- "Optional: -t|--trl : Specify turbo ratio limit\n");
exit(0);
}
isst_ctdp_display_information_start(outf);
if (max_target_cpus)
for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
- NULL, &status);
+ NULL, &enable);
else
for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
- NULL, &status);
+ NULL, &enable);
isst_ctdp_display_information_end(outf);
-}
-static void set_fact_disable(void)
-{
- int status = 0;
+ if (!fact_enable_fail && enable && auto_mode) {
+ /*
+ * When we adjust CLOS param, we have to set for siblings also.
+ * So for the each user specified CPU, also add the sibling
+ * in the present_cpu_mask.
+ */
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ char buffer[128], sibling_list[128], *cpu_str;
+ int fd, len;
- if (cmd_help) {
- fprintf(stderr,
- "Disable Intel Speed Select Technology turbo frequency feature\n");
- fprintf(stderr,
- "Optional: -t|--trl : Specify turbo ratio limit\n");
- exit(0);
+ if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
+ continue;
+
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i);
+
+ fd = open(buffer, O_RDONLY);
+ if (fd < 0)
+ continue;
+
+ len = read(fd, sibling_list, sizeof(sibling_list));
+ close(fd);
+
+ if (len < 0)
+ continue;
+
+ cpu_str = strtok(sibling_list, ",");
+ while (cpu_str != NULL) {
+ int cpu;
+
+ sscanf(cpu_str, "%d", &cpu);
+ CPU_SET_S(cpu, target_cpumask_size, target_cpumask);
+ cpu_str = strtok(NULL, ",");
+ }
+ }
+
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ int clos;
+
+ if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
+ continue;
+
+ ret = set_clos_param(i, 0, 0, 0, 0, 0xff);
+ if (ret)
+ goto error_disp;
+
+ ret = set_clos_param(i, 1, 15, 15, 0, 0xff);
+ if (ret)
+ goto error_disp;
+
+ ret = set_clos_param(i, 2, 15, 15, 0, 0xff);
+ if (ret)
+ goto error_disp;
+
+ ret = set_clos_param(i, 3, 15, 15, 0, 0xff);
+ if (ret)
+ goto error_disp;
+
+ if (CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
+ clos = 0;
+ else
+ clos = 3;
+
+ debug_printf("Associate cpu: %d clos: %d\n", i, clos);
+ ret = isst_clos_associate(i, clos);
+ if (ret)
+ goto error_disp;
+ }
+ isst_display_result(-1, outf, "turbo-freq --auto", "enable", 0);
}
- isst_ctdp_display_information_start(outf);
- if (max_target_cpus)
- for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
- NULL, &status);
- else
- for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
- NULL, &status);
- isst_ctdp_display_information_end(outf);
+ return;
+
+error_disp:
+ isst_display_result(i, outf, "turbo-freq --auto", "enable", ret);
+
}
static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3,
@@ -1038,32 +2032,42 @@
int ret;
int status = *(int *)arg4;
+ if (is_skx_based_platform())
+ clos_priority_type = 1;
+
ret = isst_pm_qos_config(cpu, status, clos_priority_type);
- if (ret) {
- perror("isst_pm_qos_config");
- } else {
- if (status)
- isst_display_result(cpu, outf, "core-power", "enable",
- ret);
- else
- isst_display_result(cpu, outf, "core-power", "disable",
- ret);
- }
+ if (ret)
+ isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0);
+
+ if (status)
+ isst_display_result(cpu, outf, "core-power", "enable",
+ ret);
+ else
+ isst_display_result(cpu, outf, "core-power", "disable",
+ ret);
}
-static void set_clos_enable(void)
+static void set_clos_enable(int arg)
{
- int status = 1;
+ int enable = arg;
if (cmd_help) {
- fprintf(stderr, "Enable core-power for a package/die\n");
- fprintf(stderr,
- "\tClos Enable: Specify priority type with [--priority|-p]\n");
- fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
+ if (enable) {
+ fprintf(stderr,
+ "Enable core-power for a package/die\n");
+ if (!is_skx_based_platform()) {
+ fprintf(stderr,
+ "\tClos Enable: Specify priority type with [--priority|-p]\n");
+ fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
+ }
+ } else {
+ fprintf(stderr,
+ "Disable core-power: [No command arguments are required]\n");
+ }
exit(0);
}
- if (cpufreq_sysfs_present()) {
+ if (enable && cpufreq_sysfs_present()) {
fprintf(stderr,
"cpufreq subsystem and core-power enable will interfere with each other!\n");
}
@@ -1071,30 +2075,10 @@
isst_ctdp_display_information_start(outf);
if (max_target_cpus)
for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
- NULL, NULL, &status);
+ NULL, NULL, &enable);
else
for_each_online_package_in_set(enable_clos_qos_config, NULL,
- NULL, NULL, &status);
- isst_ctdp_display_information_end(outf);
-}
-
-static void set_clos_disable(void)
-{
- int status = 0;
-
- if (cmd_help) {
- fprintf(stderr,
- "Disable core-power: [No command arguments are required]\n");
- exit(0);
- }
-
- isst_ctdp_display_information_start(outf);
- if (max_target_cpus)
- for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
- NULL, NULL, &status);
- else
- for_each_online_package_in_set(enable_clos_qos_config, NULL,
- NULL, NULL, &status);
+ NULL, NULL, &enable);
isst_ctdp_display_information_end(outf);
}
@@ -1106,13 +2090,13 @@
ret = isst_pm_get_clos(cpu, current_clos, &clos_config);
if (ret)
- perror("isst_pm_get_clos");
+ isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
else
isst_clos_display_information(cpu, outf, current_clos,
&clos_config);
}
-static void dump_clos_config(void)
+static void dump_clos_config(int arg)
{
if (cmd_help) {
fprintf(stderr,
@@ -1122,7 +2106,8 @@
exit(0);
}
if (current_clos < 0 || current_clos > 3) {
- fprintf(stderr, "Invalid clos id\n");
+ isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
+ isst_ctdp_display_information_end(outf);
exit(0);
}
@@ -1143,29 +2128,32 @@
ret = isst_clos_get_clos_information(cpu, &enable, &prio_type);
if (ret)
- perror("isst_clos_get_info");
- else
- isst_clos_display_clos_information(cpu, outf, enable, prio_type);
+ isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0);
+ else {
+ int cp_state, cp_cap;
+
+ isst_read_pm_config(cpu, &cp_state, &cp_cap);
+ isst_clos_display_clos_information(cpu, outf, enable, prio_type,
+ cp_state, cp_cap);
+ }
}
-static void dump_clos_info(void)
+static void dump_clos_info(int arg)
{
if (cmd_help) {
fprintf(stderr,
"Print Intel Speed Select Technology core power information\n");
- fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
- exit(0);
- }
-
- if (!max_target_cpus) {
- fprintf(stderr,
- "Invalid target cpu. Specify with [-c|--cpu]\n");
+ fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n");
exit(0);
}
isst_ctdp_display_information_start(outf);
- for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
- NULL, NULL, NULL);
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
+ NULL, NULL, NULL);
+ else
+ for_each_online_package_in_set(get_clos_info_for_cpu, NULL,
+ NULL, NULL, NULL);
isst_ctdp_display_information_end(outf);
}
@@ -1186,38 +2174,39 @@
clos_config.clos_desired = clos_desired;
ret = isst_set_clos(cpu, current_clos, &clos_config);
if (ret)
- perror("isst_set_clos");
+ isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
else
isst_display_result(cpu, outf, "core-power", "config", ret);
}
-static void set_clos_config(void)
+static void set_clos_config(int arg)
{
if (cmd_help) {
fprintf(stderr,
"Set core-power configuration for one of the four clos ids\n");
fprintf(stderr,
"\tSpecify targeted clos id with [--clos|-c]\n");
- fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
- fprintf(stderr,
- "\tSpecify clos Proportional Priority [--weight|-w]\n");
- fprintf(stderr, "\tSpecify clos min with [--min|-n]\n");
- fprintf(stderr, "\tSpecify clos max with [--max|-m]\n");
- fprintf(stderr, "\tSpecify clos desired with [--desired|-d]\n");
+ if (!is_skx_based_platform()) {
+ fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
+ fprintf(stderr,
+ "\tSpecify clos Proportional Priority [--weight|-w]\n");
+ }
+ fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n");
+ fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n");
exit(0);
}
if (current_clos < 0 || current_clos > 3) {
- fprintf(stderr, "Invalid clos id\n");
+ isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
exit(0);
}
- if (clos_epp < 0 || clos_epp > 0x0F) {
- fprintf(stderr, "clos epp is not specified, default: 0\n");
+ if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) {
+ fprintf(stderr, "clos epp is not specified or invalid, default: 0\n");
clos_epp = 0;
}
- if (clos_prop_prio < 0 || clos_prop_prio > 0x0F) {
+ if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) {
fprintf(stderr,
- "clos frequency weight is not specified, default: 0\n");
+ "clos frequency weight is not specified or invalid, default: 0\n");
clos_prop_prio = 0;
}
if (clos_min < 0) {
@@ -1225,11 +2214,11 @@
clos_min = 0;
}
if (clos_max < 0) {
- fprintf(stderr, "clos max is not specified, default: 0xff\n");
+ fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n");
clos_max = 0xff;
}
- if (clos_desired < 0) {
- fprintf(stderr, "clos desired is not specified, default: 0\n");
+ if (clos_desired) {
+ fprintf(stderr, "clos desired is not supported on this platform\n");
clos_desired = 0x00;
}
@@ -1250,30 +2239,33 @@
ret = isst_clos_associate(cpu, current_clos);
if (ret)
- perror("isst_clos_associate");
+ debug_printf("isst_clos_associate failed");
else
isst_display_result(cpu, outf, "core-power", "assoc", ret);
}
-static void set_clos_assoc(void)
+static void set_clos_assoc(int arg)
{
if (cmd_help) {
fprintf(stderr, "Associate a clos id to a CPU\n");
fprintf(stderr,
"\tSpecify targeted clos id with [--clos|-c]\n");
+ fprintf(stderr,
+ "\tFor example to associate clos 1 to CPU 0: issue\n");
+ fprintf(stderr,
+ "\tintel-speed-select --cpu 0 core-power assoc --clos 1\n");
exit(0);
}
if (current_clos < 0 || current_clos > 3) {
- fprintf(stderr, "Invalid clos id\n");
+ isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
exit(0);
}
if (max_target_cpus)
for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
NULL, NULL, NULL);
else {
- fprintf(stderr,
- "Invalid target cpu. Specify with [-c|--cpu]\n");
+ isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
}
}
@@ -1284,12 +2276,12 @@
ret = isst_clos_get_assoc_status(cpu, &clos);
if (ret)
- perror("isst_clos_get_assoc_status");
+ isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0);
else
isst_clos_display_assoc_information(cpu, outf, clos);
}
-static void get_clos_assoc(void)
+static void get_clos_assoc(int arg)
{
if (cmd_help) {
fprintf(stderr, "Get associate clos id to a CPU\n");
@@ -1298,8 +2290,7 @@
}
if (!max_target_cpus) {
- fprintf(stderr,
- "Invalid target cpu. Specify with [-c|--cpu]\n");
+ isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
exit(0);
}
@@ -1309,27 +2300,36 @@
isst_ctdp_display_information_end(outf);
}
+static struct process_cmd_struct clx_n_cmds[] = {
+ { "perf-profile", "info", dump_isst_config, 0 },
+ { "base-freq", "info", dump_pbf_config, 0 },
+ { "base-freq", "enable", set_pbf_enable, 1 },
+ { "base-freq", "disable", set_pbf_enable, 0 },
+ { NULL, NULL, NULL, 0 }
+};
+
static struct process_cmd_struct isst_cmds[] = {
- { "perf-profile", "get-lock-status", get_tdp_locked },
- { "perf-profile", "get-config-levels", get_tdp_levels },
- { "perf-profile", "get-config-version", get_tdp_version },
- { "perf-profile", "get-config-enabled", get_tdp_enabled },
- { "perf-profile", "get-config-current-level", get_tdp_current_level },
- { "perf-profile", "set-config-level", set_tdp_level },
- { "perf-profile", "info", dump_isst_config },
- { "base-freq", "info", dump_pbf_config },
- { "base-freq", "enable", set_pbf_enable },
- { "base-freq", "disable", set_pbf_disable },
- { "turbo-freq", "info", dump_fact_config },
- { "turbo-freq", "enable", set_fact_enable },
- { "turbo-freq", "disable", set_fact_disable },
- { "core-power", "info", dump_clos_info },
- { "core-power", "enable", set_clos_enable },
- { "core-power", "disable", set_clos_disable },
- { "core-power", "config", set_clos_config },
- { "core-power", "get-config", dump_clos_config },
- { "core-power", "assoc", set_clos_assoc },
- { "core-power", "get-assoc", get_clos_assoc },
+ { "perf-profile", "get-lock-status", get_tdp_locked, 0 },
+ { "perf-profile", "get-config-levels", get_tdp_levels, 0 },
+ { "perf-profile", "get-config-version", get_tdp_version, 0 },
+ { "perf-profile", "get-config-enabled", get_tdp_enabled, 0 },
+ { "perf-profile", "get-config-current-level", get_tdp_current_level,
+ 0 },
+ { "perf-profile", "set-config-level", set_tdp_level, 0 },
+ { "perf-profile", "info", dump_isst_config, 0 },
+ { "base-freq", "info", dump_pbf_config, 0 },
+ { "base-freq", "enable", set_pbf_enable, 1 },
+ { "base-freq", "disable", set_pbf_enable, 0 },
+ { "turbo-freq", "info", dump_fact_config, 0 },
+ { "turbo-freq", "enable", set_fact_enable, 1 },
+ { "turbo-freq", "disable", set_fact_enable, 0 },
+ { "core-power", "info", dump_clos_info, 0 },
+ { "core-power", "enable", set_clos_enable, 1 },
+ { "core-power", "disable", set_clos_enable, 0 },
+ { "core-power", "config", set_clos_config, 0 },
+ { "core-power", "get-config", dump_clos_config, 0 },
+ { "core-power", "assoc", set_clos_assoc, 0 },
+ { "core-power", "get-assoc", get_clos_assoc, 0 },
{ NULL, NULL, NULL }
};
@@ -1420,15 +2420,19 @@
{ "max", required_argument, 0, 'm' },
{ "priority", required_argument, 0, 'p' },
{ "weight", required_argument, 0, 'w' },
+ { "auto", no_argument, 0, 'a' },
{ 0, 0, 0, 0 }
};
option_index = start;
optind = start + 1;
- while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:ho",
+ while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa",
long_options, &option_index)) != -1) {
switch (opt) {
+ case 'a':
+ auto_mode = 1;
+ break;
case 'b':
fact_bucket = atoi(optarg);
break;
@@ -1449,7 +2453,7 @@
fact_avx = 0x01;
} else if (!strncmp(optarg, "avx2", 4)) {
fact_avx = 0x02;
- } else if (!strncmp(optarg, "avx512", 4)) {
+ } else if (!strncmp(optarg, "avx512", 6)) {
fact_avx = 0x04;
} else {
fprintf(outf, "Invalid sse,avx options\n");
@@ -1462,26 +2466,44 @@
break;
case 'd':
clos_desired = atoi(optarg);
+ clos_desired /= DISP_FREQ_MULTIPLIER;
break;
case 'e':
clos_epp = atoi(optarg);
+ if (is_skx_based_platform()) {
+ isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0);
+ exit(0);
+ }
break;
case 'n':
clos_min = atoi(optarg);
+ clos_min /= DISP_FREQ_MULTIPLIER;
break;
case 'm':
clos_max = atoi(optarg);
+ clos_max /= DISP_FREQ_MULTIPLIER;
break;
case 'p':
clos_priority_type = atoi(optarg);
+ if (is_skx_based_platform() && !clos_priority_type) {
+ isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0);
+ exit(0);
+ }
break;
case 'w':
clos_prop_prio = atoi(optarg);
+ if (is_skx_based_platform()) {
+ isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0);
+ exit(0);
+ }
break;
default:
- printf("no match\n");
+ printf("Unknown option: ignore\n");
}
}
+
+ if (argv[optind])
+ printf("Garbage at the end of command: ignore\n");
}
static void isst_help(void)
@@ -1492,12 +2514,15 @@
TDP, etc.\n");
printf("\nCommands : For feature=perf-profile\n");
printf("\tinfo\n");
- printf("\tget-lock-status\n");
- printf("\tget-config-levels\n");
- printf("\tget-config-version\n");
- printf("\tget-config-enabled\n");
- printf("\tget-config-current-level\n");
- printf("\tset-config-level\n");
+
+ if (!is_clx_n_platform()) {
+ printf("\tget-lock-status\n");
+ printf("\tget-config-levels\n");
+ printf("\tget-config-version\n");
+ printf("\tget-config-enabled\n");
+ printf("\tget-config-current-level\n");
+ printf("\tset-config-level\n");
+ }
}
static void pbf_help(void)
@@ -1547,7 +2572,15 @@
{ NULL, NULL }
};
-void process_command(int argc, char **argv)
+static struct process_cmd_help_struct clx_n_help_cmds[] = {
+ { "perf-profile", isst_help },
+ { "base-freq", pbf_help },
+ { NULL, NULL }
+};
+
+void process_command(int argc, char **argv,
+ struct process_cmd_help_struct *help_cmds,
+ struct process_cmd_struct *cmds)
{
int i = 0, matched = 0;
char *feature = argv[optind];
@@ -1558,23 +2591,24 @@
debug_printf("feature name [%s] command [%s]\n", feature, cmd);
if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
- while (isst_help_cmds[i].feature) {
- if (!strcmp(isst_help_cmds[i].feature, feature)) {
- isst_help_cmds[i].process_fn();
+ while (help_cmds[i].feature) {
+ if (!strcmp(help_cmds[i].feature, feature)) {
+ help_cmds[i].process_fn();
exit(0);
}
++i;
}
}
- create_cpu_map();
+ if (!is_clx_n_platform())
+ create_cpu_map();
i = 0;
- while (isst_cmds[i].feature) {
- if (!strcmp(isst_cmds[i].feature, feature) &&
- !strcmp(isst_cmds[i].command, cmd)) {
+ while (cmds[i].feature) {
+ if (!strcmp(cmds[i].feature, feature) &&
+ !strcmp(cmds[i].command, cmd)) {
parse_cmd_args(argc, optind + 1, argv);
- isst_cmds[i].process_fn();
+ cmds[i].process_fn(cmds[i].arg);
matched = 1;
break;
}
@@ -1587,11 +2621,18 @@
static void usage(void)
{
- printf("Intel(R) Speed Select Technology\n");
+ if (is_clx_n_platform()) {
+ fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n");
+ fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n");
+ }
+
printf("\nUsage:\n");
printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
- printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features,\n");
- printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
+ printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n");
+ if (is_clx_n_platform())
+ printf("\nFEATURE : [perf-profile|base-freq]\n");
+ else
+ printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
printf("\nFor help on each feature, use -h|--help\n");
printf("\tFor example: intel-speed-select perf-profile -h\n");
@@ -1604,17 +2645,31 @@
printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n");
printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n");
printf("\t[-d|--debug] : Debug mode\n");
+ printf("\t[-f|--format] : output format [json|text]. Default: text\n");
printf("\t[-h|--help] : Print help\n");
printf("\t[-i|--info] : Print platform information\n");
printf("\t[-o|--out] : Output file\n");
printf("\t\t\tDefault : stderr\n");
- printf("\t[-f|--format] : output format [json|text]. Default: text\n");
+ printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n");
+ printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n");
printf("\t[-v|--version] : Print version\n");
printf("\nResult format\n");
printf("\tResult display uses a common format for each command:\n");
printf("\tResults are formatted in text/JSON with\n");
printf("\t\tPackage, Die, CPU, and command specific results.\n");
+
+ printf("\nExamples\n");
+ printf("\tTo get platform information:\n");
+ printf("\t\tintel-speed-select --info\n");
+ printf("\tTo get full perf-profile information dump:\n");
+ printf("\t\tintel-speed-select perf-profile info\n");
+ printf("\tTo get full base-freq information dump:\n");
+ printf("\t\tintel-speed-select base-freq info -l 0\n");
+ if (!is_clx_n_platform()) {
+ printf("\tTo get full turbo-freq information dump:\n");
+ printf("\t\tintel-speed-select turbo-freq info -l 0\n");
+ }
exit(1);
}
@@ -1627,6 +2682,9 @@
static void cmdline(int argc, char **argv)
{
+ const char *pathname = "/dev/isst_interface";
+ char *ptr;
+ FILE *fp;
int opt;
int option_index = 0;
int ret;
@@ -1637,11 +2695,35 @@
{ "format", required_argument, 0, 'f' },
{ "help", no_argument, 0, 'h' },
{ "info", no_argument, 0, 'i' },
+ { "pause", required_argument, 0, 'p' },
{ "out", required_argument, 0, 'o' },
+ { "retry", required_argument, 0, 'r' },
{ "version", no_argument, 0, 'v' },
{ 0, 0, 0, 0 }
};
+ if (geteuid() != 0) {
+ fprintf(stderr, "Must run as root\n");
+ exit(0);
+ }
+
+ ret = update_cpu_model();
+ if (ret)
+ err(-1, "Invalid CPU model (%d)\n", cpu_model);
+ printf("Intel(R) Speed Select Technology\n");
+ printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
+
+ if (!is_clx_n_platform()) {
+ fp = fopen(pathname, "rb");
+ if (!fp) {
+ fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n");
+ fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n");
+ fprintf(stderr, "If the config is included then this is not a supported platform.\n");
+ exit(0);
+ }
+ fclose(fp);
+ }
+
progname = argv[0];
while ((opt = getopt_long_only(argc, argv, "+c:df:hio:v", long_options,
&option_index)) != -1) {
@@ -1668,6 +2750,20 @@
fclose(outf);
outf = fopen_or_exit(optarg, "w");
break;
+ case 'p':
+ ret = strtol(optarg, &ptr, 10);
+ if (!ret)
+ fprintf(stderr, "Invalid pause interval, ignore\n");
+ else
+ mbox_delay = ret;
+ break;
+ case 'r':
+ ret = strtol(optarg, &ptr, 10);
+ if (!ret)
+ fprintf(stderr, "Invalid retry count, ignore\n");
+ else
+ mbox_retries = ret;
+ break;
case 'v':
print_version();
break;
@@ -1676,26 +2772,23 @@
}
}
- if (geteuid() != 0) {
- fprintf(stderr, "Must run as root\n");
- exit(0);
- }
-
if (optind > (argc - 2)) {
- fprintf(stderr, "Feature name and|or command not specified\n");
+ usage();
exit(0);
}
- update_cpu_model();
- printf("Intel(R) Speed Select Technology\n");
- printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
set_max_cpu_num();
+ store_cpu_topology();
set_cpu_present_cpu_mask();
set_cpu_target_cpu_mask();
- ret = isst_fill_platform_info();
- if (ret)
- goto out;
- process_command(argc, argv);
+ if (!is_clx_n_platform()) {
+ ret = isst_fill_platform_info();
+ if (ret)
+ goto out;
+ process_command(argc, argv, isst_help_cmds, isst_cmds);
+ } else {
+ process_command(argc, argv, clx_n_help_cmds, clx_n_cmds);
+ }
out:
free_cpu_set(present_cpumask);
free_cpu_set(target_cpumask);
diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c
index fde3f9c..1d7ecb5 100644
--- a/tools/power/x86/intel-speed-select/isst-core.c
+++ b/tools/power/x86/intel-speed-select/isst-core.c
@@ -6,6 +6,44 @@
#include "isst.h"
+int isst_write_pm_config(int cpu, int cp_state)
+{
+ unsigned int req, resp;
+ int ret;
+
+ if (cp_state)
+ req = BIT(16);
+ else
+ req = 0;
+
+ ret = isst_send_mbox_command(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", cpu, resp);
+
+ return 0;
+}
+
+int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", cpu, resp);
+
+ *cp_state = resp & BIT(16);
+ *cp_cap = resp & BIT(0) ? 1 : 0;
+
+ return 0;
+}
+
int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
{
unsigned int resp;
@@ -13,8 +51,14 @@
ret = isst_send_mbox_command(cpu, CONFIG_TDP,
CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
- if (ret)
- return ret;
+ if (ret) {
+ pkg_dev->levels = 0;
+ pkg_dev->locked = 1;
+ pkg_dev->current_level = 0;
+ pkg_dev->version = 0;
+ pkg_dev->enabled = 0;
+ return 0;
+ }
debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
@@ -30,6 +74,7 @@
int isst_get_ctdp_control(int cpu, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level)
{
+ int cp_state, cp_cap;
unsigned int resp;
int ret;
@@ -44,6 +89,15 @@
ctdp_level->fact_enabled = !!(resp & BIT(16));
ctdp_level->pbf_enabled = !!(resp & BIT(17));
+ ret = isst_read_pm_config(cpu, &cp_state, &cp_cap);
+ if (ret) {
+ debug_printf("cpu:%d pm_config is not supported \n", cpu);
+ } else {
+ debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d \n", cpu, cp_state, cp_cap);
+ ctdp_level->sst_cp_support = cp_cap;
+ ctdp_level->sst_cp_enabled = cp_state;
+ }
+
debug_printf(
"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
@@ -60,8 +114,10 @@
ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
0, config_index, &resp);
- if (ret)
+ if (ret) {
+ isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
return ret;
+ }
ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
@@ -95,6 +151,69 @@
return 0;
}
+void isst_get_uncore_p0_p1_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
+ config_index, &resp);
+ if (ret) {
+ ctdp_level->uncore_p0 = 0;
+ ctdp_level->uncore_p1 = 0;
+ return;
+ }
+
+ ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
+ ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
+ cpu, config_index, resp, ctdp_level->uncore_p0,
+ ctdp_level->uncore_p1);
+}
+
+void isst_get_p1_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
+ config_index, &resp);
+ if (ret) {
+ ctdp_level->sse_p1 = 0;
+ ctdp_level->avx2_p1 = 0;
+ ctdp_level->avx512_p1 = 0;
+ return;
+ }
+
+ ctdp_level->sse_p1 = resp & GENMASK(7, 0);
+ ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
+ ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
+ cpu, config_index, resp, ctdp_level->sse_p1,
+ ctdp_level->avx2_p1, ctdp_level->avx512_p1);
+}
+
+void isst_get_uncore_mem_freq(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
+ 0, config_index, &resp);
+ if (ret) {
+ ctdp_level->mem_freq = 0;
+ return;
+ }
+
+ ctdp_level->mem_freq = resp & GENMASK(7, 0);
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
+ cpu, config_index, resp, ctdp_level->mem_freq);
+}
+
int isst_get_tjmax_info(int cpu, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level)
{
@@ -149,6 +268,27 @@
return 0;
}
+int isst_get_get_trl_from_msr(int cpu, int *trl)
+{
+ unsigned long long msr_trl;
+ int ret;
+
+ ret = isst_send_msr_command(cpu, 0x1AD, 0, &msr_trl);
+ if (ret)
+ return ret;
+
+ trl[0] = msr_trl & GENMASK(7, 0);
+ trl[1] = (msr_trl & GENMASK(15, 8)) >> 8;
+ trl[2] = (msr_trl & GENMASK(23, 16)) >> 16;
+ trl[3] = (msr_trl & GENMASK(31, 24)) >> 24;
+ trl[4] = (msr_trl & GENMASK(39, 32)) >> 32;
+ trl[5] = (msr_trl & GENMASK(47, 40)) >> 40;
+ trl[6] = (msr_trl & GENMASK(55, 48)) >> 48;
+ trl[7] = (msr_trl & GENMASK(63, 56)) >> 56;
+
+ return 0;
+}
+
int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
{
unsigned int req, resp;
@@ -214,7 +354,7 @@
debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
if (isst_get_config_tdp_lock_status(cpu)) {
- debug_printf("cpu: tdp_locked %d\n", cpu);
+ isst_display_error_info_message(1, "tdp_locked", 0, 0);
return -1;
}
@@ -235,22 +375,56 @@
unsigned int resp;
int ret;
+
+ if (isst_get_config_tdp_lock_status(cpu)) {
+ isst_display_error_info_message(1, "TDP is locked", 0, 0);
+ return -1;
+
+ }
+
ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
tdp_level, &resp);
- if (ret)
- return isst_set_tdp_level_msr(cpu, tdp_level);
+ if (ret) {
+ isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
+ return ret;
+ }
return 0;
}
int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
{
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ struct isst_pkg_ctdp pkg_dev;
+ int i, ret, max_punit_core, max_mask_index;
unsigned int req, resp;
- int i, ret;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret) {
+ isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
+ return ret;
+ }
+
+ if (level > pkg_dev.levels) {
+ isst_display_error_info_message(1, "Invalid level", 1, level);
+ return -1;
+ }
+
+ ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (!ctdp_level.pbf_support) {
+ isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, level);
+ return -1;
+ }
pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
- for (i = 0; i < 2; ++i) {
+ max_punit_core = get_max_punit_core_id(get_physical_package_id(cpu), get_physical_die_id(cpu));
+ max_mask_index = max_punit_core > 32 ? 2 : 1;
+
+ for (i = 0; i < max_mask_index; ++i) {
unsigned long long mask;
int count;
@@ -258,7 +432,7 @@
CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
0, (i << 8) | level, &resp);
if (ret)
- return ret;
+ break;
debug_printf(
"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
@@ -323,7 +497,7 @@
ret = isst_get_ctdp_levels(cpu, &pkg_dev);
if (ret)
- return ret;
+ debug_printf("cpu:%d No support for dynamic ISST\n", cpu);
current_level = pkg_dev.current_level;
@@ -340,6 +514,10 @@
else
req &= ~BIT(17);
} else {
+
+ if (enable && !ctdp_level.sst_cp_enabled)
+ isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
+
if (ctdp_level.pbf_enabled)
req = BIT(17);
@@ -425,10 +603,32 @@
return 0;
}
-int isst_get_fact_info(int cpu, int level, struct isst_fact_info *fact_info)
+int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_info *fact_info)
{
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ struct isst_pkg_ctdp pkg_dev;
unsigned int resp;
- int ret;
+ int j, ret, print;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret) {
+ isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
+ return ret;
+ }
+
+ if (level > pkg_dev.levels) {
+ isst_display_error_info_message(1, "Invalid level", 1, level);
+ return -1;
+ }
+
+ ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (!ctdp_level.fact_support) {
+ isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level);
+ return -1;
+ }
ret = isst_send_mbox_command(cpu, CONFIG_TDP,
CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
@@ -444,8 +644,25 @@
fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff;
ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info);
+ if (ret)
+ return ret;
- return ret;
+ print = 0;
+ for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
+ if (fact_bucket != 0xff && fact_bucket != j)
+ continue;
+
+ if (!fact_info->bucket_info[j].high_priority_cores_count)
+ break;
+
+ print = 1;
+ }
+ if (!print) {
+ isst_display_error_info_message(1, "Invalid bucket", 0, 0);
+ return -1;
+ }
+
+ return 0;
}
int isst_set_trl(int cpu, unsigned long long trl)
@@ -530,7 +747,7 @@
int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
{
- int i, ret;
+ int i, ret, valid = 0;
if (pkg_dev->processed)
return 0;
@@ -543,6 +760,14 @@
cpu, pkg_dev->enabled, pkg_dev->current_level,
pkg_dev->levels);
+ if (tdp_level != 0xff && tdp_level > pkg_dev->levels) {
+ isst_display_error_info_message(1, "Invalid level", 0, 0);
+ return -1;
+ }
+
+ if (!pkg_dev->enabled)
+ isst_display_error_info_message(0, "perf-profile feature is not supported, just base-config level 0 is valid", 0, 0);
+
for (i = 0; i <= pkg_dev->levels; ++i) {
struct isst_pkg_ctdp_level_info *ctdp_level;
@@ -562,9 +787,37 @@
if (ret)
continue;
+ valid = 1;
pkg_dev->processed = 1;
ctdp_level->processed = 1;
+ if (ctdp_level->pbf_support) {
+ ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
+ if (!ret)
+ ctdp_level->pbf_found = 1;
+ }
+
+ if (ctdp_level->fact_support) {
+ ret = isst_get_fact_info(cpu, i, 0xff,
+ &ctdp_level->fact_info);
+ if (ret)
+ return ret;
+ }
+
+ if (!pkg_dev->enabled) {
+ int freq;
+
+ freq = get_cpufreq_base_freq(cpu);
+ if (freq > 0) {
+ ctdp_level->sse_p1 = freq / 100000;
+ ctdp_level->tdp_ratio = ctdp_level->sse_p1;
+ }
+
+ isst_get_get_trl_from_msr(cpu, ctdp_level->trl_sse_active_cores);
+ isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
+ continue;
+ }
+
ret = isst_get_tdp_info(cpu, i, ctdp_level);
if (ret)
return ret;
@@ -602,20 +855,14 @@
if (ret)
return ret;
- if (ctdp_level->pbf_support) {
- ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
- if (!ret)
- ctdp_level->pbf_found = 1;
- }
-
- if (ctdp_level->fact_support) {
- ret = isst_get_fact_info(cpu, i,
- &ctdp_level->fact_info);
- if (ret)
- return ret;
- }
+ isst_get_uncore_p0_p1_info(cpu, i, ctdp_level);
+ isst_get_p1_info(cpu, i, ctdp_level);
+ isst_get_uncore_mem_freq(cpu, i, ctdp_level);
}
+ if (!valid)
+ isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, cpu);
+
return 0;
}
@@ -649,10 +896,40 @@
unsigned int req, resp;
int ret;
+ if (!enable_clos) {
+ struct isst_pkg_ctdp pkg_dev;
+ struct isst_pkg_ctdp_level_info ctdp_level;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret) {
+ debug_printf("isst_get_ctdp_levels\n");
+ return ret;
+ }
+
+ ret = isst_get_ctdp_control(cpu, pkg_dev.current_level,
+ &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (ctdp_level.fact_enabled) {
+ isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
+ return -EINVAL;
+ }
+ ret = isst_write_pm_config(cpu, 0);
+ if (ret)
+ isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
+ } else {
+ ret = isst_write_pm_config(cpu, 1);
+ if (ret)
+ isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
+ }
+
ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
&resp);
- if (ret)
+ if (ret) {
+ isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
return ret;
+ }
debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
@@ -663,6 +940,9 @@
else
req = req & ~BIT(1);
+ if (priority_type > 1)
+ isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
+
if (priority_type)
req = req | BIT(2);
else
diff --git a/tools/power/x86/intel-speed-select/isst-display.c b/tools/power/x86/intel-speed-select/isst-display.c
index b11575c..f32ce03 100644
--- a/tools/power/x86/intel-speed-select/isst-display.c
+++ b/tools/power/x86/intel-speed-select/isst-display.c
@@ -6,8 +6,6 @@
#include "isst.h"
-#define DISP_FREQ_MULTIPLIER 100
-
static void printcpulist(int str_len, char *str, int mask_size,
cpu_set_t *cpu_mask)
{
@@ -27,10 +25,14 @@
index = snprintf(&str[curr_index],
str_len - curr_index, ",");
curr_index += index;
+ if (curr_index >= str_len)
+ break;
}
index = snprintf(&str[curr_index], str_len - curr_index, "%d",
i);
curr_index += index;
+ if (curr_index >= str_len)
+ break;
first = 0;
}
}
@@ -66,10 +68,14 @@
index = snprintf(&str[curr_index], str_len - curr_index, "%08x",
mask[i]);
curr_index += index;
+ if (curr_index >= str_len)
+ break;
if (i) {
strncat(&str[curr_index], ",", str_len - curr_index);
curr_index++;
}
+ if (curr_index >= str_len)
+ break;
}
free(mask);
@@ -160,10 +166,17 @@
last_level = level;
}
-static void print_package_info(int cpu, FILE *outf)
+static int print_package_info(int cpu, FILE *outf)
{
char header[256];
+ if (out_format_is_json()) {
+ snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
+ get_physical_package_id(cpu), get_physical_die_id(cpu),
+ cpu);
+ format_and_print(outf, 1, header, NULL);
+ return 1;
+ }
snprintf(header, sizeof(header), "package-%d",
get_physical_package_id(cpu));
format_and_print(outf, 1, header, NULL);
@@ -171,6 +184,8 @@
format_and_print(outf, 2, header, NULL);
snprintf(header, sizeof(header), "cpu-%d", cpu);
format_and_print(outf, 3, header, NULL);
+
+ return 3;
}
static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
@@ -178,9 +193,9 @@
int disp_level)
{
char header[256];
- char value[256];
+ char value[512];
- snprintf(header, sizeof(header), "speed-select-base-freq");
+ snprintf(header, sizeof(header), "speed-select-base-freq-properties");
format_and_print(outf, disp_level, header, NULL);
snprintf(header, sizeof(header), "high-priority-base-frequency(MHz)");
@@ -204,6 +219,9 @@
pbf_info->p1_low * DISP_FREQ_MULTIPLIER);
format_and_print(outf, disp_level + 1, header, value);
+ if (is_clx_n_platform())
+ return;
+
snprintf(header, sizeof(header), "tjunction-temperature(C)");
snprintf(value, sizeof(value), "%d", pbf_info->t_prochot);
format_and_print(outf, disp_level + 1, header, value);
@@ -221,9 +239,23 @@
struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info;
char header[256];
char value[256];
- int j;
+ int print = 0, j;
- snprintf(header, sizeof(header), "speed-select-turbo-freq");
+ for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
+ if (fact_bucket != 0xff && fact_bucket != j)
+ continue;
+
+ if (!bucket_info[j].high_priority_cores_count)
+ break;
+
+ print = 1;
+ }
+ if (!print) {
+ fprintf(stderr, "Invalid bucket\n");
+ return;
+ }
+
+ snprintf(header, sizeof(header), "speed-select-turbo-freq-properties");
format_and_print(outf, base_level, header, NULL);
for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
if (fact_bucket != 0xff && fact_bucket != j)
@@ -288,21 +320,35 @@
}
void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix,
- unsigned int val)
+ unsigned int val, char *str0, char *str1)
{
char header[256];
char value[256];
+ int level = 1;
- snprintf(header, sizeof(header), "package-%d",
- get_physical_package_id(cpu));
- format_and_print(outf, 1, header, NULL);
- snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
- format_and_print(outf, 2, header, NULL);
- snprintf(header, sizeof(header), "cpu-%d", cpu);
- format_and_print(outf, 3, header, NULL);
+ if (out_format_is_json()) {
+ snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
+ get_physical_package_id(cpu), get_physical_die_id(cpu),
+ cpu);
+ format_and_print(outf, level++, header, NULL);
+ } else {
+ snprintf(header, sizeof(header), "package-%d",
+ get_physical_package_id(cpu));
+ format_and_print(outf, level++, header, NULL);
+ snprintf(header, sizeof(header), "die-%d",
+ get_physical_die_id(cpu));
+ format_and_print(outf, level++, header, NULL);
+ snprintf(header, sizeof(header), "cpu-%d", cpu);
+ format_and_print(outf, level++, header, NULL);
+ }
- snprintf(value, sizeof(value), "%u", val);
- format_and_print(outf, 4, prefix, value);
+ if (str0 && !val)
+ snprintf(value, sizeof(value), "%s", str0);
+ else if (str1 && val)
+ snprintf(value, sizeof(value), "%s", str1);
+ else
+ snprintf(value, sizeof(value), "%u", val);
+ format_and_print(outf, level, prefix, value);
format_and_print(outf, 1, NULL, NULL);
}
@@ -311,11 +357,12 @@
struct isst_pkg_ctdp *pkg_dev)
{
char header[256];
- char value[256];
- int i, base_level = 1;
+ char value[512];
+ static int level;
+ int i;
if (pkg_dev->processed)
- print_package_info(cpu, outf);
+ level = print_package_info(cpu, outf);
for (i = 0; i <= pkg_dev->levels; ++i) {
struct isst_pkg_ctdp_level_info *ctdp_level;
@@ -327,34 +374,81 @@
snprintf(header, sizeof(header), "perf-profile-level-%d",
ctdp_level->level);
- format_and_print(outf, base_level + 3, header, NULL);
+ format_and_print(outf, level + 1, header, NULL);
snprintf(header, sizeof(header), "cpu-count");
j = get_cpu_count(get_physical_die_id(cpu),
get_physical_die_id(cpu));
snprintf(value, sizeof(value), "%d", j);
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
- snprintf(header, sizeof(header), "enable-cpu-mask");
- printcpumask(sizeof(value), value,
- ctdp_level->core_cpumask_size,
- ctdp_level->core_cpumask);
- format_and_print(outf, base_level + 4, header, value);
+ j = CPU_COUNT_S(ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask);
+ if (j) {
+ snprintf(header, sizeof(header), "enable-cpu-count");
+ snprintf(value, sizeof(value), "%d", j);
+ format_and_print(outf, level + 2, header, value);
+ }
- snprintf(header, sizeof(header), "enable-cpu-list");
- printcpulist(sizeof(value), value,
- ctdp_level->core_cpumask_size,
- ctdp_level->core_cpumask);
- format_and_print(outf, base_level + 4, header, value);
+ if (ctdp_level->core_cpumask_size) {
+ snprintf(header, sizeof(header), "enable-cpu-mask");
+ printcpumask(sizeof(value), value,
+ ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask);
+ format_and_print(outf, level + 2, header, value);
+
+ snprintf(header, sizeof(header), "enable-cpu-list");
+ printcpulist(sizeof(value), value,
+ ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask);
+ format_and_print(outf, level + 2, header, value);
+ }
snprintf(header, sizeof(header), "thermal-design-power-ratio");
snprintf(value, sizeof(value), "%d", ctdp_level->tdp_ratio);
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "base-frequency(MHz)");
+ if (!ctdp_level->sse_p1)
+ ctdp_level->sse_p1 = ctdp_level->tdp_ratio;
snprintf(value, sizeof(value), "%d",
- ctdp_level->tdp_ratio * DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 4, header, value);
+ ctdp_level->sse_p1 * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 2, header, value);
+
+ if (ctdp_level->avx2_p1) {
+ snprintf(header, sizeof(header), "base-frequency-avx2(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->avx2_p1 * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (ctdp_level->avx512_p1) {
+ snprintf(header, sizeof(header), "base-frequency-avx512(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->avx512_p1 * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (ctdp_level->uncore_p1) {
+ snprintf(header, sizeof(header), "uncore-frequency-min(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->uncore_p1 * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (ctdp_level->uncore_p0) {
+ snprintf(header, sizeof(header), "uncore-frequency-max(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->uncore_p0 * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (ctdp_level->mem_freq) {
+ snprintf(header, sizeof(header), "mem-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->mem_freq * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 2, header, value);
+ }
snprintf(header, sizeof(header),
"speed-select-turbo-freq");
@@ -365,7 +459,7 @@
snprintf(value, sizeof(value), "disabled");
} else
snprintf(value, sizeof(value), "unsupported");
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header),
"speed-select-base-freq");
@@ -376,97 +470,126 @@
snprintf(value, sizeof(value), "disabled");
} else
snprintf(value, sizeof(value), "unsupported");
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
- snprintf(header, sizeof(header), "thermal-design-power(W)");
- snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp);
- format_and_print(outf, base_level + 4, header, value);
+ snprintf(header, sizeof(header),
+ "speed-select-core-power");
+ if (ctdp_level->sst_cp_support) {
+ if (ctdp_level->sst_cp_enabled)
+ snprintf(value, sizeof(value), "enabled");
+ else
+ snprintf(value, sizeof(value), "disabled");
+ } else
+ snprintf(value, sizeof(value), "unsupported");
+ format_and_print(outf, level + 2, header, value);
- snprintf(header, sizeof(header), "tjunction-max(C)");
- snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot);
- format_and_print(outf, base_level + 4, header, value);
+ if (is_clx_n_platform()) {
+ if (ctdp_level->pbf_support)
+ _isst_pbf_display_information(cpu, outf,
+ tdp_level,
+ &ctdp_level->pbf_info,
+ level + 2);
+ continue;
+ }
+
+ if (ctdp_level->pkg_tdp) {
+ snprintf(header, sizeof(header), "thermal-design-power(W)");
+ snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp);
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (ctdp_level->t_proc_hot) {
+ snprintf(header, sizeof(header), "tjunction-max(C)");
+ snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot);
+ format_and_print(outf, level + 2, header, value);
+ }
snprintf(header, sizeof(header), "turbo-ratio-limits-sse");
- format_and_print(outf, base_level + 4, header, NULL);
+ format_and_print(outf, level + 2, header, NULL);
for (j = 0; j < 8; ++j) {
snprintf(header, sizeof(header), "bucket-%d", j);
- format_and_print(outf, base_level + 5, header, NULL);
+ format_and_print(outf, level + 3, header, NULL);
snprintf(header, sizeof(header), "core-count");
snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
- format_and_print(outf, base_level + 6, header, value);
+ format_and_print(outf, level + 4, header, value);
snprintf(header, sizeof(header),
"max-turbo-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->trl_sse_active_cores[j] *
DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 6, header, value);
- }
- snprintf(header, sizeof(header), "turbo-ratio-limits-avx");
- format_and_print(outf, base_level + 4, header, NULL);
- for (j = 0; j < 8; ++j) {
- snprintf(header, sizeof(header), "bucket-%d", j);
- format_and_print(outf, base_level + 5, header, NULL);
-
- snprintf(header, sizeof(header), "core-count");
- snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
- format_and_print(outf, base_level + 6, header, value);
-
- snprintf(header, sizeof(header),
- "max-turbo-frequency(MHz)");
- snprintf(value, sizeof(value), "%d",
- ctdp_level->trl_avx_active_cores[j] *
- DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 6, header, value);
+ format_and_print(outf, level + 4, header, value);
}
- snprintf(header, sizeof(header), "turbo-ratio-limits-avx512");
- format_and_print(outf, base_level + 4, header, NULL);
- for (j = 0; j < 8; ++j) {
- snprintf(header, sizeof(header), "bucket-%d", j);
- format_and_print(outf, base_level + 5, header, NULL);
+ if (ctdp_level->trl_avx_active_cores[0]) {
+ snprintf(header, sizeof(header), "turbo-ratio-limits-avx2");
+ format_and_print(outf, level + 2, header, NULL);
+ for (j = 0; j < 8; ++j) {
+ snprintf(header, sizeof(header), "bucket-%d", j);
+ format_and_print(outf, level + 3, header, NULL);
- snprintf(header, sizeof(header), "core-count");
- snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
- format_and_print(outf, base_level + 6, header, value);
+ snprintf(header, sizeof(header), "core-count");
+ snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
+ format_and_print(outf, level + 4, header, value);
- snprintf(header, sizeof(header),
- "max-turbo-frequency(MHz)");
- snprintf(value, sizeof(value), "%d",
- ctdp_level->trl_avx_512_active_cores[j] *
- DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 6, header, value);
+ snprintf(header, sizeof(header), "max-turbo-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_active_cores[j] * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 4, header, value);
+ }
}
+
+ if (ctdp_level->trl_avx_512_active_cores[0]) {
+ snprintf(header, sizeof(header), "turbo-ratio-limits-avx512");
+ format_and_print(outf, level + 2, header, NULL);
+ for (j = 0; j < 8; ++j) {
+ snprintf(header, sizeof(header), "bucket-%d", j);
+ format_and_print(outf, level + 3, header, NULL);
+
+ snprintf(header, sizeof(header), "core-count");
+ snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
+ format_and_print(outf, level + 4, header, value);
+
+ snprintf(header, sizeof(header), "max-turbo-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_512_active_cores[j] * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 4, header, value);
+ }
+ }
+
if (ctdp_level->pbf_support)
_isst_pbf_display_information(cpu, outf, i,
&ctdp_level->pbf_info,
- base_level + 4);
+ level + 2);
if (ctdp_level->fact_support)
_isst_fact_display_information(cpu, outf, i, 0xff, 0xff,
&ctdp_level->fact_info,
- base_level + 4);
+ level + 2);
}
format_and_print(outf, 1, NULL, NULL);
}
+static int start;
void isst_ctdp_display_information_start(FILE *outf)
{
last_level = 0;
format_and_print(outf, 0, "start", NULL);
+ start = 1;
}
void isst_ctdp_display_information_end(FILE *outf)
{
format_and_print(outf, 0, NULL, NULL);
+ start = 0;
}
void isst_pbf_display_information(int cpu, FILE *outf, int level,
struct isst_pbf_info *pbf_info)
{
- print_package_info(cpu, outf);
- _isst_pbf_display_information(cpu, outf, level, pbf_info, 4);
+ int _level;
+
+ _level = print_package_info(cpu, outf);
+ _isst_pbf_display_information(cpu, outf, level, pbf_info, _level + 1);
format_and_print(outf, 1, NULL, NULL);
}
@@ -474,9 +597,11 @@
int fact_bucket, int fact_avx,
struct isst_fact_info *fact_info)
{
- print_package_info(cpu, outf);
+ int _level;
+
+ _level = print_package_info(cpu, outf);
_isst_fact_display_information(cpu, outf, level, fact_bucket, fact_avx,
- fact_info, 4);
+ fact_info, _level + 1);
format_and_print(outf, 1, NULL, NULL);
}
@@ -485,94 +610,103 @@
{
char header[256];
char value[256];
+ int level;
- snprintf(header, sizeof(header), "package-%d",
- get_physical_package_id(cpu));
- format_and_print(outf, 1, header, NULL);
- snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
- format_and_print(outf, 2, header, NULL);
- snprintf(header, sizeof(header), "cpu-%d", cpu);
- format_and_print(outf, 3, header, NULL);
+ level = print_package_info(cpu, outf);
snprintf(header, sizeof(header), "core-power");
- format_and_print(outf, 4, header, NULL);
+ format_and_print(outf, level + 1, header, NULL);
snprintf(header, sizeof(header), "clos");
snprintf(value, sizeof(value), "%d", clos);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "epp");
snprintf(value, sizeof(value), "%d", clos_config->epp);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "clos-proportional-priority");
snprintf(value, sizeof(value), "%d", clos_config->clos_prop_prio);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "clos-min");
- snprintf(value, sizeof(value), "%d", clos_config->clos_min);
- format_and_print(outf, 5, header, value);
+ snprintf(value, sizeof(value), "%d MHz", clos_config->clos_min * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "clos-max");
- snprintf(value, sizeof(value), "%d", clos_config->clos_max);
- format_and_print(outf, 5, header, value);
+ if (clos_config->clos_max == 0xff)
+ snprintf(value, sizeof(value), "Max Turbo frequency");
+ else
+ snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "clos-desired");
- snprintf(value, sizeof(value), "%d", clos_config->clos_desired);
- format_and_print(outf, 5, header, value);
+ snprintf(value, sizeof(value), "%d MHz", clos_config->clos_desired * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, level + 2, header, value);
- format_and_print(outf, 1, NULL, NULL);
+ format_and_print(outf, level, NULL, NULL);
}
void isst_clos_display_clos_information(int cpu, FILE *outf,
- int clos_enable, int type)
+ int clos_enable, int type,
+ int state, int cap)
{
char header[256];
char value[256];
+ int level;
- snprintf(header, sizeof(header), "package-%d",
- get_physical_package_id(cpu));
- format_and_print(outf, 1, header, NULL);
- snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
- format_and_print(outf, 2, header, NULL);
- snprintf(header, sizeof(header), "cpu-%d", cpu);
- format_and_print(outf, 3, header, NULL);
+ level = print_package_info(cpu, outf);
snprintf(header, sizeof(header), "core-power");
- format_and_print(outf, 4, header, NULL);
+ format_and_print(outf, level + 1, header, NULL);
+
+ snprintf(header, sizeof(header), "support-status");
+ if (cap)
+ snprintf(value, sizeof(value), "supported");
+ else
+ snprintf(value, sizeof(value), "unsupported");
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "enable-status");
- snprintf(value, sizeof(value), "%d", clos_enable);
- format_and_print(outf, 5, header, value);
+ if (state)
+ snprintf(value, sizeof(value), "enabled");
+ else
+ snprintf(value, sizeof(value), "disabled");
+ format_and_print(outf, level + 2, header, value);
+
+ snprintf(header, sizeof(header), "clos-enable-status");
+ if (clos_enable)
+ snprintf(value, sizeof(value), "enabled");
+ else
+ snprintf(value, sizeof(value), "disabled");
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "priority-type");
- snprintf(value, sizeof(value), "%d", type);
- format_and_print(outf, 5, header, value);
+ if (type)
+ snprintf(value, sizeof(value), "ordered");
+ else
+ snprintf(value, sizeof(value), "proportional");
+ format_and_print(outf, level + 2, header, value);
- format_and_print(outf, 1, NULL, NULL);
+ format_and_print(outf, level, NULL, NULL);
}
void isst_clos_display_assoc_information(int cpu, FILE *outf, int clos)
{
char header[256];
char value[256];
+ int level;
- snprintf(header, sizeof(header), "package-%d",
- get_physical_package_id(cpu));
- format_and_print(outf, 1, header, NULL);
- snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
- format_and_print(outf, 2, header, NULL);
- snprintf(header, sizeof(header), "cpu-%d", cpu);
- format_and_print(outf, 3, header, NULL);
+ level = print_package_info(cpu, outf);
snprintf(header, sizeof(header), "get-assoc");
- format_and_print(outf, 4, header, NULL);
+ format_and_print(outf, level + 1, header, NULL);
snprintf(header, sizeof(header), "clos");
snprintf(value, sizeof(value), "%d", clos);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
- format_and_print(outf, 1, NULL, NULL);
+ format_and_print(outf, level, NULL, NULL);
}
void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
@@ -580,22 +714,60 @@
{
char header[256];
char value[256];
+ int level = 3;
- snprintf(header, sizeof(header), "package-%d",
- get_physical_package_id(cpu));
- format_and_print(outf, 1, header, NULL);
- snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
- format_and_print(outf, 2, header, NULL);
- snprintf(header, sizeof(header), "cpu-%d", cpu);
- format_and_print(outf, 3, header, NULL);
+ if (cpu >= 0)
+ level = print_package_info(cpu, outf);
+
snprintf(header, sizeof(header), "%s", feature);
- format_and_print(outf, 4, header, NULL);
+ format_and_print(outf, level + 1, header, NULL);
snprintf(header, sizeof(header), "%s", cmd);
if (!result)
snprintf(value, sizeof(value), "success");
else
snprintf(value, sizeof(value), "failed(error %d)", result);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
+ format_and_print(outf, level, NULL, NULL);
+}
+
+void isst_display_error_info_message(int error, char *msg, int arg_valid, int arg)
+{
+ FILE *outf = get_output_file();
+ static int error_index;
+ char header[256];
+ char value[256];
+
+ if (!out_format_is_json()) {
+ if (arg_valid)
+ snprintf(value, sizeof(value), "%s %d", msg, arg);
+ else
+ snprintf(value, sizeof(value), "%s", msg);
+
+ if (error)
+ fprintf(outf, "Error: %s\n", value);
+ else
+ fprintf(outf, "Information: %s\n", value);
+ return;
+ }
+
+ if (!start)
+ format_and_print(outf, 0, "start", NULL);
+
+ if (error)
+ snprintf(header, sizeof(header), "Error%d", error_index++);
+ else
+ snprintf(header, sizeof(header), "Information:%d", error_index++);
+ format_and_print(outf, 1, header, NULL);
+
+ snprintf(header, sizeof(header), "message");
+ if (arg_valid)
+ snprintf(value, sizeof(value), "%s %d", msg, arg);
+ else
+ snprintf(value, sizeof(value), "%s", msg);
+
+ format_and_print(outf, 2, header, value);
format_and_print(outf, 1, NULL, NULL);
+ if (!start)
+ format_and_print(outf, 0, NULL, NULL);
}
diff --git a/tools/power/x86/intel-speed-select/isst.h b/tools/power/x86/intel-speed-select/isst.h
index d280b27..29715e9 100644
--- a/tools/power/x86/intel-speed-select/isst.h
+++ b/tools/power/x86/intel-speed-select/isst.h
@@ -29,6 +29,7 @@
#include <sys/ioctl.h>
#define BIT(x) (1 << (x))
+#define BIT_ULL(nr) (1ULL << (nr))
#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (sizeof(long) * 8 - 1 - (h))))
#define GENMASK_ULL(h, l) \
(((~0ULL) << (l)) & (~0ULL >> (sizeof(long long) * 8 - 1 - (h))))
@@ -69,6 +70,12 @@
#define PM_CLOS_OFFSET 0x08
#define PQR_ASSOC_OFFSET 0x20
+#define READ_PM_CONFIG 0x94
+#define WRITE_PM_CONFIG 0x95
+#define PM_FEATURE 0x03
+
+#define DISP_FREQ_MULTIPLIER 100
+
struct isst_clos_config {
int pkg_id;
int die_id;
@@ -117,6 +124,8 @@
int pbf_support;
int fact_enabled;
int pbf_enabled;
+ int sst_cp_support;
+ int sst_cp_enabled;
int tdp_ratio;
int active;
int tdp_control;
@@ -161,8 +170,10 @@
extern int get_topo_max_cpus(void);
extern int get_cpu_count(int pkg_id, int die_id);
+extern int get_max_punit_core_id(int pkg_id, int die_id);
/* Common interfaces */
+FILE *get_output_file(void);
extern void debug_printf(const char *format, ...);
extern int out_format_is_json(void);
extern int get_physical_package_id(int cpu);
@@ -187,6 +198,8 @@
int write, unsigned long long *req_resp);
extern int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev);
+extern int isst_get_ctdp_control(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level);
extern int isst_get_coremask_info(int cpu, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level);
extern int isst_get_process_ctdp(int cpu, int tdp_level,
@@ -196,7 +209,7 @@
extern void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
struct isst_pkg_ctdp *pkg_dev);
extern void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix,
- unsigned int val);
+ unsigned int val, char *str0, char *str1);
extern void isst_ctdp_display_information_start(FILE *outf);
extern void isst_ctdp_display_information_end(FILE *outf);
extern void isst_pbf_display_information(int cpu, FILE *outf, int level,
@@ -207,7 +220,7 @@
extern int isst_get_pbf_info(int cpu, int level,
struct isst_pbf_info *pbf_info);
extern void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info);
-extern int isst_get_fact_info(int cpu, int level,
+extern int isst_get_fact_info(int cpu, int level, int fact_bucket,
struct isst_fact_info *fact_info);
extern int isst_get_fact_bucket_info(int cpu, int level,
struct isst_fact_bucket_info *bucket_info);
@@ -236,5 +249,10 @@
extern int isst_clos_get_clos_information(int cpu, int *enable, int *type);
extern void isst_clos_display_clos_information(int cpu, FILE *outf,
- int clos_enable, int type);
+ int clos_enable, int type,
+ int state, int cap);
+extern int is_clx_n_platform(void);
+extern int get_cpufreq_base_freq(int cpu);
+extern int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap);
+extern void isst_display_error_info_message(int error, char *msg, int arg_valid, int arg);
#endif
diff --git a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
index 085cbe4..e15e206 100755
--- a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
+++ b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
@@ -104,7 +104,7 @@
if os.path.exists(file_name):
output_png = "cpu%03d_perf_busy_vs_samples.png" % cpu_index
g_plot = common_all_gnuplot_settings(output_png)
- g_plot('set yrange [0:40]')
+# autoscale this one, no set y1 range
g_plot('set y2range [0:200]')
g_plot('set y2tics 0, 10')
g_plot('set title "{} : cpu perf busy vs. sample : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
@@ -125,7 +125,7 @@
if os.path.exists(file_name):
output_png = "cpu%03d_perf_busy.png" % cpu_index
g_plot = common_all_gnuplot_settings(output_png)
- g_plot('set yrange [0:40]')
+# autoscale this one, no set y1 range
g_plot('set y2range [0:200]')
g_plot('set y2tics 0, 10')
g_plot('set title "{} : perf busy : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
@@ -144,9 +144,7 @@
if os.path.exists(file_name):
output_png = "cpu%03d_durations.png" % cpu_index
g_plot = common_all_gnuplot_settings(output_png)
-# Should autoscale be used here? Should seconds be used here?
- g_plot('set yrange [0:5000]')
- g_plot('set ytics 0, 500')
+# autoscale this one, no set y range
g_plot('set title "{} : durations : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
g_plot('set ylabel "Timer Duration (MilliSeconds)"')
# override common
@@ -176,7 +174,7 @@
if os.path.exists('cpu.csv'):
output_png = 'all_cpu_pstates_vs_samples.png'
g_plot = common_all_gnuplot_settings(output_png)
- g_plot('set yrange [0:40]')
+# autoscale this one, no set y range
# override common
g_plot('set xlabel "Samples"')
g_plot('set ylabel "P-State"')
@@ -191,7 +189,7 @@
output_png = 'all_cpu_pstates.png'
g_plot = common_all_gnuplot_settings(output_png)
- g_plot('set yrange [0:40]')
+# autoscale this one, no set y range
g_plot('set ylabel "P-State"')
g_plot('set title "{} : cpu pstates : {:%F %H:%M}"'.format(testname, datetime.now()))
@@ -222,7 +220,7 @@
output_png = 'all_cpu_frequencies.png'
g_plot = common_all_gnuplot_settings(output_png)
- g_plot('set yrange [0:4]')
+# autoscale this one, no set y range
g_plot('set ylabel "CPU Frequency (GHz)"')
g_plot('set title "{} : cpu frequencies : {:%F %H:%M}"'.format(testname, datetime.now()))
@@ -236,8 +234,7 @@
output_png = 'all_cpu_durations.png'
g_plot = common_all_gnuplot_settings(output_png)
- g_plot('set yrange [0:5000]')
- g_plot('set ytics 0, 500')
+# autoscale this one, no set y range
g_plot('set ylabel "Timer Duration (MilliSeconds)"')
g_plot('set title "{} : cpu durations : {:%F %H:%M}"'.format(testname, datetime.now()))
diff --git a/tools/power/x86/turbostat/.gitignore b/tools/power/x86/turbostat/.gitignore
index 7521370..e13109b 100644
--- a/tools/power/x86/turbostat/.gitignore
+++ b/tools/power/x86/turbostat/.gitignore
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
turbostat
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
index 2b65512..f3e3c94 100644
--- a/tools/power/x86/turbostat/Makefile
+++ b/tools/power/x86/turbostat/Makefile
@@ -12,11 +12,12 @@
override CFLAGS += -O2 -Wall -I../../../include
override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
override CFLAGS += -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"'
+override CFLAGS += -D_FILE_OFFSET_BITS=64
override CFLAGS += -D_FORTIFY_SOURCE=2
%: %.c
@mkdir -p $(BUILD_OUTPUT)
- $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS) -lcap
+ $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS) -lcap -lrt
.PHONY : clean
clean :
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index a6db83a..f6b7e85 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -335,7 +335,7 @@
.SH REFERENCES
Volume 3B: System Programming Guide"
-http://www.intel.com/products/processor/manuals/
+https://www.intel.com/products/processor/manuals/
.SH FILES
.ta
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 988326b..424ed19 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -79,6 +79,7 @@
unsigned long long cpuidle_cur_cpu_lpi_us;
unsigned long long cpuidle_cur_sys_lpi_us;
unsigned int gfx_cur_mhz;
+unsigned int gfx_act_mhz;
unsigned int tcc_activation_temp;
unsigned int tcc_activation_temp_override;
double rapl_power_units, rapl_time_units;
@@ -210,13 +211,14 @@
unsigned long long pkg_both_core_gfxe_c0;
long long gfx_rc6_ms;
unsigned int gfx_mhz;
+ unsigned int gfx_act_mhz;
unsigned int package_id;
- unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */
- unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */
- unsigned int energy_cores; /* MSR_PP0_ENERGY_STATUS */
- unsigned int energy_gfx; /* MSR_PP1_ENERGY_STATUS */
- unsigned int rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */
- unsigned int rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */
+ unsigned long long energy_pkg; /* MSR_PKG_ENERGY_STATUS */
+ unsigned long long energy_dram; /* MSR_DRAM_ENERGY_STATUS */
+ unsigned long long energy_cores; /* MSR_PP0_ENERGY_STATUS */
+ unsigned long long energy_gfx; /* MSR_PP1_ENERGY_STATUS */
+ unsigned long long rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */
+ unsigned long long rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */
unsigned int pkg_temp_c;
unsigned long long counter[MAX_ADDED_COUNTERS];
} *package_even, *package_odd;
@@ -259,6 +261,117 @@
#define SYSFS_PERCPU (1 << 1)
};
+/*
+ * The accumulated sum of MSR is defined as a monotonic
+ * increasing MSR, it will be accumulated periodically,
+ * despite its register's bit width.
+ */
+enum {
+ IDX_PKG_ENERGY,
+ IDX_DRAM_ENERGY,
+ IDX_PP0_ENERGY,
+ IDX_PP1_ENERGY,
+ IDX_PKG_PERF,
+ IDX_DRAM_PERF,
+ IDX_COUNT,
+};
+
+int get_msr_sum(int cpu, off_t offset, unsigned long long *msr);
+
+struct msr_sum_array {
+ /* get_msr_sum() = sum + (get_msr() - last) */
+ struct {
+ /*The accumulated MSR value is updated by the timer*/
+ unsigned long long sum;
+ /*The MSR footprint recorded in last timer*/
+ unsigned long long last;
+ } entries[IDX_COUNT];
+};
+
+/* The percpu MSR sum array.*/
+struct msr_sum_array *per_cpu_msr_sum;
+
+off_t idx_to_offset(int idx)
+{
+ off_t offset;
+
+ switch (idx) {
+ case IDX_PKG_ENERGY:
+ if (do_rapl & RAPL_AMD_F17H)
+ offset = MSR_PKG_ENERGY_STAT;
+ else
+ offset = MSR_PKG_ENERGY_STATUS;
+ break;
+ case IDX_DRAM_ENERGY:
+ offset = MSR_DRAM_ENERGY_STATUS;
+ break;
+ case IDX_PP0_ENERGY:
+ offset = MSR_PP0_ENERGY_STATUS;
+ break;
+ case IDX_PP1_ENERGY:
+ offset = MSR_PP1_ENERGY_STATUS;
+ break;
+ case IDX_PKG_PERF:
+ offset = MSR_PKG_PERF_STATUS;
+ break;
+ case IDX_DRAM_PERF:
+ offset = MSR_DRAM_PERF_STATUS;
+ break;
+ default:
+ offset = -1;
+ }
+ return offset;
+}
+
+int offset_to_idx(off_t offset)
+{
+ int idx;
+
+ switch (offset) {
+ case MSR_PKG_ENERGY_STATUS:
+ case MSR_PKG_ENERGY_STAT:
+ idx = IDX_PKG_ENERGY;
+ break;
+ case MSR_DRAM_ENERGY_STATUS:
+ idx = IDX_DRAM_ENERGY;
+ break;
+ case MSR_PP0_ENERGY_STATUS:
+ idx = IDX_PP0_ENERGY;
+ break;
+ case MSR_PP1_ENERGY_STATUS:
+ idx = IDX_PP1_ENERGY;
+ break;
+ case MSR_PKG_PERF_STATUS:
+ idx = IDX_PKG_PERF;
+ break;
+ case MSR_DRAM_PERF_STATUS:
+ idx = IDX_DRAM_PERF;
+ break;
+ default:
+ idx = -1;
+ }
+ return idx;
+}
+
+int idx_valid(int idx)
+{
+ switch (idx) {
+ case IDX_PKG_ENERGY:
+ return do_rapl & (RAPL_PKG | RAPL_AMD_F17H);
+ case IDX_DRAM_ENERGY:
+ return do_rapl & RAPL_DRAM;
+ case IDX_PP0_ENERGY:
+ return do_rapl & RAPL_CORES_ENERGY_STATUS;
+ case IDX_PP1_ENERGY:
+ return do_rapl & RAPL_GFX;
+ case IDX_PKG_PERF:
+ return do_rapl & RAPL_PKG_PERF_STATUS;
+ case IDX_DRAM_PERF:
+ return do_rapl & RAPL_DRAM_PERF_STATUS;
+ default:
+ return 0;
+ }
+}
struct sys_counters {
unsigned int added_thread_counters;
unsigned int added_core_counters;
@@ -451,6 +564,7 @@
{ 0x0, "APIC" },
{ 0x0, "X2APIC" },
{ 0x0, "Die" },
+ { 0x0, "GFXAMHz" },
};
#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
@@ -505,6 +619,7 @@
#define BIC_APIC (1ULL << 48)
#define BIC_X2APIC (1ULL << 49)
#define BIC_Die (1ULL << 50)
+#define BIC_GFXACTMHz (1ULL << 51)
#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
@@ -724,6 +839,9 @@
if (DO_BIC(BIC_GFXMHz))
outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));
+ if (DO_BIC(BIC_GFXACTMHz))
+ outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : ""));
+
if (DO_BIC(BIC_Totl_c0))
outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));
if (DO_BIC(BIC_Any_c0))
@@ -858,13 +976,13 @@
outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);
outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);
- outp += sprintf(outp, "Joules PKG: %0X\n", p->energy_pkg);
- outp += sprintf(outp, "Joules COR: %0X\n", p->energy_cores);
- outp += sprintf(outp, "Joules GFX: %0X\n", p->energy_gfx);
- outp += sprintf(outp, "Joules RAM: %0X\n", p->energy_dram);
- outp += sprintf(outp, "Throttle PKG: %0X\n",
+ outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg);
+ outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores);
+ outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx);
+ outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram);
+ outp += sprintf(outp, "Throttle PKG: %0llX\n",
p->rapl_pkg_perf_status);
- outp += sprintf(outp, "Throttle RAM: %0X\n",
+ outp += sprintf(outp, "Throttle RAM: %0llX\n",
p->rapl_dram_perf_status);
outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c);
@@ -1062,14 +1180,7 @@
}
}
- /*
- * If measurement interval exceeds minimum RAPL Joule Counter range,
- * indicate that results are suspect by printing "**" in fraction place.
- */
- if (interval_float < rapl_joule_counter_range)
- fmt8 = "%s%.2f";
- else
- fmt8 = "%6.0f**";
+ fmt8 = "%s%.2f";
if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY))
outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units / interval_float);
@@ -1098,6 +1209,10 @@
if (DO_BIC(BIC_GFXMHz))
outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);
+ /* GFXACTMHz */
+ if (DO_BIC(BIC_GFXACTMHz))
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz);
+
/* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
if (DO_BIC(BIC_Totl_c0))
outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0/tsc);
@@ -1210,11 +1325,7 @@
}
#define DELTA_WRAP32(new, old) \
- if (new > old) { \
- old = new - old; \
- } else { \
- old = 0x100000000 + new - old; \
- }
+ old = ((((unsigned long long)new << 32) - ((unsigned long long)old << 32)) >> 32);
int
delta_package(struct pkg_data *new, struct pkg_data *old)
@@ -1253,13 +1364,14 @@
old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;
old->gfx_mhz = new->gfx_mhz;
+ old->gfx_act_mhz = new->gfx_act_mhz;
- DELTA_WRAP32(new->energy_pkg, old->energy_pkg);
- DELTA_WRAP32(new->energy_cores, old->energy_cores);
- DELTA_WRAP32(new->energy_gfx, old->energy_gfx);
- DELTA_WRAP32(new->energy_dram, old->energy_dram);
- DELTA_WRAP32(new->rapl_pkg_perf_status, old->rapl_pkg_perf_status);
- DELTA_WRAP32(new->rapl_dram_perf_status, old->rapl_dram_perf_status);
+ old->energy_pkg = new->energy_pkg - old->energy_pkg;
+ old->energy_cores = new->energy_cores - old->energy_cores;
+ old->energy_gfx = new->energy_gfx - old->energy_gfx;
+ old->energy_dram = new->energy_dram - old->energy_dram;
+ old->rapl_pkg_perf_status = new->rapl_pkg_perf_status - old->rapl_pkg_perf_status;
+ old->rapl_dram_perf_status = new->rapl_dram_perf_status - old->rapl_dram_perf_status;
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW)
@@ -1469,6 +1581,7 @@
p->gfx_rc6_ms = 0;
p->gfx_mhz = 0;
+ p->gfx_act_mhz = 0;
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)
t->counter[i] = 0;
@@ -1564,6 +1677,7 @@
average.packages.gfx_rc6_ms = p->gfx_rc6_ms;
average.packages.gfx_mhz = p->gfx_mhz;
+ average.packages.gfx_act_mhz = p->gfx_act_mhz;
average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c);
@@ -1784,7 +1898,7 @@
int i;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "get_counters: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -1966,39 +2080,39 @@
p->sys_lpi = cpuidle_cur_sys_lpi_us;
if (do_rapl & RAPL_PKG) {
- if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr))
return -13;
- p->energy_pkg = msr & 0xFFFFFFFF;
+ p->energy_pkg = msr;
}
if (do_rapl & RAPL_CORES_ENERGY_STATUS) {
- if (get_msr(cpu, MSR_PP0_ENERGY_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr))
return -14;
- p->energy_cores = msr & 0xFFFFFFFF;
+ p->energy_cores = msr;
}
if (do_rapl & RAPL_DRAM) {
- if (get_msr(cpu, MSR_DRAM_ENERGY_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr))
return -15;
- p->energy_dram = msr & 0xFFFFFFFF;
+ p->energy_dram = msr;
}
if (do_rapl & RAPL_GFX) {
- if (get_msr(cpu, MSR_PP1_ENERGY_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr))
return -16;
- p->energy_gfx = msr & 0xFFFFFFFF;
+ p->energy_gfx = msr;
}
if (do_rapl & RAPL_PKG_PERF_STATUS) {
- if (get_msr(cpu, MSR_PKG_PERF_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr))
return -16;
- p->rapl_pkg_perf_status = msr & 0xFFFFFFFF;
+ p->rapl_pkg_perf_status = msr;
}
if (do_rapl & RAPL_DRAM_PERF_STATUS) {
- if (get_msr(cpu, MSR_DRAM_PERF_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr))
return -16;
- p->rapl_dram_perf_status = msr & 0xFFFFFFFF;
+ p->rapl_dram_perf_status = msr;
}
if (do_rapl & RAPL_AMD_F17H) {
- if (get_msr(cpu, MSR_PKG_ENERGY_STAT, &msr))
+ if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr))
return -13;
- p->energy_pkg = msr & 0xFFFFFFFF;
+ p->energy_pkg = msr;
}
if (DO_BIC(BIC_PkgTmp)) {
if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
@@ -2012,6 +2126,9 @@
if (DO_BIC(BIC_GFXMHz))
p->gfx_mhz = gfx_cur_mhz;
+ if (DO_BIC(BIC_GFXACTMHz))
+ p->gfx_act_mhz = gfx_act_mhz;
+
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
if (get_mp(cpu, mp, &p->counter[i]))
return -10;
@@ -2173,6 +2290,7 @@
case INTEL_FAM6_ATOM_GOLDMONT:
case INTEL_FAM6_SKYLAKE_X:
case INTEL_FAM6_ATOM_GOLDMONT_D:
+ case INTEL_FAM6_ATOM_TREMONT_D:
return 1;
}
return 0;
@@ -2650,7 +2768,12 @@
sprintf(path,
"/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu);
- filep = fopen_or_die(path, "r");
+ filep = fopen(path, "r");
+
+ if (!filep) {
+ warnx("%s: open failed", path);
+ return -1;
+ }
do {
offset -= BITMASK_SIZE;
if (fscanf(filep, "%lx%c", &map, &character) != 2)
@@ -2763,18 +2886,25 @@
{
free_all_buffers();
setup_all_buffers();
- printf("turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
+ fprintf(outf, "turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
}
void set_max_cpu_num(void)
{
FILE *filep;
+ int base_cpu;
unsigned long dummy;
+ char pathname[64];
+ base_cpu = sched_getcpu();
+ if (base_cpu < 0)
+ err(1, "cannot find calling cpu ID");
+ sprintf(pathname,
+ "/sys/devices/system/cpu/cpu%d/topology/thread_siblings",
+ base_cpu);
+
+ filep = fopen_or_die(pathname, "r");
topo.max_cpu_num = 0;
- filep = fopen_or_die(
- "/sys/devices/system/cpu/cpu0/topology/thread_siblings",
- "r");
while (fscanf(filep, "%lx,", &dummy) == 1)
topo.max_cpu_num += BITMASK_SIZE;
fclose(filep);
@@ -2916,6 +3046,33 @@
}
/*
+ * snapshot_gfx_cur_mhz()
+ *
+ * record snapshot of
+ * /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz
+ *
+ * return 1 if config change requires a restart, else return 0
+ */
+int snapshot_gfx_act_mhz(void)
+{
+ static FILE *fp;
+ int retval;
+
+ if (fp == NULL)
+ fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", "r");
+ else {
+ rewind(fp);
+ fflush(fp);
+ }
+
+ retval = fscanf(fp, "%d", &gfx_act_mhz);
+ if (retval != 1)
+ err(1, "GFX ACT MHz");
+
+ return 0;
+}
+
+/*
* snapshot_cpu_lpi()
*
* record snapshot of
@@ -2980,6 +3137,9 @@
if (DO_BIC(BIC_GFXMHz))
snapshot_gfx_mhz();
+ if (DO_BIC(BIC_GFXACTMHz))
+ snapshot_gfx_act_mhz();
+
if (DO_BIC(BIC_CPU_LPI))
snapshot_cpu_lpi_us();
@@ -3057,6 +3217,112 @@
}
}
+int get_msr_sum(int cpu, off_t offset, unsigned long long *msr)
+{
+ int ret, idx;
+ unsigned long long msr_cur, msr_last;
+
+ if (!per_cpu_msr_sum)
+ return 1;
+
+ idx = offset_to_idx(offset);
+ if (idx < 0)
+ return idx;
+ /* get_msr_sum() = sum + (get_msr() - last) */
+ ret = get_msr(cpu, offset, &msr_cur);
+ if (ret)
+ return ret;
+ msr_last = per_cpu_msr_sum[cpu].entries[idx].last;
+ DELTA_WRAP32(msr_cur, msr_last);
+ *msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum;
+
+ return 0;
+}
+
+timer_t timerid;
+
+/* Timer callback, update the sum of MSRs periodically. */
+static int update_msr_sum(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+{
+ int i, ret;
+ int cpu = t->cpu_id;
+
+ for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) {
+ unsigned long long msr_cur, msr_last;
+ off_t offset;
+
+ if (!idx_valid(i))
+ continue;
+ offset = idx_to_offset(i);
+ if (offset < 0)
+ continue;
+ ret = get_msr(cpu, offset, &msr_cur);
+ if (ret) {
+ fprintf(outf, "Can not update msr(0x%llx)\n",
+ (unsigned long long)offset);
+ continue;
+ }
+
+ msr_last = per_cpu_msr_sum[cpu].entries[i].last;
+ per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff;
+
+ DELTA_WRAP32(msr_cur, msr_last);
+ per_cpu_msr_sum[cpu].entries[i].sum += msr_last;
+ }
+ return 0;
+}
+
+static void
+msr_record_handler(union sigval v)
+{
+ for_all_cpus(update_msr_sum, EVEN_COUNTERS);
+}
+
+void msr_sum_record(void)
+{
+ struct itimerspec its;
+ struct sigevent sev;
+
+ per_cpu_msr_sum = calloc(topo.max_cpu_num + 1, sizeof(struct msr_sum_array));
+ if (!per_cpu_msr_sum) {
+ fprintf(outf, "Can not allocate memory for long time MSR.\n");
+ return;
+ }
+ /*
+ * Signal handler might be restricted, so use thread notifier instead.
+ */
+ memset(&sev, 0, sizeof(struct sigevent));
+ sev.sigev_notify = SIGEV_THREAD;
+ sev.sigev_notify_function = msr_record_handler;
+
+ sev.sigev_value.sival_ptr = &timerid;
+ if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
+ fprintf(outf, "Can not create timer.\n");
+ goto release_msr;
+ }
+
+ its.it_value.tv_sec = 0;
+ its.it_value.tv_nsec = 1;
+ /*
+ * A wraparound time has been calculated early.
+ * Some sources state that the peak power for a
+ * microprocessor is usually 1.5 times the TDP rating,
+ * use 2 * TDP for safety.
+ */
+ its.it_interval.tv_sec = rapl_joule_counter_range / 2;
+ its.it_interval.tv_nsec = 0;
+
+ if (timer_settime(timerid, 0, &its, NULL) == -1) {
+ fprintf(outf, "Can not set timer.\n");
+ goto release_timer;
+ }
+ return;
+
+ release_timer:
+ timer_delete(timerid);
+ release_msr:
+ free(per_cpu_msr_sum);
+}
void turbostat_loop()
{
@@ -3075,7 +3341,7 @@
if (retval < -1) {
exit(retval);
} else if (retval == -1) {
- if (restarted > 1) {
+ if (restarted > 10) {
exit(retval);
}
re_initialize();
@@ -3278,6 +3544,8 @@
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
+ case INTEL_FAM6_ATOM_TREMONT: /* EHL */
+ case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
pkg_cstate_limits = glm_pkg_cstate_limits;
break;
default:
@@ -3349,6 +3617,28 @@
}
return 0;
}
+int is_ehl(unsigned int family, unsigned int model)
+{
+ if (!genuine_intel)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_ATOM_TREMONT:
+ return 1;
+ }
+ return 0;
+}
+int is_jvl(unsigned int family, unsigned int model)
+{
+ if (!genuine_intel)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_ATOM_TREMONT_D:
+ return 1;
+ }
+ return 0;
+}
int has_turbo_ratio_limit(unsigned int family, unsigned int model)
{
@@ -3463,6 +3753,20 @@
}
static void
+remove_underbar(char *s)
+{
+ char *to = s;
+
+ while (*s) {
+ if (*s != '_')
+ *to++ = *s;
+ s++;
+ }
+
+ *to = 0;
+}
+
+static void
dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
{
if (!do_nhm_platform_info)
@@ -3491,6 +3795,23 @@
dump_nhm_cst_cfg();
}
+static void dump_sysfs_file(char *path)
+{
+ FILE *input;
+ char cpuidle_buf[64];
+
+ input = fopen(path, "r");
+ if (input == NULL) {
+ if (debug)
+ fprintf(outf, "NSFOD %s\n", path);
+ return;
+ }
+ if (!fgets(cpuidle_buf, sizeof(cpuidle_buf), input))
+ err(1, "%s: failed to read file", path);
+ fclose(input);
+
+ fprintf(outf, "%s: %s", strrchr(path, '/') + 1, cpuidle_buf);
+}
static void
dump_sysfs_cstate_config(void)
{
@@ -3501,8 +3822,14 @@
int state;
char *sp;
- if (!DO_BIC(BIC_sysfs))
+ if (access("/sys/devices/system/cpu/cpuidle", R_OK)) {
+ fprintf(outf, "cpuidle not loaded\n");
return;
+ }
+
+ dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_driver");
+ dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor");
+ dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor_ro");
for (state = 0; state < 10; ++state) {
@@ -3521,6 +3848,8 @@
*sp = '\0';
fclose(input);
+ remove_underbar(name_buf);
+
sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc",
base_cpu, state);
input = fopen(path, "r");
@@ -3607,7 +3936,7 @@
return 0;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_epb: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -3651,7 +3980,7 @@
return 0;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_hwp: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -3739,7 +4068,7 @@
return 0;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_perf_limit: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -3843,13 +4172,8 @@
double get_tdp_amd(unsigned int family)
{
- switch (family) {
- case 0x17:
- case 0x18:
- default:
- /* This is the max stock TDP of HEDT/Server Fam17h chips */
- return 250.0;
- }
+ /* This is the max stock TDP of HEDT/Server Fam17h+ chips */
+ return 280.0;
}
/*
@@ -3907,6 +4231,28 @@
else
BIC_PRESENT(BIC_PkgWatt);
break;
+ case INTEL_FAM6_ATOM_TREMONT: /* EHL */
+ do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
+ if (rapl_joules) {
+ BIC_PRESENT(BIC_Pkg_J);
+ BIC_PRESENT(BIC_Cor_J);
+ BIC_PRESENT(BIC_RAM_J);
+ BIC_PRESENT(BIC_GFX_J);
+ } else {
+ BIC_PRESENT(BIC_PkgWatt);
+ BIC_PRESENT(BIC_CorWatt);
+ BIC_PRESENT(BIC_RAMWatt);
+ BIC_PRESENT(BIC_GFXWatt);
+ }
+ break;
+ case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
+ do_rapl = RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
+ BIC_PRESENT(BIC_PKG__);
+ if (rapl_joules)
+ BIC_PRESENT(BIC_Pkg_J);
+ else
+ BIC_PRESENT(BIC_PkgWatt);
+ break;
case INTEL_FAM6_SKYLAKE_L: /* SKL */
case INTEL_FAM6_CANNONLAKE_L: /* CNL */
do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
@@ -4017,27 +4363,20 @@
if (max_extended_level >= 0x80000007) {
__cpuid(0x80000007, eax, ebx, ecx, edx);
- /* RAPL (Fam 17h) */
+ /* RAPL (Fam 17h+) */
has_rapl = edx & (1 << 14);
}
- if (!has_rapl)
+ if (!has_rapl || family < 0x17)
return;
- switch (family) {
- case 0x17: /* Zen, Zen+ */
- case 0x18: /* Hygon Dhyana */
- do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
- if (rapl_joules) {
- BIC_PRESENT(BIC_Pkg_J);
- BIC_PRESENT(BIC_Cor_J);
- } else {
- BIC_PRESENT(BIC_PkgWatt);
- BIC_PRESENT(BIC_CorWatt);
- }
- break;
- default:
- return;
+ do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
+ if (rapl_joules) {
+ BIC_PRESENT(BIC_Pkg_J);
+ BIC_PRESENT(BIC_Cor_J);
+ } else {
+ BIC_PRESENT(BIC_PkgWatt);
+ BIC_PRESENT(BIC_CorWatt);
}
if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr))
@@ -4110,7 +4449,7 @@
return 0;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -4182,7 +4521,7 @@
cpu = t->cpu_id;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_rapl: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -4308,6 +4647,8 @@
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
+ case INTEL_FAM6_ATOM_TREMONT: /* EHL */
+ case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
return 1;
}
return 0;
@@ -4337,6 +4678,7 @@
case INTEL_FAM6_CANNONLAKE_L: /* CNL */
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
+ case INTEL_FAM6_ATOM_TREMONT: /* EHL */
return 1;
}
return 0;
@@ -4512,10 +4854,10 @@
{
unsigned long long msr;
- if (!get_msr(base_cpu, MSR_IA32_FEATURE_CONTROL, &msr))
+ if (!get_msr(base_cpu, MSR_IA32_FEAT_CTL, &msr))
fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n",
base_cpu, msr,
- msr & FEATURE_CONTROL_LOCKED ? "" : "UN-",
+ msr & FEAT_CTL_LOCKED ? "" : "UN-",
msr & (1 << 18) ? "SGX" : "");
}
@@ -4623,17 +4965,54 @@
case INTEL_FAM6_SKYLAKE:
case INTEL_FAM6_KABYLAKE_L:
case INTEL_FAM6_KABYLAKE:
+ case INTEL_FAM6_COMETLAKE_L:
+ case INTEL_FAM6_COMETLAKE:
return INTEL_FAM6_SKYLAKE_L;
case INTEL_FAM6_ICELAKE_L:
case INTEL_FAM6_ICELAKE_NNPI:
+ case INTEL_FAM6_TIGERLAKE_L:
+ case INTEL_FAM6_TIGERLAKE:
+ case INTEL_FAM6_ROCKETLAKE:
+ case INTEL_FAM6_LAKEFIELD:
+ case INTEL_FAM6_ALDERLAKE:
return INTEL_FAM6_CANNONLAKE_L;
- case INTEL_FAM6_ATOM_TREMONT_D:
- return INTEL_FAM6_ATOM_GOLDMONT_D;
+ case INTEL_FAM6_ATOM_TREMONT_L:
+ return INTEL_FAM6_ATOM_TREMONT;
+
+ case INTEL_FAM6_ICELAKE_X:
+ case INTEL_FAM6_SAPPHIRERAPIDS_X:
+ return INTEL_FAM6_SKYLAKE_X;
}
return model;
}
+
+void print_dev_latency(void)
+{
+ char *path = "/dev/cpu_dma_latency";
+ int fd;
+ int value;
+ int retval;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ warn("fopen %s\n", path);
+ return;
+ }
+
+ retval = read(fd, (void *)&value, sizeof(int));
+ if (retval != sizeof(int)) {
+ warn("read %s\n", path);
+ close(fd);
+ return;
+ }
+ fprintf(outf, "/dev/cpu_dma_latency: %d usec (%s)\n",
+ value, value == 2000000000 ? "default" : "constrained");
+
+ close(fd);
+}
+
void process_cpuid()
{
unsigned int eax, ebx, ecx, edx;
@@ -4852,6 +5231,14 @@
BIC_PRESENT(BIC_Mod_c6);
use_c1_residency_msr = 1;
}
+ if (is_jvl(family, model)) {
+ BIC_NOT_PRESENT(BIC_CPU_c3);
+ BIC_NOT_PRESENT(BIC_CPU_c7);
+ BIC_NOT_PRESENT(BIC_Pkgpc2);
+ BIC_NOT_PRESENT(BIC_Pkgpc3);
+ BIC_NOT_PRESENT(BIC_Pkgpc6);
+ BIC_NOT_PRESENT(BIC_Pkgpc7);
+ }
if (is_dnv(family, model)) {
BIC_PRESENT(BIC_CPU_c1);
BIC_NOT_PRESENT(BIC_CPU_c3);
@@ -4871,9 +5258,12 @@
BIC_NOT_PRESENT(BIC_Pkgpc7);
}
if (has_c8910_msrs(family, model)) {
- BIC_PRESENT(BIC_Pkgpc8);
- BIC_PRESENT(BIC_Pkgpc9);
- BIC_PRESENT(BIC_Pkgpc10);
+ if (pkg_cstate_limit >= PCL__8)
+ BIC_PRESENT(BIC_Pkgpc8);
+ if (pkg_cstate_limit >= PCL__9)
+ BIC_PRESENT(BIC_Pkgpc9);
+ if (pkg_cstate_limit >= PCL_10)
+ BIC_PRESENT(BIC_Pkgpc10);
}
do_irtl_hsw = has_c8910_msrs(family, model);
if (has_skl_msrs(family, model)) {
@@ -4885,7 +5275,8 @@
do_slm_cstates = is_slm(family, model);
do_knl_cstates = is_knl(family, model);
- if (do_slm_cstates || do_knl_cstates || is_cnl(family, model))
+ if (do_slm_cstates || do_knl_cstates || is_cnl(family, model) ||
+ is_ehl(family, model))
BIC_NOT_PRESENT(BIC_CPU_c3);
if (!quiet)
@@ -4902,6 +5293,8 @@
dump_cstate_pstate_config_info(family, model);
if (!quiet)
+ print_dev_latency();
+ if (!quiet)
dump_sysfs_cstate_config();
if (!quiet)
dump_sysfs_pstate_config();
@@ -4915,6 +5308,9 @@
if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
BIC_PRESENT(BIC_GFXMHz);
+ if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK))
+ BIC_PRESENT(BIC_GFXACTMHz);
+
if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK))
BIC_PRESENT(BIC_CPU_LPI);
else
@@ -5325,7 +5721,7 @@
}
void print_version() {
- fprintf(outf, "turbostat version 19.08.31"
+ fprintf(outf, "turbostat version 20.09.30"
" - Len Brown <lenb@kernel.org>\n");
}
@@ -5532,6 +5928,8 @@
*sp = '%';
*(sp + 1) = '\0';
+ remove_underbar(name_buf);
+
fclose(input);
sprintf(path, "cpuidle/state%d/time", state);
@@ -5559,6 +5957,8 @@
*sp = '\0';
fclose(input);
+ remove_underbar(name_buf);
+
sprintf(path, "cpuidle/state%d/usage", state);
if (is_deferred_skip(name_buf))
@@ -5803,6 +6203,7 @@
return 0;
}
+ msr_sum_record();
/*
* if any params left, it must be a command to fork
*/
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
index 3fe1eed..ff6c666 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
@@ -622,6 +622,57 @@
}
}
+/*
+ * Open a file, and exit on failure
+ */
+FILE *fopen_or_die(const char *path, const char *mode)
+{
+ FILE *filep = fopen(path, "r");
+
+ if (!filep)
+ err(1, "%s: open failed", path);
+ return filep;
+}
+
+void err_on_hypervisor(void)
+{
+ FILE *cpuinfo;
+ char *flags, *hypervisor;
+ char *buffer;
+
+ /* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */
+ cpuinfo = fopen_or_die("/proc/cpuinfo", "ro");
+
+ buffer = malloc(4096);
+ if (!buffer) {
+ fclose(cpuinfo);
+ err(-ENOMEM, "buffer malloc fail");
+ }
+
+ if (!fread(buffer, 1024, 1, cpuinfo)) {
+ fclose(cpuinfo);
+ free(buffer);
+ err(1, "Reading /proc/cpuinfo failed");
+ }
+
+ flags = strstr(buffer, "flags");
+ rewind(cpuinfo);
+ fseek(cpuinfo, flags - buffer, SEEK_SET);
+ if (!fgets(buffer, 4096, cpuinfo)) {
+ fclose(cpuinfo);
+ free(buffer);
+ err(1, "Reading /proc/cpuinfo failed");
+ }
+ fclose(cpuinfo);
+
+ hypervisor = strstr(buffer, "hypervisor");
+
+ free(buffer);
+
+ if (hypervisor)
+ err(-1,
+ "not supported on this virtual machine");
+}
int get_msr(int cpu, int offset, unsigned long long *msr)
{
@@ -635,8 +686,10 @@
err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
retval = pread(fd, msr, sizeof(*msr), offset);
- if (retval != sizeof(*msr))
+ if (retval != sizeof(*msr)) {
+ err_on_hypervisor();
err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
+ }
if (debug > 1)
fprintf(stderr, "get_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, *msr);
@@ -1086,18 +1139,6 @@
return 0;
}
-/*
- * Open a file, and exit on failure
- */
-FILE *fopen_or_die(const char *path, const char *mode)
-{
- FILE *filep = fopen(path, "r");
-
- if (!filep)
- err(1, "%s: open failed", path);
- return filep;
-}
-
unsigned int get_pkg_num(int cpu)
{
FILE *fp;