1
2
3
4
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;
41static int force_online_offline;
42
43
44static int current_clos = -1;
45static int clos_epp = -1;
46static int clos_prop_prio = -1;
47static int clos_min = -1;
48static int clos_max = -1;
49static int clos_desired = -1;
50static int clos_priority_type;
51
52struct _cpu_map {
53 unsigned short core_id;
54 unsigned short pkg_id;
55 unsigned short die_id;
56 unsigned short punit_cpu;
57 unsigned short punit_cpu_core;
58};
59struct _cpu_map *cpu_map;
60
61void debug_printf(const char *format, ...)
62{
63 va_list args;
64
65 va_start(args, format);
66
67 if (debug_flag)
68 vprintf(format, args);
69
70 va_end(args);
71}
72
73static void update_cpu_model(void)
74{
75 unsigned int ebx, ecx, edx;
76 unsigned int fms, family;
77
78 __cpuid(1, fms, ebx, ecx, edx);
79 family = (fms >> 8) & 0xf;
80 cpu_model = (fms >> 4) & 0xf;
81 if (family == 6 || family == 0xf)
82 cpu_model += ((fms >> 16) & 0xf) << 4;
83}
84
85
86static FILE *fopen_or_exit(const char *path, const char *mode)
87{
88 FILE *filep = fopen(path, mode);
89
90 if (!filep)
91 err(1, "%s: open failed", path);
92
93 return filep;
94}
95
96
97static int parse_int_file(int fatal, const char *fmt, ...)
98{
99 va_list args;
100 char path[PATH_MAX];
101 FILE *filep;
102 int value;
103
104 va_start(args, fmt);
105 vsnprintf(path, sizeof(path), fmt, args);
106 va_end(args);
107 if (fatal) {
108 filep = fopen_or_exit(path, "r");
109 } else {
110 filep = fopen(path, "r");
111 if (!filep)
112 return -1;
113 }
114 if (fscanf(filep, "%d", &value) != 1)
115 err(1, "%s: failed to parse number from file", path);
116 fclose(filep);
117
118 return value;
119}
120
121int cpufreq_sysfs_present(void)
122{
123 DIR *dir;
124
125 dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq");
126 if (dir) {
127 closedir(dir);
128 return 1;
129 }
130
131 return 0;
132}
133
134int out_format_is_json(void)
135{
136 return out_format_json;
137}
138
139int get_physical_package_id(int cpu)
140{
141 return parse_int_file(
142 0, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
143 cpu);
144}
145
146int get_physical_core_id(int cpu)
147{
148 return parse_int_file(
149 0, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
150}
151
152int get_physical_die_id(int cpu)
153{
154 int ret;
155
156 ret = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/topology/die_id",
157 cpu);
158 if (ret < 0)
159 ret = 0;
160
161 return ret;
162}
163
164int get_topo_max_cpus(void)
165{
166 return topo_max_cpus;
167}
168
169static void set_cpu_online_offline(int cpu, int state)
170{
171 char buffer[128];
172 int fd;
173
174 snprintf(buffer, sizeof(buffer),
175 "/sys/devices/system/cpu/cpu%d/online", cpu);
176
177 fd = open(buffer, O_WRONLY);
178 if (fd < 0)
179 err(-1, "%s open failed", buffer);
180
181 if (state)
182 write(fd, "1\n", 2);
183 else
184 write(fd, "0\n", 2);
185
186 close(fd);
187}
188
189#define MAX_PACKAGE_COUNT 8
190#define MAX_DIE_PER_PACKAGE 2
191static void for_each_online_package_in_set(void (*callback)(int, void *, void *,
192 void *, void *),
193 void *arg1, void *arg2, void *arg3,
194 void *arg4)
195{
196 int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT];
197 int pkg_index = 0, i;
198
199 memset(max_packages, 0xff, sizeof(max_packages));
200 for (i = 0; i < topo_max_cpus; ++i) {
201 int j, online, pkg_id, die_id = 0, skip = 0;
202
203 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
204 continue;
205 if (i)
206 online = parse_int_file(
207 1, "/sys/devices/system/cpu/cpu%d/online", i);
208 else
209 online =
210 1;
211
212 die_id = get_physical_die_id(i);
213 if (die_id < 0)
214 die_id = 0;
215 pkg_id = get_physical_package_id(i);
216
217 pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
218
219 for (j = 0; j < pkg_index; ++j) {
220 if (max_packages[j] == pkg_id) {
221 skip = 1;
222 break;
223 }
224 }
225
226 if (!skip && online && callback) {
227 callback(i, arg1, arg2, arg3, arg4);
228 max_packages[pkg_index++] = pkg_id;
229 }
230 }
231}
232
233static void for_each_online_target_cpu_in_set(
234 void (*callback)(int, void *, void *, void *, void *), void *arg1,
235 void *arg2, void *arg3, void *arg4)
236{
237 int i;
238
239 for (i = 0; i < topo_max_cpus; ++i) {
240 int online;
241
242 if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
243 continue;
244 if (i)
245 online = parse_int_file(
246 1, "/sys/devices/system/cpu/cpu%d/online", i);
247 else
248 online =
249 1;
250
251 if (online && callback)
252 callback(i, arg1, arg2, arg3, arg4);
253 }
254}
255
256#define BITMASK_SIZE 32
257static void set_max_cpu_num(void)
258{
259 FILE *filep;
260 unsigned long dummy;
261
262 topo_max_cpus = 0;
263 filep = fopen_or_exit(
264 "/sys/devices/system/cpu/cpu0/topology/thread_siblings", "r");
265 while (fscanf(filep, "%lx,", &dummy) == 1)
266 topo_max_cpus += BITMASK_SIZE;
267 fclose(filep);
268 topo_max_cpus--;
269
270 debug_printf("max cpus %d\n", topo_max_cpus);
271}
272
273size_t alloc_cpu_set(cpu_set_t **cpu_set)
274{
275 cpu_set_t *_cpu_set;
276 size_t size;
277
278 _cpu_set = CPU_ALLOC((topo_max_cpus + 1));
279 if (_cpu_set == NULL)
280 err(3, "CPU_ALLOC");
281 size = CPU_ALLOC_SIZE((topo_max_cpus + 1));
282 CPU_ZERO_S(size, _cpu_set);
283
284 *cpu_set = _cpu_set;
285 return size;
286}
287
288void free_cpu_set(cpu_set_t *cpu_set)
289{
290 CPU_FREE(cpu_set);
291}
292
293static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
294static void set_cpu_present_cpu_mask(void)
295{
296 size_t size;
297 DIR *dir;
298 int i;
299
300 size = alloc_cpu_set(&present_cpumask);
301 present_cpumask_size = size;
302 for (i = 0; i < topo_max_cpus; ++i) {
303 char buffer[256];
304
305 snprintf(buffer, sizeof(buffer),
306 "/sys/devices/system/cpu/cpu%d", i);
307 dir = opendir(buffer);
308 if (dir) {
309 int pkg_id, die_id;
310
311 CPU_SET_S(i, size, present_cpumask);
312 die_id = get_physical_die_id(i);
313 if (die_id < 0)
314 die_id = 0;
315
316 pkg_id = get_physical_package_id(i);
317 if (pkg_id < MAX_PACKAGE_COUNT &&
318 die_id < MAX_DIE_PER_PACKAGE)
319 cpu_cnt[pkg_id][die_id]++;
320 }
321 closedir(dir);
322 }
323}
324
325int get_cpu_count(int pkg_id, int die_id)
326{
327 if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
328 return cpu_cnt[pkg_id][die_id];
329
330 return 0;
331}
332
333static void set_cpu_target_cpu_mask(void)
334{
335 size_t size;
336 int i;
337
338 size = alloc_cpu_set(&target_cpumask);
339 target_cpumask_size = size;
340 for (i = 0; i < max_target_cpus; ++i) {
341 if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size,
342 present_cpumask))
343 continue;
344
345 CPU_SET_S(target_cpus[i], size, target_cpumask);
346 }
347}
348
349static void create_cpu_map(void)
350{
351 const char *pathname = "/dev/isst_interface";
352 int i, fd = 0;
353 struct isst_if_cpu_maps map;
354
355 cpu_map = malloc(sizeof(*cpu_map) * topo_max_cpus);
356 if (!cpu_map)
357 err(3, "cpumap");
358
359 fd = open(pathname, O_RDWR);
360 if (fd < 0)
361 err(-1, "%s open failed", pathname);
362
363 for (i = 0; i < topo_max_cpus; ++i) {
364 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
365 continue;
366
367 map.cmd_count = 1;
368 map.cpu_map[0].logical_cpu = i;
369
370 debug_printf(" map logical_cpu:%d\n",
371 map.cpu_map[0].logical_cpu);
372 if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
373 perror("ISST_IF_GET_PHY_ID");
374 fprintf(outf, "Error: map logical_cpu:%d\n",
375 map.cpu_map[0].logical_cpu);
376 continue;
377 }
378 cpu_map[i].core_id = get_physical_core_id(i);
379 cpu_map[i].pkg_id = get_physical_package_id(i);
380 cpu_map[i].die_id = get_physical_die_id(i);
381 cpu_map[i].punit_cpu = map.cpu_map[0].physical_cpu;
382 cpu_map[i].punit_cpu_core = (map.cpu_map[0].physical_cpu >>
383 1);
384
385 debug_printf(
386 "map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n",
387 i, cpu_map[i].core_id, cpu_map[i].die_id,
388 cpu_map[i].pkg_id, cpu_map[i].punit_cpu,
389 cpu_map[i].punit_cpu_core);
390 }
391
392 if (fd)
393 close(fd);
394}
395
396int find_logical_cpu(int pkg_id, int die_id, int punit_core_id)
397{
398 int i;
399
400 for (i = 0; i < topo_max_cpus; ++i) {
401 if (cpu_map[i].pkg_id == pkg_id &&
402 cpu_map[i].die_id == die_id &&
403 cpu_map[i].punit_cpu_core == punit_core_id)
404 return i;
405 }
406
407 return -EINVAL;
408}
409
410void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask,
411 size_t core_cpumask_size,
412 cpu_set_t *core_cpumask, int *cpu_cnt)
413{
414 int i, cnt = 0;
415 int die_id, pkg_id;
416
417 *cpu_cnt = 0;
418 die_id = get_physical_die_id(cpu);
419 pkg_id = get_physical_package_id(cpu);
420
421 for (i = 0; i < 64; ++i) {
422 if (core_mask & BIT(i)) {
423 int j;
424
425 for (j = 0; j < topo_max_cpus; ++j) {
426 if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask))
427 continue;
428
429 if (cpu_map[j].pkg_id == pkg_id &&
430 cpu_map[j].die_id == die_id &&
431 cpu_map[j].punit_cpu_core == i) {
432 CPU_SET_S(j, core_cpumask_size,
433 core_cpumask);
434 ++cnt;
435 }
436 }
437 }
438 }
439
440 *cpu_cnt = cnt;
441}
442
443int find_phy_core_num(int logical_cpu)
444{
445 if (logical_cpu < topo_max_cpus)
446 return cpu_map[logical_cpu].punit_cpu_core;
447
448 return -EINVAL;
449}
450
451static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
452 unsigned int *value)
453{
454 struct isst_if_io_regs io_regs;
455 const char *pathname = "/dev/isst_interface";
456 int cmd;
457 int fd;
458
459 debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
460
461 fd = open(pathname, O_RDWR);
462 if (fd < 0)
463 err(-1, "%s open failed", pathname);
464
465 io_regs.req_count = 1;
466 io_regs.io_reg[0].logical_cpu = cpu;
467 io_regs.io_reg[0].reg = reg;
468 cmd = ISST_IF_IO_CMD;
469 if (write) {
470 io_regs.io_reg[0].read_write = 1;
471 io_regs.io_reg[0].value = *value;
472 } else {
473 io_regs.io_reg[0].read_write = 0;
474 }
475
476 if (ioctl(fd, cmd, &io_regs) == -1) {
477 perror("ISST_IF_IO_CMD");
478 fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
479 cpu, reg, write);
480 } else {
481 if (!write)
482 *value = io_regs.io_reg[0].value;
483
484 debug_printf(
485 "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
486 cpu, reg, write, *value);
487 }
488
489 close(fd);
490
491 return 0;
492}
493
494int isst_send_mbox_command(unsigned int cpu, unsigned char command,
495 unsigned char sub_command, unsigned int parameter,
496 unsigned int req_data, unsigned int *resp)
497{
498 const char *pathname = "/dev/isst_interface";
499 int fd;
500 struct isst_if_mbox_cmds mbox_cmds = { 0 };
501
502 debug_printf(
503 "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
504 cpu, command, sub_command, parameter, req_data);
505
506 if (isst_platform_info.mmio_supported && command == CONFIG_CLOS) {
507 unsigned int value;
508 int write = 0;
509 int clos_id, core_id, ret = 0;
510
511 debug_printf("CPU %d\n", cpu);
512
513 if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
514 value = req_data;
515 write = 1;
516 }
517
518 switch (sub_command) {
519 case CLOS_PQR_ASSOC:
520 core_id = parameter & 0xff;
521 ret = isst_send_mmio_command(
522 cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
523 &value);
524 if (!ret && !write)
525 *resp = value;
526 break;
527 case CLOS_PM_CLOS:
528 clos_id = parameter & 0x03;
529 ret = isst_send_mmio_command(
530 cpu, PM_CLOS_OFFSET + clos_id * 4, write,
531 &value);
532 if (!ret && !write)
533 *resp = value;
534 break;
535 case CLOS_PM_QOS_CONFIG:
536 ret = isst_send_mmio_command(cpu, PM_QOS_CONFIG_OFFSET,
537 write, &value);
538 if (!ret && !write)
539 *resp = value;
540 break;
541 case CLOS_STATUS:
542 break;
543 default:
544 break;
545 }
546 return ret;
547 }
548
549 mbox_cmds.cmd_count = 1;
550 mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
551 mbox_cmds.mbox_cmd[0].command = command;
552 mbox_cmds.mbox_cmd[0].sub_command = sub_command;
553 mbox_cmds.mbox_cmd[0].parameter = parameter;
554 mbox_cmds.mbox_cmd[0].req_data = req_data;
555
556 fd = open(pathname, O_RDWR);
557 if (fd < 0)
558 err(-1, "%s open failed", pathname);
559
560 if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
561 perror("ISST_IF_MBOX_COMMAND");
562 fprintf(outf,
563 "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
564 cpu, command, sub_command, parameter, req_data);
565 } else {
566 *resp = mbox_cmds.mbox_cmd[0].resp_data;
567 debug_printf(
568 "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
569 cpu, command, sub_command, parameter, req_data, *resp);
570 }
571
572 close(fd);
573
574 return 0;
575}
576
577int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
578 unsigned long long *req_resp)
579{
580 struct isst_if_msr_cmds msr_cmds;
581 const char *pathname = "/dev/isst_interface";
582 int fd;
583
584 fd = open(pathname, O_RDWR);
585 if (fd < 0)
586 err(-1, "%s open failed", pathname);
587
588 msr_cmds.cmd_count = 1;
589 msr_cmds.msr_cmd[0].logical_cpu = cpu;
590 msr_cmds.msr_cmd[0].msr = msr;
591 msr_cmds.msr_cmd[0].read_write = write;
592 if (write)
593 msr_cmds.msr_cmd[0].data = *req_resp;
594
595 if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
596 perror("ISST_IF_MSR_COMMAD");
597 fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
598 cpu, msr, write);
599 } else {
600 if (!write)
601 *req_resp = msr_cmds.msr_cmd[0].data;
602
603 debug_printf(
604 "msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
605 cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
606 }
607
608 close(fd);
609
610 return 0;
611}
612
613static int isst_fill_platform_info(void)
614{
615 const char *pathname = "/dev/isst_interface";
616 int fd;
617
618 fd = open(pathname, O_RDWR);
619 if (fd < 0)
620 err(-1, "%s open failed", pathname);
621
622 if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) {
623 perror("ISST_IF_GET_PLATFORM_INFO");
624 close(fd);
625 return -1;
626 }
627
628 close(fd);
629
630 if (isst_platform_info.api_version > supported_api_ver) {
631 printf("Incompatible API versions; Upgrade of tool is required\n");
632 return -1;
633 }
634 return 0;
635}
636
637static void isst_print_platform_information(void)
638{
639 struct isst_if_platform_info platform_info;
640 const char *pathname = "/dev/isst_interface";
641 int fd;
642
643 fd = open(pathname, O_RDWR);
644 if (fd < 0)
645 err(-1, "%s open failed", pathname);
646
647 if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) {
648 perror("ISST_IF_GET_PLATFORM_INFO");
649 } else {
650 fprintf(outf, "Platform: API version : %d\n",
651 platform_info.api_version);
652 fprintf(outf, "Platform: Driver version : %d\n",
653 platform_info.driver_version);
654 fprintf(outf, "Platform: mbox supported : %d\n",
655 platform_info.mbox_supported);
656 fprintf(outf, "Platform: mmio supported : %d\n",
657 platform_info.mmio_supported);
658 }
659
660 close(fd);
661
662 exit(0);
663}
664
665static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
666 void *arg4)
667{
668 int (*fn_ptr)(int cpu, void *arg);
669 int ret;
670
671 fn_ptr = arg1;
672 ret = fn_ptr(cpu, arg2);
673 if (ret)
674 perror("get_tdp_*");
675 else
676 isst_ctdp_display_core_info(cpu, outf, arg3,
677 *(unsigned int *)arg4);
678}
679
680#define _get_tdp_level(desc, suffix, object, help) \
681 static void get_tdp_##object(void) \
682 { \
683 struct isst_pkg_ctdp ctdp; \
684\
685 if (cmd_help) { \
686 fprintf(stderr, \
687 "Print %s [No command arguments are required]\n", \
688 help); \
689 exit(0); \
690 } \
691 isst_ctdp_display_information_start(outf); \
692 if (max_target_cpus) \
693 for_each_online_target_cpu_in_set( \
694 exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix, \
695 &ctdp, desc, &ctdp.object); \
696 else \
697 for_each_online_package_in_set(exec_on_get_ctdp_cpu, \
698 isst_get_ctdp_##suffix, \
699 &ctdp, desc, \
700 &ctdp.object); \
701 isst_ctdp_display_information_end(outf); \
702 }
703
704_get_tdp_level("get-config-levels", levels, levels, "TDP levels");
705_get_tdp_level("get-config-version", levels, version, "TDP version");
706_get_tdp_level("get-config-enabled", levels, enabled, "TDP enable status");
707_get_tdp_level("get-config-current_level", levels, current_level,
708 "Current TDP Level");
709_get_tdp_level("get-lock-status", levels, locked, "TDP lock status");
710
711static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2,
712 void *arg3, void *arg4)
713{
714 struct isst_pkg_ctdp pkg_dev;
715 int ret;
716
717 memset(&pkg_dev, 0, sizeof(pkg_dev));
718 ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev);
719 if (ret) {
720 perror("isst_get_process_ctdp");
721 } else {
722 isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev);
723 isst_get_process_ctdp_complete(cpu, &pkg_dev);
724 }
725}
726
727static void dump_isst_config(void)
728{
729 if (cmd_help) {
730 fprintf(stderr,
731 "Print Intel(R) Speed Select Technology Performance profile configuration\n");
732 fprintf(stderr,
733 "including base frequency and turbo frequency configurations\n");
734 fprintf(stderr, "Optional: -l|--level : Specify tdp level\n");
735 fprintf(stderr,
736 "\tIf no arguments, dump information for all TDP levels\n");
737 exit(0);
738 }
739
740 isst_ctdp_display_information_start(outf);
741
742 if (max_target_cpus)
743 for_each_online_target_cpu_in_set(dump_isst_config_for_cpu,
744 NULL, NULL, NULL, NULL);
745 else
746 for_each_online_package_in_set(dump_isst_config_for_cpu, NULL,
747 NULL, NULL, NULL);
748
749 isst_ctdp_display_information_end(outf);
750}
751
752static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
753 void *arg4)
754{
755 int ret;
756
757 ret = isst_set_tdp_level(cpu, tdp_level);
758 if (ret)
759 perror("set_tdp_level_for_cpu");
760 else {
761 isst_display_result(cpu, outf, "perf-profile", "set_tdp_level",
762 ret);
763 if (force_online_offline) {
764 struct isst_pkg_ctdp_level_info ctdp_level;
765 int pkg_id = get_physical_package_id(cpu);
766 int die_id = get_physical_die_id(cpu);
767
768 fprintf(stderr, "Option is set to online/offline\n");
769 ctdp_level.core_cpumask_size =
770 alloc_cpu_set(&ctdp_level.core_cpumask);
771 isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
772 if (ctdp_level.cpu_count) {
773 int i, max_cpus = get_topo_max_cpus();
774 for (i = 0; i < max_cpus; ++i) {
775 if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i))
776 continue;
777 if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
778 fprintf(stderr, "online cpu %d\n", i);
779 set_cpu_online_offline(i, 1);
780 } else {
781 fprintf(stderr, "offline cpu %d\n", i);
782 set_cpu_online_offline(i, 0);
783 }
784 }
785 }
786 }
787 }
788}
789
790static void set_tdp_level(void)
791{
792 if (cmd_help) {
793 fprintf(stderr, "Set Config TDP level\n");
794 fprintf(stderr,
795 "\t Arguments: -l|--level : Specify tdp level\n");
796 fprintf(stderr,
797 "\t Optional Arguments: -o | online : online/offline for the tdp level\n");
798 exit(0);
799 }
800
801 if (tdp_level == 0xff) {
802 fprintf(outf, "Invalid command: specify tdp_level\n");
803 exit(1);
804 }
805 isst_ctdp_display_information_start(outf);
806 if (max_target_cpus)
807 for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
808 NULL, NULL, NULL);
809 else
810 for_each_online_package_in_set(set_tdp_level_for_cpu, NULL,
811 NULL, NULL, NULL);
812 isst_ctdp_display_information_end(outf);
813}
814
815static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
816 void *arg4)
817{
818 struct isst_pbf_info pbf_info;
819 int ret;
820
821 ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info);
822 if (ret) {
823 perror("isst_get_pbf_info");
824 } else {
825 isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info);
826 isst_get_pbf_info_complete(&pbf_info);
827 }
828}
829
830static void dump_pbf_config(void)
831{
832 if (cmd_help) {
833 fprintf(stderr,
834 "Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n");
835 fprintf(stderr,
836 "\tArguments: -l|--level : Specify tdp level\n");
837 exit(0);
838 }
839
840 if (tdp_level == 0xff) {
841 fprintf(outf, "Invalid command: specify tdp_level\n");
842 exit(1);
843 }
844
845 isst_ctdp_display_information_start(outf);
846 if (max_target_cpus)
847 for_each_online_target_cpu_in_set(dump_pbf_config_for_cpu, NULL,
848 NULL, NULL, NULL);
849 else
850 for_each_online_package_in_set(dump_pbf_config_for_cpu, NULL,
851 NULL, NULL, NULL);
852 isst_ctdp_display_information_end(outf);
853}
854
855static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
856 void *arg4)
857{
858 int ret;
859 int status = *(int *)arg4;
860
861 ret = isst_set_pbf_fact_status(cpu, 1, status);
862 if (ret) {
863 perror("isst_set_pbf");
864 } else {
865 if (status)
866 isst_display_result(cpu, outf, "base-freq", "enable",
867 ret);
868 else
869 isst_display_result(cpu, outf, "base-freq", "disable",
870 ret);
871 }
872}
873
874static void set_pbf_enable(void)
875{
876 int status = 1;
877
878 if (cmd_help) {
879 fprintf(stderr,
880 "Enable Intel Speed Select Technology base frequency feature [No command arguments are required]\n");
881 exit(0);
882 }
883
884 isst_ctdp_display_information_start(outf);
885 if (max_target_cpus)
886 for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
887 NULL, &status);
888 else
889 for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
890 NULL, &status);
891 isst_ctdp_display_information_end(outf);
892}
893
894static void set_pbf_disable(void)
895{
896 int status = 0;
897
898 if (cmd_help) {
899 fprintf(stderr,
900 "Disable Intel Speed Select Technology base frequency feature [No command arguments are required]\n");
901 exit(0);
902 }
903
904 isst_ctdp_display_information_start(outf);
905 if (max_target_cpus)
906 for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
907 NULL, &status);
908 else
909 for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
910 NULL, &status);
911 isst_ctdp_display_information_end(outf);
912}
913
914static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2,
915 void *arg3, void *arg4)
916{
917 struct isst_fact_info fact_info;
918 int ret;
919
920 ret = isst_get_fact_info(cpu, tdp_level, &fact_info);
921 if (ret)
922 perror("isst_get_fact_bucket_info");
923 else
924 isst_fact_display_information(cpu, outf, tdp_level, fact_bucket,
925 fact_avx, &fact_info);
926}
927
928static void dump_fact_config(void)
929{
930 if (cmd_help) {
931 fprintf(stderr,
932 "Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n");
933 fprintf(stderr,
934 "\tArguments: -l|--level : Specify tdp level\n");
935 fprintf(stderr,
936 "\tArguments: -b|--bucket : Bucket index to dump\n");
937 fprintf(stderr,
938 "\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n");
939 exit(0);
940 }
941
942 if (tdp_level == 0xff) {
943 fprintf(outf, "Invalid command: specify tdp_level\n");
944 exit(1);
945 }
946
947 isst_ctdp_display_information_start(outf);
948 if (max_target_cpus)
949 for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
950 NULL, NULL, NULL, NULL);
951 else
952 for_each_online_package_in_set(dump_fact_config_for_cpu, NULL,
953 NULL, NULL, NULL);
954 isst_ctdp_display_information_end(outf);
955}
956
957static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
958 void *arg4)
959{
960 int ret;
961 int status = *(int *)arg4;
962
963 ret = isst_set_pbf_fact_status(cpu, 0, status);
964 if (ret)
965 perror("isst_set_fact");
966 else {
967 if (status) {
968 struct isst_pkg_ctdp pkg_dev;
969
970 ret = isst_get_ctdp_levels(cpu, &pkg_dev);
971 if (ret) {
972 isst_display_result(cpu, outf, "turbo-freq",
973 "enable", ret);
974 return;
975 }
976 ret = isst_set_trl(cpu, fact_trl);
977 isst_display_result(cpu, outf, "turbo-freq", "enable",
978 ret);
979 } else {
980
981 isst_set_trl_from_current_tdp(cpu, fact_trl);
982 isst_display_result(cpu, outf, "turbo-freq", "disable",
983 ret);
984 }
985 }
986}
987
988static void set_fact_enable(void)
989{
990 int status = 1;
991
992 if (cmd_help) {
993 fprintf(stderr,
994 "Enable Intel Speed Select Technology Turbo frequency feature\n");
995 fprintf(stderr,
996 "Optional: -t|--trl : Specify turbo ratio limit\n");
997 exit(0);
998 }
999
1000 isst_ctdp_display_information_start(outf);
1001 if (max_target_cpus)
1002 for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
1003 NULL, &status);
1004 else
1005 for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
1006 NULL, &status);
1007 isst_ctdp_display_information_end(outf);
1008}
1009
1010static void set_fact_disable(void)
1011{
1012 int status = 0;
1013
1014 if (cmd_help) {
1015 fprintf(stderr,
1016 "Disable Intel Speed Select Technology turbo frequency feature\n");
1017 fprintf(stderr,
1018 "Optional: -t|--trl : Specify turbo ratio limit\n");
1019 exit(0);
1020 }
1021
1022 isst_ctdp_display_information_start(outf);
1023 if (max_target_cpus)
1024 for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
1025 NULL, &status);
1026 else
1027 for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
1028 NULL, &status);
1029 isst_ctdp_display_information_end(outf);
1030}
1031
1032static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3,
1033 void *arg4)
1034{
1035 int ret;
1036 int status = *(int *)arg4;
1037
1038 ret = isst_pm_qos_config(cpu, status, clos_priority_type);
1039 if (ret) {
1040 perror("isst_pm_qos_config");
1041 } else {
1042 if (status)
1043 isst_display_result(cpu, outf, "core-power", "enable",
1044 ret);
1045 else
1046 isst_display_result(cpu, outf, "core-power", "disable",
1047 ret);
1048 }
1049}
1050
1051static void set_clos_enable(void)
1052{
1053 int status = 1;
1054
1055 if (cmd_help) {
1056 fprintf(stderr, "Enable core-power for a package/die\n");
1057 fprintf(stderr,
1058 "\tClos Enable: Specify priority type with [--priority|-p]\n");
1059 fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
1060 exit(0);
1061 }
1062
1063 if (cpufreq_sysfs_present()) {
1064 fprintf(stderr,
1065 "cpufreq subsystem and core-power enable will interfere with each other!\n");
1066 }
1067
1068 isst_ctdp_display_information_start(outf);
1069 if (max_target_cpus)
1070 for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
1071 NULL, NULL, &status);
1072 else
1073 for_each_online_package_in_set(enable_clos_qos_config, NULL,
1074 NULL, NULL, &status);
1075 isst_ctdp_display_information_end(outf);
1076}
1077
1078static void set_clos_disable(void)
1079{
1080 int status = 0;
1081
1082 if (cmd_help) {
1083 fprintf(stderr,
1084 "Disable core-power: [No command arguments are required]\n");
1085 exit(0);
1086 }
1087
1088 isst_ctdp_display_information_start(outf);
1089 if (max_target_cpus)
1090 for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
1091 NULL, NULL, &status);
1092 else
1093 for_each_online_package_in_set(enable_clos_qos_config, NULL,
1094 NULL, NULL, &status);
1095 isst_ctdp_display_information_end(outf);
1096}
1097
1098static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2,
1099 void *arg3, void *arg4)
1100{
1101 struct isst_clos_config clos_config;
1102 int ret;
1103
1104 ret = isst_pm_get_clos(cpu, current_clos, &clos_config);
1105 if (ret)
1106 perror("isst_pm_get_clos");
1107 else
1108 isst_clos_display_information(cpu, outf, current_clos,
1109 &clos_config);
1110}
1111
1112static void dump_clos_config(void)
1113{
1114 if (cmd_help) {
1115 fprintf(stderr,
1116 "Print Intel Speed Select Technology core power configuration\n");
1117 fprintf(stderr,
1118 "\tArguments: [-c | --clos]: Specify clos id\n");
1119 exit(0);
1120 }
1121 if (current_clos < 0 || current_clos > 3) {
1122 fprintf(stderr, "Invalid clos id\n");
1123 exit(0);
1124 }
1125
1126 isst_ctdp_display_information_start(outf);
1127 if (max_target_cpus)
1128 for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
1129 NULL, NULL, NULL, NULL);
1130 else
1131 for_each_online_package_in_set(dump_clos_config_for_cpu, NULL,
1132 NULL, NULL, NULL);
1133 isst_ctdp_display_information_end(outf);
1134}
1135
1136static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1137 void *arg4)
1138{
1139 int enable, ret, prio_type;
1140
1141 ret = isst_clos_get_clos_information(cpu, &enable, &prio_type);
1142 if (ret)
1143 perror("isst_clos_get_info");
1144 else
1145 isst_clos_display_clos_information(cpu, outf, enable, prio_type);
1146}
1147
1148static void dump_clos_info(void)
1149{
1150 if (cmd_help) {
1151 fprintf(stderr,
1152 "Print Intel Speed Select Technology core power information\n");
1153 fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
1154 exit(0);
1155 }
1156
1157 if (!max_target_cpus) {
1158 fprintf(stderr,
1159 "Invalid target cpu. Specify with [-c|--cpu]\n");
1160 exit(0);
1161 }
1162
1163 isst_ctdp_display_information_start(outf);
1164 for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
1165 NULL, NULL, NULL);
1166 isst_ctdp_display_information_end(outf);
1167
1168}
1169
1170static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1171 void *arg4)
1172{
1173 struct isst_clos_config clos_config;
1174 int ret;
1175
1176 clos_config.pkg_id = get_physical_package_id(cpu);
1177 clos_config.die_id = get_physical_die_id(cpu);
1178
1179 clos_config.epp = clos_epp;
1180 clos_config.clos_prop_prio = clos_prop_prio;
1181 clos_config.clos_min = clos_min;
1182 clos_config.clos_max = clos_max;
1183 clos_config.clos_desired = clos_desired;
1184 ret = isst_set_clos(cpu, current_clos, &clos_config);
1185 if (ret)
1186 perror("isst_set_clos");
1187 else
1188 isst_display_result(cpu, outf, "core-power", "config", ret);
1189}
1190
1191static void set_clos_config(void)
1192{
1193 if (cmd_help) {
1194 fprintf(stderr,
1195 "Set core-power configuration for one of the four clos ids\n");
1196 fprintf(stderr,
1197 "\tSpecify targeted clos id with [--clos|-c]\n");
1198 fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
1199 fprintf(stderr,
1200 "\tSpecify clos Proportional Priority [--weight|-w]\n");
1201 fprintf(stderr, "\tSpecify clos min with [--min|-n]\n");
1202 fprintf(stderr, "\tSpecify clos max with [--max|-m]\n");
1203 fprintf(stderr, "\tSpecify clos desired with [--desired|-d]\n");
1204 exit(0);
1205 }
1206
1207 if (current_clos < 0 || current_clos > 3) {
1208 fprintf(stderr, "Invalid clos id\n");
1209 exit(0);
1210 }
1211 if (clos_epp < 0 || clos_epp > 0x0F) {
1212 fprintf(stderr, "clos epp is not specified, default: 0\n");
1213 clos_epp = 0;
1214 }
1215 if (clos_prop_prio < 0 || clos_prop_prio > 0x0F) {
1216 fprintf(stderr,
1217 "clos frequency weight is not specified, default: 0\n");
1218 clos_prop_prio = 0;
1219 }
1220 if (clos_min < 0) {
1221 fprintf(stderr, "clos min is not specified, default: 0\n");
1222 clos_min = 0;
1223 }
1224 if (clos_max < 0) {
1225 fprintf(stderr, "clos max is not specified, default: 0xff\n");
1226 clos_max = 0xff;
1227 }
1228 if (clos_desired < 0) {
1229 fprintf(stderr, "clos desired is not specified, default: 0\n");
1230 clos_desired = 0x00;
1231 }
1232
1233 isst_ctdp_display_information_start(outf);
1234 if (max_target_cpus)
1235 for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
1236 NULL, NULL, NULL);
1237 else
1238 for_each_online_package_in_set(set_clos_config_for_cpu, NULL,
1239 NULL, NULL, NULL);
1240 isst_ctdp_display_information_end(outf);
1241}
1242
1243static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1244 void *arg4)
1245{
1246 int ret;
1247
1248 ret = isst_clos_associate(cpu, current_clos);
1249 if (ret)
1250 perror("isst_clos_associate");
1251 else
1252 isst_display_result(cpu, outf, "core-power", "assoc", ret);
1253}
1254
1255static void set_clos_assoc(void)
1256{
1257 if (cmd_help) {
1258 fprintf(stderr, "Associate a clos id to a CPU\n");
1259 fprintf(stderr,
1260 "\tSpecify targeted clos id with [--clos|-c]\n");
1261 exit(0);
1262 }
1263
1264 if (current_clos < 0 || current_clos > 3) {
1265 fprintf(stderr, "Invalid clos id\n");
1266 exit(0);
1267 }
1268 if (max_target_cpus)
1269 for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
1270 NULL, NULL, NULL);
1271 else {
1272 fprintf(stderr,
1273 "Invalid target cpu. Specify with [-c|--cpu]\n");
1274 }
1275}
1276
1277static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1278 void *arg4)
1279{
1280 int clos, ret;
1281
1282 ret = isst_clos_get_assoc_status(cpu, &clos);
1283 if (ret)
1284 perror("isst_clos_get_assoc_status");
1285 else
1286 isst_clos_display_assoc_information(cpu, outf, clos);
1287}
1288
1289static void get_clos_assoc(void)
1290{
1291 if (cmd_help) {
1292 fprintf(stderr, "Get associate clos id to a CPU\n");
1293 fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
1294 exit(0);
1295 }
1296
1297 if (!max_target_cpus) {
1298 fprintf(stderr,
1299 "Invalid target cpu. Specify with [-c|--cpu]\n");
1300 exit(0);
1301 }
1302
1303 isst_ctdp_display_information_start(outf);
1304 for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL,
1305 NULL, NULL, NULL);
1306 isst_ctdp_display_information_end(outf);
1307}
1308
1309static struct process_cmd_struct isst_cmds[] = {
1310 { "perf-profile", "get-lock-status", get_tdp_locked },
1311 { "perf-profile", "get-config-levels", get_tdp_levels },
1312 { "perf-profile", "get-config-version", get_tdp_version },
1313 { "perf-profile", "get-config-enabled", get_tdp_enabled },
1314 { "perf-profile", "get-config-current-level", get_tdp_current_level },
1315 { "perf-profile", "set-config-level", set_tdp_level },
1316 { "perf-profile", "info", dump_isst_config },
1317 { "base-freq", "info", dump_pbf_config },
1318 { "base-freq", "enable", set_pbf_enable },
1319 { "base-freq", "disable", set_pbf_disable },
1320 { "turbo-freq", "info", dump_fact_config },
1321 { "turbo-freq", "enable", set_fact_enable },
1322 { "turbo-freq", "disable", set_fact_disable },
1323 { "core-power", "info", dump_clos_info },
1324 { "core-power", "enable", set_clos_enable },
1325 { "core-power", "disable", set_clos_disable },
1326 { "core-power", "config", set_clos_config },
1327 { "core-power", "get-config", dump_clos_config },
1328 { "core-power", "assoc", set_clos_assoc },
1329 { "core-power", "get-assoc", get_clos_assoc },
1330 { NULL, NULL, NULL }
1331};
1332
1333
1334
1335
1336
1337void parse_cpu_command(char *optarg)
1338{
1339 unsigned int start, end;
1340 char *next;
1341
1342 next = optarg;
1343
1344 while (next && *next) {
1345 if (*next == '-')
1346 goto error;
1347
1348 start = strtoul(next, &next, 10);
1349
1350 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
1351 target_cpus[max_target_cpus++] = start;
1352
1353 if (*next == '\0')
1354 break;
1355
1356 if (*next == ',') {
1357 next += 1;
1358 continue;
1359 }
1360
1361 if (*next == '-') {
1362 next += 1;
1363 } else if (*next == '.') {
1364 next += 1;
1365 if (*next == '.')
1366 next += 1;
1367 else
1368 goto error;
1369 }
1370
1371 end = strtoul(next, &next, 10);
1372 if (end <= start)
1373 goto error;
1374
1375 while (++start <= end) {
1376 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
1377 target_cpus[max_target_cpus++] = start;
1378 }
1379
1380 if (*next == ',')
1381 next += 1;
1382 else if (*next != '\0')
1383 goto error;
1384 }
1385
1386#ifdef DEBUG
1387 {
1388 int i;
1389
1390 for (i = 0; i < max_target_cpus; ++i)
1391 printf("cpu [%d] in arg\n", target_cpus[i]);
1392 }
1393#endif
1394 return;
1395
1396error:
1397 fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
1398 exit(-1);
1399}
1400
1401static void parse_cmd_args(int argc, int start, char **argv)
1402{
1403 int opt;
1404 int option_index;
1405
1406 static struct option long_options[] = {
1407 { "bucket", required_argument, 0, 'b' },
1408 { "level", required_argument, 0, 'l' },
1409 { "online", required_argument, 0, 'o' },
1410 { "trl-type", required_argument, 0, 'r' },
1411 { "trl", required_argument, 0, 't' },
1412 { "help", no_argument, 0, 'h' },
1413 { "clos", required_argument, 0, 'c' },
1414 { "desired", required_argument, 0, 'd' },
1415 { "epp", required_argument, 0, 'e' },
1416 { "min", required_argument, 0, 'n' },
1417 { "max", required_argument, 0, 'm' },
1418 { "priority", required_argument, 0, 'p' },
1419 { "weight", required_argument, 0, 'w' },
1420 { 0, 0, 0, 0 }
1421 };
1422
1423 option_index = start;
1424
1425 optind = start + 1;
1426 while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:ho",
1427 long_options, &option_index)) != -1) {
1428 switch (opt) {
1429 case 'b':
1430 fact_bucket = atoi(optarg);
1431 break;
1432 case 'h':
1433 cmd_help = 1;
1434 break;
1435 case 'l':
1436 tdp_level = atoi(optarg);
1437 break;
1438 case 'o':
1439 force_online_offline = 1;
1440 break;
1441 case 't':
1442 sscanf(optarg, "0x%llx", &fact_trl);
1443 break;
1444 case 'r':
1445 if (!strncmp(optarg, "sse", 3)) {
1446 fact_avx = 0x01;
1447 } else if (!strncmp(optarg, "avx2", 4)) {
1448 fact_avx = 0x02;
1449 } else if (!strncmp(optarg, "avx512", 4)) {
1450 fact_avx = 0x04;
1451 } else {
1452 fprintf(outf, "Invalid sse,avx options\n");
1453 exit(1);
1454 }
1455 break;
1456
1457 case 'c':
1458 current_clos = atoi(optarg);
1459 break;
1460 case 'd':
1461 clos_desired = atoi(optarg);
1462 break;
1463 case 'e':
1464 clos_epp = atoi(optarg);
1465 break;
1466 case 'n':
1467 clos_min = atoi(optarg);
1468 break;
1469 case 'm':
1470 clos_max = atoi(optarg);
1471 break;
1472 case 'p':
1473 clos_priority_type = atoi(optarg);
1474 break;
1475 case 'w':
1476 clos_prop_prio = atoi(optarg);
1477 break;
1478 default:
1479 printf("no match\n");
1480 }
1481 }
1482}
1483
1484static void isst_help(void)
1485{
1486 printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\
1487 performance profiles per system via static and/or dynamic\n\
1488 adjustment of core count, workload, Tjmax, and\n\
1489 TDP, etc.\n");
1490 printf("\nCommands : For feature=perf-profile\n");
1491 printf("\tinfo\n");
1492 printf("\tget-lock-status\n");
1493 printf("\tget-config-levels\n");
1494 printf("\tget-config-version\n");
1495 printf("\tget-config-enabled\n");
1496 printf("\tget-config-current-level\n");
1497 printf("\tset-config-level\n");
1498}
1499
1500static void pbf_help(void)
1501{
1502 printf("base-freq:\tEnables users to increase guaranteed base frequency\n\
1503 on certain cores (high priority cores) in exchange for lower\n\
1504 base frequency on remaining cores (low priority cores).\n");
1505 printf("\tcommand : info\n");
1506 printf("\tcommand : enable\n");
1507 printf("\tcommand : disable\n");
1508}
1509
1510static void fact_help(void)
1511{
1512 printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\
1513 limits to cores based on priority.\n");
1514 printf("\nCommand: For feature=turbo-freq\n");
1515 printf("\tcommand : info\n");
1516 printf("\tcommand : enable\n");
1517 printf("\tcommand : disable\n");
1518}
1519
1520static void core_power_help(void)
1521{
1522 printf("core-power:\tInterface that allows user to define per core/tile\n\
1523 priority.\n");
1524 printf("\nCommands : For feature=core-power\n");
1525 printf("\tinfo\n");
1526 printf("\tenable\n");
1527 printf("\tdisable\n");
1528 printf("\tconfig\n");
1529 printf("\tget-config\n");
1530 printf("\tassoc\n");
1531 printf("\tget-assoc\n");
1532}
1533
1534struct process_cmd_help_struct {
1535 char *feature;
1536 void (*process_fn)(void);
1537};
1538
1539static struct process_cmd_help_struct isst_help_cmds[] = {
1540 { "perf-profile", isst_help },
1541 { "base-freq", pbf_help },
1542 { "turbo-freq", fact_help },
1543 { "core-power", core_power_help },
1544 { NULL, NULL }
1545};
1546
1547void process_command(int argc, char **argv)
1548{
1549 int i = 0, matched = 0;
1550 char *feature = argv[optind];
1551 char *cmd = argv[optind + 1];
1552
1553 if (!feature || !cmd)
1554 return;
1555
1556 debug_printf("feature name [%s] command [%s]\n", feature, cmd);
1557 if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
1558 while (isst_help_cmds[i].feature) {
1559 if (!strcmp(isst_help_cmds[i].feature, feature)) {
1560 isst_help_cmds[i].process_fn();
1561 exit(0);
1562 }
1563 ++i;
1564 }
1565 }
1566
1567 create_cpu_map();
1568
1569 i = 0;
1570 while (isst_cmds[i].feature) {
1571 if (!strcmp(isst_cmds[i].feature, feature) &&
1572 !strcmp(isst_cmds[i].command, cmd)) {
1573 parse_cmd_args(argc, optind + 1, argv);
1574 isst_cmds[i].process_fn();
1575 matched = 1;
1576 break;
1577 }
1578 ++i;
1579 }
1580
1581 if (!matched)
1582 fprintf(stderr, "Invalid command\n");
1583}
1584
1585static void usage(void)
1586{
1587 printf("Intel(R) Speed Select Technology\n");
1588 printf("\nUsage:\n");
1589 printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
1590 printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features,\n");
1591 printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
1592 printf("\nFor help on each feature, use -h|--help\n");
1593 printf("\tFor example: intel-speed-select perf-profile -h\n");
1594
1595 printf("\nFor additional help on each command for a feature, use --h|--help\n");
1596 printf("\tFor example: intel-speed-select perf-profile get-lock-status -h\n");
1597 printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n");
1598
1599 printf("\nOPTIONS\n");
1600 printf("\t[-c|--cpu] : logical cpu number\n");
1601 printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n");
1602 printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n");
1603 printf("\t[-d|--debug] : Debug mode\n");
1604 printf("\t[-h|--help] : Print help\n");
1605 printf("\t[-i|--info] : Print platform information\n");
1606 printf("\t[-o|--out] : Output file\n");
1607 printf("\t\t\tDefault : stderr\n");
1608 printf("\t[-f|--format] : output format [json|text]. Default: text\n");
1609 printf("\t[-v|--version] : Print version\n");
1610
1611 printf("\nResult format\n");
1612 printf("\tResult display uses a common format for each command:\n");
1613 printf("\tResults are formatted in text/JSON with\n");
1614 printf("\t\tPackage, Die, CPU, and command specific results.\n");
1615 exit(1);
1616}
1617
1618static void print_version(void)
1619{
1620 fprintf(outf, "Version %s\n", version_str);
1621 fprintf(outf, "Build date %s time %s\n", __DATE__, __TIME__);
1622 exit(0);
1623}
1624
1625static void cmdline(int argc, char **argv)
1626{
1627 int opt;
1628 int option_index = 0;
1629 int ret;
1630
1631 static struct option long_options[] = {
1632 { "cpu", required_argument, 0, 'c' },
1633 { "debug", no_argument, 0, 'd' },
1634 { "format", required_argument, 0, 'f' },
1635 { "help", no_argument, 0, 'h' },
1636 { "info", no_argument, 0, 'i' },
1637 { "out", required_argument, 0, 'o' },
1638 { "version", no_argument, 0, 'v' },
1639 { 0, 0, 0, 0 }
1640 };
1641
1642 progname = argv[0];
1643 while ((opt = getopt_long_only(argc, argv, "+c:df:hio:v", long_options,
1644 &option_index)) != -1) {
1645 switch (opt) {
1646 case 'c':
1647 parse_cpu_command(optarg);
1648 break;
1649 case 'd':
1650 debug_flag = 1;
1651 printf("Debug Mode ON\n");
1652 break;
1653 case 'f':
1654 if (!strncmp(optarg, "json", 4))
1655 out_format_json = 1;
1656 break;
1657 case 'h':
1658 usage();
1659 break;
1660 case 'i':
1661 isst_print_platform_information();
1662 break;
1663 case 'o':
1664 if (outf)
1665 fclose(outf);
1666 outf = fopen_or_exit(optarg, "w");
1667 break;
1668 case 'v':
1669 print_version();
1670 break;
1671 default:
1672 usage();
1673 }
1674 }
1675
1676 if (geteuid() != 0) {
1677 fprintf(stderr, "Must run as root\n");
1678 exit(0);
1679 }
1680
1681 if (optind > (argc - 2)) {
1682 fprintf(stderr, "Feature name and|or command not specified\n");
1683 exit(0);
1684 }
1685 update_cpu_model();
1686 printf("Intel(R) Speed Select Technology\n");
1687 printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
1688 set_max_cpu_num();
1689 set_cpu_present_cpu_mask();
1690 set_cpu_target_cpu_mask();
1691 ret = isst_fill_platform_info();
1692 if (ret)
1693 goto out;
1694
1695 process_command(argc, argv);
1696out:
1697 free_cpu_set(present_cpumask);
1698 free_cpu_set(target_cpumask);
1699}
1700
1701int main(int argc, char **argv)
1702{
1703 outf = stderr;
1704 cmdline(argc, argv);
1705 return 0;
1706}
1707