summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2019-06-30 13:14:08 -0400
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>2019-07-03 08:37:09 -0400
commit3fb4f7cd472c7f5905c91508e988f6b28372210d (patch)
treeba535d3f37214f60122820515f74cae7cf361d7d
parentf607874f35cbd276a837d7147d4e1ec752dfef44 (diff)
tools/power/x86: A tool to validate Intel Speed Select commands
The Intel(R) Speed select technologies contains four features. Performance profile:An non architectural mechanism that allows multiple optimized performance profiles per system via static and/or dynamic adjustment of core count, workload, Tjmax, and TDP, etc. aka ISS in the documentation. Base Frequency: Enables users to increase guaranteed base frequency on certain cores (high priority cores) in exchange for lower base frequency on remaining cores (low priority cores). aka PBF in the documenation. Turbo frequency: Enables the ability to set different turbo ratio limits to cores based on priority. aka FACT in the documentation. Core power: An Interface that allows user to define per core/tile priority. There is a multi level help for commands and options. This can be used to check required arguments for each feature and commands for the feature. To start navigating the features start with $sudo intel-speed-select --help For help on a specific feature for example $sudo intel-speed-select perf-profile --help To get help for a command for a feature for example $sudo intel-speed-select perf-profile get-lock-status --help Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Acked-by: Len Brown <len.brown@intel.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-rw-r--r--tools/Makefile12
-rw-r--r--tools/power/x86/intel-speed-select/Build1
-rw-r--r--tools/power/x86/intel-speed-select/Makefile56
-rw-r--r--tools/power/x86/intel-speed-select/isst-config.c1607
-rw-r--r--tools/power/x86/intel-speed-select/isst-core.c721
-rw-r--r--tools/power/x86/intel-speed-select/isst-display.c479
-rw-r--r--tools/power/x86/intel-speed-select/isst.h231
7 files changed, 3102 insertions, 5 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 3dfd72ae6c1a..68defd7ecf5d 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
19 @echo ' gpio - GPIO tools' 19 @echo ' gpio - GPIO tools'
20 @echo ' hv - tools used when in Hyper-V clients' 20 @echo ' hv - tools used when in Hyper-V clients'
21 @echo ' iio - IIO tools' 21 @echo ' iio - IIO tools'
22 @echo ' intel-speed-select - Intel Speed Select tool'
22 @echo ' kvm_stat - top-like utility for displaying kvm statistics' 23 @echo ' kvm_stat - top-like utility for displaying kvm statistics'
23 @echo ' leds - LEDs tools' 24 @echo ' leds - LEDs tools'
24 @echo ' liblockdep - user-space wrapper for kernel locking-validator' 25 @echo ' liblockdep - user-space wrapper for kernel locking-validator'
@@ -82,7 +83,7 @@ perf: FORCE
82selftests: FORCE 83selftests: FORCE
83 $(call descend,testing/$@) 84 $(call descend,testing/$@)
84 85
85turbostat x86_energy_perf_policy: FORCE 86turbostat x86_energy_perf_policy intel-speed-select: FORCE
86 $(call descend,power/x86/$@) 87 $(call descend,power/x86/$@)
87 88
88tmon: FORCE 89tmon: FORCE
@@ -115,7 +116,7 @@ liblockdep_install:
115selftests_install: 116selftests_install:
116 $(call descend,testing/$(@:_install=),install) 117 $(call descend,testing/$(@:_install=),install)
117 118
118turbostat_install x86_energy_perf_policy_install: 119turbostat_install x86_energy_perf_policy_install intel-speed-select_install:
119 $(call descend,power/x86/$(@:_install=),install) 120 $(call descend,power/x86/$(@:_install=),install)
120 121
121tmon_install: 122tmon_install:
@@ -132,7 +133,7 @@ install: acpi_install cgroup_install cpupower_install gpio_install \
132 perf_install selftests_install turbostat_install usb_install \ 133 perf_install selftests_install turbostat_install usb_install \
133 virtio_install vm_install bpf_install x86_energy_perf_policy_install \ 134 virtio_install vm_install bpf_install x86_energy_perf_policy_install \
134 tmon_install freefall_install objtool_install kvm_stat_install \ 135 tmon_install freefall_install objtool_install kvm_stat_install \
135 wmi_install pci_install debugging_install 136 wmi_install pci_install debugging_install intel-speed-select_install
136 137
137acpi_clean: 138acpi_clean:
138 $(call descend,power/acpi,clean) 139 $(call descend,power/acpi,clean)
@@ -162,7 +163,7 @@ perf_clean:
162selftests_clean: 163selftests_clean:
163 $(call descend,testing/$(@:_clean=),clean) 164 $(call descend,testing/$(@:_clean=),clean)
164 165
165turbostat_clean x86_energy_perf_policy_clean: 166turbostat_clean x86_energy_perf_policy_clean intel-speed-select_clean:
166 $(call descend,power/x86/$(@:_clean=),clean) 167 $(call descend,power/x86/$(@:_clean=),clean)
167 168
168tmon_clean: 169tmon_clean:
@@ -178,6 +179,7 @@ clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \
178 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ 179 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
179 vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ 180 vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
180 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ 181 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
181 gpio_clean objtool_clean leds_clean wmi_clean pci_clean firmware_clean debugging_clean 182 gpio_clean objtool_clean leds_clean wmi_clean pci_clean firmware_clean debugging_clean \
183 intel-speed-select_clean
182 184
183.PHONY: FORCE 185.PHONY: FORCE
diff --git a/tools/power/x86/intel-speed-select/Build b/tools/power/x86/intel-speed-select/Build
new file mode 100644
index 000000000000..b61456d75190
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/Build
@@ -0,0 +1 @@
intel-speed-select-y += isst-config.o isst-core.o isst-display.o
diff --git a/tools/power/x86/intel-speed-select/Makefile b/tools/power/x86/intel-speed-select/Makefile
new file mode 100644
index 000000000000..12c6939dca2a
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/Makefile
@@ -0,0 +1,56 @@
1# SPDX-License-Identifier: GPL-2.0
2include ../../../scripts/Makefile.include
3
4bindir ?= /usr/bin
5
6ifeq ($(srctree),)
7srctree := $(patsubst %/,%,$(dir $(CURDIR)))
8srctree := $(patsubst %/,%,$(dir $(srctree)))
9srctree := $(patsubst %/,%,$(dir $(srctree)))
10srctree := $(patsubst %/,%,$(dir $(srctree)))
11endif
12
13# Do not use make's built-in rules
14# (this improves performance and avoids hard-to-debug behaviour);
15MAKEFLAGS += -r
16
17override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
18
19ALL_TARGETS := intel-speed-select
20ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
21
22all: $(ALL_PROGRAMS)
23
24export srctree OUTPUT CC LD CFLAGS
25include $(srctree)/tools/build/Makefile.include
26
27#
28# We need the following to be outside of kernel tree
29#
30$(OUTPUT)include/linux/isst_if.h: ../../../../include/uapi/linux/isst_if.h
31 mkdir -p $(OUTPUT)include/linux 2>&1 || true
32 ln -sf $(CURDIR)/../../../../include/uapi/linux/isst_if.h $@
33
34prepare: $(OUTPUT)include/linux/isst_if.h
35
36ISST_IN := $(OUTPUT)intel-speed-select-in.o
37
38$(ISST_IN): prepare FORCE
39 $(Q)$(MAKE) $(build)=intel-speed-select
40$(OUTPUT)intel-speed-select: $(ISST_IN)
41 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
42
43clean:
44 rm -f $(ALL_PROGRAMS)
45 rm -rf $(OUTPUT)include/linux/isst_if.h
46 find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
47
48install: $(ALL_PROGRAMS)
49 install -d -m 755 $(DESTDIR)$(bindir); \
50 for program in $(ALL_PROGRAMS); do \
51 install $$program $(DESTDIR)$(bindir); \
52 done
53
54FORCE:
55
56.PHONY: all install clean FORCE prepare
diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c
new file mode 100644
index 000000000000..91c5ad1685a1
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-config.c
@@ -0,0 +1,1607 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Intel Speed Select -- Enumerate and control features
4 * Copyright (c) 2019 Intel Corporation.
5 */
6
7#include <linux/isst_if.h>
8
9#include "isst.h"
10
11struct process_cmd_struct {
12 char *feature;
13 char *command;
14 void (*process_fn)(void);
15};
16
17static const char *version_str = "v1.0";
18static const int supported_api_ver = 1;
19static struct isst_if_platform_info isst_platform_info;
20static char *progname;
21static int debug_flag;
22static FILE *outf;
23
24static int cpu_model;
25
26#define MAX_CPUS_IN_ONE_REQ 64
27static short max_target_cpus;
28static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
29
30static int topo_max_cpus;
31static size_t present_cpumask_size;
32static cpu_set_t *present_cpumask;
33static size_t target_cpumask_size;
34static cpu_set_t *target_cpumask;
35static int tdp_level = 0xFF;
36static int fact_bucket = 0xFF;
37static int fact_avx = 0xFF;
38static unsigned long long fact_trl;
39static int out_format_json;
40static int cmd_help;
41
42/* clos related */
43static int current_clos = -1;
44static int clos_epp = -1;
45static int clos_prop_prio = -1;
46static int clos_min = -1;
47static int clos_max = -1;
48static int clos_desired = -1;
49static int clos_priority_type;
50
51struct _cpu_map {
52 unsigned short core_id;
53 unsigned short pkg_id;
54 unsigned short die_id;
55 unsigned short punit_cpu;
56 unsigned short punit_cpu_core;
57};
58struct _cpu_map *cpu_map;
59
60void debug_printf(const char *format, ...)
61{
62 va_list args;
63
64 va_start(args, format);
65
66 if (debug_flag)
67 vprintf(format, args);
68
69 va_end(args);
70}
71
72static void update_cpu_model(void)
73{
74 unsigned int ebx, ecx, edx;
75 unsigned int fms, family;
76
77 __cpuid(1, fms, ebx, ecx, edx);
78 family = (fms >> 8) & 0xf;
79 cpu_model = (fms >> 4) & 0xf;
80 if (family == 6 || family == 0xf)
81 cpu_model += ((fms >> 16) & 0xf) << 4;
82}
83
84/* Open a file, and exit on failure */
85static FILE *fopen_or_exit(const char *path, const char *mode)
86{
87 FILE *filep = fopen(path, mode);
88
89 if (!filep)
90 err(1, "%s: open failed", path);
91
92 return filep;
93}
94
95/* Parse a file containing a single int */
96static int parse_int_file(int fatal, const char *fmt, ...)
97{
98 va_list args;
99 char path[PATH_MAX];
100 FILE *filep;
101 int value;
102
103 va_start(args, fmt);
104 vsnprintf(path, sizeof(path), fmt, args);
105 va_end(args);
106 if (fatal) {
107 filep = fopen_or_exit(path, "r");
108 } else {
109 filep = fopen(path, "r");
110 if (!filep)
111 return -1;
112 }
113 if (fscanf(filep, "%d", &value) != 1)
114 err(1, "%s: failed to parse number from file", path);
115 fclose(filep);
116
117 return value;
118}
119
120int cpufreq_sysfs_present(void)
121{
122 DIR *dir;
123
124 dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq");
125 if (dir) {
126 closedir(dir);
127 return 1;
128 }
129
130 return 0;
131}
132
133int out_format_is_json(void)
134{
135 return out_format_json;
136}
137
138int get_physical_package_id(int cpu)
139{
140 return parse_int_file(
141 1, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
142 cpu);
143}
144
145int get_physical_core_id(int cpu)
146{
147 return parse_int_file(
148 1, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
149}
150
151int get_physical_die_id(int cpu)
152{
153 int ret;
154
155 ret = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/topology/die_id",
156 cpu);
157 if (ret < 0)
158 ret = 0;
159
160 return ret;
161}
162
163int get_topo_max_cpus(void)
164{
165 return topo_max_cpus;
166}
167
168#define MAX_PACKAGE_COUNT 8
169#define MAX_DIE_PER_PACKAGE 2
170static void for_each_online_package_in_set(void (*callback)(int, void *, void *,
171 void *, void *),
172 void *arg1, void *arg2, void *arg3,
173 void *arg4)
174{
175 int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT];
176 int pkg_index = 0, i;
177
178 memset(max_packages, 0xff, sizeof(max_packages));
179 for (i = 0; i < topo_max_cpus; ++i) {
180 int j, online, pkg_id, die_id = 0, skip = 0;
181
182 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
183 continue;
184 if (i)
185 online = parse_int_file(
186 1, "/sys/devices/system/cpu/cpu%d/online", i);
187 else
188 online =
189 1; /* online entry for CPU 0 needs some special configs */
190
191 die_id = get_physical_die_id(i);
192 if (die_id < 0)
193 die_id = 0;
194 pkg_id = get_physical_package_id(i);
195 /* Create an unique id for package, die combination to store */
196 pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
197
198 for (j = 0; j < pkg_index; ++j) {
199 if (max_packages[j] == pkg_id) {
200 skip = 1;
201 break;
202 }
203 }
204
205 if (!skip && online && callback) {
206 callback(i, arg1, arg2, arg3, arg4);
207 max_packages[pkg_index++] = pkg_id;
208 }
209 }
210}
211
212static void for_each_online_target_cpu_in_set(
213 void (*callback)(int, void *, void *, void *, void *), void *arg1,
214 void *arg2, void *arg3, void *arg4)
215{
216 int i;
217
218 for (i = 0; i < topo_max_cpus; ++i) {
219 int online;
220
221 if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
222 continue;
223 if (i)
224 online = parse_int_file(
225 1, "/sys/devices/system/cpu/cpu%d/online", i);
226 else
227 online =
228 1; /* online entry for CPU 0 needs some special configs */
229
230 if (online && callback)
231 callback(i, arg1, arg2, arg3, arg4);
232 }
233}
234
235#define BITMASK_SIZE 32
236static void set_max_cpu_num(void)
237{
238 FILE *filep;
239 unsigned long dummy;
240
241 topo_max_cpus = 0;
242 filep = fopen_or_exit(
243 "/sys/devices/system/cpu/cpu0/topology/thread_siblings", "r");
244 while (fscanf(filep, "%lx,", &dummy) == 1)
245 topo_max_cpus += BITMASK_SIZE;
246 fclose(filep);
247 topo_max_cpus--; /* 0 based */
248
249 debug_printf("max cpus %d\n", topo_max_cpus);
250}
251
252size_t alloc_cpu_set(cpu_set_t **cpu_set)
253{
254 cpu_set_t *_cpu_set;
255 size_t size;
256
257 _cpu_set = CPU_ALLOC((topo_max_cpus + 1));
258 if (_cpu_set == NULL)
259 err(3, "CPU_ALLOC");
260 size = CPU_ALLOC_SIZE((topo_max_cpus + 1));
261 CPU_ZERO_S(size, _cpu_set);
262
263 *cpu_set = _cpu_set;
264 return size;
265}
266
267void free_cpu_set(cpu_set_t *cpu_set)
268{
269 CPU_FREE(cpu_set);
270}
271
272static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
273static void set_cpu_present_cpu_mask(void)
274{
275 size_t size;
276 DIR *dir;
277 int i;
278
279 size = alloc_cpu_set(&present_cpumask);
280 present_cpumask_size = size;
281 for (i = 0; i < topo_max_cpus; ++i) {
282 char buffer[256];
283
284 snprintf(buffer, sizeof(buffer),
285 "/sys/devices/system/cpu/cpu%d", i);
286 dir = opendir(buffer);
287 if (dir) {
288 int pkg_id, die_id;
289
290 CPU_SET_S(i, size, present_cpumask);
291 die_id = get_physical_die_id(i);
292 if (die_id < 0)
293 die_id = 0;
294
295 pkg_id = get_physical_package_id(i);
296 if (pkg_id < MAX_PACKAGE_COUNT &&
297 die_id < MAX_DIE_PER_PACKAGE)
298 cpu_cnt[pkg_id][die_id]++;
299 }
300 closedir(dir);
301 }
302}
303
304int get_cpu_count(int pkg_id, int die_id)
305{
306 if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
307 return cpu_cnt[pkg_id][die_id] + 1;
308
309 return 0;
310}
311
312static void set_cpu_target_cpu_mask(void)
313{
314 size_t size;
315 int i;
316
317 size = alloc_cpu_set(&target_cpumask);
318 target_cpumask_size = size;
319 for (i = 0; i < max_target_cpus; ++i) {
320 if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size,
321 present_cpumask))
322 continue;
323
324 CPU_SET_S(target_cpus[i], size, target_cpumask);
325 }
326}
327
328static void create_cpu_map(void)
329{
330 const char *pathname = "/dev/isst_interface";
331 int i, fd = 0;
332 struct isst_if_cpu_maps map;
333
334 cpu_map = malloc(sizeof(*cpu_map) * topo_max_cpus);
335 if (!cpu_map)
336 err(3, "cpumap");
337
338 fd = open(pathname, O_RDWR);
339 if (fd < 0)
340 err(-1, "%s open failed", pathname);
341
342 for (i = 0; i < topo_max_cpus; ++i) {
343 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
344 continue;
345
346 map.cmd_count = 1;
347 map.cpu_map[0].logical_cpu = i;
348
349 debug_printf(" map logical_cpu:%d\n",
350 map.cpu_map[0].logical_cpu);
351 if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
352 perror("ISST_IF_GET_PHY_ID");
353 fprintf(outf, "Error: map logical_cpu:%d\n",
354 map.cpu_map[0].logical_cpu);
355 continue;
356 }
357 cpu_map[i].core_id = get_physical_core_id(i);
358 cpu_map[i].pkg_id = get_physical_package_id(i);
359 cpu_map[i].die_id = get_physical_die_id(i);
360 cpu_map[i].punit_cpu = map.cpu_map[0].physical_cpu;
361 cpu_map[i].punit_cpu_core = (map.cpu_map[0].physical_cpu >>
362 1); // shift to get core id
363
364 debug_printf(
365 "map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n",
366 i, cpu_map[i].core_id, cpu_map[i].die_id,
367 cpu_map[i].pkg_id, cpu_map[i].punit_cpu,
368 cpu_map[i].punit_cpu_core);
369 }
370
371 if (fd)
372 close(fd);
373}
374
375int find_logical_cpu(int pkg_id, int die_id, int punit_core_id)
376{
377 int i;
378
379 for (i = 0; i < topo_max_cpus; ++i) {
380 if (cpu_map[i].pkg_id == pkg_id &&
381 cpu_map[i].die_id == die_id &&
382 cpu_map[i].punit_cpu_core == punit_core_id)
383 return i;
384 }
385
386 return -EINVAL;
387}
388
389void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask,
390 size_t core_cpumask_size,
391 cpu_set_t *core_cpumask, int *cpu_cnt)
392{
393 int i, cnt = 0;
394 int die_id, pkg_id;
395
396 *cpu_cnt = 0;
397 die_id = get_physical_die_id(cpu);
398 pkg_id = get_physical_package_id(cpu);
399
400 for (i = 0; i < 64; ++i) {
401 if (core_mask & BIT(i)) {
402 int j;
403
404 for (j = 0; j < topo_max_cpus; ++j) {
405 if (cpu_map[j].pkg_id == pkg_id &&
406 cpu_map[j].die_id == die_id &&
407 cpu_map[j].punit_cpu_core == i) {
408 CPU_SET_S(j, core_cpumask_size,
409 core_cpumask);
410 ++cnt;
411 }
412 }
413 }
414 }
415
416 *cpu_cnt = cnt;
417}
418
419int find_phy_core_num(int logical_cpu)
420{
421 if (logical_cpu < topo_max_cpus)
422 return cpu_map[logical_cpu].punit_cpu_core;
423
424 return -EINVAL;
425}
426
427static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
428 unsigned int *value)
429{
430 struct isst_if_io_regs io_regs;
431 const char *pathname = "/dev/isst_interface";
432 int cmd;
433 int fd;
434
435 debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
436
437 fd = open(pathname, O_RDWR);
438 if (fd < 0)
439 err(-1, "%s open failed", pathname);
440
441 io_regs.req_count = 1;
442 io_regs.io_reg[0].logical_cpu = cpu;
443 io_regs.io_reg[0].reg = reg;
444 cmd = ISST_IF_IO_CMD;
445 if (write) {
446 io_regs.io_reg[0].read_write = 1;
447 io_regs.io_reg[0].value = *value;
448 } else {
449 io_regs.io_reg[0].read_write = 0;
450 }
451
452 if (ioctl(fd, cmd, &io_regs) == -1) {
453 perror("ISST_IF_IO_CMD");
454 fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
455 cpu, reg, write);
456 } else {
457 if (!write)
458 *value = io_regs.io_reg[0].value;
459
460 debug_printf(
461 "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
462 cpu, reg, write, *value);
463 }
464
465 close(fd);
466
467 return 0;
468}
469
470int isst_send_mbox_command(unsigned int cpu, unsigned char command,
471 unsigned char sub_command, unsigned int parameter,
472 unsigned int req_data, unsigned int *resp)
473{
474 const char *pathname = "/dev/isst_interface";
475 int fd;
476 struct isst_if_mbox_cmds mbox_cmds = { 0 };
477
478 debug_printf(
479 "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
480 cpu, command, sub_command, parameter, req_data);
481
482 if (isst_platform_info.mmio_supported && command == CONFIG_CLOS) {
483 unsigned int value;
484 int write = 0;
485 int clos_id, core_id, ret = 0;
486
487 debug_printf("CLOS %d\n", cpu);
488
489 if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
490 value = req_data;
491 write = 1;
492 }
493
494 switch (sub_command) {
495 case CLOS_PQR_ASSOC:
496 core_id = parameter & 0xff;
497 ret = isst_send_mmio_command(
498 cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
499 &value);
500 if (!ret && !write)
501 *resp = value;
502 break;
503 case CLOS_PM_CLOS:
504 clos_id = parameter & 0x03;
505 ret = isst_send_mmio_command(
506 cpu, PM_CLOS_OFFSET + clos_id * 4, write,
507 &value);
508 if (!ret && !write)
509 *resp = value;
510 break;
511 case CLOS_PM_QOS_CONFIG:
512 ret = isst_send_mmio_command(cpu, PM_QOS_CONFIG_OFFSET,
513 write, &value);
514 if (!ret && !write)
515 *resp = value;
516 break;
517 case CLOS_STATUS:
518 break;
519 default:
520 break;
521 }
522 return ret;
523 }
524
525 mbox_cmds.cmd_count = 1;
526 mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
527 mbox_cmds.mbox_cmd[0].command = command;
528 mbox_cmds.mbox_cmd[0].sub_command = sub_command;
529 mbox_cmds.mbox_cmd[0].parameter = parameter;
530 mbox_cmds.mbox_cmd[0].req_data = req_data;
531
532 fd = open(pathname, O_RDWR);
533 if (fd < 0)
534 err(-1, "%s open failed", pathname);
535
536 if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
537 perror("ISST_IF_MBOX_COMMAND");
538 fprintf(outf,
539 "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
540 cpu, command, sub_command, parameter, req_data);
541 } else {
542 *resp = mbox_cmds.mbox_cmd[0].resp_data;
543 debug_printf(
544 "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
545 cpu, command, sub_command, parameter, req_data, *resp);
546 }
547
548 close(fd);
549
550 return 0;
551}
552
553int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
554 unsigned long long *req_resp)
555{
556 struct isst_if_msr_cmds msr_cmds;
557 const char *pathname = "/dev/isst_interface";
558 int fd;
559
560 fd = open(pathname, O_RDWR);
561 if (fd < 0)
562 err(-1, "%s open failed", pathname);
563
564 msr_cmds.cmd_count = 1;
565 msr_cmds.msr_cmd[0].logical_cpu = cpu;
566 msr_cmds.msr_cmd[0].msr = msr;
567 msr_cmds.msr_cmd[0].read_write = write;
568 if (write)
569 msr_cmds.msr_cmd[0].data = *req_resp;
570
571 if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
572 perror("ISST_IF_MSR_COMMAD");
573 fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
574 cpu, msr, write);
575 } else {
576 if (!write)
577 *req_resp = msr_cmds.msr_cmd[0].data;
578
579 debug_printf(
580 "msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
581 cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
582 }
583
584 close(fd);
585
586 return 0;
587}
588
589static int isst_fill_platform_info(void)
590{
591 const char *pathname = "/dev/isst_interface";
592 int fd;
593
594 fd = open(pathname, O_RDWR);
595 if (fd < 0)
596 err(-1, "%s open failed", pathname);
597
598 if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) {
599 perror("ISST_IF_GET_PLATFORM_INFO");
600 close(fd);
601 return -1;
602 }
603
604 close(fd);
605
606 return 0;
607}
608
609static void isst_print_platform_information(void)
610{
611 struct isst_if_platform_info platform_info;
612 const char *pathname = "/dev/isst_interface";
613 int fd;
614
615 fd = open(pathname, O_RDWR);
616 if (fd < 0)
617 err(-1, "%s open failed", pathname);
618
619 if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) {
620 perror("ISST_IF_GET_PLATFORM_INFO");
621 } else {
622 fprintf(outf, "Platform: API version : %d\n",
623 platform_info.api_version);
624 fprintf(outf, "Platform: Driver version : %d\n",
625 platform_info.driver_version);
626 fprintf(outf, "Platform: mbox supported : %d\n",
627 platform_info.mbox_supported);
628 fprintf(outf, "Platform: mmio supported : %d\n",
629 platform_info.mmio_supported);
630 }
631
632 close(fd);
633
634 exit(0);
635}
636
637static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
638 void *arg4)
639{
640 int (*fn_ptr)(int cpu, void *arg);
641 int ret;
642
643 fn_ptr = arg1;
644 ret = fn_ptr(cpu, arg2);
645 if (ret)
646 perror("get_tdp_*");
647 else
648 isst_display_result(cpu, outf, "perf-profile", (char *)arg3,
649 *(unsigned int *)arg4);
650}
651
652#define _get_tdp_level(desc, suffix, object, help) \
653 static void get_tdp_##object(void) \
654 { \
655 struct isst_pkg_ctdp ctdp; \
656\
657 if (cmd_help) { \
658 fprintf(stderr, \
659 "Print %s [No command arguments are required]\n", \
660 help); \
661 exit(0); \
662 } \
663 isst_ctdp_display_information_start(outf); \
664 if (max_target_cpus) \
665 for_each_online_target_cpu_in_set( \
666 exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix, \
667 &ctdp, desc, &ctdp.object); \
668 else \
669 for_each_online_package_in_set(exec_on_get_ctdp_cpu, \
670 isst_get_ctdp_##suffix, \
671 &ctdp, desc, \
672 &ctdp.object); \
673 isst_ctdp_display_information_end(outf); \
674 }
675
676_get_tdp_level("get-config-levels", levels, levels, "TDP levels");
677_get_tdp_level("get-config-version", levels, version, "TDP version");
678_get_tdp_level("get-config-enabled", levels, enabled, "TDP enable status");
679_get_tdp_level("get-config-current_level", levels, current_level,
680 "Current TDP Level");
681_get_tdp_level("get-lock-status", levels, locked, "TDP lock status");
682
683static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2,
684 void *arg3, void *arg4)
685{
686 struct isst_pkg_ctdp pkg_dev;
687 int ret;
688
689 memset(&pkg_dev, 0, sizeof(pkg_dev));
690 ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev);
691 if (ret) {
692 perror("isst_get_process_ctdp");
693 } else {
694 isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev);
695 isst_get_process_ctdp_complete(cpu, &pkg_dev);
696 }
697}
698
699static void dump_isst_config(void)
700{
701 if (cmd_help) {
702 fprintf(stderr,
703 "Print Intel(R) Speed Select Technology Performance profile configuration\n");
704 fprintf(stderr,
705 "including base frequency and turbo frequency configurations\n");
706 fprintf(stderr, "Optional: -l|--level : Specify tdp level\n");
707 fprintf(stderr,
708 "\tIf no arguments, dump information for all TDP levels\n");
709 exit(0);
710 }
711
712 isst_ctdp_display_information_start(outf);
713
714 if (max_target_cpus)
715 for_each_online_target_cpu_in_set(dump_isst_config_for_cpu,
716 NULL, NULL, NULL, NULL);
717 else
718 for_each_online_package_in_set(dump_isst_config_for_cpu, NULL,
719 NULL, NULL, NULL);
720
721 isst_ctdp_display_information_end(outf);
722}
723
724static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
725 void *arg4)
726{
727 int ret;
728
729 ret = isst_set_tdp_level(cpu, tdp_level);
730 if (ret)
731 perror("set_tdp_level_for_cpu");
732 else
733 isst_display_result(cpu, outf, "perf-profile", "set_tdp_level",
734 ret);
735}
736
737static void set_tdp_level(void)
738{
739 if (cmd_help) {
740 fprintf(stderr, "Set Config TDP level\n");
741 fprintf(stderr,
742 "\t Arguments: -l|--level : Specify tdp level\n");
743 exit(0);
744 }
745
746 if (tdp_level == 0xff) {
747 fprintf(outf, "Invalid command: specify tdp_level\n");
748 exit(1);
749 }
750 isst_ctdp_display_information_start(outf);
751 if (max_target_cpus)
752 for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
753 NULL, NULL, NULL);
754 else
755 for_each_online_package_in_set(set_tdp_level_for_cpu, NULL,
756 NULL, NULL, NULL);
757 isst_ctdp_display_information_end(outf);
758}
759
760static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
761 void *arg4)
762{
763 struct isst_pbf_info pbf_info;
764 int ret;
765
766 ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info);
767 if (ret) {
768 perror("isst_get_pbf_info");
769 } else {
770 isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info);
771 isst_get_pbf_info_complete(&pbf_info);
772 }
773}
774
775static void dump_pbf_config(void)
776{
777 if (cmd_help) {
778 fprintf(stderr,
779 "Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n");
780 fprintf(stderr,
781 "\tArguments: -l|--level : Specify tdp level\n");
782 exit(0);
783 }
784
785 if (tdp_level == 0xff) {
786 fprintf(outf, "Invalid command: specify tdp_level\n");
787 exit(1);
788 }
789
790 isst_ctdp_display_information_start(outf);
791 if (max_target_cpus)
792 for_each_online_target_cpu_in_set(dump_pbf_config_for_cpu, NULL,
793 NULL, NULL, NULL);
794 else
795 for_each_online_package_in_set(dump_pbf_config_for_cpu, NULL,
796 NULL, NULL, NULL);
797 isst_ctdp_display_information_end(outf);
798}
799
800static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
801 void *arg4)
802{
803 int ret;
804 int status = *(int *)arg4;
805
806 ret = isst_set_pbf_fact_status(cpu, 1, status);
807 if (ret) {
808 perror("isst_set_pbf");
809 } else {
810 if (status)
811 isst_display_result(cpu, outf, "base-freq", "enable",
812 ret);
813 else
814 isst_display_result(cpu, outf, "base-freq", "disable",
815 ret);
816 }
817}
818
819static void set_pbf_enable(void)
820{
821 int status = 1;
822
823 if (cmd_help) {
824 fprintf(stderr,
825 "Enable Intel Speed Select Technology base frequency feature [No command arguments are required]\n");
826 exit(0);
827 }
828
829 isst_ctdp_display_information_start(outf);
830 if (max_target_cpus)
831 for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
832 NULL, &status);
833 else
834 for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
835 NULL, &status);
836 isst_ctdp_display_information_end(outf);
837}
838
839static void set_pbf_disable(void)
840{
841 int status = 0;
842
843 if (cmd_help) {
844 fprintf(stderr,
845 "Disable Intel Speed Select Technology base frequency feature [No command arguments are required]\n");
846 exit(0);
847 }
848
849 isst_ctdp_display_information_start(outf);
850 if (max_target_cpus)
851 for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
852 NULL, &status);
853 else
854 for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
855 NULL, &status);
856 isst_ctdp_display_information_end(outf);
857}
858
859static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2,
860 void *arg3, void *arg4)
861{
862 struct isst_fact_info fact_info;
863 int ret;
864
865 ret = isst_get_fact_info(cpu, tdp_level, &fact_info);
866 if (ret)
867 perror("isst_get_fact_bucket_info");
868 else
869 isst_fact_display_information(cpu, outf, tdp_level, fact_bucket,
870 fact_avx, &fact_info);
871}
872
873static void dump_fact_config(void)
874{
875 if (cmd_help) {
876 fprintf(stderr,
877 "Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n");
878 fprintf(stderr,
879 "\tArguments: -l|--level : Specify tdp level\n");
880 fprintf(stderr,
881 "\tArguments: -b|--bucket : Bucket index to dump\n");
882 fprintf(stderr,
883 "\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n");
884 exit(0);
885 }
886
887 if (tdp_level == 0xff) {
888 fprintf(outf, "Invalid command: specify tdp_level\n");
889 exit(1);
890 }
891
892 isst_ctdp_display_information_start(outf);
893 if (max_target_cpus)
894 for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
895 NULL, NULL, NULL, NULL);
896 else
897 for_each_online_package_in_set(dump_fact_config_for_cpu, NULL,
898 NULL, NULL, NULL);
899 isst_ctdp_display_information_end(outf);
900}
901
902static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
903 void *arg4)
904{
905 int ret;
906 int status = *(int *)arg4;
907
908 ret = isst_set_pbf_fact_status(cpu, 0, status);
909 if (ret)
910 perror("isst_set_fact");
911 else {
912 if (status) {
913 struct isst_pkg_ctdp pkg_dev;
914
915 ret = isst_get_ctdp_levels(cpu, &pkg_dev);
916 if (ret) {
917 isst_display_result(cpu, outf, "turbo-freq",
918 "enable", ret);
919 return;
920 }
921 ret = isst_set_trl(cpu, fact_trl);
922 isst_display_result(cpu, outf, "turbo-freq", "enable",
923 ret);
924 } else {
925 /* Since we modified TRL during Fact enable, restore it */
926 isst_set_trl_from_current_tdp(cpu, fact_trl);
927 isst_display_result(cpu, outf, "turbo-freq", "disable",
928 ret);
929 }
930 }
931}
932
933static void set_fact_enable(void)
934{
935 int status = 1;
936
937 if (cmd_help) {
938 fprintf(stderr,
939 "Enable Intel Speed Select Technology Turbo frequency feature\n");
940 fprintf(stderr,
941 "Optional: -t|--trl : Specify turbo ratio limit\n");
942 exit(0);
943 }
944
945 isst_ctdp_display_information_start(outf);
946 if (max_target_cpus)
947 for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
948 NULL, &status);
949 else
950 for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
951 NULL, &status);
952 isst_ctdp_display_information_end(outf);
953}
954
955static void set_fact_disable(void)
956{
957 int status = 0;
958
959 if (cmd_help) {
960 fprintf(stderr,
961 "Disable Intel Speed Select Technology turbo frequency feature\n");
962 fprintf(stderr,
963 "Optional: -t|--trl : Specify turbo ratio limit\n");
964 exit(0);
965 }
966
967 isst_ctdp_display_information_start(outf);
968 if (max_target_cpus)
969 for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
970 NULL, &status);
971 else
972 for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
973 NULL, &status);
974 isst_ctdp_display_information_end(outf);
975}
976
977static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3,
978 void *arg4)
979{
980 int ret;
981 int status = *(int *)arg4;
982
983 ret = isst_pm_qos_config(cpu, status, clos_priority_type);
984 if (ret) {
985 perror("isst_pm_qos_config");
986 } else {
987 if (status)
988 isst_display_result(cpu, outf, "core-power", "enable",
989 ret);
990 else
991 isst_display_result(cpu, outf, "core-power", "disable",
992 ret);
993 }
994}
995
996static void set_clos_enable(void)
997{
998 int status = 1;
999
1000 if (cmd_help) {
1001 fprintf(stderr, "Enable core-power for a package/die\n");
1002 fprintf(stderr,
1003 "\tClos Enable: Specify priority type with [--priority|-p]\n");
1004 fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
1005 exit(0);
1006 }
1007
1008 if (cpufreq_sysfs_present()) {
1009 fprintf(stderr,
1010 "cpufreq subsystem and core-power enable will interfere with each other!\n");
1011 }
1012
1013 isst_ctdp_display_information_start(outf);
1014 if (max_target_cpus)
1015 for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
1016 NULL, NULL, &status);
1017 else
1018 for_each_online_package_in_set(enable_clos_qos_config, NULL,
1019 NULL, NULL, &status);
1020 isst_ctdp_display_information_end(outf);
1021}
1022
1023static void set_clos_disable(void)
1024{
1025 int status = 0;
1026
1027 if (cmd_help) {
1028 fprintf(stderr,
1029 "Disable core-power: [No command arguments are required]\n");
1030 exit(0);
1031 }
1032
1033 isst_ctdp_display_information_start(outf);
1034 if (max_target_cpus)
1035 for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
1036 NULL, NULL, &status);
1037 else
1038 for_each_online_package_in_set(enable_clos_qos_config, NULL,
1039 NULL, NULL, &status);
1040 isst_ctdp_display_information_end(outf);
1041}
1042
1043static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2,
1044 void *arg3, void *arg4)
1045{
1046 struct isst_clos_config clos_config;
1047 int ret;
1048
1049 ret = isst_pm_get_clos(cpu, current_clos, &clos_config);
1050 if (ret)
1051 perror("isst_pm_get_clos");
1052 else
1053 isst_clos_display_information(cpu, outf, current_clos,
1054 &clos_config);
1055}
1056
1057static void dump_clos_config(void)
1058{
1059 if (cmd_help) {
1060 fprintf(stderr,
1061 "Print Intel Speed Select Technology core power configuration\n");
1062 fprintf(stderr,
1063 "\tArguments: [-c | --clos]: Specify clos id\n");
1064 exit(0);
1065 }
1066 if (current_clos < 0 || current_clos > 3) {
1067 fprintf(stderr, "Invalid clos id\n");
1068 exit(0);
1069 }
1070
1071 isst_ctdp_display_information_start(outf);
1072 if (max_target_cpus)
1073 for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
1074 NULL, NULL, NULL, NULL);
1075 else
1076 for_each_online_package_in_set(dump_clos_config_for_cpu, NULL,
1077 NULL, NULL, NULL);
1078 isst_ctdp_display_information_end(outf);
1079}
1080
1081static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1082 void *arg4)
1083{
1084 struct isst_clos_config clos_config;
1085 int ret;
1086
1087 clos_config.pkg_id = get_physical_package_id(cpu);
1088 clos_config.die_id = get_physical_die_id(cpu);
1089
1090 clos_config.epp = clos_epp;
1091 clos_config.clos_prop_prio = clos_prop_prio;
1092 clos_config.clos_min = clos_min;
1093 clos_config.clos_max = clos_max;
1094 clos_config.clos_desired = clos_desired;
1095 ret = isst_set_clos(cpu, current_clos, &clos_config);
1096 if (ret)
1097 perror("isst_set_clos");
1098 else
1099 isst_display_result(cpu, outf, "core-power", "config", ret);
1100}
1101
1102static void set_clos_config(void)
1103{
1104 if (cmd_help) {
1105 fprintf(stderr,
1106 "Set core-power configuration for one of the four clos ids\n");
1107 fprintf(stderr,
1108 "\tSpecify targeted clos id with [--clos|-c]\n");
1109 fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
1110 fprintf(stderr,
1111 "\tSpecify clos Proportional Priority [--weight|-w]\n");
1112 fprintf(stderr, "\tSpecify clos min with [--min|-n]\n");
1113 fprintf(stderr, "\tSpecify clos max with [--max|-m]\n");
1114 fprintf(stderr, "\tSpecify clos desired with [--desired|-d]\n");
1115 exit(0);
1116 }
1117
1118 if (current_clos < 0 || current_clos > 3) {
1119 fprintf(stderr, "Invalid clos id\n");
1120 exit(0);
1121 }
1122 if (clos_epp < 0 || clos_epp > 0x0F) {
1123 fprintf(stderr, "clos epp is not specified, default: 0\n");
1124 clos_epp = 0;
1125 }
1126 if (clos_prop_prio < 0 || clos_prop_prio > 0x0F) {
1127 fprintf(stderr,
1128 "clos frequency weight is not specified, default: 0\n");
1129 clos_prop_prio = 0;
1130 }
1131 if (clos_min < 0) {
1132 fprintf(stderr, "clos min is not specified, default: 0\n");
1133 clos_min = 0;
1134 }
1135 if (clos_max < 0) {
1136 fprintf(stderr, "clos max is not specified, default: 0xff\n");
1137 clos_max = 0xff;
1138 }
1139 if (clos_desired < 0) {
1140 fprintf(stderr, "clos desired is not specified, default: 0\n");
1141 clos_desired = 0x00;
1142 }
1143
1144 isst_ctdp_display_information_start(outf);
1145 if (max_target_cpus)
1146 for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
1147 NULL, NULL, NULL);
1148 else
1149 for_each_online_package_in_set(set_clos_config_for_cpu, NULL,
1150 NULL, NULL, NULL);
1151 isst_ctdp_display_information_end(outf);
1152}
1153
1154static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1155 void *arg4)
1156{
1157 int ret;
1158
1159 ret = isst_clos_associate(cpu, current_clos);
1160 if (ret)
1161 perror("isst_clos_associate");
1162 else
1163 isst_display_result(cpu, outf, "core-power", "assoc", ret);
1164}
1165
1166static void set_clos_assoc(void)
1167{
1168 if (cmd_help) {
1169 fprintf(stderr, "Associate a clos id to a CPU\n");
1170 fprintf(stderr,
1171 "\tSpecify targeted clos id with [--clos|-c]\n");
1172 exit(0);
1173 }
1174
1175 if (current_clos < 0 || current_clos > 3) {
1176 fprintf(stderr, "Invalid clos id\n");
1177 exit(0);
1178 }
1179 if (max_target_cpus)
1180 for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
1181 NULL, NULL, NULL);
1182 else {
1183 fprintf(stderr,
1184 "Invalid target cpu. Specify with [-c|--cpu]\n");
1185 }
1186}
1187
1188static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1189 void *arg4)
1190{
1191 int clos, ret;
1192
1193 ret = isst_clos_get_assoc_status(cpu, &clos);
1194 if (ret)
1195 perror("isst_clos_get_assoc_status");
1196 else
1197 isst_display_result(cpu, outf, "core-power", "get-assoc", clos);
1198}
1199
1200static void get_clos_assoc(void)
1201{
1202 if (cmd_help) {
1203 fprintf(stderr, "Get associate clos id to a CPU\n");
1204 fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
1205 exit(0);
1206 }
1207 if (max_target_cpus)
1208 for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL,
1209 NULL, NULL, NULL);
1210 else {
1211 fprintf(stderr,
1212 "Invalid target cpu. Specify with [-c|--cpu]\n");
1213 }
1214}
1215
1216static struct process_cmd_struct isst_cmds[] = {
1217 { "perf-profile", "get-lock-status", get_tdp_locked },
1218 { "perf-profile", "get-config-levels", get_tdp_levels },
1219 { "perf-profile", "get-config-version", get_tdp_version },
1220 { "perf-profile", "get-config-enabled", get_tdp_enabled },
1221 { "perf-profile", "get-config-current-level", get_tdp_current_level },
1222 { "perf-profile", "set-config-level", set_tdp_level },
1223 { "perf-profile", "info", dump_isst_config },
1224 { "base-freq", "info", dump_pbf_config },
1225 { "base-freq", "enable", set_pbf_enable },
1226 { "base-freq", "disable", set_pbf_disable },
1227 { "turbo-freq", "info", dump_fact_config },
1228 { "turbo-freq", "enable", set_fact_enable },
1229 { "turbo-freq", "disable", set_fact_disable },
1230 { "core-power", "info", dump_clos_config },
1231 { "core-power", "enable", set_clos_enable },
1232 { "core-power", "disable", set_clos_disable },
1233 { "core-power", "config", set_clos_config },
1234 { "core-power", "assoc", set_clos_assoc },
1235 { "core-power", "get-assoc", get_clos_assoc },
1236 { NULL, NULL, NULL }
1237};
1238
1239/*
1240 * parse cpuset with following syntax
1241 * 1,2,4..6,8-10 and set bits in cpu_subset
1242 */
1243void parse_cpu_command(char *optarg)
1244{
1245 unsigned int start, end;
1246 char *next;
1247
1248 next = optarg;
1249
1250 while (next && *next) {
1251 if (*next == '-') /* no negative cpu numbers */
1252 goto error;
1253
1254 start = strtoul(next, &next, 10);
1255
1256 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
1257 target_cpus[max_target_cpus++] = start;
1258
1259 if (*next == '\0')
1260 break;
1261
1262 if (*next == ',') {
1263 next += 1;
1264 continue;
1265 }
1266
1267 if (*next == '-') {
1268 next += 1; /* start range */
1269 } else if (*next == '.') {
1270 next += 1;
1271 if (*next == '.')
1272 next += 1; /* start range */
1273 else
1274 goto error;
1275 }
1276
1277 end = strtoul(next, &next, 10);
1278 if (end <= start)
1279 goto error;
1280
1281 while (++start <= end) {
1282 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
1283 target_cpus[max_target_cpus++] = start;
1284 }
1285
1286 if (*next == ',')
1287 next += 1;
1288 else if (*next != '\0')
1289 goto error;
1290 }
1291
1292#ifdef DEBUG
1293 {
1294 int i;
1295
1296 for (i = 0; i < max_target_cpus; ++i)
1297 printf("cpu [%d] in arg\n", target_cpus[i]);
1298 }
1299#endif
1300 return;
1301
1302error:
1303 fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
1304 exit(-1);
1305}
1306
1307static void parse_cmd_args(int argc, int start, char **argv)
1308{
1309 int opt;
1310 int option_index;
1311
1312 static struct option long_options[] = {
1313 { "bucket", required_argument, 0, 'b' },
1314 { "level", required_argument, 0, 'l' },
1315 { "trl-type", required_argument, 0, 'r' },
1316 { "trl", required_argument, 0, 't' },
1317 { "help", no_argument, 0, 'h' },
1318 { "clos", required_argument, 0, 'c' },
1319 { "desired", required_argument, 0, 'd' },
1320 { "epp", required_argument, 0, 'e' },
1321 { "min", required_argument, 0, 'n' },
1322 { "max", required_argument, 0, 'm' },
1323 { "priority", required_argument, 0, 'p' },
1324 { "weight", required_argument, 0, 'w' },
1325 { 0, 0, 0, 0 }
1326 };
1327
1328 option_index = start;
1329
1330 optind = start + 1;
1331 while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:h",
1332 long_options, &option_index)) != -1) {
1333 switch (opt) {
1334 case 'b':
1335 fact_bucket = atoi(optarg);
1336 break;
1337 case 'h':
1338 cmd_help = 1;
1339 break;
1340 case 'l':
1341 tdp_level = atoi(optarg);
1342 break;
1343 case 't':
1344 sscanf(optarg, "0x%llx", &fact_trl);
1345 break;
1346 case 'r':
1347 if (!strncmp(optarg, "sse", 3)) {
1348 fact_avx = 0x01;
1349 } else if (!strncmp(optarg, "avx2", 4)) {
1350 fact_avx = 0x02;
1351 } else if (!strncmp(optarg, "avx512", 4)) {
1352 fact_avx = 0x04;
1353 } else {
1354 fprintf(outf, "Invalid sse,avx options\n");
1355 exit(1);
1356 }
1357 break;
1358 /* CLOS related */
1359 case 'c':
1360 current_clos = atoi(optarg);
1361 printf("clos %d\n", current_clos);
1362 break;
1363 case 'd':
1364 clos_desired = atoi(optarg);
1365 break;
1366 case 'e':
1367 clos_epp = atoi(optarg);
1368 break;
1369 case 'n':
1370 clos_min = atoi(optarg);
1371 break;
1372 case 'm':
1373 clos_max = atoi(optarg);
1374 break;
1375 case 'p':
1376 clos_priority_type = atoi(optarg);
1377 break;
1378 case 'w':
1379 clos_prop_prio = atoi(optarg);
1380 break;
1381 default:
1382 printf("no match\n");
1383 }
1384 }
1385}
1386
1387static void isst_help(void)
1388{
1389 printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\
1390 performance profiles per system via static and/or dynamic\n\
1391 adjustment of core count, workload, Tjmax, and\n\
1392 TDP, etc.\n");
1393 printf("\nCommands : For feature=perf-profile\n");
1394 printf("\tinfo\n");
1395 printf("\tget-lock-status\n");
1396 printf("\tget-config-levels\n");
1397 printf("\tget-config-version\n");
1398 printf("\tget-config-enabled\n");
1399 printf("\tget-config-current-level\n");
1400 printf("\tset-config-level\n");
1401}
1402
1403static void pbf_help(void)
1404{
1405 printf("base-freq:\tEnables users to increase guaranteed base frequency\n\
1406 on certain cores (high priority cores) in exchange for lower\n\
1407 base frequency on remaining cores (low priority cores).\n");
1408 printf("\tcommand : info\n");
1409 printf("\tcommand : enable\n");
1410 printf("\tcommand : disable\n");
1411}
1412
1413static void fact_help(void)
1414{
1415 printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\
1416 limits to cores based on priority.\n");
1417 printf("\nCommand: For feature=turbo-freq\n");
1418 printf("\tcommand : info\n");
1419 printf("\tcommand : enable\n");
1420 printf("\tcommand : disable\n");
1421}
1422
1423static void core_power_help(void)
1424{
1425 printf("core-power:\tInterface that allows user to define per core/tile\n\
1426 priority.\n");
1427 printf("\nCommands : For feature=core-power\n");
1428 printf("\tinfo\n");
1429 printf("\tenable\n");
1430 printf("\tdisable\n");
1431 printf("\tconfig\n");
1432 printf("\tassoc\n");
1433 printf("\tget-assoc\n");
1434}
1435
1436struct process_cmd_help_struct {
1437 char *feature;
1438 void (*process_fn)(void);
1439};
1440
1441static struct process_cmd_help_struct isst_help_cmds[] = {
1442 { "perf-profile", isst_help },
1443 { "base-freq", pbf_help },
1444 { "turbo-freq", fact_help },
1445 { "core-power", core_power_help },
1446 { NULL, NULL }
1447};
1448
1449void process_command(int argc, char **argv)
1450{
1451 int i = 0, matched = 0;
1452 char *feature = argv[optind];
1453 char *cmd = argv[optind + 1];
1454
1455 if (!feature || !cmd)
1456 return;
1457
1458 debug_printf("feature name [%s] command [%s]\n", feature, cmd);
1459 if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
1460 while (isst_help_cmds[i].feature) {
1461 if (!strcmp(isst_help_cmds[i].feature, feature)) {
1462 isst_help_cmds[i].process_fn();
1463 exit(0);
1464 }
1465 ++i;
1466 }
1467 }
1468
1469 create_cpu_map();
1470
1471 i = 0;
1472 while (isst_cmds[i].feature) {
1473 if (!strcmp(isst_cmds[i].feature, feature) &&
1474 !strcmp(isst_cmds[i].command, cmd)) {
1475 parse_cmd_args(argc, optind + 1, argv);
1476 isst_cmds[i].process_fn();
1477 matched = 1;
1478 break;
1479 }
1480 ++i;
1481 }
1482
1483 if (!matched)
1484 fprintf(stderr, "Invalid command\n");
1485}
1486
1487static void usage(void)
1488{
1489 printf("Intel(R) Speed Select Technology\n");
1490 printf("\nUsage:\n");
1491 printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
1492 printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features,\n");
1493 printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
1494 printf("\nFor help on each feature, use --h|--help\n");
1495 printf("\tFor example: intel-speed-select perf-profile -h\n");
1496
1497 printf("\nFor additional help on each command for a feature, use --h|--help\n");
1498 printf("\tFor example: intel-speed-select perf-profile get-lock-status -h\n");
1499 printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n");
1500
1501 printf("\nOPTIONS\n");
1502 printf("\t[-c|--cpu] : logical cpu number\n");
1503 printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n");
1504 printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n");
1505 printf("\t[-d|--debug] : Debug mode\n");
1506 printf("\t[-h|--help] : Print help\n");
1507 printf("\t[-i|--info] : Print platform information\n");
1508 printf("\t[-o|--out] : Output file\n");
1509 printf("\t\t\tDefault : stderr\n");
1510 printf("\t[-f|--format] : output format [json|text]. Default: text\n");
1511 printf("\t[-v|--version] : Print version\n");
1512
1513 printf("\nResult format\n");
1514 printf("\tResult display uses a common format for each command:\n");
1515 printf("\tResults are formatted in text/JSON with\n");
1516 printf("\t\tPackage, Die, CPU, and command specific results.\n");
1517 printf("\t\t\tFor Set commands, status is 0 for success and rest for failures\n");
1518 exit(1);
1519}
1520
1521static void print_version(void)
1522{
1523 fprintf(outf, "Version %s\n", version_str);
1524 fprintf(outf, "Build date %s time %s\n", __DATE__, __TIME__);
1525 exit(0);
1526}
1527
1528static void cmdline(int argc, char **argv)
1529{
1530 int opt;
1531 int option_index = 0;
1532
1533 static struct option long_options[] = {
1534 { "cpu", required_argument, 0, 'c' },
1535 { "debug", no_argument, 0, 'd' },
1536 { "format", required_argument, 0, 'f' },
1537 { "help", no_argument, 0, 'h' },
1538 { "info", no_argument, 0, 'i' },
1539 { "out", required_argument, 0, 'o' },
1540 { "version", no_argument, 0, 'v' },
1541 { 0, 0, 0, 0 }
1542 };
1543
1544 progname = argv[0];
1545 while ((opt = getopt_long_only(argc, argv, "+c:df:hio:v", long_options,
1546 &option_index)) != -1) {
1547 switch (opt) {
1548 case 'c':
1549 parse_cpu_command(optarg);
1550 break;
1551 case 'd':
1552 debug_flag = 1;
1553 printf("Debug Mode ON\n");
1554 break;
1555 case 'f':
1556 if (!strncmp(optarg, "json", 4))
1557 out_format_json = 1;
1558 break;
1559 case 'h':
1560 usage();
1561 break;
1562 case 'i':
1563 isst_print_platform_information();
1564 break;
1565 case 'o':
1566 if (outf)
1567 fclose(outf);
1568 outf = fopen_or_exit(optarg, "w");
1569 break;
1570 case 'v':
1571 print_version();
1572 break;
1573 default:
1574 usage();
1575 }
1576 }
1577
1578 if (geteuid() != 0) {
1579 fprintf(stderr, "Must run as root\n");
1580 exit(0);
1581 }
1582
1583 if (optind > (argc - 2)) {
1584 fprintf(stderr, "Feature name and|or command not specified\n");
1585 exit(0);
1586 }
1587 update_cpu_model();
1588 printf("Intel(R) Speed Select Technology\n");
1589 printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
1590 set_max_cpu_num();
1591 set_cpu_present_cpu_mask();
1592 set_cpu_target_cpu_mask();
1593 isst_fill_platform_info();
1594 if (isst_platform_info.api_version > supported_api_ver) {
1595 printf("Incompatible API versions; Upgrade of tool is required\n");
1596 exit(0);
1597 }
1598
1599 process_command(argc, argv);
1600}
1601
1602int main(int argc, char **argv)
1603{
1604 outf = stderr;
1605 cmdline(argc, argv);
1606 return 0;
1607}
diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c
new file mode 100644
index 000000000000..8de4ac39a008
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-core.c
@@ -0,0 +1,721 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Intel Speed Select -- Enumerate and control features
4 * Copyright (c) 2019 Intel Corporation.
5 */
6
7#include "isst.h"
8
9int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
10{
11 unsigned int resp;
12 int ret;
13
14 ret = isst_send_mbox_command(cpu, CONFIG_TDP,
15 CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
16 if (ret)
17 return ret;
18
19 debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
20
21 pkg_dev->version = resp & 0xff;
22 pkg_dev->levels = (resp >> 8) & 0xff;
23 pkg_dev->current_level = (resp >> 16) & 0xff;
24 pkg_dev->locked = !!(resp & BIT(24));
25 pkg_dev->enabled = !!(resp & BIT(31));
26
27 return 0;
28}
29
30int isst_get_ctdp_control(int cpu, int config_index,
31 struct isst_pkg_ctdp_level_info *ctdp_level)
32{
33 unsigned int resp;
34 int ret;
35
36 ret = isst_send_mbox_command(cpu, CONFIG_TDP,
37 CONFIG_TDP_GET_TDP_CONTROL, 0,
38 config_index, &resp);
39 if (ret)
40 return ret;
41
42 ctdp_level->fact_support = resp & BIT(0);
43 ctdp_level->pbf_support = !!(resp & BIT(1));
44 ctdp_level->fact_enabled = !!(resp & BIT(16));
45 ctdp_level->pbf_enabled = !!(resp & BIT(17));
46
47 debug_printf(
48 "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
49 cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
50 ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
51
52 return 0;
53}
54
55int isst_get_tdp_info(int cpu, int config_index,
56 struct isst_pkg_ctdp_level_info *ctdp_level)
57{
58 unsigned int resp;
59 int ret;
60
61 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
62 0, config_index, &resp);
63 if (ret)
64 return ret;
65
66 ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
67 ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
68
69 debug_printf(
70 "cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
71 cpu, config_index, resp, ctdp_level->tdp_ratio,
72 ctdp_level->pkg_tdp);
73 return 0;
74}
75
76int isst_get_pwr_info(int cpu, int config_index,
77 struct isst_pkg_ctdp_level_info *ctdp_level)
78{
79 unsigned int resp;
80 int ret;
81
82 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
83 0, config_index, &resp);
84 if (ret)
85 return ret;
86
87 ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
88 ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
89
90 debug_printf(
91 "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
92 cpu, config_index, resp, ctdp_level->pkg_max_power,
93 ctdp_level->pkg_min_power);
94
95 return 0;
96}
97
98int isst_get_tjmax_info(int cpu, int config_index,
99 struct isst_pkg_ctdp_level_info *ctdp_level)
100{
101 unsigned int resp;
102 int ret;
103
104 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
105 0, config_index, &resp);
106 if (ret)
107 return ret;
108
109 ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
110
111 debug_printf(
112 "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
113 cpu, config_index, resp, ctdp_level->t_proc_hot);
114
115 return 0;
116}
117
118int isst_get_coremask_info(int cpu, int config_index,
119 struct isst_pkg_ctdp_level_info *ctdp_level)
120{
121 unsigned int resp;
122 int i, ret;
123
124 ctdp_level->cpu_count = 0;
125 for (i = 0; i < 2; ++i) {
126 unsigned long long mask;
127 int cpu_count = 0;
128
129 ret = isst_send_mbox_command(cpu, CONFIG_TDP,
130 CONFIG_TDP_GET_CORE_MASK, 0,
131 (i << 8) | config_index, &resp);
132 if (ret)
133 return ret;
134
135 debug_printf(
136 "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
137 cpu, config_index, i, resp);
138
139 mask = (unsigned long long)resp << (32 * i);
140 set_cpu_mask_from_punit_coremask(cpu, mask,
141 ctdp_level->core_cpumask_size,
142 ctdp_level->core_cpumask,
143 &cpu_count);
144 ctdp_level->cpu_count += cpu_count;
145 debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", cpu,
146 config_index, i, ctdp_level->cpu_count);
147 }
148
149 return 0;
150}
151
152int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
153{
154 unsigned int req, resp;
155 int ret;
156
157 req = level | (avx_level << 16);
158 ret = isst_send_mbox_command(cpu, CONFIG_TDP,
159 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
160 &resp);
161 if (ret)
162 return ret;
163
164 debug_printf(
165 "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
166 cpu, req, resp);
167
168 trl[0] = resp & GENMASK(7, 0);
169 trl[1] = (resp & GENMASK(15, 8)) >> 8;
170 trl[2] = (resp & GENMASK(23, 16)) >> 16;
171 trl[3] = (resp & GENMASK(31, 24)) >> 24;
172
173 req = level | BIT(8) | (avx_level << 16);
174 ret = isst_send_mbox_command(cpu, CONFIG_TDP,
175 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
176 &resp);
177 if (ret)
178 return ret;
179
180 debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", cpu,
181 req, resp);
182
183 trl[4] = resp & GENMASK(7, 0);
184 trl[5] = (resp & GENMASK(15, 8)) >> 8;
185 trl[6] = (resp & GENMASK(23, 16)) >> 16;
186 trl[7] = (resp & GENMASK(31, 24)) >> 24;
187
188 return 0;
189}
190
191int isst_set_tdp_level_msr(int cpu, int tdp_level)
192{
193 int ret;
194
195 debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
196
197 if (isst_get_config_tdp_lock_status(cpu)) {
198 debug_printf("cpu: tdp_locked %d\n", cpu);
199 return -1;
200 }
201
202 if (tdp_level > 2)
203 return -1; /* invalid value */
204
205 ret = isst_send_msr_command(cpu, 0x64b, 1,
206 (unsigned long long *)&tdp_level);
207 if (ret)
208 return ret;
209
210 debug_printf("cpu: tdp_level via MSR successful %d\n", cpu, tdp_level);
211
212 return 0;
213}
214
215int isst_set_tdp_level(int cpu, int tdp_level)
216{
217 unsigned int resp;
218 int ret;
219
220 ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
221 tdp_level, &resp);
222 if (ret)
223 return isst_set_tdp_level_msr(cpu, tdp_level);
224
225 return 0;
226}
227
228int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
229{
230 unsigned int req, resp;
231 int i, ret;
232
233 pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
234
235 for (i = 0; i < 2; ++i) {
236 unsigned long long mask;
237 int count;
238
239 ret = isst_send_mbox_command(cpu, CONFIG_TDP,
240 CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
241 0, (i << 8) | level, &resp);
242 if (ret)
243 return ret;
244
245 debug_printf(
246 "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
247 cpu, resp);
248
249 mask = (unsigned long long)resp << (32 * i);
250 set_cpu_mask_from_punit_coremask(cpu, mask,
251 pbf_info->core_cpumask_size,
252 pbf_info->core_cpumask,
253 &count);
254 }
255
256 req = level;
257 ret = isst_send_mbox_command(cpu, CONFIG_TDP,
258 CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
259 &resp);
260 if (ret)
261 return ret;
262
263 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", cpu,
264 resp);
265
266 pbf_info->p1_low = resp & 0xff;
267 pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
268
269 req = level;
270 ret = isst_send_mbox_command(
271 cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
272 if (ret)
273 return ret;
274
275 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", cpu, resp);
276
277 pbf_info->tdp = resp & 0xffff;
278
279 req = level;
280 ret = isst_send_mbox_command(
281 cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
282 if (ret)
283 return ret;
284
285 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", cpu,
286 resp);
287 pbf_info->t_control = (resp >> 8) & 0xff;
288 pbf_info->t_prochot = resp & 0xff;
289
290 return 0;
291}
292
293void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info)
294{
295 free_cpu_set(pbf_info->core_cpumask);
296}
297
298int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
299{
300 struct isst_pkg_ctdp pkg_dev;
301 struct isst_pkg_ctdp_level_info ctdp_level;
302 int current_level;
303 unsigned int req = 0, resp;
304 int ret;
305
306 ret = isst_get_ctdp_levels(cpu, &pkg_dev);
307 if (ret)
308 return ret;
309
310 current_level = pkg_dev.current_level;
311
312 ret = isst_get_ctdp_control(cpu, current_level, &ctdp_level);
313 if (ret)
314 return ret;
315
316 if (pbf) {
317 if (ctdp_level.fact_enabled)
318 req = BIT(16);
319
320 if (enable)
321 req |= BIT(17);
322 else
323 req &= ~BIT(17);
324 } else {
325 if (ctdp_level.pbf_enabled)
326 req = BIT(17);
327
328 if (enable)
329 req |= BIT(16);
330 else
331 req &= ~BIT(16);
332 }
333
334 ret = isst_send_mbox_command(cpu, CONFIG_TDP,
335 CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
336 if (ret)
337 return ret;
338
339 debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
340 cpu, pbf, req);
341
342 return 0;
343}
344
345int isst_get_fact_bucket_info(int cpu, int level,
346 struct isst_fact_bucket_info *bucket_info)
347{
348 unsigned int resp;
349 int i, k, ret;
350
351 for (i = 0; i < 2; ++i) {
352 int j;
353
354 ret = isst_send_mbox_command(
355 cpu, CONFIG_TDP,
356 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
357 (i << 8) | level, &resp);
358 if (ret)
359 return ret;
360
361 debug_printf(
362 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
363 cpu, i, level, resp);
364
365 for (j = 0; j < 4; ++j) {
366 bucket_info[j + (i * 4)].high_priority_cores_count =
367 (resp >> (j * 8)) & 0xff;
368 }
369 }
370
371 for (k = 0; k < 3; ++k) {
372 for (i = 0; i < 2; ++i) {
373 int j;
374
375 ret = isst_send_mbox_command(
376 cpu, CONFIG_TDP,
377 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
378 (k << 16) | (i << 8) | level, &resp);
379 if (ret)
380 return ret;
381
382 debug_printf(
383 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
384 cpu, i, level, k, resp);
385
386 for (j = 0; j < 4; ++j) {
387 switch (k) {
388 case 0:
389 bucket_info[j + (i * 4)].sse_trl =
390 (resp >> (j * 8)) & 0xff;
391 break;
392 case 1:
393 bucket_info[j + (i * 4)].avx_trl =
394 (resp >> (j * 8)) & 0xff;
395 break;
396 case 2:
397 bucket_info[j + (i * 4)].avx512_trl =
398 (resp >> (j * 8)) & 0xff;
399 break;
400 default:
401 break;
402 }
403 }
404 }
405 }
406
407 return 0;
408}
409
410int isst_get_fact_info(int cpu, int level, struct isst_fact_info *fact_info)
411{
412 unsigned int resp;
413 int ret;
414
415 ret = isst_send_mbox_command(cpu, CONFIG_TDP,
416 CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
417 level, &resp);
418 if (ret)
419 return ret;
420
421 debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
422 cpu, resp);
423
424 fact_info->lp_clipping_ratio_license_sse = resp & 0xff;
425 fact_info->lp_clipping_ratio_license_avx2 = (resp >> 8) & 0xff;
426 fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff;
427
428 ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info);
429
430 return ret;
431}
432
433int isst_set_trl(int cpu, unsigned long long trl)
434{
435 int ret;
436
437 if (!trl)
438 trl = 0xFFFFFFFFFFFFFFFFULL;
439
440 ret = isst_send_msr_command(cpu, 0x1AD, 1, &trl);
441 if (ret)
442 return ret;
443
444 return 0;
445}
446
447int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
448{
449 unsigned long long msr_trl;
450 int ret;
451
452 if (trl) {
453 msr_trl = trl;
454 } else {
455 struct isst_pkg_ctdp pkg_dev;
456 int trl[8];
457 int i;
458
459 ret = isst_get_ctdp_levels(cpu, &pkg_dev);
460 if (ret)
461 return ret;
462
463 ret = isst_get_get_trl(cpu, pkg_dev.current_level, 0, trl);
464 if (ret)
465 return ret;
466
467 msr_trl = 0;
468 for (i = 0; i < 8; ++i) {
469 unsigned long long _trl = trl[i];
470
471 msr_trl |= (_trl << (i * 8));
472 }
473 }
474 ret = isst_send_msr_command(cpu, 0x1AD, 1, &msr_trl);
475 if (ret)
476 return ret;
477
478 return 0;
479}
480
481/* Return 1 if locked */
482int isst_get_config_tdp_lock_status(int cpu)
483{
484 unsigned long long tdp_control = 0;
485 int ret;
486
487 ret = isst_send_msr_command(cpu, 0x64b, 0, &tdp_control);
488 if (ret)
489 return ret;
490
491 ret = !!(tdp_control & BIT(31));
492
493 return ret;
494}
495
496void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev)
497{
498 int i;
499
500 if (!pkg_dev->processed)
501 return;
502
503 for (i = 0; i < pkg_dev->levels; ++i) {
504 struct isst_pkg_ctdp_level_info *ctdp_level;
505
506 ctdp_level = &pkg_dev->ctdp_level[i];
507 if (ctdp_level->pbf_support)
508 free_cpu_set(ctdp_level->pbf_info.core_cpumask);
509 free_cpu_set(ctdp_level->core_cpumask);
510 }
511}
512
513int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
514{
515 int i, ret;
516
517 if (pkg_dev->processed)
518 return 0;
519
520 ret = isst_get_ctdp_levels(cpu, pkg_dev);
521 if (ret)
522 return ret;
523
524 debug_printf("cpu: %d ctdp enable:%d current level: %d levels:%d\n",
525 cpu, pkg_dev->enabled, pkg_dev->current_level,
526 pkg_dev->levels);
527
528 for (i = 0; i <= pkg_dev->levels; ++i) {
529 struct isst_pkg_ctdp_level_info *ctdp_level;
530
531 if (tdp_level != 0xff && i != tdp_level)
532 continue;
533
534 debug_printf("cpu:%d Get Information for TDP level:%d\n", cpu,
535 i);
536 ctdp_level = &pkg_dev->ctdp_level[i];
537
538 ctdp_level->processed = 1;
539 ctdp_level->level = i;
540 ctdp_level->control_cpu = cpu;
541 ctdp_level->pkg_id = get_physical_package_id(cpu);
542 ctdp_level->die_id = get_physical_die_id(cpu);
543
544 ret = isst_get_ctdp_control(cpu, i, ctdp_level);
545 if (ret)
546 return ret;
547
548 ret = isst_get_tdp_info(cpu, i, ctdp_level);
549 if (ret)
550 return ret;
551
552 ret = isst_get_pwr_info(cpu, i, ctdp_level);
553 if (ret)
554 return ret;
555
556 ret = isst_get_tjmax_info(cpu, i, ctdp_level);
557 if (ret)
558 return ret;
559
560 ctdp_level->core_cpumask_size =
561 alloc_cpu_set(&ctdp_level->core_cpumask);
562 ret = isst_get_coremask_info(cpu, i, ctdp_level);
563 if (ret)
564 return ret;
565
566 ret = isst_get_get_trl(cpu, i, 0,
567 ctdp_level->trl_sse_active_cores);
568 if (ret)
569 return ret;
570
571 ret = isst_get_get_trl(cpu, i, 1,
572 ctdp_level->trl_avx_active_cores);
573 if (ret)
574 return ret;
575
576 ret = isst_get_get_trl(cpu, i, 2,
577 ctdp_level->trl_avx_512_active_cores);
578 if (ret)
579 return ret;
580
581 if (ctdp_level->pbf_support) {
582 ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
583 if (!ret)
584 ctdp_level->pbf_found = 1;
585 }
586
587 if (ctdp_level->fact_support) {
588 ret = isst_get_fact_info(cpu, i,
589 &ctdp_level->fact_info);
590 if (ret)
591 return ret;
592 }
593 }
594
595 pkg_dev->processed = 1;
596
597 return 0;
598}
599
600int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
601{
602 unsigned int req, resp;
603 int ret;
604
605 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
606 &resp);
607 if (ret)
608 return ret;
609
610 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
611
612 req = resp;
613
614 if (enable_clos)
615 req = req | BIT(1);
616 else
617 req = req & ~BIT(1);
618
619 if (priority_type)
620 req = req | BIT(2);
621 else
622 req = req & ~BIT(2);
623
624 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
625 BIT(MBOX_CMD_WRITE_BIT), req, &resp);
626 if (ret)
627 return ret;
628
629 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", cpu,
630 priority_type, req);
631
632 return 0;
633}
634
635int isst_pm_get_clos(int cpu, int clos, struct isst_clos_config *clos_config)
636{
637 unsigned int resp;
638 int ret;
639
640 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
641 &resp);
642 if (ret)
643 return ret;
644
645 clos_config->pkg_id = get_physical_package_id(cpu);
646 clos_config->die_id = get_physical_die_id(cpu);
647
648 clos_config->epp = resp & 0x0f;
649 clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
650 clos_config->clos_min = (resp >> 8) & 0xff;
651 clos_config->clos_max = (resp >> 16) & 0xff;
652 clos_config->clos_desired = (resp >> 24) & 0xff;
653
654 return 0;
655}
656
657int isst_set_clos(int cpu, int clos, struct isst_clos_config *clos_config)
658{
659 unsigned int req, resp;
660 unsigned int param;
661 int ret;
662
663 req = clos_config->epp & 0x0f;
664 req |= (clos_config->clos_prop_prio & 0x0f) << 4;
665 req |= (clos_config->clos_min & 0xff) << 8;
666 req |= (clos_config->clos_max & 0xff) << 16;
667 req |= (clos_config->clos_desired & 0xff) << 24;
668
669 param = BIT(MBOX_CMD_WRITE_BIT) | clos;
670
671 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
672 &resp);
673 if (ret)
674 return ret;
675
676 debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", cpu, param, req);
677
678 return 0;
679}
680
681int isst_clos_get_assoc_status(int cpu, int *clos_id)
682{
683 unsigned int resp;
684 unsigned int param;
685 int core_id, ret;
686
687 core_id = find_phy_core_num(cpu);
688 param = core_id;
689
690 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
691 &resp);
692 if (ret)
693 return ret;
694
695 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", cpu, param,
696 resp);
697 *clos_id = (resp >> 16) & 0x03;
698
699 return 0;
700}
701
702int isst_clos_associate(int cpu, int clos_id)
703{
704 unsigned int req, resp;
705 unsigned int param;
706 int core_id, ret;
707
708 req = (clos_id & 0x03) << 16;
709 core_id = find_phy_core_num(cpu);
710 param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
711
712 ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
713 req, &resp);
714 if (ret)
715 return ret;
716
717 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", cpu, param,
718 req);
719
720 return 0;
721}
diff --git a/tools/power/x86/intel-speed-select/isst-display.c b/tools/power/x86/intel-speed-select/isst-display.c
new file mode 100644
index 000000000000..f368b8323742
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-display.c
@@ -0,0 +1,479 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Intel dynamic_speed_select -- Enumerate and control features
4 * Copyright (c) 2019 Intel Corporation.
5 */
6
7#include "isst.h"
8
9#define DISP_FREQ_MULTIPLIER 100000
10
11static void printcpumask(int str_len, char *str, int mask_size,
12 cpu_set_t *cpu_mask)
13{
14 int i, max_cpus = get_topo_max_cpus();
15 unsigned int *mask;
16 int size, index, curr_index;
17
18 size = max_cpus / (sizeof(unsigned int) * 8);
19 if (max_cpus % (sizeof(unsigned int) * 8))
20 size++;
21
22 mask = calloc(size, sizeof(unsigned int));
23 if (!mask)
24 return;
25
26 for (i = 0; i < max_cpus; ++i) {
27 int mask_index, bit_index;
28
29 if (!CPU_ISSET_S(i, mask_size, cpu_mask))
30 continue;
31
32 mask_index = i / (sizeof(unsigned int) * 8);
33 bit_index = i % (sizeof(unsigned int) * 8);
34 mask[mask_index] |= BIT(bit_index);
35 }
36
37 curr_index = 0;
38 for (i = size - 1; i >= 0; --i) {
39 index = snprintf(&str[curr_index], str_len - curr_index, "%08x",
40 mask[i]);
41 curr_index += index;
42 if (i) {
43 strncat(&str[curr_index], ",", str_len - curr_index);
44 curr_index++;
45 }
46 }
47
48 free(mask);
49}
50
51static void format_and_print_txt(FILE *outf, int level, char *header,
52 char *value)
53{
54 char *spaces = " ";
55 static char delimiters[256];
56 int i, j = 0;
57
58 if (!level)
59 return;
60
61 if (level == 1) {
62 strcpy(delimiters, " ");
63 } else {
64 for (i = 0; i < level - 1; ++i)
65 j += snprintf(&delimiters[j], sizeof(delimiters) - j,
66 "%s", spaces);
67 }
68
69 if (header && value) {
70 fprintf(outf, "%s", delimiters);
71 fprintf(outf, "%s:%s\n", header, value);
72 } else if (header) {
73 fprintf(outf, "%s", delimiters);
74 fprintf(outf, "%s\n", header);
75 }
76}
77
78static int last_level;
79static void format_and_print(FILE *outf, int level, char *header, char *value)
80{
81 char *spaces = " ";
82 static char delimiters[256];
83 int i;
84
85 if (!out_format_is_json()) {
86 format_and_print_txt(outf, level, header, value);
87 return;
88 }
89
90 if (level == 0) {
91 if (header)
92 fprintf(outf, "{");
93 else
94 fprintf(outf, "\n}\n");
95
96 } else {
97 int j = 0;
98
99 for (i = 0; i < level; ++i)
100 j += snprintf(&delimiters[j], sizeof(delimiters) - j,
101 "%s", spaces);
102
103 if (last_level == level)
104 fprintf(outf, ",\n");
105
106 if (value) {
107 if (last_level != level)
108 fprintf(outf, "\n");
109
110 fprintf(outf, "%s\"%s\": ", delimiters, header);
111 fprintf(outf, "\"%s\"", value);
112 } else {
113 for (i = last_level - 1; i >= level; --i) {
114 int k = 0;
115
116 for (j = i; j > 0; --j)
117 k += snprintf(&delimiters[k],
118 sizeof(delimiters) - k,
119 "%s", spaces);
120 if (i == level && header)
121 fprintf(outf, "\n%s},", delimiters);
122 else
123 fprintf(outf, "\n%s}", delimiters);
124 }
125 if (abs(last_level - level) < 3)
126 fprintf(outf, "\n");
127 if (header)
128 fprintf(outf, "%s\"%s\": {", delimiters,
129 header);
130 }
131 }
132
133 last_level = level;
134}
135
136static void print_packag_info(int cpu, FILE *outf)
137{
138 char header[256];
139
140 snprintf(header, sizeof(header), "package-%d",
141 get_physical_package_id(cpu));
142 format_and_print(outf, 1, header, NULL);
143 snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
144 format_and_print(outf, 2, header, NULL);
145 snprintf(header, sizeof(header), "cpu-%d", cpu);
146 format_and_print(outf, 3, header, NULL);
147}
148
149static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
150 struct isst_pbf_info *pbf_info,
151 int disp_level)
152{
153 char header[256];
154 char value[256];
155
156 snprintf(header, sizeof(header), "speed-select-base-freq");
157 format_and_print(outf, disp_level, header, NULL);
158
159 snprintf(header, sizeof(header), "high-priority-base-frequency(KHz)");
160 snprintf(value, sizeof(value), "%d",
161 pbf_info->p1_high * DISP_FREQ_MULTIPLIER);
162 format_and_print(outf, disp_level + 1, header, value);
163
164 snprintf(header, sizeof(header), "high-priority-cpu-mask");
165 printcpumask(sizeof(value), value, pbf_info->core_cpumask_size,
166 pbf_info->core_cpumask);
167 format_and_print(outf, disp_level + 1, header, value);
168
169 snprintf(header, sizeof(header), "low-priority-base-frequency(KHz)");
170 snprintf(value, sizeof(value), "%d",
171 pbf_info->p1_low * DISP_FREQ_MULTIPLIER);
172 format_and_print(outf, disp_level + 1, header, value);
173
174 snprintf(header, sizeof(header), "tjunction-temperature(C)");
175 snprintf(value, sizeof(value), "%d", pbf_info->t_prochot);
176 format_and_print(outf, disp_level + 1, header, value);
177
178 snprintf(header, sizeof(header), "thermal-design-power(W)");
179 snprintf(value, sizeof(value), "%d", pbf_info->tdp);
180 format_and_print(outf, disp_level + 1, header, value);
181}
182
183static void _isst_fact_display_information(int cpu, FILE *outf, int level,
184 int fact_bucket, int fact_avx,
185 struct isst_fact_info *fact_info,
186 int base_level)
187{
188 struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info;
189 char header[256];
190 char value[256];
191 int j;
192
193 snprintf(header, sizeof(header), "speed-select-turbo-freq");
194 format_and_print(outf, base_level, header, NULL);
195 for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
196 if (fact_bucket != 0xff && fact_bucket != j)
197 continue;
198
199 if (!bucket_info[j].high_priority_cores_count)
200 break;
201
202 snprintf(header, sizeof(header), "bucket-%d", j);
203 format_and_print(outf, base_level + 1, header, NULL);
204
205 snprintf(header, sizeof(header), "high-priority-cores-count");
206 snprintf(value, sizeof(value), "%d",
207 bucket_info[j].high_priority_cores_count);
208 format_and_print(outf, base_level + 2, header, value);
209
210 if (fact_avx & 0x01) {
211 snprintf(header, sizeof(header),
212 "high-priority-max-frequency(KHz)");
213 snprintf(value, sizeof(value), "%d",
214 bucket_info[j].sse_trl * DISP_FREQ_MULTIPLIER);
215 format_and_print(outf, base_level + 2, header, value);
216 }
217
218 if (fact_avx & 0x02) {
219 snprintf(header, sizeof(header),
220 "high-priority-max-avx2-frequency(KHz)");
221 snprintf(value, sizeof(value), "%d",
222 bucket_info[j].avx_trl * DISP_FREQ_MULTIPLIER);
223 format_and_print(outf, base_level + 2, header, value);
224 }
225
226 if (fact_avx & 0x04) {
227 snprintf(header, sizeof(header),
228 "high-priority-max-avx512-frequency(KHz)");
229 snprintf(value, sizeof(value), "%d",
230 bucket_info[j].avx512_trl *
231 DISP_FREQ_MULTIPLIER);
232 format_and_print(outf, base_level + 2, header, value);
233 }
234 }
235 snprintf(header, sizeof(header),
236 "speed-select-turbo-freq-clip-frequencies");
237 format_and_print(outf, base_level + 1, header, NULL);
238 snprintf(header, sizeof(header), "low-priority-max-frequency(KHz)");
239 snprintf(value, sizeof(value), "%d",
240 fact_info->lp_clipping_ratio_license_sse *
241 DISP_FREQ_MULTIPLIER);
242 format_and_print(outf, base_level + 2, header, value);
243 snprintf(header, sizeof(header),
244 "low-priority-max-avx2-frequency(KHz)");
245 snprintf(value, sizeof(value), "%d",
246 fact_info->lp_clipping_ratio_license_avx2 *
247 DISP_FREQ_MULTIPLIER);
248 format_and_print(outf, base_level + 2, header, value);
249 snprintf(header, sizeof(header),
250 "low-priority-max-avx512-frequency(KHz)");
251 snprintf(value, sizeof(value), "%d",
252 fact_info->lp_clipping_ratio_license_avx512 *
253 DISP_FREQ_MULTIPLIER);
254 format_and_print(outf, base_level + 2, header, value);
255}
256
257void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
258 struct isst_pkg_ctdp *pkg_dev)
259{
260 char header[256];
261 char value[256];
262 int i, base_level = 1;
263
264 print_packag_info(cpu, outf);
265
266 for (i = 0; i <= pkg_dev->levels; ++i) {
267 struct isst_pkg_ctdp_level_info *ctdp_level;
268 int j;
269
270 ctdp_level = &pkg_dev->ctdp_level[i];
271 if (!ctdp_level->processed)
272 continue;
273
274 snprintf(header, sizeof(header), "perf-profile-level-%d",
275 ctdp_level->level);
276 format_and_print(outf, base_level + 3, header, NULL);
277
278 snprintf(header, sizeof(header), "cpu-count");
279 j = get_cpu_count(get_physical_die_id(cpu),
280 get_physical_die_id(cpu));
281 snprintf(value, sizeof(value), "%d", j);
282 format_and_print(outf, base_level + 4, header, value);
283
284 snprintf(header, sizeof(header), "enable-cpu-mask");
285 printcpumask(sizeof(value), value,
286 ctdp_level->core_cpumask_size,
287 ctdp_level->core_cpumask);
288 format_and_print(outf, base_level + 4, header, value);
289
290 snprintf(header, sizeof(header), "thermal-design-power-ratio");
291 snprintf(value, sizeof(value), "%d", ctdp_level->tdp_ratio);
292 format_and_print(outf, base_level + 4, header, value);
293
294 snprintf(header, sizeof(header), "base-frequency(KHz)");
295 snprintf(value, sizeof(value), "%d",
296 ctdp_level->tdp_ratio * DISP_FREQ_MULTIPLIER);
297 format_and_print(outf, base_level + 4, header, value);
298
299 snprintf(header, sizeof(header),
300 "speed-select-turbo-freq-support");
301 snprintf(value, sizeof(value), "%d", ctdp_level->fact_support);
302 format_and_print(outf, base_level + 4, header, value);
303
304 snprintf(header, sizeof(header),
305 "speed-select-base-freq-support");
306 snprintf(value, sizeof(value), "%d", ctdp_level->pbf_support);
307 format_and_print(outf, base_level + 4, header, value);
308
309 snprintf(header, sizeof(header),
310 "speed-select-base-freq-enabled");
311 snprintf(value, sizeof(value), "%d", ctdp_level->pbf_enabled);
312 format_and_print(outf, base_level + 4, header, value);
313
314 snprintf(header, sizeof(header),
315 "speed-select-turbo-freq-enabled");
316 snprintf(value, sizeof(value), "%d", ctdp_level->fact_enabled);
317 format_and_print(outf, base_level + 4, header, value);
318
319 snprintf(header, sizeof(header), "thermal-design-power(W)");
320 snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp);
321 format_and_print(outf, base_level + 4, header, value);
322
323 snprintf(header, sizeof(header), "tjunction-max(C)");
324 snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot);
325 format_and_print(outf, base_level + 4, header, value);
326
327 snprintf(header, sizeof(header), "turbo-ratio-limits-sse");
328 format_and_print(outf, base_level + 4, header, NULL);
329 for (j = 0; j < 8; ++j) {
330 snprintf(header, sizeof(header), "bucket-%d", j);
331 format_and_print(outf, base_level + 5, header, NULL);
332
333 snprintf(header, sizeof(header), "core-count");
334 snprintf(value, sizeof(value), "%d", j);
335 format_and_print(outf, base_level + 6, header, value);
336
337 snprintf(header, sizeof(header), "turbo-ratio");
338 snprintf(value, sizeof(value), "%d",
339 ctdp_level->trl_sse_active_cores[j]);
340 format_and_print(outf, base_level + 6, header, value);
341 }
342 snprintf(header, sizeof(header), "turbo-ratio-limits-avx");
343 format_and_print(outf, base_level + 4, header, NULL);
344 for (j = 0; j < 8; ++j) {
345 snprintf(header, sizeof(header), "bucket-%d", j);
346 format_and_print(outf, base_level + 5, header, NULL);
347
348 snprintf(header, sizeof(header), "core-count");
349 snprintf(value, sizeof(value), "%d", j);
350 format_and_print(outf, base_level + 6, header, value);
351
352 snprintf(header, sizeof(header), "turbo-ratio");
353 snprintf(value, sizeof(value), "%d",
354 ctdp_level->trl_avx_active_cores[j]);
355 format_and_print(outf, base_level + 6, header, value);
356 }
357
358 snprintf(header, sizeof(header), "turbo-ratio-limits-avx512");
359 format_and_print(outf, base_level + 4, header, NULL);
360 for (j = 0; j < 8; ++j) {
361 snprintf(header, sizeof(header), "bucket-%d", j);
362 format_and_print(outf, base_level + 5, header, NULL);
363
364 snprintf(header, sizeof(header), "core-count");
365 snprintf(value, sizeof(value), "%d", j);
366 format_and_print(outf, base_level + 6, header, value);
367
368 snprintf(header, sizeof(header), "turbo-ratio");
369 snprintf(value, sizeof(value), "%d",
370 ctdp_level->trl_avx_512_active_cores[j]);
371 format_and_print(outf, base_level + 6, header, value);
372 }
373 if (ctdp_level->pbf_support)
374 _isst_pbf_display_information(cpu, outf, i,
375 &ctdp_level->pbf_info,
376 base_level + 4);
377 if (ctdp_level->fact_support)
378 _isst_fact_display_information(cpu, outf, i, 0xff, 0xff,
379 &ctdp_level->fact_info,
380 base_level + 4);
381 }
382
383 format_and_print(outf, 1, NULL, NULL);
384}
385
386void isst_ctdp_display_information_start(FILE *outf)
387{
388 last_level = 0;
389 format_and_print(outf, 0, "start", NULL);
390}
391
392void isst_ctdp_display_information_end(FILE *outf)
393{
394 format_and_print(outf, 0, NULL, NULL);
395}
396
397void isst_pbf_display_information(int cpu, FILE *outf, int level,
398 struct isst_pbf_info *pbf_info)
399{
400 print_packag_info(cpu, outf);
401 _isst_pbf_display_information(cpu, outf, level, pbf_info, 4);
402 format_and_print(outf, 1, NULL, NULL);
403}
404
405void isst_fact_display_information(int cpu, FILE *outf, int level,
406 int fact_bucket, int fact_avx,
407 struct isst_fact_info *fact_info)
408{
409 print_packag_info(cpu, outf);
410 _isst_fact_display_information(cpu, outf, level, fact_bucket, fact_avx,
411 fact_info, 4);
412 format_and_print(outf, 1, NULL, NULL);
413}
414
415void isst_clos_display_information(int cpu, FILE *outf, int clos,
416 struct isst_clos_config *clos_config)
417{
418 char header[256];
419 char value[256];
420
421 snprintf(header, sizeof(header), "package-%d",
422 get_physical_package_id(cpu));
423 format_and_print(outf, 1, header, NULL);
424 snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
425 format_and_print(outf, 2, header, NULL);
426 snprintf(header, sizeof(header), "cpu-%d", cpu);
427 format_and_print(outf, 3, header, NULL);
428
429 snprintf(header, sizeof(header), "core-power");
430 format_and_print(outf, 4, header, NULL);
431
432 snprintf(header, sizeof(header), "clos");
433 snprintf(value, sizeof(value), "%d", clos);
434 format_and_print(outf, 5, header, value);
435
436 snprintf(header, sizeof(header), "epp");
437 snprintf(value, sizeof(value), "%d", clos_config->epp);
438 format_and_print(outf, 5, header, value);
439
440 snprintf(header, sizeof(header), "clos-proportional-priority");
441 snprintf(value, sizeof(value), "%d", clos_config->clos_prop_prio);
442 format_and_print(outf, 5, header, value);
443
444 snprintf(header, sizeof(header), "clos-min");
445 snprintf(value, sizeof(value), "%d", clos_config->clos_min);
446 format_and_print(outf, 5, header, value);
447
448 snprintf(header, sizeof(header), "clos-max");
449 snprintf(value, sizeof(value), "%d", clos_config->clos_max);
450 format_and_print(outf, 5, header, value);
451
452 snprintf(header, sizeof(header), "clos-desired");
453 snprintf(value, sizeof(value), "%d", clos_config->clos_desired);
454 format_and_print(outf, 5, header, value);
455
456 format_and_print(outf, 1, NULL, NULL);
457}
458
459void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
460 int result)
461{
462 char header[256];
463 char value[256];
464
465 snprintf(header, sizeof(header), "package-%d",
466 get_physical_package_id(cpu));
467 format_and_print(outf, 1, header, NULL);
468 snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
469 format_and_print(outf, 2, header, NULL);
470 snprintf(header, sizeof(header), "cpu-%d", cpu);
471 format_and_print(outf, 3, header, NULL);
472 snprintf(header, sizeof(header), "%s", feature);
473 format_and_print(outf, 4, header, NULL);
474 snprintf(header, sizeof(header), "%s", cmd);
475 snprintf(value, sizeof(value), "%d", result);
476 format_and_print(outf, 5, header, value);
477
478 format_and_print(outf, 1, NULL, NULL);
479}
diff --git a/tools/power/x86/intel-speed-select/isst.h b/tools/power/x86/intel-speed-select/isst.h
new file mode 100644
index 000000000000..221881761609
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst.h
@@ -0,0 +1,231 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Intel Speed Select -- Enumerate and control features
4 * Copyright (c) 2019 Intel Corporation.
5 */
6
7#ifndef _ISST_H_
8#define _ISST_H_
9
10#include <stdio.h>
11#include <unistd.h>
12#include <sys/types.h>
13#include <sched.h>
14#include <sys/stat.h>
15#include <sys/resource.h>
16#include <getopt.h>
17#include <err.h>
18#include <fcntl.h>
19#include <signal.h>
20#include <sys/time.h>
21#include <limits.h>
22#include <stdlib.h>
23#include <string.h>
24#include <cpuid.h>
25#include <dirent.h>
26#include <errno.h>
27
28#include <stdarg.h>
29#include <sys/ioctl.h>
30
31#define BIT(x) (1 << (x))
32#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (sizeof(long) * 8 - 1 - (h))))
33#define GENMASK_ULL(h, l) \
34 (((~0ULL) << (l)) & (~0ULL >> (sizeof(long long) * 8 - 1 - (h))))
35
36#define CONFIG_TDP 0x7f
37#define CONFIG_TDP_GET_LEVELS_INFO 0x00
38#define CONFIG_TDP_GET_TDP_CONTROL 0x01
39#define CONFIG_TDP_SET_TDP_CONTROL 0x02
40#define CONFIG_TDP_GET_TDP_INFO 0x03
41#define CONFIG_TDP_GET_PWR_INFO 0x04
42#define CONFIG_TDP_GET_TJMAX_INFO 0x05
43#define CONFIG_TDP_GET_CORE_MASK 0x06
44#define CONFIG_TDP_GET_TURBO_LIMIT_RATIOS 0x07
45#define CONFIG_TDP_SET_LEVEL 0x08
46#define CONFIG_TDP_GET_UNCORE_P0_P1_INFO 0X09
47#define CONFIG_TDP_GET_P1_INFO 0x0a
48#define CONFIG_TDP_GET_MEM_FREQ 0x0b
49
50#define CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES 0x10
51#define CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS 0x11
52#define CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO 0x12
53
54#define CONFIG_TDP_PBF_GET_CORE_MASK_INFO 0x20
55#define CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO 0x21
56#define CONFIG_TDP_PBF_GET_TJ_MAX_INFO 0x22
57#define CONFIG_TDP_PBF_GET_TDP_INFO 0X23
58
59#define CONFIG_CLOS 0xd0
60#define CLOS_PQR_ASSOC 0x00
61#define CLOS_PM_CLOS 0x01
62#define CLOS_PM_QOS_CONFIG 0x02
63#define CLOS_STATUS 0x03
64
65#define MBOX_CMD_WRITE_BIT 0x08
66
67#define PM_QOS_INFO_OFFSET 0x00
68#define PM_QOS_CONFIG_OFFSET 0x04
69#define PM_CLOS_OFFSET 0x08
70#define PQR_ASSOC_OFFSET 0x20
71
72struct isst_clos_config {
73 int pkg_id;
74 int die_id;
75 unsigned char epp;
76 unsigned char clos_prop_prio;
77 unsigned char clos_min;
78 unsigned char clos_max;
79 unsigned char clos_desired;
80};
81
82struct isst_fact_bucket_info {
83 int high_priority_cores_count;
84 int sse_trl;
85 int avx_trl;
86 int avx512_trl;
87};
88
89struct isst_pbf_info {
90 int pbf_acticated;
91 int pbf_available;
92 size_t core_cpumask_size;
93 cpu_set_t *core_cpumask;
94 int p1_high;
95 int p1_low;
96 int t_control;
97 int t_prochot;
98 int tdp;
99};
100
101#define ISST_TRL_MAX_ACTIVE_CORES 8
102#define ISST_FACT_MAX_BUCKETS 8
103struct isst_fact_info {
104 int lp_clipping_ratio_license_sse;
105 int lp_clipping_ratio_license_avx2;
106 int lp_clipping_ratio_license_avx512;
107 struct isst_fact_bucket_info bucket_info[ISST_FACT_MAX_BUCKETS];
108};
109
110struct isst_pkg_ctdp_level_info {
111 int processed;
112 int control_cpu;
113 int pkg_id;
114 int die_id;
115 int level;
116 int fact_support;
117 int pbf_support;
118 int fact_enabled;
119 int pbf_enabled;
120 int tdp_ratio;
121 int active;
122 int tdp_control;
123 int pkg_tdp;
124 int pkg_min_power;
125 int pkg_max_power;
126 int fact;
127 int t_proc_hot;
128 int uncore_p0;
129 int uncore_p1;
130 int sse_p1;
131 int avx2_p1;
132 int avx512_p1;
133 int mem_freq;
134 size_t core_cpumask_size;
135 cpu_set_t *core_cpumask;
136 int cpu_count;
137 int trl_sse_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
138 int trl_avx_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
139 int trl_avx_512_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
140 int kobj_bucket_index;
141 int active_bucket;
142 int fact_max_index;
143 int fact_max_config;
144 int pbf_found;
145 int pbf_active;
146 struct isst_pbf_info pbf_info;
147 struct isst_fact_info fact_info;
148};
149
150#define ISST_MAX_TDP_LEVELS (4 + 1) /* +1 for base config */
151struct isst_pkg_ctdp {
152 int locked;
153 int version;
154 int processed;
155 int levels;
156 int current_level;
157 int enabled;
158 struct isst_pkg_ctdp_level_info ctdp_level[ISST_MAX_TDP_LEVELS];
159};
160
161extern int get_topo_max_cpus(void);
162extern int get_cpu_count(int pkg_id, int die_id);
163
164/* Common interfaces */
165extern void debug_printf(const char *format, ...);
166extern int out_format_is_json(void);
167extern int get_physical_package_id(int cpu);
168extern int get_physical_die_id(int cpu);
169extern size_t alloc_cpu_set(cpu_set_t **cpu_set);
170extern void free_cpu_set(cpu_set_t *cpu_set);
171extern int find_logical_cpu(int pkg_id, int die_id, int phy_cpu);
172extern int find_phy_cpu_num(int logical_cpu);
173extern int find_phy_core_num(int logical_cpu);
174extern void set_cpu_mask_from_punit_coremask(int cpu,
175 unsigned long long core_mask,
176 size_t core_cpumask_size,
177 cpu_set_t *core_cpumask,
178 int *cpu_cnt);
179
180extern int isst_send_mbox_command(unsigned int cpu, unsigned char command,
181 unsigned char sub_command,
182 unsigned int write,
183 unsigned int req_data, unsigned int *resp);
184
185extern int isst_send_msr_command(unsigned int cpu, unsigned int command,
186 int write, unsigned long long *req_resp);
187
188extern int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev);
189extern int isst_get_process_ctdp(int cpu, int tdp_level,
190 struct isst_pkg_ctdp *pkg_dev);
191extern void isst_get_process_ctdp_complete(int cpu,
192 struct isst_pkg_ctdp *pkg_dev);
193extern void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
194 struct isst_pkg_ctdp *pkg_dev);
195extern void isst_ctdp_display_information_start(FILE *outf);
196extern void isst_ctdp_display_information_end(FILE *outf);
197extern void isst_pbf_display_information(int cpu, FILE *outf, int level,
198 struct isst_pbf_info *info);
199extern int isst_set_tdp_level(int cpu, int tdp_level);
200extern int isst_set_tdp_level_msr(int cpu, int tdp_level);
201extern int isst_set_pbf_fact_status(int cpu, int pbf, int enable);
202extern int isst_get_pbf_info(int cpu, int level,
203 struct isst_pbf_info *pbf_info);
204extern void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info);
205extern int isst_get_fact_info(int cpu, int level,
206 struct isst_fact_info *fact_info);
207extern int isst_get_fact_bucket_info(int cpu, int level,
208 struct isst_fact_bucket_info *bucket_info);
209extern void isst_fact_display_information(int cpu, FILE *outf, int level,
210 int fact_bucket, int fact_avx,
211 struct isst_fact_info *fact_info);
212extern int isst_set_trl(int cpu, unsigned long long trl);
213extern int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl);
214extern int isst_get_config_tdp_lock_status(int cpu);
215
216extern int isst_pm_qos_config(int cpu, int enable_clos, int priority_type);
217extern int isst_pm_get_clos(int cpu, int clos,
218 struct isst_clos_config *clos_config);
219extern int isst_set_clos(int cpu, int clos,
220 struct isst_clos_config *clos_config);
221extern int isst_clos_associate(int cpu, int clos);
222extern int isst_clos_get_assoc_status(int cpu, int *clos_id);
223extern void isst_clos_display_information(int cpu, FILE *outf, int clos,
224 struct isst_clos_config *clos_config);
225
226extern int isst_read_reg(unsigned short reg, unsigned int *val);
227extern int isst_write_reg(int reg, unsigned int val);
228
229extern void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
230 int result);
231#endif