diff options
Diffstat (limited to 'tools/power/x86')
-rw-r--r-- | tools/power/x86/intel-speed-select/isst-config.c | 1133 | ||||
-rw-r--r-- | tools/power/x86/intel-speed-select/isst-core.c | 280 | ||||
-rw-r--r-- | tools/power/x86/intel-speed-select/isst-display.c | 324 | ||||
-rw-r--r-- | tools/power/x86/intel-speed-select/isst.h | 22 | ||||
-rwxr-xr-x | tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py | 38 | ||||
-rw-r--r-- | tools/power/x86/turbostat/Makefile | 3 | ||||
-rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 219 | ||||
-rw-r--r-- | tools/power/x86/x86_energy_perf_policy/Makefile | 3 | ||||
-rw-r--r-- | tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 | 2 | ||||
-rw-r--r-- | tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c | 28 |
10 files changed, 1635 insertions, 417 deletions
diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c index 91c5ad1685a1..2b2b8167c65b 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.2"; static const int supported_api_ver = 1; static struct isst_if_platform_info isst_platform_info; static char *progname; @@ -22,6 +23,7 @@ static int debug_flag; static FILE *outf; static int cpu_model; +static int cpu_stepping; #define MAX_CPUS_IN_ONE_REQ 64 static short max_target_cpus; @@ -38,6 +40,8 @@ static int fact_avx = 0xFF; static unsigned long long fact_trl; static int out_format_json; static int cmd_help; +static int force_online_offline; +static int auto_mode; /* clos related */ static int current_clos = -1; @@ -69,7 +73,16 @@ void debug_printf(const char *format, ...) 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; +} + +static int update_cpu_model(void) { unsigned int ebx, ecx, edx; unsigned int fms, family; @@ -79,6 +92,33 @@ static void update_cpu_model(void) 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 */ @@ -138,14 +178,14 @@ int out_format_is_json(void) int get_physical_package_id(int cpu) { return parse_int_file( - 1, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", + 0, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); } int get_physical_core_id(int cpu) { return parse_int_file( - 1, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); + 0, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); } int get_physical_die_id(int cpu) @@ -160,11 +200,39 @@ int get_physical_die_id(int cpu) 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; } +static void set_cpu_online_offline(int cpu, int state) +{ + char buffer[128]; + int fd, ret; + + snprintf(buffer, sizeof(buffer), + "/sys/devices/system/cpu/cpu%d/online", cpu); + + fd = open(buffer, O_WRONLY); + if (fd < 0) + err(-1, "%s open failed", buffer); + + if (state) + ret = write(fd, "1\n", 2); + else + ret = write(fd, "0\n", 2); + + if (ret == -1) + perror("Online/Offline: Operation failed\n"); + + close(fd); +} + #define MAX_PACKAGE_COUNT 8 #define MAX_DIE_PER_PACKAGE 2 static void for_each_online_package_in_set(void (*callback)(int, void *, void *, @@ -270,6 +338,7 @@ void free_cpu_set(cpu_set_t *cpu_set) } 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; @@ -294,17 +363,37 @@ static void set_cpu_present_cpu_mask(void) pkg_id = get_physical_package_id(i); 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_core_count(int pkg_id, int die_id) +{ + int cnt = 0; + + if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE) { + int i; + + for (i = 0; i < sizeof(long long) * 8; ++i) { + if (core_mask[pkg_id][die_id] & (1ULL << i)) + cnt++; + } + } + + return cnt; +} + int get_cpu_count(int pkg_id, int die_id) { if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE) - return cpu_cnt[pkg_id][die_id] + 1; + return cpu_cnt[pkg_id][die_id]; return 0; } @@ -402,6 +491,9 @@ void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask, int j; for (j = 0; j < topo_max_cpus; ++j) { + if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask)) + continue; + if (cpu_map[j].pkg_id == pkg_id && cpu_map[j].die_id == die_id && cpu_map[j].punit_cpu_core == i) { @@ -484,7 +576,7 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char command, int write = 0; int clos_id, core_id, ret = 0; - debug_printf("CLOS %d\n", cpu); + debug_printf("CPU %d\n", cpu); if (parameter & BIT(MBOX_CMD_WRITE_BIT)) { value = req_data; @@ -508,12 +600,6 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char command, 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: @@ -538,6 +624,7 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char 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); + return -1; } else { *resp = mbox_cmds.mbox_cmd[0].resp_data; debug_printf( @@ -603,6 +690,10 @@ static int isst_fill_platform_info(void) close(fd); + if (isst_platform_info.api_version > supported_api_ver) { + printf("Incompatible API versions; Upgrade of tool is required\n"); + return -1; + } return 0; } @@ -645,12 +736,12 @@ static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3, if (ret) perror("get_tdp_*"); else - isst_display_result(cpu, outf, "perf-profile", (char *)arg3, - *(unsigned int *)arg4); + isst_ctdp_display_core_info(cpu, outf, arg3, + *(unsigned int *)arg4); } #define _get_tdp_level(desc, suffix, object, help) \ - static void get_tdp_##object(void) \ + static void get_tdp_##object(int arg) \ { \ struct isst_pkg_ctdp ctdp; \ \ @@ -680,6 +771,152 @@ _get_tdp_level("get-config-current_level", levels, current_level, "Current TDP Level"); _get_tdp_level("get-lock-status", levels, locked, "TDP lock status"); +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; + + ret = clx_n_config(cpu); + if (ret) { + perror("isst_get_process_ctdp"); + } 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_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) { @@ -696,8 +933,10 @@ static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2, } } -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"); @@ -709,14 +948,17 @@ static void dump_isst_config(void) 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); } @@ -729,17 +971,44 @@ static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, ret = isst_set_tdp_level(cpu, tdp_level); if (ret) perror("set_tdp_level_for_cpu"); - else + else { isst_display_result(cpu, outf, "perf-profile", "set_tdp_level", ret); + if (force_online_offline) { + struct isst_pkg_ctdp_level_info ctdp_level; + int pkg_id = get_physical_package_id(cpu); + int die_id = get_physical_die_id(cpu); + + 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); + if (ctdp_level.cpu_count) { + int i, max_cpus = get_topo_max_cpus(); + for (i = 0; i < max_cpus; ++i) { + if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i)) + continue; + 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); + } else { + fprintf(stderr, "offline cpu %d\n", i); + set_cpu_online_offline(i, 0); + } + } + } + } + } } -static void set_tdp_level(void) +static void set_tdp_level(int arg) { if (cmd_help) { fprintf(stderr, "Set Config TDP level\n"); fprintf(stderr, "\t Arguments: -l|--level : Specify tdp level\n"); + fprintf(stderr, + "\t Optional Arguments: -o | online : online/offline for the tdp level\n"); exit(0); } @@ -757,6 +1026,26 @@ static void set_tdp_level(void) 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) { + perror("isst_get_process_ctdp"); + } 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) { @@ -772,8 +1061,10 @@ static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, } } -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"); @@ -787,72 +1078,371 @@ static void dump_pbf_config(void) exit(1); } + if (!is_clx_n_platform()) + fn = dump_pbf_config_for_cpu; + else + 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(dump_pbf_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_pbf_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 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) { + perror("isst_pm_get_clos"); + 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) { + perror("isst_pm_set_clos"); + 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 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) { + perror("set_clx_pbf_cpufreq_scaling_min_max"); + 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); + } +} + +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) { + perror("isst_clos_associate"); + 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) { + perror("isst_get_ctdp_levels"); + 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) { + perror("isst_get_pbf_info"); + 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) { + perror("set_core_priority_and_min"); + return ret; + } + + ret = isst_pm_qos_config(cpu, 1, 1); + if (ret) { + perror("isst_pm_qos_config"); + return ret; + } + + return 0; +} + static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, void *arg4) { int ret; int status = *(int *)arg4; + if (is_clx_n_platform()) { + if (status) { + ret = 0; + if (auto_mode) + set_clx_pbf_cpufreq_scaling_min_max(cpu); + + } else { + ret = -1; + if (auto_mode) { + set_scaling_max_to_cpuinfo_max(cpu); + set_scaling_min_to_cpuinfo_min(cpu); + } + } + 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"); + 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); + } } -} - -static void set_pbf_enable(void) -{ - int status = 1; - if (cmd_help) { - fprintf(stderr, - "Enable Intel Speed Select Technology base frequency feature [No command arguments are required]\n"); - exit(0); - } + if (auto_mode && !status) + isst_pm_qos_config(cpu, 0, 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); +disp_result: + if (status) + isst_display_result(cpu, outf, "base-freq", "enable", + ret); else - for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL, - NULL, &status); - isst_ctdp_display_information_end(outf); + isst_display_result(cpu, outf, "base-freq", "disable", + ret); } -static void set_pbf_disable(void) +static void set_pbf_enable(int arg) { - int status = 0; + int enable = arg; if (cmd_help) { - fprintf(stderr, - "Disable 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"); + fprintf(stderr, + "\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n"); + } else { + + 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); + NULL, &enable); isst_ctdp_display_information_end(outf); } @@ -870,7 +1460,7 @@ static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2, fact_avx, &fact_info); } -static void dump_fact_config(void) +static void dump_fact_config(int arg) { if (cmd_help) { fprintf(stderr, @@ -905,73 +1495,155 @@ static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, int ret; int status = *(int *)arg4; + if (auto_mode && 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) + if (ret) { perror("isst_set_fact"); - else { - if (status) { - struct isst_pkg_ctdp pkg_dev; + 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); - } 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); - } + 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); + } 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(void) +static void set_fact_enable(int arg) { - int status = 1; + int i, ret, enable = arg; if (cmd_help) { - fprintf(stderr, - "Enable Intel Speed Select Technology Turbo frequency feature\n"); - fprintf(stderr, - "Optional: -t|--trl : Specify turbo ratio limit\n"); + 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 { + 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"); + } 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 (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, @@ -981,31 +1653,36 @@ static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3, int status = *(int *)arg4; ret = isst_pm_qos_config(cpu, status, clos_priority_type); - if (ret) { + 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 (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"); + 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"); } @@ -1013,30 +1690,10 @@ static void set_clos_enable(void) 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); - 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); + NULL, NULL, &enable); else for_each_online_package_in_set(enable_clos_qos_config, NULL, - NULL, NULL, &status); + NULL, NULL, &enable); isst_ctdp_display_information_end(outf); } @@ -1054,7 +1711,7 @@ static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2, &clos_config); } -static void dump_clos_config(void) +static void dump_clos_config(int arg) { if (cmd_help) { fprintf(stderr, @@ -1078,6 +1735,40 @@ static void dump_clos_config(void) isst_ctdp_display_information_end(outf); } +static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, + void *arg4) +{ + int enable, ret, prio_type; + + 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); +} + +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"); + exit(0); + } + + isst_ctdp_display_information_start(outf); + for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL, + NULL, NULL, NULL); + isst_ctdp_display_information_end(outf); + +} + static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, void *arg4) { @@ -1099,7 +1790,7 @@ static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 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, @@ -1109,9 +1800,9 @@ static void set_clos_config(void) 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"); + fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n"); + fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n"); + fprintf(stderr, "\tSpecify clos desired in MHz with [--desired|-d]\n"); exit(0); } @@ -1133,7 +1824,7 @@ static void set_clos_config(void) 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: 25500 MHz\n"); clos_max = 0xff; } if (clos_desired < 0) { @@ -1163,7 +1854,7 @@ static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 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"); @@ -1194,45 +1885,59 @@ static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, if (ret) perror("isst_clos_get_assoc_status"); else - isst_display_result(cpu, outf, "core-power", "get-assoc", clos); + 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"); fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n"); exit(0); } - if (max_target_cpus) - for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL, - NULL, NULL, NULL); - else { + + if (!max_target_cpus) { fprintf(stderr, "Invalid target cpu. Specify with [-c|--cpu]\n"); + exit(0); } + + isst_ctdp_display_information_start(outf); + for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL, + NULL, NULL, NULL); + 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_config }, - { "core-power", "enable", set_clos_enable }, - { "core-power", "disable", set_clos_disable }, - { "core-power", "config", set_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 } }; @@ -1312,6 +2017,7 @@ static void parse_cmd_args(int argc, int start, char **argv) static struct option long_options[] = { { "bucket", required_argument, 0, 'b' }, { "level", required_argument, 0, 'l' }, + { "online", required_argument, 0, 'o' }, { "trl-type", required_argument, 0, 'r' }, { "trl", required_argument, 0, 't' }, { "help", no_argument, 0, 'h' }, @@ -1322,15 +2028,19 @@ static void parse_cmd_args(int argc, int start, char **argv) { "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:h", + while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:hoa", long_options, &option_index)) != -1) { switch (opt) { + case 'a': + auto_mode = 1; + break; case 'b': fact_bucket = atoi(optarg); break; @@ -1340,6 +2050,9 @@ static void parse_cmd_args(int argc, int start, char **argv) case 'l': tdp_level = atoi(optarg); break; + case 'o': + force_online_offline = 1; + break; case 't': sscanf(optarg, "0x%llx", &fact_trl); break; @@ -1358,19 +2071,21 @@ static void parse_cmd_args(int argc, int start, char **argv) /* CLOS related */ case 'c': current_clos = atoi(optarg); - printf("clos %d\n", current_clos); break; case 'd': clos_desired = atoi(optarg); + clos_desired /= DISP_FREQ_MULTIPLIER; break; case 'e': clos_epp = atoi(optarg); 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); @@ -1392,12 +2107,15 @@ static void isst_help(void) 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) @@ -1429,6 +2147,7 @@ static void core_power_help(void) printf("\tenable\n"); printf("\tdisable\n"); printf("\tconfig\n"); + printf("\tget-config\n"); printf("\tassoc\n"); printf("\tget-assoc\n"); } @@ -1446,7 +2165,15 @@ static struct process_cmd_help_struct isst_help_cmds[] = { { 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]; @@ -1457,23 +2184,24 @@ void process_command(int argc, char **argv) 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; } @@ -1491,7 +2219,7 @@ static void usage(void) 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("\nFor help on each feature, use --h|--help\n"); + printf("\nFor help on each feature, use -h|--help\n"); printf("\tFor example: intel-speed-select perf-profile -h\n"); printf("\nFor additional help on each command for a feature, use --h|--help\n"); @@ -1514,7 +2242,6 @@ static void usage(void) 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("\t\t\tFor Set commands, status is 0 for success and rest for failures\n"); exit(1); } @@ -1529,6 +2256,7 @@ static void cmdline(int argc, char **argv) { int opt; int option_index = 0; + int ret; static struct option long_options[] = { { "cpu", required_argument, 0, 'c' }, @@ -1584,19 +2312,26 @@ static void cmdline(int argc, char **argv) fprintf(stderr, "Feature name and|or command not specified\n"); exit(0); } - update_cpu_model(); + 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); set_max_cpu_num(); set_cpu_present_cpu_mask(); set_cpu_target_cpu_mask(); - isst_fill_platform_info(); - if (isst_platform_info.api_version > supported_api_ver) { - printf("Incompatible API versions; Upgrade of tool is required\n"); - exit(0); - } - 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); } int main(int argc, char **argv) diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c index 8de4ac39a008..81a119f688a3 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 @@ int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev) 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_levels(int cpu, struct isst_pkg_ctdp *pkg_dev) 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 @@ int isst_get_ctdp_control(int cpu, int config_index, 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, @@ -95,6 +149,69 @@ int isst_get_pwr_info(int cpu, int config_index, 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 +266,27 @@ int isst_get_coremask_info(int cpu, int config_index, 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; @@ -188,8 +326,27 @@ int isst_get_get_trl(int cpu, int level, int avx_level, int *trl) return 0; } +int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info) +{ + int ret; + + debug_printf("cpu:%d bucket info via MSR\n", cpu); + + *buckets_info = 0; + + ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info); + if (ret) + return ret; + + debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", cpu, + *buckets_info); + + return 0; +} + int isst_set_tdp_level_msr(int cpu, int tdp_level) { + unsigned long long level = tdp_level; int ret; debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level); @@ -202,8 +359,7 @@ int isst_set_tdp_level_msr(int cpu, int tdp_level) if (tdp_level > 2) return -1; /* invalid value */ - ret = isst_send_msr_command(cpu, 0x64b, 1, - (unsigned long long *)&tdp_level); + ret = isst_send_msr_command(cpu, 0x64b, 1, &level); if (ret) return ret; @@ -227,12 +383,15 @@ int isst_set_tdp_level(int cpu, int tdp_level) int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info) { + int i, ret, core_cnt, max; unsigned int req, resp; - int i, ret; pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask); - for (i = 0; i < 2; ++i) { + core_cnt = get_core_count(get_physical_package_id(cpu), get_physical_die_id(cpu)); + max = core_cnt > 32 ? 2 : 1; + + for (i = 0; i < max; ++i) { unsigned long long mask; int count; @@ -240,7 +399,7 @@ int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info) 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", @@ -305,7 +464,7 @@ int isst_set_pbf_fact_status(int cpu, int pbf, int enable) 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; @@ -535,7 +694,6 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) i); ctdp_level = &pkg_dev->ctdp_level[i]; - ctdp_level->processed = 1; ctdp_level->level = i; ctdp_level->control_cpu = cpu; ctdp_level->pkg_id = get_physical_package_id(cpu); @@ -543,7 +701,37 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) ret = isst_get_ctdp_control(cpu, i, ctdp_level); if (ret) - return ret; + continue; + + 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, + &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) @@ -563,6 +751,10 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) if (ret) return ret; + ret = isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info); + if (ret) + return ret; + ret = isst_get_get_trl(cpu, i, 0, ctdp_level->trl_sse_active_cores); if (ret) @@ -578,21 +770,35 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev) 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); } - pkg_dev->processed = 1; + return 0; +} + +int isst_clos_get_clos_information(int cpu, int *enable, int *type) +{ + unsigned int resp; + int ret; + + ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0, + &resp); + if (ret) + return ret; + + debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp); + + if (resp & BIT(1)) + *enable = 1; + else + *enable = 0; + + if (resp & BIT(2)) + *type = 1; + else + *type = 0; return 0; } @@ -602,6 +808,34 @@ int isst_pm_qos_config(int cpu, int enable_clos, int priority_type) 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) { + debug_printf("Turbo-freq feature must be disabled first\n"); + return -EINVAL; + } + ret = isst_write_pm_config(cpu, 0); + if (ret) + perror("isst_write_pm_config\n"); + } else { + ret = isst_write_pm_config(cpu, 1); + if (ret) + perror("isst_write_pm_config\n"); + } + ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0, &resp); if (ret) diff --git a/tools/power/x86/intel-speed-select/isst-display.c b/tools/power/x86/intel-speed-select/isst-display.c index f368b8323742..4fb0c1d49d64 100644 --- a/tools/power/x86/intel-speed-select/isst-display.c +++ b/tools/power/x86/intel-speed-select/isst-display.c @@ -6,7 +6,32 @@ #include "isst.h" -#define DISP_FREQ_MULTIPLIER 100000 +static void printcpulist(int str_len, char *str, int mask_size, + cpu_set_t *cpu_mask) +{ + int i, first, curr_index, index; + + if (!CPU_COUNT_S(mask_size, cpu_mask)) { + snprintf(str, str_len, "none"); + return; + } + + curr_index = 0; + first = 1; + for (i = 0; i < get_topo_max_cpus(); ++i) { + if (!CPU_ISSET_S(i, mask_size, cpu_mask)) + continue; + if (!first) { + index = snprintf(&str[curr_index], + str_len - curr_index, ","); + curr_index += index; + } + index = snprintf(&str[curr_index], str_len - curr_index, "%d", + i); + curr_index += index; + first = 0; + } +} static void printcpumask(int str_len, char *str, int mask_size, cpu_set_t *cpu_mask) @@ -133,7 +158,7 @@ static void format_and_print(FILE *outf, int level, char *header, char *value) last_level = level; } -static void print_packag_info(int cpu, FILE *outf) +static void print_package_info(int cpu, FILE *outf) { char header[256]; @@ -156,7 +181,7 @@ static void _isst_pbf_display_information(int cpu, FILE *outf, int level, snprintf(header, sizeof(header), "speed-select-base-freq"); format_and_print(outf, disp_level, header, NULL); - snprintf(header, sizeof(header), "high-priority-base-frequency(KHz)"); + snprintf(header, sizeof(header), "high-priority-base-frequency(MHz)"); snprintf(value, sizeof(value), "%d", pbf_info->p1_high * DISP_FREQ_MULTIPLIER); format_and_print(outf, disp_level + 1, header, value); @@ -166,11 +191,20 @@ static void _isst_pbf_display_information(int cpu, FILE *outf, int level, pbf_info->core_cpumask); format_and_print(outf, disp_level + 1, header, value); - snprintf(header, sizeof(header), "low-priority-base-frequency(KHz)"); + snprintf(header, sizeof(header), "high-priority-cpu-list"); + printcpulist(sizeof(value), value, + pbf_info->core_cpumask_size, + pbf_info->core_cpumask); + format_and_print(outf, disp_level + 1, header, value); + + snprintf(header, sizeof(header), "low-priority-base-frequency(MHz)"); snprintf(value, sizeof(value), "%d", 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); @@ -209,7 +243,7 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level, if (fact_avx & 0x01) { snprintf(header, sizeof(header), - "high-priority-max-frequency(KHz)"); + "high-priority-max-frequency(MHz)"); snprintf(value, sizeof(value), "%d", bucket_info[j].sse_trl * DISP_FREQ_MULTIPLIER); format_and_print(outf, base_level + 2, header, value); @@ -217,7 +251,7 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level, if (fact_avx & 0x02) { snprintf(header, sizeof(header), - "high-priority-max-avx2-frequency(KHz)"); + "high-priority-max-avx2-frequency(MHz)"); snprintf(value, sizeof(value), "%d", bucket_info[j].avx_trl * DISP_FREQ_MULTIPLIER); format_and_print(outf, base_level + 2, header, value); @@ -225,7 +259,7 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level, if (fact_avx & 0x04) { snprintf(header, sizeof(header), - "high-priority-max-avx512-frequency(KHz)"); + "high-priority-max-avx512-frequency(MHz)"); snprintf(value, sizeof(value), "%d", bucket_info[j].avx512_trl * DISP_FREQ_MULTIPLIER); @@ -235,25 +269,45 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level, snprintf(header, sizeof(header), "speed-select-turbo-freq-clip-frequencies"); format_and_print(outf, base_level + 1, header, NULL); - snprintf(header, sizeof(header), "low-priority-max-frequency(KHz)"); + snprintf(header, sizeof(header), "low-priority-max-frequency(MHz)"); snprintf(value, sizeof(value), "%d", fact_info->lp_clipping_ratio_license_sse * DISP_FREQ_MULTIPLIER); format_and_print(outf, base_level + 2, header, value); snprintf(header, sizeof(header), - "low-priority-max-avx2-frequency(KHz)"); + "low-priority-max-avx2-frequency(MHz)"); snprintf(value, sizeof(value), "%d", fact_info->lp_clipping_ratio_license_avx2 * DISP_FREQ_MULTIPLIER); format_and_print(outf, base_level + 2, header, value); snprintf(header, sizeof(header), - "low-priority-max-avx512-frequency(KHz)"); + "low-priority-max-avx512-frequency(MHz)"); snprintf(value, sizeof(value), "%d", fact_info->lp_clipping_ratio_license_avx512 * DISP_FREQ_MULTIPLIER); format_and_print(outf, base_level + 2, header, value); } +void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix, + unsigned int val) +{ + char header[256]; + char value[256]; + + 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); + + snprintf(value, sizeof(value), "%u", val); + format_and_print(outf, 4, prefix, value); + + format_and_print(outf, 1, NULL, NULL); +} + void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, struct isst_pkg_ctdp *pkg_dev) { @@ -261,7 +315,8 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, char value[256]; int i, base_level = 1; - print_packag_info(cpu, outf); + if (pkg_dev->processed) + print_package_info(cpu, outf); for (i = 0; i <= pkg_dev->levels; ++i) { struct isst_pkg_ctdp_level_info *ctdp_level; @@ -281,48 +336,119 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, snprintf(value, sizeof(value), "%d", j); format_and_print(outf, base_level + 4, 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); + 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, base_level + 4, 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); + } 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); - snprintf(header, sizeof(header), "base-frequency(KHz)"); + 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); + ctdp_level->sse_p1 * DISP_FREQ_MULTIPLIER); format_and_print(outf, base_level + 4, header, value); - snprintf(header, sizeof(header), - "speed-select-turbo-freq-support"); - snprintf(value, sizeof(value), "%d", ctdp_level->fact_support); - format_and_print(outf, base_level + 4, 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, base_level + 4, 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, base_level + 4, 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, base_level + 4, 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, base_level + 4, 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, base_level + 4, header, value); + } snprintf(header, sizeof(header), - "speed-select-base-freq-support"); - snprintf(value, sizeof(value), "%d", ctdp_level->pbf_support); + "speed-select-turbo-freq"); + if (ctdp_level->fact_support) { + if (ctdp_level->fact_enabled) + snprintf(value, sizeof(value), "enabled"); + else + snprintf(value, sizeof(value), "disabled"); + } else + snprintf(value, sizeof(value), "unsupported"); format_and_print(outf, base_level + 4, header, value); snprintf(header, sizeof(header), - "speed-select-base-freq-enabled"); - snprintf(value, sizeof(value), "%d", ctdp_level->pbf_enabled); + "speed-select-base-freq"); + if (ctdp_level->pbf_support) { + if (ctdp_level->pbf_enabled) + snprintf(value, sizeof(value), "enabled"); + else + snprintf(value, sizeof(value), "disabled"); + } else + snprintf(value, sizeof(value), "unsupported"); format_and_print(outf, base_level + 4, header, value); snprintf(header, sizeof(header), - "speed-select-turbo-freq-enabled"); - snprintf(value, sizeof(value), "%d", ctdp_level->fact_enabled); + "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, base_level + 4, 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); + if (is_clx_n_platform()) { + if (ctdp_level->pbf_support) + _isst_pbf_display_information(cpu, outf, + tdp_level, + &ctdp_level->pbf_info, + base_level + 4); + continue; + } - 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 (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, base_level + 4, 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, base_level + 4, header, value); + } snprintf(header, sizeof(header), "turbo-ratio-limits-sse"); format_and_print(outf, base_level + 4, header, NULL); @@ -331,45 +457,51 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level, format_and_print(outf, base_level + 5, header, NULL); snprintf(header, sizeof(header), "core-count"); - snprintf(value, sizeof(value), "%d", j); + 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), "turbo-ratio"); + snprintf(header, sizeof(header), + "max-turbo-frequency(MHz)"); snprintf(value, sizeof(value), "%d", - ctdp_level->trl_sse_active_cores[j]); + 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), "%d", j); - format_and_print(outf, base_level + 6, header, value); + if (ctdp_level->trl_avx_active_cores[0]) { + snprintf(header, sizeof(header), "turbo-ratio-limits-avx2"); + 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), "turbo-ratio"); - snprintf(value, sizeof(value), "%d", - ctdp_level->trl_avx_active_cores[j]); - 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, 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); + } } - 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_512_active_cores[0]) { + 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); - snprintf(header, sizeof(header), "core-count"); - snprintf(value, sizeof(value), "%d", j); - 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, base_level + 6, header, value); - snprintf(header, sizeof(header), "turbo-ratio"); - snprintf(value, sizeof(value), "%d", - ctdp_level->trl_avx_512_active_cores[j]); + 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); + } } + if (ctdp_level->pbf_support) _isst_pbf_display_information(cpu, outf, i, &ctdp_level->pbf_info, @@ -397,7 +529,7 @@ void isst_ctdp_display_information_end(FILE *outf) void isst_pbf_display_information(int cpu, FILE *outf, int level, struct isst_pbf_info *pbf_info) { - print_packag_info(cpu, outf); + print_package_info(cpu, outf); _isst_pbf_display_information(cpu, outf, level, pbf_info, 4); format_and_print(outf, 1, NULL, NULL); } @@ -406,7 +538,7 @@ void isst_fact_display_information(int cpu, FILE *outf, int level, int fact_bucket, int fact_avx, struct isst_fact_info *fact_info) { - print_packag_info(cpu, outf); + print_package_info(cpu, outf); _isst_fact_display_information(cpu, outf, level, fact_bucket, fact_avx, fact_info, 4); format_and_print(outf, 1, NULL, NULL); @@ -442,22 +574,49 @@ void isst_clos_display_information(int cpu, FILE *outf, int clos, format_and_print(outf, 5, header, value); snprintf(header, sizeof(header), "clos-min"); - snprintf(value, sizeof(value), "%d", clos_config->clos_min); + snprintf(value, sizeof(value), "%d MHz", clos_config->clos_min * DISP_FREQ_MULTIPLIER); format_and_print(outf, 5, header, value); snprintf(header, sizeof(header), "clos-max"); - snprintf(value, sizeof(value), "%d", clos_config->clos_max); + snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * DISP_FREQ_MULTIPLIER); format_and_print(outf, 5, header, value); snprintf(header, sizeof(header), "clos-desired"); - snprintf(value, sizeof(value), "%d", clos_config->clos_desired); + snprintf(value, sizeof(value), "%d MHz", clos_config->clos_desired * DISP_FREQ_MULTIPLIER); format_and_print(outf, 5, header, value); format_and_print(outf, 1, NULL, NULL); } -void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd, - int result) +void isst_clos_display_clos_information(int cpu, FILE *outf, + int clos_enable, int type) +{ + char header[256]; + char value[256]; + + 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); + + snprintf(header, sizeof(header), "core-power"); + format_and_print(outf, 4, header, NULL); + + snprintf(header, sizeof(header), "enable-status"); + snprintf(value, sizeof(value), "%d", clos_enable); + format_and_print(outf, 5, header, value); + + snprintf(header, sizeof(header), "priority-type"); + snprintf(value, sizeof(value), "%d", type); + format_and_print(outf, 5, header, value); + + format_and_print(outf, 1, NULL, NULL); +} + +void isst_clos_display_assoc_information(int cpu, FILE *outf, int clos) { char header[256]; char value[256]; @@ -469,10 +628,39 @@ void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd, format_and_print(outf, 2, header, NULL); snprintf(header, sizeof(header), "cpu-%d", cpu); format_and_print(outf, 3, header, NULL); + + snprintf(header, sizeof(header), "get-assoc"); + format_and_print(outf, 4, header, NULL); + + snprintf(header, sizeof(header), "clos"); + snprintf(value, sizeof(value), "%d", clos); + format_and_print(outf, 5, header, value); + + format_and_print(outf, 1, NULL, NULL); +} + +void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd, + int result) +{ + char header[256]; + char value[256]; + + if (cpu >= 0) { + 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); + } snprintf(header, sizeof(header), "%s", feature); format_and_print(outf, 4, header, NULL); snprintf(header, sizeof(header), "%s", cmd); - snprintf(value, sizeof(value), "%d", result); + 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, 1, NULL, NULL); diff --git a/tools/power/x86/intel-speed-select/isst.h b/tools/power/x86/intel-speed-select/isst.h index 221881761609..ad5aa6341d0f 100644 --- a/tools/power/x86/intel-speed-select/isst.h +++ b/tools/power/x86/intel-speed-select/isst.h @@ -69,6 +69,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 +123,8 @@ struct isst_pkg_ctdp_level_info { 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; @@ -134,6 +142,7 @@ struct isst_pkg_ctdp_level_info { size_t core_cpumask_size; cpu_set_t *core_cpumask; int cpu_count; + unsigned long long buckets_info; int trl_sse_active_cores[ISST_TRL_MAX_ACTIVE_CORES]; int trl_avx_active_cores[ISST_TRL_MAX_ACTIVE_CORES]; int trl_avx_512_active_cores[ISST_TRL_MAX_ACTIVE_CORES]; @@ -160,6 +169,7 @@ struct isst_pkg_ctdp { extern int get_topo_max_cpus(void); extern int get_cpu_count(int pkg_id, int die_id); +extern int get_core_count(int pkg_id, int die_id); /* Common interfaces */ extern void debug_printf(const char *format, ...); @@ -186,12 +196,16 @@ extern int isst_send_msr_command(unsigned int cpu, unsigned int command, 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_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, struct isst_pkg_ctdp *pkg_dev); extern void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev); 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); 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, @@ -222,10 +236,16 @@ extern int isst_clos_associate(int cpu, int clos); extern int isst_clos_get_assoc_status(int cpu, int *clos_id); extern void isst_clos_display_information(int cpu, FILE *outf, int clos, struct isst_clos_config *clos_config); - +extern void isst_clos_display_assoc_information(int cpu, FILE *outf, int clos); extern int isst_read_reg(unsigned short reg, unsigned int *val); extern int isst_write_reg(int reg, unsigned int val); extern void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd, int result); + +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); +extern int is_clx_n_platform(void); +extern int get_cpufreq_base_freq(int cpu); #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 2d6d342b148f..256199c7a182 100755 --- a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py +++ b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py @@ -11,11 +11,11 @@ then this utility enables and collects trace data for a user specified interval and generates performance plots. Prerequisites: - Python version 2.7.x + Python version 2.7.x or higher gnuplot 5.0 or higher - gnuplot-py 1.8 + gnuplot-py 1.8 or higher (Most of the distributions have these required packages. They may be called - gnuplot-py, phython-gnuplot. ) + gnuplot-py, phython-gnuplot or phython3-gnuplot, gnuplot-nox, ... ) HWP (Hardware P-States are disabled) Kernel config for Linux trace is enabled @@ -104,7 +104,7 @@ def plot_perf_busy_with_sample(cpu_index): 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 @@ def plot_perf_busy(cpu_index): 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 @@ def plot_durations(cpu_index): 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,12 +174,12 @@ def plot_pstate_cpu_with_sample(): 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"') g_plot('set title "{} : cpu pstate vs. sample : {:%F %H:%M}"'.format(testname, datetime.now())) - title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ') + title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ') plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_SAMPLE, C_TO) g_plot('title_list = "{}"'.format(title_list)) g_plot(plot_str) @@ -191,14 +189,14 @@ def plot_pstate_cpu(): 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())) # the following command is really cool, but doesn't work with the CPU masking option because it aborts on the first missing file. # plot_str = 'plot for [i=0:*] file=sprintf("cpu%03d.csv",i) title_s=sprintf("cpu%03d",i) file using 16:7 pt 7 ps 1 title title_s' # - title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ') + title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ') plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_TO) g_plot('title_list = "{}"'.format(title_list)) g_plot(plot_str) @@ -212,7 +210,7 @@ def plot_load_cpu(): g_plot('set ylabel "CPU load (percent)"') g_plot('set title "{} : cpu loads : {:%F %H:%M}"'.format(testname, datetime.now())) - title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ') + title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ') plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_LOAD) g_plot('title_list = "{}"'.format(title_list)) g_plot(plot_str) @@ -222,11 +220,11 @@ def plot_frequency_cpu(): 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())) - title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ') + title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ') plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_FREQ) g_plot('title_list = "{}"'.format(title_list)) g_plot(plot_str) @@ -236,12 +234,12 @@ def plot_duration_cpu(): output_png = 'all_cpu_durations.png' g_plot = common_all_gnuplot_settings(output_png) - g_plot('set yrange [0:5000]') +# autoscale this one, no set y range g_plot('set ytics 0, 500') g_plot('set ylabel "Timer Duration (MilliSeconds)"') g_plot('set title "{} : cpu durations : {:%F %H:%M}"'.format(testname, datetime.now())) - title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ') + title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ') plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_DURATION) g_plot('title_list = "{}"'.format(title_list)) g_plot(plot_str) @@ -255,7 +253,7 @@ def plot_scaled_cpu(): g_plot('set ylabel "Scaled Busy (Unitless)"') g_plot('set title "{} : cpu scaled busy : {:%F %H:%M}"'.format(testname, datetime.now())) - title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ') + title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ') plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_SCALED) g_plot('title_list = "{}"'.format(title_list)) g_plot(plot_str) @@ -269,7 +267,7 @@ def plot_boost_cpu(): g_plot('set ylabel "CPU IO Boost (percent)"') g_plot('set title "{} : cpu io boost : {:%F %H:%M}"'.format(testname, datetime.now())) - title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ') + title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ') plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_BOOST) g_plot('title_list = "{}"'.format(title_list)) g_plot(plot_str) @@ -283,7 +281,7 @@ def plot_ghz_cpu(): g_plot('set ylabel "TSC Frequency (GHz)"') g_plot('set title "{} : cpu TSC Frequencies (Sanity check calculation) : {:%F %H:%M}"'.format(testname, datetime.now())) - title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ') + title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ') plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_GHZ) g_plot('title_list = "{}"'.format(title_list)) g_plot(plot_str) diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile index 045f5f7d68ab..13f1e8b9ac52 100644 --- a/tools/power/x86/turbostat/Makefile +++ b/tools/power/x86/turbostat/Makefile @@ -9,9 +9,10 @@ ifeq ("$(origin O)", "command line") endif turbostat : turbostat.c -override CFLAGS += -Wall -I../../../include +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_FORTIFY_SOURCE=2 %: %.c @mkdir -p $(BUILD_OUTPUT) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 75fc4fb9901c..31c1ca0bb3ee 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -39,7 +39,6 @@ FILE *outf; int *fd_percpu; struct timeval interval_tv = {5, 0}; struct timespec interval_ts = {5, 0}; -struct timespec one_msec = {0, 1000000}; unsigned int num_iterations; unsigned int debug; unsigned int quiet; @@ -60,6 +59,7 @@ unsigned int do_irtl_hsw; unsigned int units = 1000000; /* MHz etc */ unsigned int genuine_intel; unsigned int authentic_amd; +unsigned int hygon_genuine; unsigned int max_level, max_extended_level; unsigned int has_invariant_tsc; unsigned int do_nhm_platform_info; @@ -100,6 +100,7 @@ unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */ unsigned int has_misc_feature_control; unsigned int first_counter_read = 1; +int ignore_stdin; #define RAPL_PKG (1 << 0) /* 0x610 MSR_PKG_POWER_LIMIT */ @@ -166,6 +167,7 @@ size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size; struct thread_data { struct timeval tv_begin; struct timeval tv_end; + struct timeval tv_delta; unsigned long long tsc; unsigned long long aperf; unsigned long long mperf; @@ -506,6 +508,7 @@ unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAU unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC; #define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME) +#define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME) #define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME) #define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT) #define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT) @@ -849,7 +852,6 @@ int dump_counters(struct thread_data *t, struct core_data *c, outp += sprintf(outp, "pc8: %016llX\n", p->pc8); outp += sprintf(outp, "pc9: %016llX\n", p->pc9); outp += sprintf(outp, "pc10: %016llX\n", p->pc10); - 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); @@ -911,7 +913,7 @@ int format_counters(struct thread_data *t, struct core_data *c, if (DO_BIC(BIC_TOD)) outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec); - interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0; + interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec/1000000.0; tsc = t->tsc * tsc_tweak; @@ -1287,6 +1289,14 @@ delta_core(struct core_data *new, struct core_data *old) } } +int soft_c1_residency_display(int bic) +{ + if (!DO_BIC(BIC_CPU_c1) || use_c1_residency_msr) + return 0; + + return DO_BIC_READ(bic); +} + /* * old = new - old */ @@ -1309,6 +1319,7 @@ delta_thread(struct thread_data *new, struct thread_data *old, * over-write old w/ new so we can print end of interval values */ + timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta); old->tv_begin = new->tv_begin; old->tv_end = new->tv_end; @@ -1322,7 +1333,8 @@ delta_thread(struct thread_data *new, struct thread_data *old, old->c1 = new->c1 - old->c1; - if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) { + if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || + soft_c1_residency_display(BIC_Avg_MHz)) { if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) { old->aperf = new->aperf - old->aperf; old->mperf = new->mperf - old->mperf; @@ -1404,6 +1416,8 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data t->tv_begin.tv_usec = 0; t->tv_end.tv_sec = 0; t->tv_end.tv_usec = 0; + t->tv_delta.tv_sec = 0; + t->tv_delta.tv_usec = 0; t->tsc = 0; t->aperf = 0; @@ -1573,6 +1587,9 @@ void compute_average(struct thread_data *t, struct core_data *c, for_all_cpus(sum_counters, t, c, p); + /* Use the global time delta for the average. */ + average.threads.tv_delta = tv_delta; + average.threads.tsc /= topo.num_cpus; average.threads.aperf /= topo.num_cpus; average.threads.mperf /= topo.num_cpus; @@ -1714,7 +1731,7 @@ void get_apic_id(struct thread_data *t) if (!DO_BIC(BIC_X2APIC)) return; - if (authentic_amd) { + if (authentic_amd || hygon_genuine) { unsigned int topology_extensions; if (max_extended_level < 0x8000001e) @@ -1762,19 +1779,20 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) struct msr_counter *mp; int i; - gettimeofday(&t->tv_begin, (struct timezone *)NULL); - if (cpu_migrate(cpu)) { fprintf(outf, "Could not migrate to CPU %d\n", cpu); return -1; } + gettimeofday(&t->tv_begin, (struct timezone *)NULL); + if (first_counter_read) get_apic_id(t); retry: t->tsc = rdtsc(); /* we are running on local CPU of interest */ - if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) { + if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || + soft_c1_residency_display(BIC_Avg_MHz)) { unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time; /* @@ -1851,20 +1869,20 @@ retry: if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) goto done; - if (DO_BIC(BIC_CPU_c3)) { + if (DO_BIC(BIC_CPU_c3) || soft_c1_residency_display(BIC_CPU_c3)) { if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3)) return -6; } - if (DO_BIC(BIC_CPU_c6) && !do_knl_cstates) { + if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !do_knl_cstates) { if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6)) return -7; - } else if (do_knl_cstates) { + } else if (do_knl_cstates || soft_c1_residency_display(BIC_CPU_c6)) { if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6)) return -7; } - if (DO_BIC(BIC_CPU_c7)) + if (DO_BIC(BIC_CPU_c7) || soft_c1_residency_display(BIC_CPU_c7)) if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7)) return -8; @@ -2150,7 +2168,7 @@ int has_turbo_ratio_group_limits(int family, int model) switch (model) { case INTEL_FAM6_ATOM_GOLDMONT: case INTEL_FAM6_SKYLAKE_X: - case INTEL_FAM6_ATOM_GOLDMONT_X: + case INTEL_FAM6_ATOM_GOLDMONT_D: return 1; } return 0; @@ -2912,6 +2930,7 @@ int snapshot_cpu_lpi_us(void) if (retval != 1) { fprintf(stderr, "Disabling Low Power Idle CPU output\n"); BIC_NOT_PRESENT(BIC_CPU_LPI); + fclose(fp); return -1; } @@ -2938,6 +2957,7 @@ int snapshot_sys_lpi_us(void) if (retval != 1) { fprintf(stderr, "Disabling Low Power Idle System output\n"); BIC_NOT_PRESENT(BIC_SYS_LPI); + fclose(fp); return -1; } fclose(fp); @@ -2985,8 +3005,6 @@ static void signal_handler (int signal) fprintf(stderr, "SIGUSR1\n"); break; } - /* make sure this manually-invoked interval is at least 1ms long */ - nanosleep(&one_msec, NULL); } void setup_signal_handler(void) @@ -3005,29 +3023,38 @@ void setup_signal_handler(void) void do_sleep(void) { - struct timeval select_timeout; + struct timeval tout; + struct timespec rest; fd_set readfds; int retval; FD_ZERO(&readfds); FD_SET(0, &readfds); - if (!isatty(fileno(stdin))) { + if (ignore_stdin) { nanosleep(&interval_ts, NULL); return; } - select_timeout = interval_tv; - retval = select(1, &readfds, NULL, NULL, &select_timeout); + tout = interval_tv; + retval = select(1, &readfds, NULL, NULL, &tout); if (retval == 1) { switch (getc(stdin)) { case 'q': exit_requested = 1; break; + case EOF: + /* + * 'stdin' is a pipe closed on the other end. There + * won't be any further input. + */ + ignore_stdin = 1; + /* Sleep the rest of the time */ + rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000); + rest.tv_nsec = (tout.tv_usec % 1000000) * 1000; + nanosleep(&rest, NULL); } - /* make sure this manually-invoked interval is at least 1ms long */ - nanosleep(&one_msec, NULL); } } @@ -3207,14 +3234,15 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) pkg_cstate_limits = snb_pkg_cstate_limits; has_misc_feature_control = 1; break; - case INTEL_FAM6_HASWELL_CORE: /* HSW */ + case INTEL_FAM6_HASWELL: /* HSW */ + case INTEL_FAM6_HASWELL_G: /* HSW */ case INTEL_FAM6_HASWELL_X: /* HSX */ - case INTEL_FAM6_HASWELL_GT3E: /* HSW */ - case INTEL_FAM6_BROADWELL_CORE: /* BDW */ - case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ + case INTEL_FAM6_HASWELL_L: /* HSW */ + case INTEL_FAM6_BROADWELL: /* BDW */ + case INTEL_FAM6_BROADWELL_G: /* BDW */ case INTEL_FAM6_BROADWELL_X: /* BDX */ - case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ - case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ + case INTEL_FAM6_SKYLAKE_L: /* SKL */ + case INTEL_FAM6_CANNONLAKE_L: /* CNL */ pkg_cstate_limits = hsw_pkg_cstate_limits; has_misc_feature_control = 1; break; @@ -3224,7 +3252,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) break; case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ no_MSR_MISC_PWR_MGMT = 1; - case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */ + case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ pkg_cstate_limits = slv_pkg_cstate_limits; break; case INTEL_FAM6_ATOM_AIRMONT: /* AMT */ @@ -3236,7 +3264,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) break; case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: - case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ + case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ pkg_cstate_limits = glm_pkg_cstate_limits; break; default: @@ -3279,7 +3307,7 @@ int is_dnv(unsigned int family, unsigned int model) return 0; switch (model) { - case INTEL_FAM6_ATOM_GOLDMONT_X: + case INTEL_FAM6_ATOM_GOLDMONT_D: return 1; } return 0; @@ -3403,14 +3431,15 @@ int has_config_tdp(unsigned int family, unsigned int model) switch (model) { case INTEL_FAM6_IVYBRIDGE: /* IVB */ - case INTEL_FAM6_HASWELL_CORE: /* HSW */ + case INTEL_FAM6_HASWELL: /* HSW */ case INTEL_FAM6_HASWELL_X: /* HSX */ - case INTEL_FAM6_HASWELL_GT3E: /* HSW */ - case INTEL_FAM6_BROADWELL_CORE: /* BDW */ - case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ + case INTEL_FAM6_HASWELL_L: /* HSW */ + case INTEL_FAM6_HASWELL_G: /* HSW */ + case INTEL_FAM6_BROADWELL: /* BDW */ + case INTEL_FAM6_BROADWELL_G: /* BDW */ case INTEL_FAM6_BROADWELL_X: /* BDX */ - case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ - case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ + case INTEL_FAM6_SKYLAKE_L: /* SKL */ + case INTEL_FAM6_CANNONLAKE_L: /* CNL */ case INTEL_FAM6_SKYLAKE_X: /* SKX */ case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */ @@ -3792,7 +3821,7 @@ double get_tdp_intel(unsigned int model) switch (model) { case INTEL_FAM6_ATOM_SILVERMONT: - case INTEL_FAM6_ATOM_SILVERMONT_X: + case INTEL_FAM6_ATOM_SILVERMONT_D: return 30.0; default: return 135.0; @@ -3803,6 +3832,7 @@ 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; @@ -3840,10 +3870,11 @@ void rapl_probe_intel(unsigned int family, unsigned int model) switch (model) { case INTEL_FAM6_SANDYBRIDGE: case INTEL_FAM6_IVYBRIDGE: - case INTEL_FAM6_HASWELL_CORE: /* HSW */ - case INTEL_FAM6_HASWELL_GT3E: /* HSW */ - case INTEL_FAM6_BROADWELL_CORE: /* BDW */ - case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ + case INTEL_FAM6_HASWELL: /* HSW */ + case INTEL_FAM6_HASWELL_L: /* HSW */ + case INTEL_FAM6_HASWELL_G: /* HSW */ + case INTEL_FAM6_BROADWELL: /* BDW */ + case INTEL_FAM6_BROADWELL_G: /* BDW */ do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; if (rapl_joules) { BIC_PRESENT(BIC_Pkg_J); @@ -3863,8 +3894,8 @@ void rapl_probe_intel(unsigned int family, unsigned int model) else BIC_PRESENT(BIC_PkgWatt); break; - case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ - case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ + 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; BIC_PRESENT(BIC_PKG__); BIC_PRESENT(BIC_RAM__); @@ -3911,7 +3942,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) } break; case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ - case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */ + case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ do_rapl = RAPL_PKG | RAPL_CORES; if (rapl_joules) { BIC_PRESENT(BIC_Pkg_J); @@ -3921,7 +3952,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) BIC_PRESENT(BIC_CorWatt); } break; - case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ + case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS; BIC_PRESENT(BIC_PKG__); BIC_PRESENT(BIC_RAM__); @@ -3982,6 +4013,7 @@ void rapl_probe_amd(unsigned int family, unsigned int model) 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); @@ -4002,7 +4034,7 @@ void rapl_probe_amd(unsigned int family, unsigned int model) rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f)); rapl_power_units = ldexp(1.0, -(msr & 0xf)); - tdp = get_tdp_amd(model); + tdp = get_tdp_amd(family); rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; if (!quiet) @@ -4018,7 +4050,7 @@ void rapl_probe(unsigned int family, unsigned int model) { if (genuine_intel) rapl_probe_intel(family, model); - if (authentic_amd) + if (authentic_amd || hygon_genuine) rapl_probe_amd(family, model); } @@ -4031,8 +4063,9 @@ void perf_limit_reasons_probe(unsigned int family, unsigned int model) return; switch (model) { - case INTEL_FAM6_HASWELL_CORE: /* HSW */ - case INTEL_FAM6_HASWELL_GT3E: /* HSW */ + case INTEL_FAM6_HASWELL: /* HSW */ + case INTEL_FAM6_HASWELL_L: /* HSW */ + case INTEL_FAM6_HASWELL_G: /* HSW */ do_gfx_perf_limit_reasons = 1; case INTEL_FAM6_HASWELL_X: /* HSX */ do_core_perf_limit_reasons = 1; @@ -4247,27 +4280,28 @@ int has_snb_msrs(unsigned int family, unsigned int model) switch (model) { case INTEL_FAM6_SANDYBRIDGE: case INTEL_FAM6_SANDYBRIDGE_X: - case INTEL_FAM6_IVYBRIDGE: /* IVB */ - case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ - case INTEL_FAM6_HASWELL_CORE: /* HSW */ - case INTEL_FAM6_HASWELL_X: /* HSW */ - case INTEL_FAM6_HASWELL_GT3E: /* HSW */ - case INTEL_FAM6_BROADWELL_CORE: /* BDW */ - case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ - case INTEL_FAM6_BROADWELL_X: /* BDX */ - case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ - case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ - case INTEL_FAM6_SKYLAKE_X: /* SKX */ - case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ + case INTEL_FAM6_IVYBRIDGE: /* IVB */ + case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ + case INTEL_FAM6_HASWELL: /* HSW */ + case INTEL_FAM6_HASWELL_X: /* HSW */ + case INTEL_FAM6_HASWELL_L: /* HSW */ + case INTEL_FAM6_HASWELL_G: /* HSW */ + case INTEL_FAM6_BROADWELL: /* BDW */ + case INTEL_FAM6_BROADWELL_G: /* BDW */ + case INTEL_FAM6_BROADWELL_X: /* BDX */ + case INTEL_FAM6_SKYLAKE_L: /* SKL */ + case INTEL_FAM6_CANNONLAKE_L: /* CNL */ + case INTEL_FAM6_SKYLAKE_X: /* SKX */ + case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: - case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ + case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ return 1; } return 0; } /* - * HSW adds support for additional MSRs: + * HSW ULT added support for C8/C9/C10 MSRs: * * MSR_PKG_C8_RESIDENCY 0x00000630 * MSR_PKG_C9_RESIDENCY 0x00000631 @@ -4278,16 +4312,16 @@ int has_snb_msrs(unsigned int family, unsigned int model) * MSR_PKGC10_IRTL 0x00000635 * */ -int has_hsw_msrs(unsigned int family, unsigned int model) +int has_c8910_msrs(unsigned int family, unsigned int model) { if (!genuine_intel) return 0; switch (model) { - case INTEL_FAM6_HASWELL_CORE: - case INTEL_FAM6_BROADWELL_CORE: /* BDW */ - case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ - case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ + case INTEL_FAM6_HASWELL_L: /* HSW */ + case INTEL_FAM6_BROADWELL: /* BDW */ + case INTEL_FAM6_SKYLAKE_L: /* SKL */ + case INTEL_FAM6_CANNONLAKE_L: /* CNL */ case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: return 1; @@ -4309,8 +4343,8 @@ int has_skl_msrs(unsigned int family, unsigned int model) return 0; switch (model) { - case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ - case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ + case INTEL_FAM6_SKYLAKE_L: /* SKL */ + case INTEL_FAM6_CANNONLAKE_L: /* CNL */ return 1; } return 0; @@ -4322,7 +4356,7 @@ int is_slm(unsigned int family, unsigned int model) return 0; switch (model) { case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ - case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */ + case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ return 1; } return 0; @@ -4345,7 +4379,7 @@ int is_cnl(unsigned int family, unsigned int model) return 0; switch (model) { - case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */ + case INTEL_FAM6_CANNONLAKE_L: /* CNL */ return 1; } @@ -4465,10 +4499,10 @@ void decode_feature_control_msr(void) { 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" : ""); } @@ -4568,21 +4602,22 @@ unsigned int intel_model_duplicates(unsigned int model) case INTEL_FAM6_XEON_PHI_KNM: return INTEL_FAM6_XEON_PHI_KNL; - case INTEL_FAM6_HASWELL_ULT: - return INTEL_FAM6_HASWELL_CORE; - case INTEL_FAM6_BROADWELL_X: - case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */ + case INTEL_FAM6_BROADWELL_D: /* BDX-DE */ return INTEL_FAM6_BROADWELL_X; - case INTEL_FAM6_SKYLAKE_MOBILE: - case INTEL_FAM6_SKYLAKE_DESKTOP: - case INTEL_FAM6_KABYLAKE_MOBILE: - case INTEL_FAM6_KABYLAKE_DESKTOP: - return INTEL_FAM6_SKYLAKE_MOBILE; + case INTEL_FAM6_SKYLAKE_L: + case INTEL_FAM6_SKYLAKE: + case INTEL_FAM6_KABYLAKE_L: + case INTEL_FAM6_KABYLAKE: + return INTEL_FAM6_SKYLAKE_L; + + case INTEL_FAM6_ICELAKE_L: + case INTEL_FAM6_ICELAKE_NNPI: + return INTEL_FAM6_CANNONLAKE_L; - case INTEL_FAM6_ICELAKE_MOBILE: - return INTEL_FAM6_CANNONLAKE_MOBILE; + case INTEL_FAM6_ATOM_TREMONT_D: + return INTEL_FAM6_ATOM_GOLDMONT_D; } return model; } @@ -4600,6 +4635,8 @@ void process_cpuid() genuine_intel = 1; else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) authentic_amd = 1; + else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e) + hygon_genuine = 1; if (!quiet) fprintf(outf, "CPUID(0): %.4s%.4s%.4s ", @@ -4731,10 +4768,10 @@ void process_cpuid() if (crystal_hz == 0) switch(model) { - case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ + case INTEL_FAM6_SKYLAKE_L: /* SKL */ crystal_hz = 24000000; /* 24.0 MHz */ break; - case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */ + case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ crystal_hz = 25000000; /* 25.0 MHz */ break; case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ @@ -4820,12 +4857,12 @@ void process_cpuid() BIC_NOT_PRESENT(BIC_CPU_c7); BIC_NOT_PRESENT(BIC_Pkgpc7); } - if (has_hsw_msrs(family, model)) { + if (has_c8910_msrs(family, model)) { BIC_PRESENT(BIC_Pkgpc8); BIC_PRESENT(BIC_Pkgpc9); BIC_PRESENT(BIC_Pkgpc10); } - do_irtl_hsw = has_hsw_msrs(family, model); + do_irtl_hsw = has_c8910_msrs(family, model); if (has_skl_msrs(family, model)) { BIC_PRESENT(BIC_Totl_c0); BIC_PRESENT(BIC_Any_c0); @@ -5123,7 +5160,7 @@ int initialize_counters(int cpu_id) void allocate_output_buffer() { - output_buffer = calloc(1, (1 + topo.num_cpus) * 1024); + output_buffer = calloc(1, (1 + topo.num_cpus) * 2048); outp = output_buffer; if (outp == NULL) err(-1, "calloc output buffer"); @@ -5269,7 +5306,7 @@ int get_and_dump_counters(void) } void print_version() { - fprintf(outf, "turbostat version 19.03.20" + fprintf(outf, "turbostat version 19.08.31" " - Len Brown <lenb@kernel.org>\n"); } diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile index 1fdeef864e7c..666b325a62a2 100644 --- a/tools/power/x86/x86_energy_perf_policy/Makefile +++ b/tools/power/x86/x86_energy_perf_policy/Makefile @@ -9,8 +9,9 @@ ifeq ("$(origin O)", "command line") endif x86_energy_perf_policy : x86_energy_perf_policy.c -override CFLAGS += -Wall -I../../../include +override CFLAGS += -O2 -Wall -I../../../include override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"' +override CFLAGS += -D_FORTIFY_SOURCE=2 %: %.c @mkdir -p $(BUILD_OUTPUT) diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 index 17db1c3af4d0..78c6361898b1 100644 --- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 +++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 @@ -40,7 +40,7 @@ in the same processor package. Hardware P-States (HWP) are effectively an expansion of hardware P-state control from the opportunistic turbo-mode P-state range to include the entire range of available P-states. -On Broadwell Xeon, the initial HWP implementation, EBP influenced HWP. +On Broadwell Xeon, the initial HWP implementation, EPB influenced HWP. That influence was removed in subsequent generations, where it was moved to the Energy_Performance_Preference (EPP) field in 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 34a796b303fe..3fe1eed900d4 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 @@ -545,7 +545,7 @@ void cmdline(int argc, char **argv) progname = argv[0]; - while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw", + while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw:", long_options, &option_index)) != -1) { switch (opt) { case 'a': @@ -1259,6 +1259,15 @@ void probe_dev_msr(void) if (system("/sbin/modprobe msr > /dev/null 2>&1")) err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" "); } + +static void get_cpuid_or_exit(unsigned int leaf, + unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + if (!__get_cpuid(leaf, eax, ebx, ecx, edx)) + errx(1, "Processor not supported\n"); +} + /* * early_cpuid() * initialize turbo_is_enabled, has_hwp, has_epb @@ -1266,15 +1275,10 @@ void probe_dev_msr(void) */ void early_cpuid(void) { - unsigned int eax, ebx, ecx, edx, max_level; + unsigned int eax, ebx, ecx, edx; unsigned int fms, family, model; - __get_cpuid(0, &max_level, &ebx, &ecx, &edx); - - if (max_level < 6) - errx(1, "Processor not supported\n"); - - __get_cpuid(1, &fms, &ebx, &ecx, &edx); + get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx); family = (fms >> 8) & 0xf; model = (fms >> 4) & 0xf; if (family == 6 || family == 0xf) @@ -1288,7 +1292,7 @@ void early_cpuid(void) bdx_highest_ratio = msr & 0xFF; } - __get_cpuid(0x6, &eax, &ebx, &ecx, &edx); + get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx); turbo_is_enabled = (eax >> 1) & 1; has_hwp = (eax >> 7) & 1; has_epb = (ecx >> 3) & 1; @@ -1306,7 +1310,7 @@ void parse_cpuid(void) eax = ebx = ecx = edx = 0; - __get_cpuid(0, &max_level, &ebx, &ecx, &edx); + get_cpuid_or_exit(0, &max_level, &ebx, &ecx, &edx); if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) genuine_intel = 1; @@ -1315,7 +1319,7 @@ void parse_cpuid(void) fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", (char *)&ebx, (char *)&edx, (char *)&ecx); - __get_cpuid(1, &fms, &ebx, &ecx, &edx); + get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx); family = (fms >> 8) & 0xf; model = (fms >> 4) & 0xf; stepping = fms & 0xf; @@ -1340,7 +1344,7 @@ void parse_cpuid(void) errx(1, "CPUID: no MSR"); - __get_cpuid(0x6, &eax, &ebx, &ecx, &edx); + get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx); /* turbo_is_enabled already set */ /* has_hwp already set */ has_hwp_notify = eax & (1 << 8); |