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 11 struct process_cmd_struct { 12 char *feature; 13 char *command; 14 void (*process_fn)(void); 15 }; 16 17 static const char *version_str = "v1.0"; 18 static const int supported_api_ver = 1; 19 static struct isst_if_platform_info isst_platform_info; 20 static char *progname; 21 static int debug_flag; 22 static FILE *outf; 23 24 static int cpu_model; 25 26 #define MAX_CPUS_IN_ONE_REQ 64 27 static short max_target_cpus; 28 static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ]; 29 30 static int topo_max_cpus; 31 static size_t present_cpumask_size; 32 static cpu_set_t *present_cpumask; 33 static size_t target_cpumask_size; 34 static cpu_set_t *target_cpumask; 35 static int tdp_level = 0xFF; 36 static int fact_bucket = 0xFF; 37 static int fact_avx = 0xFF; 38 static unsigned long long fact_trl; 39 static int out_format_json; 40 static int cmd_help; 41 static int force_online_offline; 42 43 /* clos related */ 44 static int current_clos = -1; 45 static int clos_epp = -1; 46 static int clos_prop_prio = -1; 47 static int clos_min = -1; 48 static int clos_max = -1; 49 static int clos_desired = -1; 50 static int clos_priority_type; 51 52 struct _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 }; 59 struct _cpu_map *cpu_map; 60 61 void 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 73 static 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 /* Open a file, and exit on failure */ 86 static 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 /* Parse a file containing a single int */ 97 static 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 121 int 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 134 int out_format_is_json(void) 135 { 136 return out_format_json; 137 } 138 139 int 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 146 int 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 152 int 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 164 int get_topo_max_cpus(void) 165 { 166 return topo_max_cpus; 167 } 168 169 static 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 191 static 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; /* online entry for CPU 0 needs some special configs */ 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 /* Create an unique id for package, die combination to store */ 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 233 static 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; /* online entry for CPU 0 needs some special configs */ 250 251 if (online && callback) 252 callback(i, arg1, arg2, arg3, arg4); 253 } 254 } 255 256 #define BITMASK_SIZE 32 257 static 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--; /* 0 based */ 269 270 debug_printf("max cpus %d\n", topo_max_cpus); 271 } 272 273 size_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 288 void free_cpu_set(cpu_set_t *cpu_set) 289 { 290 CPU_FREE(cpu_set); 291 } 292 293 static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE]; 294 static 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 325 int 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 333 static 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 349 static 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); // shift to get core id 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 396 int 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 410 void 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 443 int 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 451 static 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 494 int 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 577 int 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 613 static 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 637 static 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 665 static 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 711 static 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 727 static 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 752 static 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 790 static 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 815 static 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 830 static 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 855 static 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 874 static 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 894 static 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 914 static 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 928 static 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 957 static 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 /* Since we modified TRL during Fact enable, restore it */ 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 988 static 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 1010 static 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 1032 static 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 1051 static 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 1078 static 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 1098 static 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 1112 static 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 1136 static 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 1148 static 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 1170 static 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 1191 static 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 1243 static 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 1255 static 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 1277 static 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 1289 static 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 1309 static 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 * parse cpuset with following syntax 1335 * 1,2,4..6,8-10 and set bits in cpu_subset 1336 */ 1337 void 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 == '-') /* no negative cpu numbers */ 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; /* start range */ 1363 } else if (*next == '.') { 1364 next += 1; 1365 if (*next == '.') 1366 next += 1; /* start range */ 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 1396 error: 1397 fprintf(stderr, "\"--cpu %s\" malformed\n", optarg); 1398 exit(-1); 1399 } 1400 1401 static 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 /* CLOS related */ 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 1484 static 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 1500 static 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 1510 static 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 1520 static 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 1534 struct process_cmd_help_struct { 1535 char *feature; 1536 void (*process_fn)(void); 1537 }; 1538 1539 static 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 1547 void 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 1585 static 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 1618 static 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 1625 static 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); 1696 out: 1697 free_cpu_set(present_cpumask); 1698 free_cpu_set(target_cpumask); 1699 } 1700 1701 int main(int argc, char **argv) 1702 { 1703 outf = stderr; 1704 cmdline(argc, argv); 1705 return 0; 1706 } 1707