diff options
Diffstat (limited to 'tools/power')
| -rw-r--r-- | tools/power/cpupower/man/cpupower-frequency-info.1 | 8 | ||||
| -rw-r--r-- | tools/power/cpupower/man/cpupower-idle-info.1 | 4 | ||||
| -rw-r--r-- | tools/power/cpupower/man/cpupower-info.1 | 9 | ||||
| -rw-r--r-- | tools/power/cpupower/utils/cpufreq-info.c | 2 | ||||
| -rw-r--r-- | tools/power/cpupower/utils/cpufreq-set.c | 2 | ||||
| -rw-r--r-- | tools/power/cpupower/utils/cpuidle-info.c | 2 | ||||
| -rw-r--r-- | tools/power/cpupower/utils/cpuidle-set.c | 2 | ||||
| -rw-r--r-- | tools/power/cpupower/utils/cpupower-info.c | 2 | ||||
| -rw-r--r-- | tools/power/cpupower/utils/cpupower-set.c | 2 | ||||
| -rw-r--r-- | tools/power/x86/intel-speed-select/isst-config.c | 41 | ||||
| -rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 319 | ||||
| -rw-r--r-- | tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 | 26 | ||||
| -rw-r--r-- | tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c | 399 |
13 files changed, 550 insertions, 268 deletions
diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1 index 47fdd7218748..b0d69c9adcbd 100644 --- a/tools/power/cpupower/man/cpupower-frequency-info.1 +++ b/tools/power/cpupower/man/cpupower-frequency-info.1 @@ -32,6 +32,12 @@ Gets the currently used cpufreq policy. \fB\-g\fR \fB\-\-governors\fR Determines available cpufreq governors. .TP +\fB\-b\fR \fB\-\-boost\fR +Gets the current boost state support. +.TP +\fB\-z\fR \fB\-\-epp\fR +Gets the current EPP (energy performance preference). +.TP \fB\-r\fR \fB\-\-related\-cpus\fR Determines which CPUs run at the same hardware frequency. .TP @@ -53,7 +59,7 @@ human\-readable output for the \-f, \-w, \-s and \-y parameters. \fB\-n\fR \fB\-\-no-rounding\fR Output frequencies and latencies without rounding off values. .TP -\fB\-c\fR \fB\-\-perf\fR +\fB\-c\fR \fB\-\-performance\fR Get performances and frequencies capabilities of CPPC, by reading it from hardware (only available on the hardware with CPPC). .TP .SH "REMARKS" diff --git a/tools/power/cpupower/man/cpupower-idle-info.1 b/tools/power/cpupower/man/cpupower-idle-info.1 index 20b6345c53ad..b2f92aba5f5b 100644 --- a/tools/power/cpupower/man/cpupower-idle-info.1 +++ b/tools/power/cpupower/man/cpupower-idle-info.1 @@ -11,10 +11,10 @@ A tool which prints out per cpu idle information helpful to developers and inter .SH "OPTIONS" .LP .TP -\fB\-f\fR \fB\-\-silent\fR +\fB\-s\fR \fB\-\-silent\fR Only print a summary of all available C-states in the system. .TP -\fB\-e\fR \fB\-\-proc\fR +\fB\-o\fR \fB\-\-proc\fR deprecated. Prints out idle information in old /proc/acpi/processor/*/power format. This interface has been removed from the kernel for quite some time, do not let diff --git a/tools/power/cpupower/man/cpupower-info.1 b/tools/power/cpupower/man/cpupower-info.1 index 340bcd0be7de..1f42d8c388a0 100644 --- a/tools/power/cpupower/man/cpupower-info.1 +++ b/tools/power/cpupower/man/cpupower-info.1 @@ -3,7 +3,7 @@ cpupower\-info \- Shows processor power related kernel or hardware configurations .SH SYNOPSIS .ft B -.B cpupower info [ \-b ] +.B cpupower info [\fIoptions\fP] .SH DESCRIPTION \fBcpupower info \fP shows kernel configurations or processor hardware @@ -13,6 +13,13 @@ Some options are platform wide, some affect single cores. By default values of core zero are displayed only. cpupower --cpu all cpuinfo will show the settings of all cores, see cpupower(1) how to choose specific cores. +.SH "OPTIONS" +.LP +.TP +\fB\-b\fR \fB\-\-perf-bias\fR +Gets the current performance bias value. +.TP + .SH "SEE ALSO" Options are described in detail in: diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c index 5fe01e516817..5a242b491a9d 100644 --- a/tools/power/cpupower/utils/cpufreq-info.c +++ b/tools/power/cpupower/utils/cpufreq-info.c @@ -542,8 +542,6 @@ static struct option info_opts[] = { int cmd_freq_info(int argc, char **argv) { - extern char *optarg; - extern int optind, opterr, optopt; int ret = 0, cont = 1; unsigned int cpu = 0; unsigned int human = 0; diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c index c5e60a39cfa6..06cd4b280132 100644 --- a/tools/power/cpupower/utils/cpufreq-set.c +++ b/tools/power/cpupower/utils/cpufreq-set.c @@ -195,8 +195,6 @@ static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol, int cmd_freq_set(int argc, char **argv) { - extern char *optarg; - extern int optind, opterr, optopt; int ret = 0, cont = 1; int double_parm = 0, related = 0, policychange = 0; unsigned long freq = 0; diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c index 81b4763a97d6..ccb37125bd37 100644 --- a/tools/power/cpupower/utils/cpuidle-info.c +++ b/tools/power/cpupower/utils/cpuidle-info.c @@ -139,8 +139,6 @@ static inline void cpuidle_exit(int fail) int cmd_idle_info(int argc, char **argv) { - extern char *optarg; - extern int optind, opterr, optopt; int ret = 0, cont = 1, output_param = 0, verbose = 1; unsigned int cpu = 0; diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c index a551d1d4ac51..703094f1343c 100644 --- a/tools/power/cpupower/utils/cpuidle-set.c +++ b/tools/power/cpupower/utils/cpuidle-set.c @@ -24,8 +24,6 @@ static struct option info_opts[] = { int cmd_idle_set(int argc, char **argv) { - extern char *optarg; - extern int optind, opterr, optopt; int ret = 0, cont = 1, param = 0, disabled; unsigned long long latency = 0, state_latency; unsigned int cpu = 0, idlestate = 0, idlestates = 0; diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c index 18fd7751f509..79154d71e498 100644 --- a/tools/power/cpupower/utils/cpupower-info.c +++ b/tools/power/cpupower/utils/cpupower-info.c @@ -28,8 +28,6 @@ static void print_wrong_arg_exit(void) int cmd_info(int argc, char **argv) { - extern char *optarg; - extern int optind, opterr, optopt; unsigned int cpu; struct utsname uts; diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c index 550a942e72ce..c2176b9fa57d 100644 --- a/tools/power/cpupower/utils/cpupower-set.c +++ b/tools/power/cpupower/utils/cpupower-set.c @@ -33,8 +33,6 @@ static void print_wrong_arg_exit(void) int cmd_set(int argc, char **argv) { - extern char *optarg; - extern int optind, opterr, optopt; unsigned int cpu; struct utsname uts; diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c index dd9056ddb016..2faff1aead52 100644 --- a/tools/power/x86/intel-speed-select/isst-config.c +++ b/tools/power/x86/intel-speed-select/isst-config.c @@ -16,7 +16,7 @@ struct process_cmd_struct { int arg; }; -static const char *version_str = "v1.25"; +static const char *version_str = "v1.26"; static const int supported_api_ver = 3; static struct isst_if_platform_info isst_platform_info; @@ -26,7 +26,7 @@ static FILE *outf; static int cpu_model; static int cpu_stepping; -static int extended_family; +static int cpu_family; #define MAX_CPUS_IN_ONE_REQ 512 static short max_target_cpus; @@ -82,6 +82,11 @@ struct cpu_topology { static int read_only; +static void print_version(void) +{ + fprintf(outf, "Version %s\n", version_str); +} + static void check_privilege(void) { if (!read_only) @@ -158,7 +163,7 @@ int is_icx_platform(void) static int is_dmr_plus_platform(void) { - if (extended_family == 0x04) + if (cpu_family == 19) return 1; return 0; @@ -167,13 +172,14 @@ static int is_dmr_plus_platform(void) static int update_cpu_model(void) { unsigned int ebx, ecx, edx; - unsigned int fms, family; + unsigned int fms; __cpuid(1, fms, ebx, ecx, edx); - family = (fms >> 8) & 0xf; - extended_family = (fms >> 20) & 0x0f; + cpu_family = (fms >> 8) & 0xf; + if (cpu_family == 0xf) + cpu_family += (fms >> 20) & 0xff; cpu_model = (fms >> 4) & 0xf; - if (family == 6 || family == 0xf) + if (cpu_family == 6 || cpu_family == 0xf) cpu_model += ((fms >> 16) & 0xf) << 4; cpu_stepping = fms & 0xf; @@ -1137,8 +1143,9 @@ static int isst_fill_platform_info(void) close(fd); if (isst_platform_info.api_version > supported_api_ver) { + print_version(); printf("Incompatible API versions; Upgrade of tool is required\n"); - return -1; + exit(1); } set_platform_ops: @@ -1744,6 +1751,9 @@ static int no_turbo(void) return parse_int_file(0, "/sys/devices/system/cpu/intel_pstate/no_turbo"); } +#define U32_MAX ((unsigned int)~0U) +#define S32_MAX ((int)(U32_MAX >> 1)) + static void adjust_scaling_max_from_base_freq(int cpu) { int base_freq, scaling_max_freq; @@ -1751,7 +1761,7 @@ static void adjust_scaling_max_from_base_freq(int cpu) scaling_max_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu); base_freq = get_cpufreq_base_freq(cpu); if (scaling_max_freq < base_freq || no_turbo()) - set_cpufreq_scaling_min_max(cpu, 1, base_freq); + set_cpufreq_scaling_min_max(cpu, 1, S32_MAX); } static void adjust_scaling_min_from_base_freq(int cpu) @@ -3191,12 +3201,6 @@ static void usage(void) printf("\tTo get full turbo-freq information dump:\n"); printf("\t\tintel-speed-select turbo-freq info -l 0\n"); } - exit(1); -} - -static void print_version(void) -{ - fprintf(outf, "Version %s\n", version_str); exit(0); } @@ -3246,8 +3250,10 @@ static void cmdline(int argc, char **argv) } ret = update_cpu_model(); - if (ret) - err(-1, "Invalid CPU model (%d)\n", cpu_model); + if (ret) { + fprintf(stderr, "Invalid CPU model (%d)\n", cpu_model); + exit(1); + } printf("Intel(R) Speed Select Technology\n"); printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model); @@ -3311,6 +3317,7 @@ static void cmdline(int argc, char **argv) break; case 'v': print_version(); + exit(0); break; case 'b': oob_mode = 1; diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 1a2671c28209..920694c3c1ec 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -191,6 +191,7 @@ struct msr_counter bic[] = { { 0x0, "Any%C0", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "GFX%C0", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "CPUGFX%", NULL, 0, 0, 0, NULL, 0 }, + { 0x0, "Module", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "Core", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "CPU", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "APIC", NULL, 0, 0, 0, NULL, 0 }, @@ -264,6 +265,7 @@ enum bic_names { BIC_Any_c0, BIC_GFX_c0, BIC_CPUGFX, + BIC_Module, BIC_Core, BIC_CPU, BIC_APIC, @@ -364,6 +366,7 @@ static void bic_groups_init(void) SET_BIC(BIC_Node, &bic_group_topology); SET_BIC(BIC_CoreCnt, &bic_group_topology); SET_BIC(BIC_PkgCnt, &bic_group_topology); + SET_BIC(BIC_Module, &bic_group_topology); SET_BIC(BIC_Core, &bic_group_topology); SET_BIC(BIC_CPU, &bic_group_topology); SET_BIC(BIC_Die, &bic_group_topology); @@ -2383,6 +2386,7 @@ struct platform_counters { struct cpu_topology { int cpu_id; int core_id; /* unique within a package */ + int module_id; int package_id; int die_id; int l3_id; @@ -2404,12 +2408,14 @@ struct topo_params { int allowed_cores; int max_cpu_num; int max_core_id; /* within a package */ + int min_module_id; /* system wide */ + int max_module_id; /* system wide */ int max_package_id; int max_die_id; int max_l3_id; int max_node_num; int nodes_per_pkg; - int cores_per_node; + int cores_per_pkg; int threads_per_core; } topo; @@ -2427,11 +2433,17 @@ char *sys_lpi_file_debugfs = "/sys/kernel/debug/pmc_core/slp_s0_residency_usec"; int cpu_is_not_present(int cpu) { + if (cpu < 0) + return 1; + return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set); } int cpu_is_not_allowed(int cpu) { + if (cpu < 0) + return 1; + return !CPU_ISSET_S(cpu, cpu_allowed_setsize, cpu_allowed_set); } @@ -2443,6 +2455,22 @@ int cpu_is_not_allowed(int cpu) #define PER_THREAD_PARAMS struct thread_data *t, struct core_data *c, struct pkg_data *p +int has_allowed_lower_ht_sibling(int cpu) +{ + int i; + + for (i = 0; i <= cpus[cpu].ht_id; ++i) { + int sibling_cpu_id = cpus[cpu].ht_sibling_cpu_id[i]; + + if (sibling_cpu_id == cpu) + return 0; + + if (!cpu_is_not_allowed(sibling_cpu_id)) + return 1; + } + return 0; +} + int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pkg_data *), struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base) { @@ -2460,7 +2488,7 @@ int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pk if (cpu_is_not_allowed(cpu)) continue; - if (cpus[cpu].ht_id > 0) /* skip HT sibling */ + if (has_allowed_lower_ht_sibling(cpu)) /* skip HT sibling */ continue; t = &thread_base[cpu]; @@ -2469,13 +2497,22 @@ int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pk retval |= func(t, c, p); - /* Handle HT sibling now */ + /* Handle other HT siblings now */ int i; - for (i = MAX_HT_ID; i > 0; --i) { /* ht_id 0 is self */ - if (cpus[cpu].ht_sibling_cpu_id[i] <= 0) + for (i = 0; i <= MAX_HT_ID; ++i) { + int sibling_cpu_id = cpus[cpu].ht_sibling_cpu_id[i]; + + if (sibling_cpu_id < 0) + break; + + if (sibling_cpu_id == cpu) continue; - t = &thread_base[cpus[cpu].ht_sibling_cpu_id[i]]; + + if (cpu_is_not_allowed(sibling_cpu_id)) + continue; + + t = &thread_base[sibling_cpu_id]; retval |= func(t, c, p); } @@ -2835,32 +2872,38 @@ void bic_lookup(cpu_set_t *ret_set, char *name_list, enum show_hide_mode mode) static inline int print_name(int width, int *printed, char *delim, char *name, enum counter_type type, enum counter_format format) { UNUSED(type); + char *sep = (*printed)++ ? delim : ""; if (format == FORMAT_RAW && width >= 64) - return (sprintf(outp, "%s%-8s", (*printed++ ? delim : ""), name)); + return sprintf(outp, "%s%-8s", sep, name); else - return (sprintf(outp, "%s%s", (*printed++ ? delim : ""), name)); + return sprintf(outp, "%s%s", sep, name); } static inline int print_hex_value(int width, int *printed, char *delim, unsigned long long value) { + char *sep = (*printed)++ ? delim : ""; + if (width <= 32) - return (sprintf(outp, "%s%08x", (*printed++ ? delim : ""), (unsigned int)value)); + return sprintf(outp, "%s%08llx", sep, value); else - return (sprintf(outp, "%s%016llx", (*printed++ ? delim : ""), value)); + return sprintf(outp, "%s%016llx", sep, value); } static inline int print_decimal_value(int width, int *printed, char *delim, unsigned long long value) { - if (width <= 32) - return (sprintf(outp, "%s%d", (*printed++ ? delim : ""), (unsigned int)value)); - else - return (sprintf(outp, "%s%-8lld", (*printed++ ? delim : ""), value)); + char *sep = (*printed)++ ? delim : ""; + + UNUSED(width); + + return sprintf(outp, "%s%lld", sep, value); } static inline int print_float_value(int *printed, char *delim, double value) { - return (sprintf(outp, "%s%0.2f", (*printed++ ? delim : ""), value)); + char *sep = (*printed)++ ? delim : ""; + + return sprintf(outp, "%s%0.2f", sep, value); } void print_header(char *delim) @@ -2882,6 +2925,8 @@ void print_header(char *delim) outp += sprintf(outp, "%sL3", (printed++ ? delim : "")); if (DO_BIC(BIC_Node)) outp += sprintf(outp, "%sNode", (printed++ ? delim : "")); + if (DO_BIC(BIC_Module)) + outp += sprintf(outp, "%sModule", (printed++ ? delim : "")); if (DO_BIC(BIC_Core)) outp += sprintf(outp, "%sCore", (printed++ ? delim : "")); if (DO_BIC(BIC_CPU)) @@ -3177,7 +3222,7 @@ int dump_counters(PER_THREAD_PARAMS) } if (c && is_cpu_first_thread_in_core(t, c)) { - outp += sprintf(outp, "core: %d\n", cpus[t->cpu_id].core_id); + outp += sprintf(outp, "core: 0x%x\n", cpus[t->cpu_id].core_id); outp += sprintf(outp, "c3: %016llX\n", c->c3); outp += sprintf(outp, "c6: %016llX\n", c->c6); outp += sprintf(outp, "c7: %016llX\n", c->c7); @@ -3351,6 +3396,8 @@ int format_counters(PER_THREAD_PARAMS) outp += sprintf(outp, "%s-", (printed++ ? delim : "")); if (DO_BIC(BIC_Node)) outp += sprintf(outp, "%s-", (printed++ ? delim : "")); + if (DO_BIC(BIC_Module)) + outp += sprintf(outp, "%s-", (printed++ ? delim : "")); if (DO_BIC(BIC_Core)) outp += sprintf(outp, "%s-", (printed++ ? delim : "")); if (DO_BIC(BIC_CPU)) @@ -3384,18 +3431,24 @@ int format_counters(PER_THREAD_PARAMS) else outp += sprintf(outp, "%s-", (printed++ ? delim : "")); } + if (DO_BIC(BIC_Module)) { + if (c) + outp += sprintf(outp, "%s0x%x", (printed++ ? delim : ""), cpus[t->cpu_id].module_id); + else + outp += sprintf(outp, "%s-", (printed++ ? delim : "")); + } if (DO_BIC(BIC_Core)) { if (c) - outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].core_id); + outp += sprintf(outp, "%s0x%x", (printed++ ? delim : ""), cpus[t->cpu_id].core_id); else outp += sprintf(outp, "%s-", (printed++ ? delim : "")); } if (DO_BIC(BIC_CPU)) outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id); if (DO_BIC(BIC_APIC)) - outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->apic_id); + outp += sprintf(outp, "%s0x%x", (printed++ ? delim : ""), t->apic_id); if (DO_BIC(BIC_X2APIC)) - outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->x2apic_id); + outp += sprintf(outp, "%s0x%x", (printed++ ? delim : ""), t->x2apic_id); } if (DO_BIC(BIC_Avg_MHz)) @@ -3469,7 +3522,7 @@ int format_counters(PER_THREAD_PARAMS) for (i = 0, pp = sys.perf_tp; pp; ++i, pp = pp->next) { if (pp->format == FORMAT_RAW) outp += print_hex_value(pp->width, &printed, delim, t->perf_counter[i]); - else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE) + else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE) outp += print_decimal_value(pp->width, &printed, delim, t->perf_counter[i]); else if (pp->format == FORMAT_PERCENT) { if (pp->type == COUNTER_USEC) @@ -3490,12 +3543,12 @@ int format_counters(PER_THREAD_PARAMS) case PMT_TYPE_XTAL_TIME: value_converted = pct(value_raw / crystal_hz, interval_float); - outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted); + outp += print_float_value(&printed, delim, value_converted); break; case PMT_TYPE_TCORE_CLOCK: value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float); - outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted); + outp += print_float_value(&printed, delim, value_converted); } } @@ -3539,7 +3592,7 @@ int format_counters(PER_THREAD_PARAMS) for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) { if (pp->format == FORMAT_RAW) outp += print_hex_value(pp->width, &printed, delim, c->perf_counter[i]); - else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE) + else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE) outp += print_decimal_value(pp->width, &printed, delim, c->perf_counter[i]); else if (pp->format == FORMAT_PERCENT) outp += print_float_value(&printed, delim, pct(c->perf_counter[i], tsc)); @@ -3695,7 +3748,7 @@ int format_counters(PER_THREAD_PARAMS) outp += print_hex_value(pp->width, &printed, delim, p->perf_counter[i]); else if (pp->type == COUNTER_K2M) outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), (unsigned int)p->perf_counter[i] / 1000); - else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE) + else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE) outp += print_decimal_value(pp->width, &printed, delim, p->perf_counter[i]); else if (pp->format == FORMAT_PERCENT) outp += print_float_value(&printed, delim, pct(p->perf_counter[i], tsc)); @@ -5156,7 +5209,7 @@ static inline int get_rapl_num_domains(void) if (!platform->has_per_core_rapl) return topo.num_packages; - return topo.num_cores; + return GLOBAL_CORE_ID(topo.max_core_id, topo.num_packages) + 1; } static inline int get_rapl_domain_id(int cpu) @@ -6042,6 +6095,11 @@ int get_l3_id(int cpu) return parse_int_file("/sys/devices/system/cpu/cpu%d/cache/index3/id", cpu); } +int get_module_id(int cpu) +{ + return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/cluster_id", cpu); +} + int get_core_id(int cpu) { return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); @@ -6161,59 +6219,6 @@ static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size) return 0; } -int set_thread_siblings(struct cpu_topology *thiscpu) -{ - char path[80], character; - FILE *filep; - unsigned long map; - int so, shift, sib_core; - int cpu = thiscpu->cpu_id; - int offset = topo.max_cpu_num + 1; - size_t size; - int thread_id = 0; - - thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1)); - if (thiscpu->ht_id < 0) - thiscpu->ht_id = thread_id++; - if (!thiscpu->put_ids) - return -1; - - size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); - CPU_ZERO_S(size, thiscpu->put_ids); - - sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu); - filep = fopen(path, "r"); - - if (!filep) { - warnx("%s: open failed", path); - return -1; - } - do { - offset -= BITMASK_SIZE; - if (fscanf(filep, "%lx%c", &map, &character) != 2) - err(1, "%s: failed to parse file", path); - for (shift = 0; shift < BITMASK_SIZE; shift++) { - if ((map >> shift) & 0x1) { - so = shift + offset; - sib_core = get_core_id(so); - if (sib_core == thiscpu->core_id) { - CPU_SET_S(so, size, thiscpu->put_ids); - if ((so != cpu) && (cpus[so].ht_id < 0)) { - cpus[so].ht_id = thread_id; - cpus[cpu].ht_sibling_cpu_id[thread_id] = so; - if (debug) - fprintf(stderr, "%s: cpu%d.ht_sibling_cpu_id[%d] = %d\n", __func__, cpu, thread_id, so); - thread_id += 1; - } - } - } - } - } while (character == ','); - fclose(filep); - - return CPU_COUNT_S(size, thiscpu->put_ids); -} - /* * run func(thread, core, package) in topology order * skip non-present cpus @@ -6237,7 +6242,7 @@ int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *, if (cpu_is_not_allowed(cpu)) continue; - if (cpus[cpu].ht_id > 0) /* skip HT sibling */ + if (has_allowed_lower_ht_sibling(cpu)) /* skip HT sibling */ continue; t = &thread_base[cpu]; @@ -6252,11 +6257,20 @@ int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *, /* Handle HT sibling now */ int i; - for (i = MAX_HT_ID; i > 0; --i) { /* ht_id 0 is self */ - if (cpus[cpu].ht_sibling_cpu_id[i] <= 0) + for (i = 0; i <= MAX_HT_ID; ++i) { + int sibling_cpu_id = cpus[cpu].ht_sibling_cpu_id[i]; + + if (sibling_cpu_id < 0) + break; + + if (sibling_cpu_id == cpu) + continue; + + if (cpu_is_not_allowed(sibling_cpu_id)) continue; - t = &thread_base[cpus[cpu].ht_sibling_cpu_id[i]]; - t2 = &thread_base2[cpus[cpu].ht_sibling_cpu_id[i]]; + + t = &thread_base[sibling_cpu_id]; + t2 = &thread_base2[sibling_cpu_id]; retval |= func(t, c, p, t2, c2, p2); } @@ -9122,10 +9136,13 @@ void process_cpuid() cpuid_has_hv = ecx_flags & (1 << 31); if (!no_msr) { - if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) + if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) { warnx("get_msr(UCODE)"); - else + } else { ucode_patch_valid = true; + if (!authentic_amd && !hygon_genuine) + ucode_patch >>= 32; + } } /* @@ -9139,7 +9156,7 @@ void process_cpuid() if (!quiet) { fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)", family, model, stepping, family, model, stepping); if (ucode_patch_valid) - fprintf(outf, " microcode 0x%x", (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF)); + fprintf(outf, " microcode 0x%x", (unsigned int)ucode_patch); fputc('\n', outf); fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level); @@ -9403,13 +9420,13 @@ void perf_l2_init(void) if (!is_hybrid) { fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP); if (fd_l2_percpu[cpu] == -1) { - err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.refs); + warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.refs); free_fd_l2_percpu(); return; } retval = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP); if (retval == -1) { - err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.hits); + warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.hits); free_fd_l2_percpu(); return; } @@ -9418,39 +9435,39 @@ void perf_l2_init(void) if (perf_pcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_pcore_set)) { fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP); if (fd_l2_percpu[cpu] == -1) { - err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs); + warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs); free_fd_l2_percpu(); return; } retval = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP); if (retval == -1) { - err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.hits); + warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.hits); free_fd_l2_percpu(); return; } } else if (perf_ecore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_ecore_set)) { fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.refs, -1, PERF_FORMAT_GROUP); if (fd_l2_percpu[cpu] == -1) { - err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.refs); + warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.ecore, perf_model_support->second.refs); free_fd_l2_percpu(); return; } retval = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP); if (retval == -1) { - err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.hits); + warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.ecore, perf_model_support->second.hits); free_fd_l2_percpu(); return; } } else if (perf_lcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_lcore_set)) { fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.refs, -1, PERF_FORMAT_GROUP); if (fd_l2_percpu[cpu] == -1) { - err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.refs); + warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.lcore, perf_model_support->third.refs); free_fd_l2_percpu(); return; } retval = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP); if (retval == -1) { - err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.hits); + warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.lcore, perf_model_support->third.hits); free_fd_l2_percpu(); return; } @@ -9473,6 +9490,37 @@ int dir_filter(const struct dirent *dirp) return 0; } +int set_thread_siblings(struct cpu_topology *thiscpu) +{ + char path[80]; + int cpu = thiscpu->cpu_id; + size_t size; + int ht_id = 0; + int i; + + thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1)); + if (thiscpu->ht_id < 0) + thiscpu->ht_id = 0; /* first CPU in core */ + if (!thiscpu->put_ids) + return -1; + + size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); + CPU_ZERO_S(size, thiscpu->put_ids); + + sprintf(path, "/sys/devices/system/cpu/cpu%d/topology", cpu); + + initialize_cpu_set_from_sysfs(thiscpu->put_ids, path, "thread_siblings_list"); + + for (i = 0; i <= topo.max_cpu_num; ++i) + if (CPU_ISSET_S(i, size, thiscpu->put_ids)) { + cpus[i].ht_id = ht_id; + cpus[cpu].ht_sibling_cpu_id[ht_id] = i; + ht_id += 1; + } + + return (ht_id - 1); +} + void topology_probe(bool startup) { int i; @@ -9503,6 +9551,8 @@ void topology_probe(bool startup) cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); CPU_ZERO_S(cpu_present_setsize, cpu_present_set); for_all_proc_cpus(mark_cpu_present); + if (debug) + print_cpu_set("present set", cpu_present_set); /* * Allocate and initialize cpu_possible_set @@ -9513,6 +9563,8 @@ void topology_probe(bool startup) cpu_possible_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); CPU_ZERO_S(cpu_possible_setsize, cpu_possible_set); initialize_cpu_set_from_sysfs(cpu_possible_set, "/sys/devices/system/cpu", "possible"); + if (debug) + print_cpu_set("possible set", cpu_possible_set); /* * Allocate and initialize cpu_effective_set @@ -9523,6 +9575,8 @@ void topology_probe(bool startup) cpu_effective_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); CPU_ZERO_S(cpu_effective_setsize, cpu_effective_set); update_effective_set(startup); + if (debug) + print_cpu_set("effective set", cpu_effective_set); /* * Allocate and initialize cpu_allowed_set @@ -9566,6 +9620,8 @@ void topology_probe(bool startup) CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); } + if (debug) + print_cpu_set("allowed set", cpu_allowed_set); if (!CPU_COUNT_S(cpu_allowed_setsize, cpu_allowed_set)) err(-ENODEV, "No valid cpus found"); @@ -9588,6 +9644,7 @@ void topology_probe(bool startup) * For online cpus * find max_core_id, max_package_id, num_cores (per system) */ + topo.min_module_id = 0x7FFFFFFF; for (i = 0; i <= topo.max_cpu_num; ++i) { int siblings; @@ -9619,6 +9676,13 @@ void topology_probe(bool startup) if (cpus[i].physical_node_id > topo.max_node_num) topo.max_node_num = cpus[i].physical_node_id; + /* get module information */ + cpus[i].module_id = get_module_id(i); + if (cpus[i].module_id > topo.max_module_id) + topo.max_module_id = cpus[i].module_id; + if (cpus[i].module_id < topo.min_module_id) + topo.min_module_id = cpus[i].module_id; + /* get core information */ cpus[i].core_id = get_core_id(i); if (cpus[i].core_id > max_core_id) @@ -9634,12 +9698,17 @@ void topology_probe(bool startup) topo.max_core_id = max_core_id; /* within a package */ topo.max_package_id = max_package_id; - topo.cores_per_node = max_core_id + 1; + topo.cores_per_pkg = max_core_id + 1; if (debug > 1) - fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node); + fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_pkg); if (!summary_only) BIC_PRESENT(BIC_Core); + if (debug > 1) + fprintf(outf, "min_module_id %d max_module_id %d\n", topo.min_module_id, topo.max_module_id); + if (!summary_only && (topo.min_module_id != topo.max_module_id)) + BIC_PRESENT(BIC_Module); + topo.num_die = topo.max_die_id + 1; if (debug > 1) fprintf(outf, "max_die_id %d, sizing for %d die\n", topo.max_die_id, topo.num_die); @@ -9669,12 +9738,18 @@ void topology_probe(bool startup) return; for (i = 0; i <= topo.max_cpu_num; ++i) { + int ht_id; + if (cpu_is_not_present(i)) continue; fprintf(outf, - "cpu %d pkg %d die %d l3 %d node %d lnode %d core %d thread %d\n", + "cpu %d pkg %d die %d l3 %d node %d lnode %d module 0x%x core %d ht_id %d", i, cpus[i].package_id, cpus[i].die_id, cpus[i].l3_id, - cpus[i].physical_node_id, cpus[i].logical_node_id, cpus[i].core_id, cpus[i].ht_id); + cpus[i].physical_node_id, cpus[i].logical_node_id, cpus[i].module_id, cpus[i].core_id, cpus[i].ht_id); + fprintf(outf, " siblings"); + for (ht_id = 0; ht_id <= MAX_HT_ID; ++ht_id) + fprintf(outf, " %d", cpus[i].ht_sibling_cpu_id[ht_id]); + fprintf(outf, "\n"); } } @@ -9701,14 +9776,13 @@ error: void allocate_counters(struct counters *counters) { int i; - int num_cores = topo.cores_per_node * topo.nodes_per_pkg * topo.num_packages; - int num_threads = topo.threads_per_core * num_cores; + int num_cores = topo.cores_per_pkg * topo.num_packages; - counters->threads = calloc(num_threads, sizeof(struct thread_data)); + counters->threads = calloc(topo.max_cpu_num + 1, sizeof(struct thread_data)); if (counters->threads == NULL) goto error; - for (i = 0; i < num_threads; i++) + for (i = 0; i < topo.max_cpu_num + 1; i++) (counters->threads)[i].cpu_id = -1; counters->cores = calloc(num_cores, sizeof(struct core_data)); @@ -9816,6 +9890,8 @@ void topology_update(void) topo.allowed_cores = 0; topo.allowed_packages = 0; for_all_cpus(update_topo, ODD_COUNTERS); + if (debug) + fprintf(stderr, "allowed_cpus %d allowed_cores %d allowed_packages %d\n", topo.allowed_cpus, topo.allowed_cores, topo.allowed_packages); } void setup_all_buffers(bool startup) @@ -10532,7 +10608,7 @@ int get_and_dump_counters(void) void print_version() { - fprintf(outf, "turbostat version 2026.02.14 - Len Brown <lenb@kernel.org>\n"); + fprintf(outf, "turbostat version 2026.04.21 - Len Brown <lenb@kernel.org>\n"); } #define COMMAND_LINE_SIZE 2048 @@ -11284,6 +11360,14 @@ void probe_cpuidle_residency(void) } } +static bool cpuidle_counter_wanted(char *name) +{ + if (is_deferred_skip(name)) + return false; + + return DO_BIC(BIC_cpuidle) || is_deferred_add(name); +} + void probe_cpuidle_counts(void) { char path[64]; @@ -11293,7 +11377,7 @@ void probe_cpuidle_counts(void) int min_state = 1024, max_state = 0; char *sp; - if (!DO_BIC(BIC_cpuidle)) + if (!DO_BIC(BIC_cpuidle) && !deferred_add_index) return; for (state = 10; state >= 0; --state) { @@ -11308,12 +11392,6 @@ void probe_cpuidle_counts(void) remove_underbar(name_buf); - if (!DO_BIC(BIC_cpuidle) && !is_deferred_add(name_buf)) - continue; - - if (is_deferred_skip(name_buf)) - continue; - /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */ sp = strchr(name_buf, '-'); if (!sp) @@ -11328,16 +11406,19 @@ void probe_cpuidle_counts(void) * Add 'C1+' for C1, and so on. The 'below' sysfs file always contains 0 for * the last state, so do not add it. */ - *sp = '+'; *(sp + 1) = '\0'; - sprintf(path, "cpuidle/state%d/below", state); - add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); + if (cpuidle_counter_wanted(name_buf)) { + sprintf(path, "cpuidle/state%d/below", state); + add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); + } } *sp = '\0'; - sprintf(path, "cpuidle/state%d/usage", state); - add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); + if (cpuidle_counter_wanted(name_buf)) { + sprintf(path, "cpuidle/state%d/usage", state); + add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); + } /* * The 'above' sysfs file always contains 0 for the shallowest state (smallest @@ -11346,8 +11427,10 @@ void probe_cpuidle_counts(void) if (state != min_state) { *sp = '-'; *(sp + 1) = '\0'; - sprintf(path, "cpuidle/state%d/above", state); - add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); + if (cpuidle_counter_wanted(name_buf)) { + sprintf(path, "cpuidle/state%d/above", state); + add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); + } } } } @@ -11441,7 +11524,7 @@ void cmdline(int argc, char **argv) } optind = 0; - while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:N:o:qMST:v", long_options, &option_index)) != -1) { + while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:N:o:qMPST:v", long_options, &option_index)) != -1) { switch (opt) { case 'a': parse_add_command(optarg); 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 0aa981c18e56..836553e9a92c 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 @@ -15,6 +15,8 @@ x86_energy_perf_policy \- Manage Energy vs. Performance Policy .br .RB "other: (\-\-force | \-\-hwp-enable | \-\-turbo-enable) value)" .br +.RB "soc-slider: --soc-slider-balance # | --soc-slider-offset # | --platform-profile <name>" +.br .RB "value: # | default | performance | balance-performance | balance-power | power" .SH DESCRIPTION \fBx86_energy_perf_policy\fP @@ -154,6 +156,26 @@ level on this processor, specified in multiples of 100 MHz. in the sliding window that HWP uses to maintain average frequency. This parameter is meaningful only when the "desired" field above is non-zero. Default is 0, allowing the HW to choose. +.SH SOC SLIDER OPTIONS +.PP +Note that the Platform Profile Name must be "SoC Slider", and the +Platform Profile must be "balanced" for the --soc-slider-balance +and --soc-slider-offset options to take effect. +.PP +\fB--soc-slider-balance #\fP write numeric value to the SoC Slider. +Values range from 0 to 6. +Lower values result in higher performance, +and higher values improve energy efficiency. +Actual values are model specific. +.PP +\fB--soc-slider-offset #\fP write the numeric value to the Soc Slider Offset. +The slider offset is the maximum value that software allows the SoC to +autonomously add to the SoC Slider to improve energy efficiency. +The value 0 prohibits the SoC from autonomously changing the slider. +.PP +\fB--platform-profile <name>"\fP set the platform profile to <name>. +Available choices are in platform-profile-0/choices. The Soc Slider +driver currently supports "low-power", "balanced", and "performance". .SH OTHER OPTIONS .PP \fB-f, --force\fP writes the specified values without bounds checking. @@ -208,6 +230,10 @@ runs only as root. EPB: /sys/devices/system/cpu/cpu*/power/energy_perf_bias EPP: /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference MSR: /dev/cpu/*/msr +Platform Profile Name: /sys/class/platform-profile/platform-profile-0/name +Platform Profile: /sys/class/platform-profile/platform-profile-0/profile +SOC Slider Balanced: /sys/module/processor_thermal_soc_slider/parameters/slider_balance +SOC Slider Balanced Offset: /sys/module/processor_thermal_soc_slider/parameters/slider_offset .fi .SH "SEE ALSO" .nf 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 ac37132207a4..0dc959e30076 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 @@ -4,7 +4,7 @@ * policy preference bias on recent X86 processors. */ /* - * Copyright (c) 2010 - 2025 Intel Corporation. + * Copyright (c) 2010 - 2026 Intel Corporation. * Len Brown <len.brown@intel.com> */ @@ -82,21 +82,36 @@ size_t cpu_setsize; char *proc_stat = "/proc/stat"; -unsigned int has_epb; /* MSR_IA32_ENERGY_PERF_BIAS */ -unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ +unsigned int has_epb; /* MSR_IA32_ENERGY_PERF_BIAS */ +unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ /* IA32_HWP_REQUEST, IA32_HWP_STATUS */ -unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */ +unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */ unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */ unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ unsigned int has_hwp_request_pkg; /* IA32_HWP_REQUEST_PKG */ unsigned int bdx_highest_ratio; +unsigned char update_soc_slider_balance; +unsigned char update_soc_slider_offset; +unsigned char update_platform_profile; +int soc_slider_balance; +int soc_slider_offset; +char platform_profile[64]; + #define PATH_TO_CPU "/sys/devices/system/cpu/" #define SYSFS_PATH_MAX 255 +#define PATH_SOC_SLIDER_BALANCE "/sys/module/processor_thermal_soc_slider/parameters/slider_balance" +#define PATH_SOC_SLIDER_OFFSET "/sys/module/processor_thermal_soc_slider/parameters/slider_offset" +#define PATH_PLATFORM_PROFILE "/sys/class/platform-profile/platform-profile-0/profile" +#define PATH_PLATFORM_PROFILE_NAME "/sys/class/platform-profile/platform-profile-0/name" +#define POWER_SLIDER_NAME "SoC Power Slider" static int use_android_msr_path; +static unsigned int read_sysfs(const char *, char *, size_t); +static int sysfs_read_string(const char *, char *, size_t); + /* * maintain compatibility with original implementation, but don't document it: */ @@ -106,8 +121,8 @@ void usage(void) fprintf(stderr, "scope: --cpu cpu-list [--hwp-use-pkg #] | --pkg pkg-list\n"); fprintf(stderr, "field: --all | --epb | --hwp-epp | --hwp-min | --hwp-max | --hwp-desired\n"); fprintf(stderr, "other: --hwp-enable | --turbo-enable (0 | 1) | --help | --force\n"); - fprintf(stderr, - "value: ( # | \"normal\" | \"performance\" | \"balance-performance\" | \"balance-power\"| \"power\")\n"); + fprintf(stderr, "soc-slider: --soc-slider-balance # | --soc-slider-offset # | --platform-profile <name>\n"); + fprintf(stderr, "value: ( # | \"normal\" | \"performance\" | \"balance-performance\" | \"balance-power\"| \"power\")\n"); fprintf(stderr, "--hwp-window usec\n"); fprintf(stderr, "Specify only Energy Performance BIAS (legacy usage):\n"); @@ -135,6 +150,7 @@ int ratio_2_msr_perf(int ratio) return msr_perf; } + int msr_perf_2_ratio(int msr_perf) { int ratio; @@ -143,8 +159,8 @@ int msr_perf_2_ratio(int msr_perf) if (!bdx_highest_ratio) return msr_perf; - d = (double)msr_perf * (double) bdx_highest_ratio / 255.0; - d = d + 0.5; /* round */ + d = (double)msr_perf * (double)bdx_highest_ratio / 255.0; + d = d + 0.5; /* round */ ratio = (int)d; if (debug) @@ -152,6 +168,7 @@ int msr_perf_2_ratio(int msr_perf) return ratio; } + int parse_cmdline_epb(int i) { if (!has_epb) @@ -198,6 +215,7 @@ int parse_cmdline_hwp_min(int i) } return i; } + /* * "power" changes hwp_max to cap.lowest * All others leave it at cap.highest @@ -217,6 +235,7 @@ int parse_cmdline_hwp_max(int i) } return i; } + /* * for --hwp-des, all strings leave it in autonomous mode * If you want to change it, you need to explicitly pick a value @@ -254,7 +273,7 @@ int parse_cmdline_hwp_window(int i) fprintf(stderr, "--hwp-window: 0 for auto; 1 - 1270000000 usec for window duration\n"); usage(); } - for (exponent = 0; ; ++exponent) { + for (exponent = 0;; ++exponent) { if (debug) printf("%d 10^%d\n", i, exponent); @@ -268,6 +287,7 @@ int parse_cmdline_hwp_window(int i) return (exponent << 7) | i; } + int parse_cmdline_hwp_epp(int i) { update_hwp_epp = 1; @@ -289,6 +309,7 @@ int parse_cmdline_hwp_epp(int i) } return i; } + int parse_cmdline_turbo(int i) { update_turbo = 1; @@ -508,7 +529,7 @@ void parse_cmdline_pkg(char *s) } } -void for_packages(unsigned long long pkg_set, int (func)(int)) +void for_packages(unsigned long long pkg_set, int (func) (int)) { int pkg_num; @@ -518,9 +539,79 @@ void for_packages(unsigned long long pkg_set, int (func)(int)) } } +static int parse_cmdline_int(const char *s, int *out) +{ + char *endp; + long val; + + val = strtol(s, &endp, 0); + if (endp == s || errno == ERANGE) + return -1; + if (*endp != '\0') + return -1; + if (val < INT_MIN || val > INT_MAX) + return -1; + + *out = (int)val; + return 0; +} + void print_version(void) { - printf("x86_energy_perf_policy 2025.11.22 Len Brown <lenb@kernel.org>\n"); + printf("x86_energy_perf_policy 2026.04.25 Len Brown <lenb@kernel.org>\n"); +} + +static int platform_profile_access(int mode) +{ + if (access(PATH_PLATFORM_PROFILE, mode)) { + if (debug) + fprintf(stderr, "Can not access %s\n", PATH_PLATFORM_PROFILE); + return 0; + } + + return 1; +} + +static int platform_profile_name_is(char *name) +{ + char buf[64]; + + if (sysfs_read_string(PATH_PLATFORM_PROFILE_NAME, buf, sizeof(buf)) != 0) { + if (debug) + fprintf(stderr, "Can not read %s\n", PATH_PLATFORM_PROFILE_NAME); + return 0; + } + + if (strncmp(buf, name, 16)) { + if (debug) + fprintf(stderr, "%s does not match '%s'\n", PATH_PLATFORM_PROFILE_NAME, name); + return 0; + } + + return 1; +} + +static int soc_slider_access(int mode) +{ + if (!platform_profile_access(R_OK)) + return 0; + + if (!platform_profile_name_is(POWER_SLIDER_NAME)) + return 0; + + if (access(PATH_SOC_SLIDER_BALANCE, mode)) { + if (debug) + fprintf(stderr, "Can not access %s\n", PATH_SOC_SLIDER_BALANCE); + return 0; + } + + if (access(PATH_SOC_SLIDER_OFFSET, mode)) { + if (debug) + fprintf(stderr, "Can not access %s\n", PATH_SOC_SLIDER_OFFSET); + return 0; + } + + return 1; } void cmdline(int argc, char **argv) @@ -529,30 +620,32 @@ void cmdline(int argc, char **argv) int option_index = 0; static struct option long_options[] = { - {"all", required_argument, 0, 'a'}, - {"cpu", required_argument, 0, 'c'}, - {"pkg", required_argument, 0, 'p'}, - {"debug", no_argument, 0, 'd'}, - {"hwp-desired", required_argument, 0, 'D'}, - {"epb", required_argument, 0, 'B'}, - {"force", no_argument, 0, 'f'}, - {"hwp-enable", no_argument, 0, 'e'}, - {"help", no_argument, 0, 'h'}, - {"hwp-epp", required_argument, 0, 'P'}, - {"hwp-min", required_argument, 0, 'm'}, - {"hwp-max", required_argument, 0, 'M'}, - {"read", no_argument, 0, 'r'}, - {"turbo-enable", required_argument, 0, 't'}, - {"hwp-use-pkg", required_argument, 0, 'u'}, - {"version", no_argument, 0, 'v'}, - {"hwp-window", required_argument, 0, 'w'}, - {0, 0, 0, 0 } + { "all", required_argument, 0, 'a' }, + { "cpu", required_argument, 0, 'c' }, + { "pkg", required_argument, 0, 'p' }, + { "debug", no_argument, 0, 'd' }, + { "hwp-desired", required_argument, 0, 'D' }, + { "epb", required_argument, 0, 'B' }, + { "force", no_argument, 0, 'f' }, + { "hwp-enable", no_argument, 0, 'e' }, + { "help", no_argument, 0, 'h' }, + { "hwp-epp", required_argument, 0, 'P' }, + { "hwp-min", required_argument, 0, 'm' }, + { "hwp-max", required_argument, 0, 'M' }, + { "read", no_argument, 0, 'r' }, + { "turbo-enable", required_argument, 0, 't' }, + { "hwp-use-pkg", required_argument, 0, 'u' }, + { "version", no_argument, 0, 'v' }, + { "hwp-window", required_argument, 0, 'w' }, + { "soc-slider-balance", required_argument, 0, 'S' }, + { "soc-slider-offset", required_argument, 0, 'O' }, + { "platform-profile", required_argument, 0, 'F' }, + { 0, 0, 0, 0 } }; progname = argv[0]; - while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw:", - long_options, &option_index)) != -1) { + while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw::S:O:F:", long_options, &option_index)) != -1) { switch (opt) { case 'a': parse_cmdline_all(optarg); @@ -579,12 +672,27 @@ void cmdline(int argc, char **argv) case 'D': req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(optarg)); break; + case 'F': + if (strlen(optarg) >= sizeof(platform_profile)) + errx(1, "--platform-profile: value too long"); + if (!platform_profile_access(W_OK)) + errx(1, "Can not update platform-profile in '%s'", PATH_PLATFORM_PROFILE); + strcpy(platform_profile, optarg); + update_platform_profile = 1; + break; case 'm': req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(optarg)); break; case 'M': req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(optarg)); break; + case 'O': + if (parse_cmdline_int(optarg, &soc_slider_offset)) + errx(1, "--soc-slider-offset: invalid value"); + if (!soc_slider_access(W_OK)) + errx(1, "Unable to write SOC Slider Offset"); + update_soc_slider_offset = 1; + break; case 'p': parse_cmdline_pkg(optarg); break; @@ -594,6 +702,13 @@ void cmdline(int argc, char **argv) case 'r': /* v1 used -r to specify read-only mode, now the default */ break; + case 'S': + if (parse_cmdline_int(optarg, &soc_slider_balance)) + errx(1, "--soc-slider-balance: invalid value"); + if (!soc_slider_access(W_OK)) + errx(1, "Unable to write SOC Slider-Balance in '%s'", PATH_SOC_SLIDER_BALANCE); + update_soc_slider_balance = 1; + break; case 't': turbo_update_value = parse_cmdline_turbo(parse_optarg_string(optarg)); break; @@ -681,8 +796,7 @@ void err_on_hypervisor(void) free(buffer); if (hypervisor) - err(-1, - "not supported on this virtual machine"); + err(-1, "not supported on this virtual machine"); } int get_msr(int cpu, int offset, unsigned long long *msr) @@ -694,9 +808,7 @@ int get_msr(int cpu, int offset, unsigned long long *msr) sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu); fd = open(pathname, O_RDONLY); if (fd < 0) - err(-1, "%s open failed, try chown or chmod +r %s, or run as root", - pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr"); - + err(-1, "%s open failed, try chown or chmod +r %s, or run as root", pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr"); retval = pread(fd, msr, sizeof(*msr), offset); if (retval != sizeof(*msr)) { @@ -720,8 +832,7 @@ int put_msr(int cpu, int offset, unsigned long long new_msr) sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu); fd = open(pathname, O_RDWR); if (fd < 0) - err(-1, "%s open failed, try chown or chmod +r %s, or run as root", - pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr"); + err(-1, "%s open failed, try chown or chmod +r %s, or run as root", pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr"); retval = pwrite(fd, &new_msr, sizeof(new_msr), offset); if (retval != sizeof(new_msr)) @@ -753,7 +864,7 @@ static unsigned int read_sysfs(const char *path, char *buf, size_t buflen) buf[numread] = '\0'; close(fd); - return (unsigned int) numread; + return (unsigned int)numread; } static unsigned int write_sysfs(const char *path, char *buf, size_t buflen) @@ -767,14 +878,40 @@ static unsigned int write_sysfs(const char *path, char *buf, size_t buflen) numwritten = write(fd, buf, buflen - 1); if (numwritten < 1) { - perror("write failed\n"); + buf[strcspn(buf, "\n")] = '\0'; + warn("Write '%s' to '%s' failed", buf, path); close(fd); return -1; } close(fd); - return (unsigned int) numwritten; + return (unsigned int)numwritten; +} + +static int sysfs_read_string(const char *path, char *buf, size_t buflen) +{ + unsigned int len; + size_t n; + + len = read_sysfs(path, buf, buflen); + if (!len) + return -1; + + n = strcspn(buf, "\n"); + buf[n] = '\0'; + return 0; +} + +static int sysfs_write_string(const char *path, const char *buf) +{ + char tmp[128]; + int len; + + len = snprintf(tmp, sizeof(tmp), "%s\n", buf); + if (len < 0 || len >= (int)sizeof(tmp)) + return -1; + return write_sysfs(path, tmp, (size_t)len + 1) ? 0 : -1; } void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str) @@ -782,9 +919,9 @@ void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str) if (cpu != -1) printf("cpu%d: ", cpu); - printf("HWP_CAP: low %d eff %d guar %d high %d\n", - cap->lowest, cap->efficient, cap->guaranteed, cap->highest); + printf("HWP_CAP: low %d eff %d guar %d high %d\n", cap->lowest, cap->efficient, cap->guaranteed, cap->highest); } + void read_hwp_cap(int cpu, struct msr_hwp_cap *cap, unsigned int msr_offset) { unsigned long long msr; @@ -806,9 +943,9 @@ void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str) printf("%s", str); printf("HWP_REQ: min %d max %d des %d epp %d window 0x%x (%d*10^%dus) use_pkg %d\n", - h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp, - h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7, h->hwp_use_pkg); + h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp, h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7, h->hwp_use_pkg); } + void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, char *str) { printf("pkg%d: ", pkg); @@ -817,9 +954,9 @@ void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, char *str) printf("%s", str); printf("HWP_REQ_PKG: min %d max %d des %d epp %d window 0x%x (%d*10^%dus)\n", - h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp, - h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7); + h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp, h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7); } + void read_hwp_request_msr(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset) { unsigned long long msr; @@ -840,9 +977,7 @@ void write_hwp_request_msr(int cpu, struct msr_hwp_request *hwp_req, unsigned in if (debug > 1) printf("cpu%d: requesting min %d max %d des %d epp %d window 0x%0x use_pkg %d\n", - cpu, hwp_req->hwp_min, hwp_req->hwp_max, - hwp_req->hwp_desired, hwp_req->hwp_epp, - hwp_req->hwp_window, hwp_req->hwp_use_pkg); + cpu, hwp_req->hwp_min, hwp_req->hwp_max, hwp_req->hwp_desired, hwp_req->hwp_epp, hwp_req->hwp_window, hwp_req->hwp_use_pkg); msr |= HWP_MIN_PERF(ratio_2_msr_perf(hwp_req->hwp_min)); msr |= HWP_MAX_PERF(ratio_2_msr_perf(hwp_req->hwp_max)); @@ -900,6 +1035,58 @@ static int set_epb_sysfs(int cpu, int val) return (int)val; } +static void print_soc_slider(void) +{ + char buf[64]; + + if (!soc_slider_access(R_OK)) + return; + + if (sysfs_read_string(PATH_SOC_SLIDER_BALANCE, buf, sizeof(buf)) == 0) + printf("soc-slider-balance: %s\n", buf); + + if (sysfs_read_string(PATH_SOC_SLIDER_OFFSET, buf, sizeof(buf)) == 0) + printf("soc-slider-offset: %s\n", buf); +} + +static void print_platform_profile(void) +{ + char buf[64]; + + if (!platform_profile_access(R_OK)) + return; + + if (sysfs_read_string(PATH_PLATFORM_PROFILE_NAME, buf, sizeof(buf)) == 0) + printf("platform-profile-name: %s\n", buf); + + if (sysfs_read_string(PATH_PLATFORM_PROFILE, buf, sizeof(buf)) == 0) + printf("platform-profile: %s\n", buf); +} + +static int update_soc_slider(void) +{ + char tmp[32]; + + if (update_soc_slider_balance) { + snprintf(tmp, sizeof(tmp), "%d", soc_slider_balance); + if (sysfs_write_string(PATH_SOC_SLIDER_BALANCE, tmp)) + err(1, "soc-slider-balance write failed"); + } + + if (update_soc_slider_offset) { + snprintf(tmp, sizeof(tmp), "%d", soc_slider_offset); + if (sysfs_write_string(PATH_SOC_SLIDER_OFFSET, tmp)) + err(1, "soc-slider-offset write failed"); + } + + if (update_platform_profile) { + if (sysfs_write_string(PATH_PLATFORM_PROFILE, platform_profile)) + err(1, "platform-profile write failed"); + } + + return 0; +} + int print_cpu_msrs(int cpu) { struct msr_hwp_request req; @@ -908,7 +1095,7 @@ int print_cpu_msrs(int cpu) epb = get_epb_sysfs(cpu); if (epb >= 0) - printf("cpu%d: EPB %u\n", cpu, (unsigned int) epb); + printf("cpu%d: EPB %u\n", cpu, (unsigned int)epb); if (!has_hwp) return 0; @@ -936,17 +1123,13 @@ int print_pkg_msrs(int pkg) if (has_hwp_notify) { get_msr(first_cpu_in_pkg[pkg], MSR_HWP_INTERRUPT, &msr); fprintf(stderr, - "pkg%d: MSR_HWP_INTERRUPT: 0x%08llx (Excursion_Min-%sabled, Guaranteed_Perf_Change-%sabled)\n", - pkg, msr, - ((msr) & 0x2) ? "EN" : "Dis", - ((msr) & 0x1) ? "EN" : "Dis"); + "pkg%d: MSR_HWP_INTERRUPT: 0x%08llx (Excursion_Min-%sabled, Guaranteed_Perf_Change-%sabled)\n", + pkg, msr, ((msr) & 0x2) ? "EN" : "Dis", ((msr) & 0x1) ? "EN" : "Dis"); } get_msr(first_cpu_in_pkg[pkg], MSR_HWP_STATUS, &msr); fprintf(stderr, "pkg%d: MSR_HWP_STATUS: 0x%08llx (%sExcursion_Min, %sGuaranteed_Perf_Change)\n", - pkg, msr, - ((msr) & 0x4) ? "" : "No-", - ((msr) & 0x1) ? "" : "No-"); + pkg, msr, ((msr) & 0x4) ? "" : "No-", ((msr) & 0x1) ? "" : "No-"); return 0; } @@ -960,6 +1143,7 @@ int ratio_2_sysfs_khz(int ratio) return ratio * bclk_khz; } + /* * If HWP is enabled and cpufreq sysfs attribtes are present, * then update via sysfs. The intel_pstate driver may modify (clip) @@ -976,8 +1160,7 @@ void update_cpufreq_scaling_freq(int is_max, int cpu, unsigned int ratio) int retval; int khz; - sprintf(pathname, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq", - cpu, is_max ? "max" : "min"); + sprintf(pathname, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq", cpu, is_max ? "max" : "min"); fp = fopen(pathname, "w"); if (!fp) { @@ -1029,19 +1212,16 @@ int verify_hwp_req_self_consistency(int cpu, struct msr_hwp_request *req) { /* fail if min > max requested */ if (req->hwp_min > req->hwp_max) { - errx(1, "cpu%d: requested hwp-min %d > hwp_max %d", - cpu, req->hwp_min, req->hwp_max); + errx(1, "cpu%d: requested hwp-min %d > hwp_max %d", cpu, req->hwp_min, req->hwp_max); } /* fail if desired > max requestd */ if (req->hwp_desired && (req->hwp_desired > req->hwp_max)) { - errx(1, "cpu%d: requested hwp-desired %d > hwp_max %d", - cpu, req->hwp_desired, req->hwp_max); + errx(1, "cpu%d: requested hwp-desired %d > hwp_max %d", cpu, req->hwp_desired, req->hwp_max); } /* fail if desired < min requestd */ if (req->hwp_desired && (req->hwp_desired < req->hwp_min)) { - errx(1, "cpu%d: requested hwp-desired %d < requested hwp_min %d", - cpu, req->hwp_desired, req->hwp_min); + errx(1, "cpu%d: requested hwp-desired %d < requested hwp_min %d", cpu, req->hwp_desired, req->hwp_min); } return 0; @@ -1051,39 +1231,30 @@ int check_hwp_request_v_hwp_capabilities(int cpu, struct msr_hwp_request *req, s { if (update_hwp_max) { if (req->hwp_max > cap->highest) - errx(1, "cpu%d: requested max %d > capabilities highest %d, use --force?", - cpu, req->hwp_max, cap->highest); + errx(1, "cpu%d: requested max %d > capabilities highest %d, use --force?", cpu, req->hwp_max, cap->highest); if (req->hwp_max < cap->lowest) - errx(1, "cpu%d: requested max %d < capabilities lowest %d, use --force?", - cpu, req->hwp_max, cap->lowest); + errx(1, "cpu%d: requested max %d < capabilities lowest %d, use --force?", cpu, req->hwp_max, cap->lowest); } if (update_hwp_min) { if (req->hwp_min > cap->highest) - errx(1, "cpu%d: requested min %d > capabilities highest %d, use --force?", - cpu, req->hwp_min, cap->highest); + errx(1, "cpu%d: requested min %d > capabilities highest %d, use --force?", cpu, req->hwp_min, cap->highest); if (req->hwp_min < cap->lowest) - errx(1, "cpu%d: requested min %d < capabilities lowest %d, use --force?", - cpu, req->hwp_min, cap->lowest); + errx(1, "cpu%d: requested min %d < capabilities lowest %d, use --force?", cpu, req->hwp_min, cap->lowest); } if (update_hwp_min && update_hwp_max && (req->hwp_min > req->hwp_max)) - errx(1, "cpu%d: requested min %d > requested max %d", - cpu, req->hwp_min, req->hwp_max); + errx(1, "cpu%d: requested min %d > requested max %d", cpu, req->hwp_min, req->hwp_max); if (update_hwp_desired && req->hwp_desired) { if (req->hwp_desired > req->hwp_max) - errx(1, "cpu%d: requested desired %d > requested max %d, use --force?", - cpu, req->hwp_desired, req->hwp_max); + errx(1, "cpu%d: requested desired %d > requested max %d, use --force?", cpu, req->hwp_desired, req->hwp_max); if (req->hwp_desired < req->hwp_min) - errx(1, "cpu%d: requested desired %d < requested min %d, use --force?", - cpu, req->hwp_desired, req->hwp_min); + errx(1, "cpu%d: requested desired %d < requested min %d, use --force?", cpu, req->hwp_desired, req->hwp_min); if (req->hwp_desired < cap->lowest) - errx(1, "cpu%d: requested desired %d < capabilities lowest %d, use --force?", - cpu, req->hwp_desired, cap->lowest); + errx(1, "cpu%d: requested desired %d < capabilities lowest %d, use --force?", cpu, req->hwp_desired, cap->lowest); if (req->hwp_desired > cap->highest) - errx(1, "cpu%d: requested desired %d > capabilities highest %d, use --force?", - cpu, req->hwp_desired, cap->highest); + errx(1, "cpu%d: requested desired %d > capabilities highest %d, use --force?", cpu, req->hwp_desired, cap->highest); } return 0; @@ -1134,6 +1305,7 @@ int update_hwp_request_msr(int cpu) } return 0; } + int update_hwp_request_pkg_msr(int pkg) { struct msr_hwp_request req; @@ -1205,8 +1377,7 @@ int update_cpu_epb_sysfs(int cpu) set_epb_sysfs(cpu, new_epb); if (verbose) - printf("cpu%d: ENERGY_PERF_BIAS old: %d new: %d\n", - cpu, epb, (unsigned int) new_epb); + printf("cpu%d: ENERGY_PERF_BIAS old: %d new: %d\n", cpu, epb, (unsigned int)new_epb); return 0; } @@ -1222,7 +1393,7 @@ int update_cpu_msrs(int cpu) turbo_is_present_and_disabled = ((msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE) != 0); - if (turbo_update_value == 1) { + if (turbo_update_value == 1) { if (turbo_is_present_and_disabled) { msr &= ~MSR_IA32_MISC_ENABLE_TURBO_DISABLE; put_msr(cpu, MSR_IA32_MISC_ENABLE, msr); @@ -1291,6 +1462,7 @@ int set_max_cpu_pkg_num(int cpu) return 0; } + int mark_cpu_present(int cpu) { CPU_SET_S(cpu, cpu_setsize, cpu_present_set); @@ -1301,7 +1473,7 @@ int mark_cpu_present(int cpu) * run func(cpu) on every cpu in /proc/stat * return max_cpu number */ -int for_all_proc_cpus(int (func)(int)) +int for_all_proc_cpus(int (func) (int)) { FILE *fp; int cpu_num; @@ -1328,7 +1500,7 @@ int for_all_proc_cpus(int (func)(int)) return 0; } -void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func)(int)) +void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func) (int)) { int cpu_num; @@ -1336,7 +1508,8 @@ void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func)(int)) if (CPU_ISSET_S(cpu_num, set_size, cpu_set)) func(cpu_num); } -int for_all_cpus_in_set_and(size_t set_size, cpu_set_t *cpu_set, int (func)(int)) + +int for_all_cpus_in_set_and(size_t set_size, cpu_set_t *cpu_set, int (func) (int)) { int cpu_num; int retval = 1; @@ -1385,7 +1558,7 @@ void verify_hwp_is_enabled(void) { int retval; - if (!has_hwp) /* set in early_cpuid() */ + if (!has_hwp) /* set in early_cpuid() */ return; retval = for_all_cpus_in_set_and(cpu_setsize, cpu_selected_set, is_hwp_enabled_on_cpu); @@ -1402,21 +1575,18 @@ int req_update_bounds_check(void) return 0; /* fail if min > max requested */ - if ((update_hwp_max && update_hwp_min) && - (req_update.hwp_min > req_update.hwp_max)) { + if ((update_hwp_max && update_hwp_min) && (req_update.hwp_min > req_update.hwp_max)) { printf("hwp-min %d > hwp_max %d\n", req_update.hwp_min, req_update.hwp_max); return -EINVAL; } /* fail if desired > max requestd */ - if (req_update.hwp_desired && update_hwp_max && - (req_update.hwp_desired > req_update.hwp_max)) { + if (req_update.hwp_desired && update_hwp_max && (req_update.hwp_desired > req_update.hwp_max)) { printf("hwp-desired cannot be greater than hwp_max\n"); return -EINVAL; } /* fail if desired < min requestd */ - if (req_update.hwp_desired && update_hwp_min && - (req_update.hwp_desired < req_update.hwp_min)) { + if (req_update.hwp_desired && update_hwp_min && (req_update.hwp_desired < req_update.hwp_min)) { printf("hwp-desired cannot be less than hwp_min\n"); return -EINVAL; } @@ -1459,9 +1629,7 @@ void probe_dev_msr(void) } } -static void get_cpuid_or_exit(unsigned int leaf, - unsigned int *eax, unsigned int *ebx, - unsigned int *ecx, unsigned int *edx) +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"); @@ -1515,8 +1683,7 @@ void parse_cpuid(void) genuine_intel = 1; if (debug) - fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", - (char *)&ebx, (char *)&edx, (char *)&ecx); + fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", (char *)&ebx, (char *)&edx, (char *)&ecx); get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx); family = (fms >> 8) & 0xf; @@ -1526,23 +1693,18 @@ void parse_cpuid(void) model += ((fms >> 16) & 0xf) << 4; if (debug) { - fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", - max_level, family, model, stepping, family, model, stepping); + fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", max_level, family, model, stepping, family, model, stepping); fprintf(stderr, "CPUID(1): %s %s %s %s %s %s %s %s\n", ecx & (1 << 0) ? "SSE3" : "-", ecx & (1 << 3) ? "MONITOR" : "-", ecx & (1 << 7) ? "EIST" : "-", ecx & (1 << 8) ? "TM2" : "-", - edx & (1 << 4) ? "TSC" : "-", - edx & (1 << 5) ? "MSR" : "-", - edx & (1 << 22) ? "ACPI-TM" : "-", - edx & (1 << 29) ? "TM" : "-"); + edx & (1 << 4) ? "TSC" : "-", edx & (1 << 5) ? "MSR" : "-", edx & (1 << 22) ? "ACPI-TM" : "-", edx & (1 << 29) ? "TM" : "-"); } if (!(edx & (1 << 5))) errx(1, "CPUID: no MSR"); - get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx); /* turbo_is_enabled already set */ /* has_hwp already set */ @@ -1562,12 +1724,9 @@ void parse_cpuid(void) turbo_is_enabled ? "" : "No-", has_hwp ? "" : "No-", has_hwp_notify ? "" : "No-", - has_hwp_activity_window ? "" : "No-", - has_hwp_epp ? "" : "No-", - has_hwp_request_pkg ? "" : "No-", - has_epb ? "" : "No-"); + has_hwp_activity_window ? "" : "No-", has_hwp_epp ? "" : "No-", has_hwp_request_pkg ? "" : "No-", has_epb ? "" : "No-"); - return; /* success */ + return; /* success */ } int main(int argc, char **argv) @@ -1577,7 +1736,7 @@ int main(int argc, char **argv) probe_dev_msr(); init_data_structures(); - early_cpuid(); /* initial cpuid parse before cmdline */ + early_cpuid(); /* initial cpuid parse before cmdline */ cmdline(argc, argv); @@ -1586,7 +1745,7 @@ int main(int argc, char **argv) parse_cpuid(); - /* If CPU-set and PKG-set are not initialized, default to all CPUs */ + /* If CPU-set and PKG-set are not initialized, default to all CPUs */ if ((cpu_selected_set == 0) && (pkg_selected_set == 0)) cpu_selected_set = cpu_present_set; @@ -1604,10 +1763,13 @@ int main(int argc, char **argv) return -EINVAL; /* display information only, no updates to settings */ - if (!update_epb && !update_turbo && !hwp_update_enabled()) { + if (!update_epb && !update_turbo && !hwp_update_enabled() && !update_soc_slider_balance && !update_soc_slider_offset && !update_platform_profile) { if (cpu_selected_set) for_all_cpus_in_set(cpu_setsize, cpu_selected_set, print_cpu_msrs); + print_soc_slider(); + print_platform_profile(); + if (has_hwp_request_pkg) { if (pkg_selected_set == 0) pkg_selected_set = pkg_present_set; @@ -1628,5 +1790,8 @@ int main(int argc, char **argv) } else if (pkg_selected_set) for_packages(pkg_selected_set, update_hwp_request_pkg_msr); + if (update_soc_slider_balance || update_soc_slider_offset || update_platform_profile) + update_soc_slider(); + return 0; } |
