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)(int arg); 15 int arg; 16 }; 17 18 static const char *version_str = "v1.11"; 19 static const int supported_api_ver = 1; 20 static struct isst_if_platform_info isst_platform_info; 21 static char *progname; 22 static int debug_flag; 23 static FILE *outf; 24 25 static int cpu_model; 26 static int cpu_stepping; 27 28 #define MAX_CPUS_IN_ONE_REQ 256 29 static short max_target_cpus; 30 static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ]; 31 32 static int topo_max_cpus; 33 static size_t present_cpumask_size; 34 static cpu_set_t *present_cpumask; 35 static size_t target_cpumask_size; 36 static cpu_set_t *target_cpumask; 37 static int tdp_level = 0xFF; 38 static int fact_bucket = 0xFF; 39 static int fact_avx = 0xFF; 40 static unsigned long long fact_trl; 41 static int out_format_json; 42 static int cmd_help; 43 static int force_online_offline; 44 static int auto_mode; 45 static int fact_enable_fail; 46 47 static int mbox_delay; 48 static int mbox_retries = 3; 49 50 /* clos related */ 51 static int current_clos = -1; 52 static int clos_epp = -1; 53 static int clos_prop_prio = -1; 54 static int clos_min = -1; 55 static int clos_max = -1; 56 static int clos_desired = -1; 57 static int clos_priority_type; 58 59 struct _cpu_map { 60 unsigned short core_id; 61 unsigned short pkg_id; 62 unsigned short die_id; 63 unsigned short punit_cpu; 64 unsigned short punit_cpu_core; 65 }; 66 struct _cpu_map *cpu_map; 67 68 struct cpu_topology { 69 short cpu; 70 short core_id; 71 short pkg_id; 72 short die_id; 73 }; 74 75 FILE *get_output_file(void) 76 { 77 return outf; 78 } 79 80 void debug_printf(const char *format, ...) 81 { 82 va_list args; 83 84 va_start(args, format); 85 86 if (debug_flag) 87 vprintf(format, args); 88 89 va_end(args); 90 } 91 92 93 int is_clx_n_platform(void) 94 { 95 if (cpu_model == 0x55) 96 if (cpu_stepping == 0x6 || cpu_stepping == 0x7) 97 return 1; 98 return 0; 99 } 100 101 int is_skx_based_platform(void) 102 { 103 if (cpu_model == 0x55) 104 return 1; 105 106 return 0; 107 } 108 109 int is_spr_platform(void) 110 { 111 if (cpu_model == 0x8F) 112 return 1; 113 114 return 0; 115 } 116 117 int is_icx_platform(void) 118 { 119 if (cpu_model == 0x6A || cpu_model == 0x6C) 120 return 1; 121 122 return 0; 123 } 124 125 static int update_cpu_model(void) 126 { 127 unsigned int ebx, ecx, edx; 128 unsigned int fms, family; 129 130 __cpuid(1, fms, ebx, ecx, edx); 131 family = (fms >> 8) & 0xf; 132 cpu_model = (fms >> 4) & 0xf; 133 if (family == 6 || family == 0xf) 134 cpu_model += ((fms >> 16) & 0xf) << 4; 135 136 cpu_stepping = fms & 0xf; 137 /* only three CascadeLake-N models are supported */ 138 if (is_clx_n_platform()) { 139 FILE *fp; 140 size_t n = 0; 141 char *line = NULL; 142 int ret = 1; 143 144 fp = fopen("/proc/cpuinfo", "r"); 145 if (!fp) 146 err(-1, "cannot open /proc/cpuinfo\n"); 147 148 while (getline(&line, &n, fp) > 0) { 149 if (strstr(line, "model name")) { 150 if (strstr(line, "6252N") || 151 strstr(line, "6230N") || 152 strstr(line, "5218N")) 153 ret = 0; 154 break; 155 } 156 } 157 free(line); 158 fclose(fp); 159 return ret; 160 } 161 return 0; 162 } 163 164 /* Open a file, and exit on failure */ 165 static FILE *fopen_or_exit(const char *path, const char *mode) 166 { 167 FILE *filep = fopen(path, mode); 168 169 if (!filep) 170 err(1, "%s: open failed", path); 171 172 return filep; 173 } 174 175 /* Parse a file containing a single int */ 176 static int parse_int_file(int fatal, const char *fmt, ...) 177 { 178 va_list args; 179 char path[PATH_MAX]; 180 FILE *filep; 181 int value; 182 183 va_start(args, fmt); 184 vsnprintf(path, sizeof(path), fmt, args); 185 va_end(args); 186 if (fatal) { 187 filep = fopen_or_exit(path, "r"); 188 } else { 189 filep = fopen(path, "r"); 190 if (!filep) 191 return -1; 192 } 193 if (fscanf(filep, "%d", &value) != 1) 194 err(1, "%s: failed to parse number from file", path); 195 fclose(filep); 196 197 return value; 198 } 199 200 int cpufreq_sysfs_present(void) 201 { 202 DIR *dir; 203 204 dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq"); 205 if (dir) { 206 closedir(dir); 207 return 1; 208 } 209 210 return 0; 211 } 212 213 int out_format_is_json(void) 214 { 215 return out_format_json; 216 } 217 218 static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id) 219 { 220 const char *pathname = "/var/run/isst_cpu_topology.dat"; 221 struct cpu_topology cpu_top; 222 FILE *fp; 223 int ret; 224 225 fp = fopen(pathname, "rb"); 226 if (!fp) 227 return -1; 228 229 ret = fseek(fp, cpu * sizeof(cpu_top), SEEK_SET); 230 if (ret) 231 goto err_ret; 232 233 ret = fread(&cpu_top, sizeof(cpu_top), 1, fp); 234 if (ret != 1) { 235 ret = -1; 236 goto err_ret; 237 } 238 239 *pkg_id = cpu_top.pkg_id; 240 *core_id = cpu_top.core_id; 241 *die_id = cpu_top.die_id; 242 ret = 0; 243 244 err_ret: 245 fclose(fp); 246 247 return ret; 248 } 249 250 static void store_cpu_topology(void) 251 { 252 const char *pathname = "/var/run/isst_cpu_topology.dat"; 253 FILE *fp; 254 int i; 255 256 fp = fopen(pathname, "rb"); 257 if (fp) { 258 /* Mapping already exists */ 259 fclose(fp); 260 return; 261 } 262 263 fp = fopen(pathname, "wb"); 264 if (!fp) { 265 fprintf(stderr, "Can't create file:%s\n", pathname); 266 return; 267 } 268 269 fprintf(stderr, "Caching topology information\n"); 270 271 for (i = 0; i < topo_max_cpus; ++i) { 272 struct cpu_topology cpu_top; 273 274 cpu_top.core_id = parse_int_file(0, 275 "/sys/devices/system/cpu/cpu%d/topology/core_id", i); 276 if (cpu_top.core_id < 0) 277 cpu_top.core_id = -1; 278 279 cpu_top.pkg_id = parse_int_file(0, 280 "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i); 281 if (cpu_top.pkg_id < 0) 282 cpu_top.pkg_id = -1; 283 284 cpu_top.die_id = parse_int_file(0, 285 "/sys/devices/system/cpu/cpu%d/topology/die_id", i); 286 if (cpu_top.die_id < 0) 287 cpu_top.die_id = -1; 288 289 cpu_top.cpu = i; 290 291 if (fwrite(&cpu_top, sizeof(cpu_top), 1, fp) != 1) { 292 fprintf(stderr, "Can't write to:%s\n", pathname); 293 break; 294 } 295 } 296 297 fclose(fp); 298 } 299 300 int get_physical_package_id(int cpu) 301 { 302 int ret; 303 304 ret = parse_int_file(0, 305 "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", 306 cpu); 307 if (ret < 0) { 308 int core_id, pkg_id, die_id; 309 310 ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id); 311 if (!ret) 312 return pkg_id; 313 } 314 315 return ret; 316 } 317 318 int get_physical_core_id(int cpu) 319 { 320 int ret; 321 322 ret = parse_int_file(0, 323 "/sys/devices/system/cpu/cpu%d/topology/core_id", 324 cpu); 325 if (ret < 0) { 326 int core_id, pkg_id, die_id; 327 328 ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id); 329 if (!ret) 330 return core_id; 331 } 332 333 return ret; 334 } 335 336 int get_physical_die_id(int cpu) 337 { 338 int ret; 339 340 ret = parse_int_file(0, 341 "/sys/devices/system/cpu/cpu%d/topology/die_id", 342 cpu); 343 if (ret < 0) { 344 int core_id, pkg_id, die_id; 345 346 ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id); 347 if (!ret) { 348 if (die_id < 0) 349 die_id = 0; 350 351 return die_id; 352 } 353 } 354 355 if (ret < 0) 356 ret = 0; 357 358 return ret; 359 } 360 361 int get_cpufreq_base_freq(int cpu) 362 { 363 return parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", cpu); 364 } 365 366 int get_topo_max_cpus(void) 367 { 368 return topo_max_cpus; 369 } 370 371 static void set_cpu_online_offline(int cpu, int state) 372 { 373 char buffer[128]; 374 int fd, ret; 375 376 snprintf(buffer, sizeof(buffer), 377 "/sys/devices/system/cpu/cpu%d/online", cpu); 378 379 fd = open(buffer, O_WRONLY); 380 if (fd < 0) { 381 if (!cpu && state) { 382 fprintf(stderr, "This system is not configured for CPU 0 online/offline\n"); 383 fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n"); 384 return; 385 } 386 err(-1, "%s open failed", buffer); 387 } 388 389 if (state) 390 ret = write(fd, "1\n", 2); 391 else 392 ret = write(fd, "0\n", 2); 393 394 if (ret == -1) 395 perror("Online/Offline: Operation failed\n"); 396 397 close(fd); 398 } 399 400 static void force_all_cpus_online(void) 401 { 402 int i; 403 404 fprintf(stderr, "Forcing all CPUs online\n"); 405 406 for (i = 0; i < topo_max_cpus; ++i) 407 set_cpu_online_offline(i, 1); 408 409 unlink("/var/run/isst_cpu_topology.dat"); 410 } 411 412 #define MAX_PACKAGE_COUNT 8 413 #define MAX_DIE_PER_PACKAGE 2 414 static void for_each_online_package_in_set(void (*callback)(int, void *, void *, 415 void *, void *), 416 void *arg1, void *arg2, void *arg3, 417 void *arg4) 418 { 419 int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT]; 420 int pkg_index = 0, i; 421 422 memset(max_packages, 0xff, sizeof(max_packages)); 423 for (i = 0; i < topo_max_cpus; ++i) { 424 int j, online, pkg_id, die_id = 0, skip = 0; 425 426 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 427 continue; 428 if (i) 429 online = parse_int_file( 430 1, "/sys/devices/system/cpu/cpu%d/online", i); 431 else 432 online = 433 1; /* online entry for CPU 0 needs some special configs */ 434 435 die_id = get_physical_die_id(i); 436 if (die_id < 0) 437 die_id = 0; 438 439 pkg_id = parse_int_file(0, 440 "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i); 441 if (pkg_id < 0) 442 continue; 443 444 /* Create an unique id for package, die combination to store */ 445 pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id); 446 447 for (j = 0; j < pkg_index; ++j) { 448 if (max_packages[j] == pkg_id) { 449 skip = 1; 450 break; 451 } 452 } 453 454 if (!skip && online && callback) { 455 callback(i, arg1, arg2, arg3, arg4); 456 max_packages[pkg_index++] = pkg_id; 457 } 458 } 459 } 460 461 static void for_each_online_target_cpu_in_set( 462 void (*callback)(int, void *, void *, void *, void *), void *arg1, 463 void *arg2, void *arg3, void *arg4) 464 { 465 int i, found = 0; 466 467 for (i = 0; i < topo_max_cpus; ++i) { 468 int online; 469 470 if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask)) 471 continue; 472 if (i) 473 online = parse_int_file( 474 1, "/sys/devices/system/cpu/cpu%d/online", i); 475 else 476 online = 477 1; /* online entry for CPU 0 needs some special configs */ 478 479 if (online && callback) { 480 callback(i, arg1, arg2, arg3, arg4); 481 found = 1; 482 } 483 } 484 485 if (!found) 486 fprintf(stderr, "No valid CPU in the list\n"); 487 } 488 489 #define BITMASK_SIZE 32 490 static void set_max_cpu_num(void) 491 { 492 FILE *filep; 493 unsigned long dummy; 494 int i; 495 496 topo_max_cpus = 0; 497 for (i = 0; i < 256; ++i) { 498 char path[256]; 499 500 snprintf(path, sizeof(path), 501 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i); 502 filep = fopen(path, "r"); 503 if (filep) 504 break; 505 } 506 507 if (!filep) { 508 fprintf(stderr, "Can't get max cpu number\n"); 509 exit(0); 510 } 511 512 while (fscanf(filep, "%lx,", &dummy) == 1) 513 topo_max_cpus += BITMASK_SIZE; 514 fclose(filep); 515 516 debug_printf("max cpus %d\n", topo_max_cpus); 517 } 518 519 size_t alloc_cpu_set(cpu_set_t **cpu_set) 520 { 521 cpu_set_t *_cpu_set; 522 size_t size; 523 524 _cpu_set = CPU_ALLOC((topo_max_cpus + 1)); 525 if (_cpu_set == NULL) 526 err(3, "CPU_ALLOC"); 527 size = CPU_ALLOC_SIZE((topo_max_cpus + 1)); 528 CPU_ZERO_S(size, _cpu_set); 529 530 *cpu_set = _cpu_set; 531 return size; 532 } 533 534 void free_cpu_set(cpu_set_t *cpu_set) 535 { 536 CPU_FREE(cpu_set); 537 } 538 539 static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE]; 540 static long long core_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE]; 541 static void set_cpu_present_cpu_mask(void) 542 { 543 size_t size; 544 DIR *dir; 545 int i; 546 547 size = alloc_cpu_set(&present_cpumask); 548 present_cpumask_size = size; 549 for (i = 0; i < topo_max_cpus; ++i) { 550 char buffer[256]; 551 552 snprintf(buffer, sizeof(buffer), 553 "/sys/devices/system/cpu/cpu%d", i); 554 dir = opendir(buffer); 555 if (dir) { 556 int pkg_id, die_id; 557 558 CPU_SET_S(i, size, present_cpumask); 559 die_id = get_physical_die_id(i); 560 if (die_id < 0) 561 die_id = 0; 562 563 pkg_id = get_physical_package_id(i); 564 if (pkg_id < 0) { 565 fprintf(stderr, "Failed to get package id, CPU %d may be offline\n", i); 566 continue; 567 } 568 if (pkg_id < MAX_PACKAGE_COUNT && 569 die_id < MAX_DIE_PER_PACKAGE) { 570 int core_id = get_physical_core_id(i); 571 572 cpu_cnt[pkg_id][die_id]++; 573 core_mask[pkg_id][die_id] |= (1ULL << core_id); 574 } 575 } 576 closedir(dir); 577 } 578 } 579 580 int get_max_punit_core_id(int pkg_id, int die_id) 581 { 582 int max_id = 0; 583 int i; 584 585 for (i = 0; i < topo_max_cpus; ++i) 586 { 587 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 588 continue; 589 590 if (cpu_map[i].pkg_id == pkg_id && 591 cpu_map[i].die_id == die_id && 592 cpu_map[i].punit_cpu_core > max_id) 593 max_id = cpu_map[i].punit_cpu_core; 594 } 595 596 return max_id; 597 } 598 599 int get_cpu_count(int pkg_id, int die_id) 600 { 601 if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE) 602 return cpu_cnt[pkg_id][die_id]; 603 604 return 0; 605 } 606 607 static void set_cpu_target_cpu_mask(void) 608 { 609 size_t size; 610 int i; 611 612 size = alloc_cpu_set(&target_cpumask); 613 target_cpumask_size = size; 614 for (i = 0; i < max_target_cpus; ++i) { 615 if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size, 616 present_cpumask)) 617 continue; 618 619 CPU_SET_S(target_cpus[i], size, target_cpumask); 620 } 621 } 622 623 static void create_cpu_map(void) 624 { 625 const char *pathname = "/dev/isst_interface"; 626 int i, fd = 0; 627 struct isst_if_cpu_maps map; 628 629 cpu_map = malloc(sizeof(*cpu_map) * topo_max_cpus); 630 if (!cpu_map) 631 err(3, "cpumap"); 632 633 fd = open(pathname, O_RDWR); 634 if (fd < 0) 635 err(-1, "%s open failed", pathname); 636 637 for (i = 0; i < topo_max_cpus; ++i) { 638 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 639 continue; 640 641 map.cmd_count = 1; 642 map.cpu_map[0].logical_cpu = i; 643 644 debug_printf(" map logical_cpu:%d\n", 645 map.cpu_map[0].logical_cpu); 646 if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) { 647 perror("ISST_IF_GET_PHY_ID"); 648 fprintf(outf, "Error: map logical_cpu:%d\n", 649 map.cpu_map[0].logical_cpu); 650 continue; 651 } 652 cpu_map[i].core_id = get_physical_core_id(i); 653 cpu_map[i].pkg_id = get_physical_package_id(i); 654 cpu_map[i].die_id = get_physical_die_id(i); 655 cpu_map[i].punit_cpu = map.cpu_map[0].physical_cpu; 656 cpu_map[i].punit_cpu_core = (map.cpu_map[0].physical_cpu >> 657 1); // shift to get core id 658 659 debug_printf( 660 "map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n", 661 i, cpu_map[i].core_id, cpu_map[i].die_id, 662 cpu_map[i].pkg_id, cpu_map[i].punit_cpu, 663 cpu_map[i].punit_cpu_core); 664 } 665 666 if (fd) 667 close(fd); 668 } 669 670 int find_logical_cpu(int pkg_id, int die_id, int punit_core_id) 671 { 672 int i; 673 674 for (i = 0; i < topo_max_cpus; ++i) { 675 if (cpu_map[i].pkg_id == pkg_id && 676 cpu_map[i].die_id == die_id && 677 cpu_map[i].punit_cpu_core == punit_core_id) 678 return i; 679 } 680 681 return -EINVAL; 682 } 683 684 void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask, 685 size_t core_cpumask_size, 686 cpu_set_t *core_cpumask, int *cpu_cnt) 687 { 688 int i, cnt = 0; 689 int die_id, pkg_id; 690 691 *cpu_cnt = 0; 692 die_id = get_physical_die_id(cpu); 693 pkg_id = get_physical_package_id(cpu); 694 695 for (i = 0; i < 64; ++i) { 696 if (core_mask & BIT_ULL(i)) { 697 int j; 698 699 for (j = 0; j < topo_max_cpus; ++j) { 700 if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask)) 701 continue; 702 703 if (cpu_map[j].pkg_id == pkg_id && 704 cpu_map[j].die_id == die_id && 705 cpu_map[j].punit_cpu_core == i) { 706 CPU_SET_S(j, core_cpumask_size, 707 core_cpumask); 708 ++cnt; 709 } 710 } 711 } 712 } 713 714 *cpu_cnt = cnt; 715 } 716 717 int find_phy_core_num(int logical_cpu) 718 { 719 if (logical_cpu < topo_max_cpus) 720 return cpu_map[logical_cpu].punit_cpu_core; 721 722 return -EINVAL; 723 } 724 725 static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write, 726 unsigned int *value) 727 { 728 struct isst_if_io_regs io_regs; 729 const char *pathname = "/dev/isst_interface"; 730 int cmd; 731 int fd; 732 733 debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write); 734 735 fd = open(pathname, O_RDWR); 736 if (fd < 0) 737 err(-1, "%s open failed", pathname); 738 739 io_regs.req_count = 1; 740 io_regs.io_reg[0].logical_cpu = cpu; 741 io_regs.io_reg[0].reg = reg; 742 cmd = ISST_IF_IO_CMD; 743 if (write) { 744 io_regs.io_reg[0].read_write = 1; 745 io_regs.io_reg[0].value = *value; 746 } else { 747 io_regs.io_reg[0].read_write = 0; 748 } 749 750 if (ioctl(fd, cmd, &io_regs) == -1) { 751 if (errno == ENOTTY) { 752 perror("ISST_IF_IO_COMMAND\n"); 753 fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n"); 754 exit(0); 755 } 756 fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n", 757 cpu, reg, write); 758 } else { 759 if (!write) 760 *value = io_regs.io_reg[0].value; 761 762 debug_printf( 763 "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n", 764 cpu, reg, write, *value); 765 } 766 767 close(fd); 768 769 return 0; 770 } 771 772 int isst_send_mbox_command(unsigned int cpu, unsigned char command, 773 unsigned char sub_command, unsigned int parameter, 774 unsigned int req_data, unsigned int *resp) 775 { 776 const char *pathname = "/dev/isst_interface"; 777 int fd, retry; 778 struct isst_if_mbox_cmds mbox_cmds = { 0 }; 779 780 debug_printf( 781 "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n", 782 cpu, command, sub_command, parameter, req_data); 783 784 if (!is_skx_based_platform() && command == CONFIG_CLOS && 785 sub_command != CLOS_PM_QOS_CONFIG) { 786 unsigned int value; 787 int write = 0; 788 int clos_id, core_id, ret = 0; 789 790 debug_printf("CPU %d\n", cpu); 791 792 if (parameter & BIT(MBOX_CMD_WRITE_BIT)) { 793 value = req_data; 794 write = 1; 795 } 796 797 switch (sub_command) { 798 case CLOS_PQR_ASSOC: 799 core_id = parameter & 0xff; 800 ret = isst_send_mmio_command( 801 cpu, PQR_ASSOC_OFFSET + core_id * 4, write, 802 &value); 803 if (!ret && !write) 804 *resp = value; 805 break; 806 case CLOS_PM_CLOS: 807 clos_id = parameter & 0x03; 808 ret = isst_send_mmio_command( 809 cpu, PM_CLOS_OFFSET + clos_id * 4, write, 810 &value); 811 if (!ret && !write) 812 *resp = value; 813 break; 814 case CLOS_STATUS: 815 break; 816 default: 817 break; 818 } 819 return ret; 820 } 821 822 mbox_cmds.cmd_count = 1; 823 mbox_cmds.mbox_cmd[0].logical_cpu = cpu; 824 mbox_cmds.mbox_cmd[0].command = command; 825 mbox_cmds.mbox_cmd[0].sub_command = sub_command; 826 mbox_cmds.mbox_cmd[0].parameter = parameter; 827 mbox_cmds.mbox_cmd[0].req_data = req_data; 828 829 if (mbox_delay) 830 usleep(mbox_delay * 1000); 831 832 fd = open(pathname, O_RDWR); 833 if (fd < 0) 834 err(-1, "%s open failed", pathname); 835 836 retry = mbox_retries; 837 838 do { 839 if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) { 840 if (errno == ENOTTY) { 841 perror("ISST_IF_MBOX_COMMAND\n"); 842 fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n"); 843 exit(0); 844 } 845 debug_printf( 846 "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n", 847 cpu, command, sub_command, parameter, req_data, errno); 848 --retry; 849 } else { 850 *resp = mbox_cmds.mbox_cmd[0].resp_data; 851 debug_printf( 852 "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n", 853 cpu, command, sub_command, parameter, req_data, *resp); 854 break; 855 } 856 } while (retry); 857 858 close(fd); 859 860 if (!retry) { 861 debug_printf("Failed mbox command even after retries\n"); 862 return -1; 863 864 } 865 return 0; 866 } 867 868 int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write, 869 unsigned long long *req_resp) 870 { 871 struct isst_if_msr_cmds msr_cmds; 872 const char *pathname = "/dev/isst_interface"; 873 int fd; 874 875 fd = open(pathname, O_RDWR); 876 if (fd < 0) 877 err(-1, "%s open failed", pathname); 878 879 msr_cmds.cmd_count = 1; 880 msr_cmds.msr_cmd[0].logical_cpu = cpu; 881 msr_cmds.msr_cmd[0].msr = msr; 882 msr_cmds.msr_cmd[0].read_write = write; 883 if (write) 884 msr_cmds.msr_cmd[0].data = *req_resp; 885 886 if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) { 887 perror("ISST_IF_MSR_COMMAND"); 888 fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n", 889 cpu, msr, write); 890 } else { 891 if (!write) 892 *req_resp = msr_cmds.msr_cmd[0].data; 893 894 debug_printf( 895 "msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n", 896 cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data); 897 } 898 899 close(fd); 900 901 return 0; 902 } 903 904 static int isst_fill_platform_info(void) 905 { 906 const char *pathname = "/dev/isst_interface"; 907 int fd; 908 909 fd = open(pathname, O_RDWR); 910 if (fd < 0) 911 err(-1, "%s open failed", pathname); 912 913 if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) { 914 perror("ISST_IF_GET_PLATFORM_INFO"); 915 close(fd); 916 return -1; 917 } 918 919 close(fd); 920 921 if (isst_platform_info.api_version > supported_api_ver) { 922 printf("Incompatible API versions; Upgrade of tool is required\n"); 923 return -1; 924 } 925 return 0; 926 } 927 928 static void isst_print_extended_platform_info(void) 929 { 930 int cp_state, cp_cap, fact_support = 0, pbf_support = 0; 931 struct isst_pkg_ctdp_level_info ctdp_level; 932 struct isst_pkg_ctdp pkg_dev; 933 int ret, i, j; 934 FILE *filep; 935 936 for (i = 0; i < 256; ++i) { 937 char path[256]; 938 939 snprintf(path, sizeof(path), 940 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i); 941 filep = fopen(path, "r"); 942 if (filep) 943 break; 944 } 945 946 if (!filep) 947 return; 948 949 fclose(filep); 950 951 ret = isst_get_ctdp_levels(i, &pkg_dev); 952 if (ret) 953 return; 954 955 if (pkg_dev.enabled) { 956 fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n"); 957 } else { 958 fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n"); 959 fprintf(outf, "Only performance level 0 (base level) is present\n"); 960 } 961 962 if (pkg_dev.locked) 963 fprintf(outf, "TDP level change control is locked\n"); 964 else 965 fprintf(outf, "TDP level change control is unlocked, max level: %d \n", pkg_dev.levels); 966 967 for (j = 0; j <= pkg_dev.levels; ++j) { 968 ret = isst_get_ctdp_control(i, j, &ctdp_level); 969 if (ret) 970 continue; 971 972 if (!fact_support && ctdp_level.fact_support) 973 fact_support = 1; 974 975 if (!pbf_support && ctdp_level.pbf_support) 976 pbf_support = 1; 977 } 978 979 if (fact_support) 980 fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n"); 981 else 982 fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n"); 983 984 if (pbf_support) 985 fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n"); 986 else 987 fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n"); 988 989 ret = isst_read_pm_config(i, &cp_state, &cp_cap); 990 if (ret) { 991 fprintf(outf, "Intel(R) SST-CP (feature core-power) status is unknown\n"); 992 return; 993 } 994 if (cp_cap) 995 fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n"); 996 else 997 fprintf(outf, "Intel(R) SST-CP (feature core-power) is not supported\n"); 998 } 999 1000 static void isst_print_platform_information(void) 1001 { 1002 struct isst_if_platform_info platform_info; 1003 const char *pathname = "/dev/isst_interface"; 1004 int fd; 1005 1006 if (is_clx_n_platform()) { 1007 fprintf(stderr, "\nThis option in not supported on this platform\n"); 1008 exit(0); 1009 } 1010 1011 fd = open(pathname, O_RDWR); 1012 if (fd < 0) 1013 err(-1, "%s open failed", pathname); 1014 1015 if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) { 1016 perror("ISST_IF_GET_PLATFORM_INFO"); 1017 } else { 1018 fprintf(outf, "Platform: API version : %d\n", 1019 platform_info.api_version); 1020 fprintf(outf, "Platform: Driver version : %d\n", 1021 platform_info.driver_version); 1022 fprintf(outf, "Platform: mbox supported : %d\n", 1023 platform_info.mbox_supported); 1024 fprintf(outf, "Platform: mmio supported : %d\n", 1025 platform_info.mmio_supported); 1026 isst_print_extended_platform_info(); 1027 } 1028 1029 close(fd); 1030 1031 exit(0); 1032 } 1033 1034 static char *local_str0, *local_str1; 1035 static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3, 1036 void *arg4) 1037 { 1038 int (*fn_ptr)(int cpu, void *arg); 1039 int ret; 1040 1041 fn_ptr = arg1; 1042 ret = fn_ptr(cpu, arg2); 1043 if (ret) 1044 isst_display_error_info_message(1, "get_tdp_* failed", 0, 0); 1045 else 1046 isst_ctdp_display_core_info(cpu, outf, arg3, 1047 *(unsigned int *)arg4, 1048 local_str0, local_str1); 1049 } 1050 1051 #define _get_tdp_level(desc, suffix, object, help, str0, str1) \ 1052 static void get_tdp_##object(int arg) \ 1053 { \ 1054 struct isst_pkg_ctdp ctdp; \ 1055 \ 1056 if (cmd_help) { \ 1057 fprintf(stderr, \ 1058 "Print %s [No command arguments are required]\n", \ 1059 help); \ 1060 exit(0); \ 1061 } \ 1062 local_str0 = str0; \ 1063 local_str1 = str1; \ 1064 isst_ctdp_display_information_start(outf); \ 1065 if (max_target_cpus) \ 1066 for_each_online_target_cpu_in_set( \ 1067 exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix, \ 1068 &ctdp, desc, &ctdp.object); \ 1069 else \ 1070 for_each_online_package_in_set(exec_on_get_ctdp_cpu, \ 1071 isst_get_ctdp_##suffix, \ 1072 &ctdp, desc, \ 1073 &ctdp.object); \ 1074 isst_ctdp_display_information_end(outf); \ 1075 } 1076 1077 _get_tdp_level("get-config-levels", levels, levels, "Max TDP level", NULL, NULL); 1078 _get_tdp_level("get-config-version", levels, version, "TDP version", NULL, NULL); 1079 _get_tdp_level("get-config-enabled", levels, enabled, "perf-profile enable status", "disabled", "enabled"); 1080 _get_tdp_level("get-config-current_level", levels, current_level, 1081 "Current TDP Level", NULL, NULL); 1082 _get_tdp_level("get-lock-status", levels, locked, "TDP lock status", "unlocked", "locked"); 1083 1084 struct isst_pkg_ctdp clx_n_pkg_dev; 1085 1086 static int clx_n_get_base_ratio(void) 1087 { 1088 FILE *fp; 1089 char *begin, *end, *line = NULL; 1090 char number[5]; 1091 float value = 0; 1092 size_t n = 0; 1093 1094 fp = fopen("/proc/cpuinfo", "r"); 1095 if (!fp) 1096 err(-1, "cannot open /proc/cpuinfo\n"); 1097 1098 while (getline(&line, &n, fp) > 0) { 1099 if (strstr(line, "model name")) { 1100 /* this is true for CascadeLake-N */ 1101 begin = strstr(line, "@ ") + 2; 1102 end = strstr(line, "GHz"); 1103 strncpy(number, begin, end - begin); 1104 value = atof(number) * 10; 1105 break; 1106 } 1107 } 1108 free(line); 1109 fclose(fp); 1110 1111 return (int)(value); 1112 } 1113 1114 static int clx_n_config(int cpu) 1115 { 1116 int i, ret, pkg_id, die_id; 1117 unsigned long cpu_bf; 1118 struct isst_pkg_ctdp_level_info *ctdp_level; 1119 struct isst_pbf_info *pbf_info; 1120 1121 ctdp_level = &clx_n_pkg_dev.ctdp_level[0]; 1122 pbf_info = &ctdp_level->pbf_info; 1123 ctdp_level->core_cpumask_size = 1124 alloc_cpu_set(&ctdp_level->core_cpumask); 1125 1126 /* find the frequency base ratio */ 1127 ctdp_level->tdp_ratio = clx_n_get_base_ratio(); 1128 if (ctdp_level->tdp_ratio == 0) { 1129 debug_printf("CLX: cn base ratio is zero\n"); 1130 ret = -1; 1131 goto error_ret; 1132 } 1133 1134 /* find the high and low priority frequencies */ 1135 pbf_info->p1_high = 0; 1136 pbf_info->p1_low = ~0; 1137 1138 pkg_id = get_physical_package_id(cpu); 1139 die_id = get_physical_die_id(cpu); 1140 1141 for (i = 0; i < topo_max_cpus; i++) { 1142 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 1143 continue; 1144 1145 if (pkg_id != get_physical_package_id(i) || 1146 die_id != get_physical_die_id(i)) 1147 continue; 1148 1149 CPU_SET_S(i, ctdp_level->core_cpumask_size, 1150 ctdp_level->core_cpumask); 1151 1152 cpu_bf = parse_int_file(1, 1153 "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", 1154 i); 1155 if (cpu_bf > pbf_info->p1_high) 1156 pbf_info->p1_high = cpu_bf; 1157 if (cpu_bf < pbf_info->p1_low) 1158 pbf_info->p1_low = cpu_bf; 1159 } 1160 1161 if (pbf_info->p1_high == ~0UL) { 1162 debug_printf("CLX: maximum base frequency not set\n"); 1163 ret = -1; 1164 goto error_ret; 1165 } 1166 1167 if (pbf_info->p1_low == 0) { 1168 debug_printf("CLX: minimum base frequency not set\n"); 1169 ret = -1; 1170 goto error_ret; 1171 } 1172 1173 /* convert frequencies back to ratios */ 1174 pbf_info->p1_high = pbf_info->p1_high / 100000; 1175 pbf_info->p1_low = pbf_info->p1_low / 100000; 1176 1177 /* create high priority cpu mask */ 1178 pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask); 1179 for (i = 0; i < topo_max_cpus; i++) { 1180 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 1181 continue; 1182 1183 if (pkg_id != get_physical_package_id(i) || 1184 die_id != get_physical_die_id(i)) 1185 continue; 1186 1187 cpu_bf = parse_int_file(1, 1188 "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", 1189 i); 1190 cpu_bf = cpu_bf / 100000; 1191 if (cpu_bf == pbf_info->p1_high) 1192 CPU_SET_S(i, pbf_info->core_cpumask_size, 1193 pbf_info->core_cpumask); 1194 } 1195 1196 /* extra ctdp & pbf struct parameters */ 1197 ctdp_level->processed = 1; 1198 ctdp_level->pbf_support = 1; /* PBF is always supported and enabled */ 1199 ctdp_level->pbf_enabled = 1; 1200 ctdp_level->fact_support = 0; /* FACT is never supported */ 1201 ctdp_level->fact_enabled = 0; 1202 1203 return 0; 1204 1205 error_ret: 1206 free_cpu_set(ctdp_level->core_cpumask); 1207 return ret; 1208 } 1209 1210 static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2, 1211 void *arg3, void *arg4) 1212 { 1213 int ret; 1214 1215 if (tdp_level != 0xff && tdp_level != 0) { 1216 isst_display_error_info_message(1, "Invalid level", 1, tdp_level); 1217 exit(0); 1218 } 1219 1220 ret = clx_n_config(cpu); 1221 if (ret) { 1222 debug_printf("clx_n_config failed"); 1223 } else { 1224 struct isst_pkg_ctdp_level_info *ctdp_level; 1225 struct isst_pbf_info *pbf_info; 1226 1227 ctdp_level = &clx_n_pkg_dev.ctdp_level[0]; 1228 pbf_info = &ctdp_level->pbf_info; 1229 clx_n_pkg_dev.processed = 1; 1230 isst_ctdp_display_information(cpu, outf, tdp_level, &clx_n_pkg_dev); 1231 free_cpu_set(ctdp_level->core_cpumask); 1232 free_cpu_set(pbf_info->core_cpumask); 1233 } 1234 } 1235 1236 static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2, 1237 void *arg3, void *arg4) 1238 { 1239 struct isst_pkg_ctdp pkg_dev; 1240 int ret; 1241 1242 memset(&pkg_dev, 0, sizeof(pkg_dev)); 1243 ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev); 1244 if (ret) { 1245 isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, cpu); 1246 isst_ctdp_display_information_end(outf); 1247 exit(1); 1248 } else { 1249 isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev); 1250 isst_get_process_ctdp_complete(cpu, &pkg_dev); 1251 } 1252 } 1253 1254 static void dump_isst_config(int arg) 1255 { 1256 void *fn; 1257 1258 if (cmd_help) { 1259 fprintf(stderr, 1260 "Print Intel(R) Speed Select Technology Performance profile configuration\n"); 1261 fprintf(stderr, 1262 "including base frequency and turbo frequency configurations\n"); 1263 fprintf(stderr, "Optional: -l|--level : Specify tdp level\n"); 1264 fprintf(stderr, 1265 "\tIf no arguments, dump information for all TDP levels\n"); 1266 exit(0); 1267 } 1268 1269 if (!is_clx_n_platform()) 1270 fn = dump_isst_config_for_cpu; 1271 else 1272 fn = dump_clx_n_config_for_cpu; 1273 1274 isst_ctdp_display_information_start(outf); 1275 1276 if (max_target_cpus) 1277 for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL); 1278 else 1279 for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL); 1280 1281 isst_ctdp_display_information_end(outf); 1282 } 1283 1284 static void adjust_scaling_max_from_base_freq(int cpu); 1285 1286 static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 1287 void *arg4) 1288 { 1289 int ret; 1290 1291 ret = isst_set_tdp_level(cpu, tdp_level); 1292 if (ret) { 1293 isst_display_error_info_message(1, "Set TDP level failed", 0, 0); 1294 isst_ctdp_display_information_end(outf); 1295 exit(1); 1296 } else { 1297 isst_display_result(cpu, outf, "perf-profile", "set_tdp_level", 1298 ret); 1299 if (force_online_offline) { 1300 struct isst_pkg_ctdp_level_info ctdp_level; 1301 int pkg_id = get_physical_package_id(cpu); 1302 int die_id = get_physical_die_id(cpu); 1303 1304 /* Wait for updated base frequencies */ 1305 usleep(2000); 1306 1307 fprintf(stderr, "Option is set to online/offline\n"); 1308 ctdp_level.core_cpumask_size = 1309 alloc_cpu_set(&ctdp_level.core_cpumask); 1310 ret = isst_get_coremask_info(cpu, tdp_level, &ctdp_level); 1311 if (ret) { 1312 isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0); 1313 return; 1314 } 1315 if (ctdp_level.cpu_count) { 1316 int i, max_cpus = get_topo_max_cpus(); 1317 for (i = 0; i < max_cpus; ++i) { 1318 if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i)) 1319 continue; 1320 if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) { 1321 fprintf(stderr, "online cpu %d\n", i); 1322 set_cpu_online_offline(i, 1); 1323 adjust_scaling_max_from_base_freq(i); 1324 } else { 1325 fprintf(stderr, "offline cpu %d\n", i); 1326 set_cpu_online_offline(i, 0); 1327 } 1328 } 1329 } 1330 } 1331 } 1332 } 1333 1334 static void set_tdp_level(int arg) 1335 { 1336 if (cmd_help) { 1337 fprintf(stderr, "Set Config TDP level\n"); 1338 fprintf(stderr, 1339 "\t Arguments: -l|--level : Specify tdp level\n"); 1340 fprintf(stderr, 1341 "\t Optional Arguments: -o | online : online/offline for the tdp level\n"); 1342 fprintf(stderr, 1343 "\t online/offline operation has limitations, refer to Linux hotplug documentation\n"); 1344 exit(0); 1345 } 1346 1347 if (tdp_level == 0xff) { 1348 isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0); 1349 exit(1); 1350 } 1351 isst_ctdp_display_information_start(outf); 1352 if (max_target_cpus) 1353 for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL, 1354 NULL, NULL, NULL); 1355 else 1356 for_each_online_package_in_set(set_tdp_level_for_cpu, NULL, 1357 NULL, NULL, NULL); 1358 isst_ctdp_display_information_end(outf); 1359 } 1360 1361 static void clx_n_dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, 1362 void *arg3, void *arg4) 1363 { 1364 int ret; 1365 1366 ret = clx_n_config(cpu); 1367 if (ret) { 1368 isst_display_error_info_message(1, "clx_n_config failed", 0, 0); 1369 } else { 1370 struct isst_pkg_ctdp_level_info *ctdp_level; 1371 struct isst_pbf_info *pbf_info; 1372 1373 ctdp_level = &clx_n_pkg_dev.ctdp_level[0]; 1374 pbf_info = &ctdp_level->pbf_info; 1375 isst_pbf_display_information(cpu, outf, tdp_level, pbf_info); 1376 free_cpu_set(ctdp_level->core_cpumask); 1377 free_cpu_set(pbf_info->core_cpumask); 1378 } 1379 } 1380 1381 static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 1382 void *arg4) 1383 { 1384 struct isst_pbf_info pbf_info; 1385 int ret; 1386 1387 ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info); 1388 if (ret) { 1389 isst_display_error_info_message(1, "Failed to get base-freq info at this level", 1, tdp_level); 1390 isst_ctdp_display_information_end(outf); 1391 exit(1); 1392 } else { 1393 isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info); 1394 isst_get_pbf_info_complete(&pbf_info); 1395 } 1396 } 1397 1398 static void dump_pbf_config(int arg) 1399 { 1400 void *fn; 1401 1402 if (cmd_help) { 1403 fprintf(stderr, 1404 "Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n"); 1405 fprintf(stderr, 1406 "\tArguments: -l|--level : Specify tdp level\n"); 1407 exit(0); 1408 } 1409 1410 if (tdp_level == 0xff) { 1411 isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0); 1412 exit(1); 1413 } 1414 1415 if (!is_clx_n_platform()) 1416 fn = dump_pbf_config_for_cpu; 1417 else 1418 fn = clx_n_dump_pbf_config_for_cpu; 1419 1420 isst_ctdp_display_information_start(outf); 1421 1422 if (max_target_cpus) 1423 for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL); 1424 else 1425 for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL); 1426 1427 isst_ctdp_display_information_end(outf); 1428 } 1429 1430 static int set_clos_param(int cpu, int clos, int epp, int wt, int min, int max) 1431 { 1432 struct isst_clos_config clos_config; 1433 int ret; 1434 1435 ret = isst_pm_get_clos(cpu, clos, &clos_config); 1436 if (ret) { 1437 isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0); 1438 return ret; 1439 } 1440 clos_config.clos_min = min; 1441 clos_config.clos_max = max; 1442 clos_config.epp = epp; 1443 clos_config.clos_prop_prio = wt; 1444 ret = isst_set_clos(cpu, clos, &clos_config); 1445 if (ret) { 1446 isst_display_error_info_message(1, "isst_set_clos failed", 0, 0); 1447 return ret; 1448 } 1449 1450 return 0; 1451 } 1452 1453 static int set_cpufreq_scaling_min_max(int cpu, int max, int freq) 1454 { 1455 char buffer[128], freq_str[16]; 1456 int fd, ret, len; 1457 1458 if (max) 1459 snprintf(buffer, sizeof(buffer), 1460 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu); 1461 else 1462 snprintf(buffer, sizeof(buffer), 1463 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu); 1464 1465 fd = open(buffer, O_WRONLY); 1466 if (fd < 0) 1467 return fd; 1468 1469 snprintf(freq_str, sizeof(freq_str), "%d", freq); 1470 len = strlen(freq_str); 1471 ret = write(fd, freq_str, len); 1472 if (ret == -1) { 1473 close(fd); 1474 return ret; 1475 } 1476 close(fd); 1477 1478 return 0; 1479 } 1480 1481 static int no_turbo(void) 1482 { 1483 return parse_int_file(0, "/sys/devices/system/cpu/intel_pstate/no_turbo"); 1484 } 1485 1486 static void adjust_scaling_max_from_base_freq(int cpu) 1487 { 1488 int base_freq, scaling_max_freq; 1489 1490 scaling_max_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu); 1491 base_freq = get_cpufreq_base_freq(cpu); 1492 if (scaling_max_freq < base_freq || no_turbo()) 1493 set_cpufreq_scaling_min_max(cpu, 1, base_freq); 1494 } 1495 1496 static void adjust_scaling_min_from_base_freq(int cpu) 1497 { 1498 int base_freq, scaling_min_freq; 1499 1500 scaling_min_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu); 1501 base_freq = get_cpufreq_base_freq(cpu); 1502 if (scaling_min_freq < base_freq) 1503 set_cpufreq_scaling_min_max(cpu, 0, base_freq); 1504 } 1505 1506 static int set_clx_pbf_cpufreq_scaling_min_max(int cpu) 1507 { 1508 struct isst_pkg_ctdp_level_info *ctdp_level; 1509 struct isst_pbf_info *pbf_info; 1510 int i, pkg_id, die_id, freq, freq_high, freq_low; 1511 int ret; 1512 1513 ret = clx_n_config(cpu); 1514 if (ret) { 1515 debug_printf("cpufreq_scaling_min_max failed for CLX"); 1516 return ret; 1517 } 1518 1519 ctdp_level = &clx_n_pkg_dev.ctdp_level[0]; 1520 pbf_info = &ctdp_level->pbf_info; 1521 freq_high = pbf_info->p1_high * 100000; 1522 freq_low = pbf_info->p1_low * 100000; 1523 1524 pkg_id = get_physical_package_id(cpu); 1525 die_id = get_physical_die_id(cpu); 1526 for (i = 0; i < get_topo_max_cpus(); ++i) { 1527 if (pkg_id != get_physical_package_id(i) || 1528 die_id != get_physical_die_id(i)) 1529 continue; 1530 1531 if (CPU_ISSET_S(i, pbf_info->core_cpumask_size, 1532 pbf_info->core_cpumask)) 1533 freq = freq_high; 1534 else 1535 freq = freq_low; 1536 1537 set_cpufreq_scaling_min_max(i, 1, freq); 1538 set_cpufreq_scaling_min_max(i, 0, freq); 1539 } 1540 1541 return 0; 1542 } 1543 1544 static int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, int scaling_max) 1545 { 1546 char buffer[128], min_freq[16]; 1547 int fd, ret, len; 1548 1549 if (!CPU_ISSET_S(cpu, present_cpumask_size, present_cpumask)) 1550 return -1; 1551 1552 if (cpuinfo_max) 1553 snprintf(buffer, sizeof(buffer), 1554 "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu); 1555 else 1556 snprintf(buffer, sizeof(buffer), 1557 "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_min_freq", cpu); 1558 1559 fd = open(buffer, O_RDONLY); 1560 if (fd < 0) 1561 return fd; 1562 1563 len = read(fd, min_freq, sizeof(min_freq)); 1564 close(fd); 1565 1566 if (len < 0) 1567 return len; 1568 1569 if (scaling_max) 1570 snprintf(buffer, sizeof(buffer), 1571 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu); 1572 else 1573 snprintf(buffer, sizeof(buffer), 1574 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu); 1575 1576 fd = open(buffer, O_WRONLY); 1577 if (fd < 0) 1578 return fd; 1579 1580 len = strlen(min_freq); 1581 ret = write(fd, min_freq, len); 1582 if (ret == -1) { 1583 close(fd); 1584 return ret; 1585 } 1586 close(fd); 1587 1588 return 0; 1589 } 1590 1591 static void set_scaling_min_to_cpuinfo_max(int cpu) 1592 { 1593 int i, pkg_id, die_id; 1594 1595 pkg_id = get_physical_package_id(cpu); 1596 die_id = get_physical_die_id(cpu); 1597 for (i = 0; i < get_topo_max_cpus(); ++i) { 1598 if (pkg_id != get_physical_package_id(i) || 1599 die_id != get_physical_die_id(i)) 1600 continue; 1601 1602 adjust_scaling_max_from_base_freq(i); 1603 set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0); 1604 adjust_scaling_min_from_base_freq(i); 1605 } 1606 } 1607 1608 static void set_scaling_min_to_cpuinfo_min(int cpu) 1609 { 1610 int i, pkg_id, die_id; 1611 1612 pkg_id = get_physical_package_id(cpu); 1613 die_id = get_physical_die_id(cpu); 1614 for (i = 0; i < get_topo_max_cpus(); ++i) { 1615 if (pkg_id != get_physical_package_id(i) || 1616 die_id != get_physical_die_id(i)) 1617 continue; 1618 1619 adjust_scaling_max_from_base_freq(i); 1620 set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0); 1621 } 1622 } 1623 1624 static void set_scaling_max_to_cpuinfo_max(int cpu) 1625 { 1626 int i, pkg_id, die_id; 1627 1628 pkg_id = get_physical_package_id(cpu); 1629 die_id = get_physical_die_id(cpu); 1630 for (i = 0; i < get_topo_max_cpus(); ++i) { 1631 if (pkg_id != get_physical_package_id(i) || 1632 die_id != get_physical_die_id(i)) 1633 continue; 1634 1635 set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1); 1636 } 1637 } 1638 1639 static int set_core_priority_and_min(int cpu, int mask_size, 1640 cpu_set_t *cpu_mask, int min_high, 1641 int min_low) 1642 { 1643 int pkg_id, die_id, ret, i; 1644 1645 if (!CPU_COUNT_S(mask_size, cpu_mask)) 1646 return -1; 1647 1648 ret = set_clos_param(cpu, 0, 0, 0, min_high, 0xff); 1649 if (ret) 1650 return ret; 1651 1652 ret = set_clos_param(cpu, 1, 15, 15, min_low, 0xff); 1653 if (ret) 1654 return ret; 1655 1656 ret = set_clos_param(cpu, 2, 15, 15, min_low, 0xff); 1657 if (ret) 1658 return ret; 1659 1660 ret = set_clos_param(cpu, 3, 15, 15, min_low, 0xff); 1661 if (ret) 1662 return ret; 1663 1664 pkg_id = get_physical_package_id(cpu); 1665 die_id = get_physical_die_id(cpu); 1666 for (i = 0; i < get_topo_max_cpus(); ++i) { 1667 int clos; 1668 1669 if (pkg_id != get_physical_package_id(i) || 1670 die_id != get_physical_die_id(i)) 1671 continue; 1672 1673 if (CPU_ISSET_S(i, mask_size, cpu_mask)) 1674 clos = 0; 1675 else 1676 clos = 3; 1677 1678 debug_printf("Associate cpu: %d clos: %d\n", i, clos); 1679 ret = isst_clos_associate(i, clos); 1680 if (ret) { 1681 isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0); 1682 return ret; 1683 } 1684 } 1685 1686 return 0; 1687 } 1688 1689 static int set_pbf_core_power(int cpu) 1690 { 1691 struct isst_pbf_info pbf_info; 1692 struct isst_pkg_ctdp pkg_dev; 1693 int ret; 1694 1695 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 1696 if (ret) { 1697 debug_printf("isst_get_ctdp_levels failed"); 1698 return ret; 1699 } 1700 debug_printf("Current_level: %d\n", pkg_dev.current_level); 1701 1702 ret = isst_get_pbf_info(cpu, pkg_dev.current_level, &pbf_info); 1703 if (ret) { 1704 debug_printf("isst_get_pbf_info failed"); 1705 return ret; 1706 } 1707 debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high, 1708 pbf_info.p1_low); 1709 1710 ret = set_core_priority_and_min(cpu, pbf_info.core_cpumask_size, 1711 pbf_info.core_cpumask, 1712 pbf_info.p1_high, pbf_info.p1_low); 1713 if (ret) { 1714 debug_printf("set_core_priority_and_min failed"); 1715 return ret; 1716 } 1717 1718 ret = isst_pm_qos_config(cpu, 1, 1); 1719 if (ret) { 1720 debug_printf("isst_pm_qos_config failed"); 1721 return ret; 1722 } 1723 1724 return 0; 1725 } 1726 1727 static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 1728 void *arg4) 1729 { 1730 struct isst_pkg_ctdp_level_info ctdp_level; 1731 struct isst_pkg_ctdp pkg_dev; 1732 int ret; 1733 int status = *(int *)arg4; 1734 1735 if (is_clx_n_platform()) { 1736 ret = 0; 1737 if (status) { 1738 set_clx_pbf_cpufreq_scaling_min_max(cpu); 1739 1740 } else { 1741 set_scaling_max_to_cpuinfo_max(cpu); 1742 set_scaling_min_to_cpuinfo_min(cpu); 1743 } 1744 goto disp_result; 1745 } 1746 1747 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 1748 if (ret) { 1749 isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); 1750 goto disp_result; 1751 } 1752 1753 ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level); 1754 if (ret) { 1755 isst_display_error_info_message(1, "Failed to get current level", 0, 0); 1756 goto disp_result; 1757 } 1758 1759 if (!ctdp_level.pbf_support) { 1760 isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, pkg_dev.current_level); 1761 ret = -1; 1762 goto disp_result; 1763 } 1764 1765 if (auto_mode && status) { 1766 ret = set_pbf_core_power(cpu); 1767 if (ret) 1768 goto disp_result; 1769 } 1770 1771 ret = isst_set_pbf_fact_status(cpu, 1, status); 1772 if (ret) { 1773 debug_printf("isst_set_pbf_fact_status failed"); 1774 if (auto_mode) 1775 isst_pm_qos_config(cpu, 0, 0); 1776 } else { 1777 if (auto_mode) { 1778 if (status) 1779 set_scaling_min_to_cpuinfo_max(cpu); 1780 else 1781 set_scaling_min_to_cpuinfo_min(cpu); 1782 } 1783 } 1784 1785 if (auto_mode && !status) 1786 isst_pm_qos_config(cpu, 0, 1); 1787 1788 disp_result: 1789 if (status) 1790 isst_display_result(cpu, outf, "base-freq", "enable", 1791 ret); 1792 else 1793 isst_display_result(cpu, outf, "base-freq", "disable", 1794 ret); 1795 } 1796 1797 static void set_pbf_enable(int arg) 1798 { 1799 int enable = arg; 1800 1801 if (cmd_help) { 1802 if (enable) { 1803 fprintf(stderr, 1804 "Enable Intel Speed Select Technology base frequency feature\n"); 1805 if (is_clx_n_platform()) { 1806 fprintf(stderr, 1807 "\tOn this platform this command doesn't enable feature in the hardware.\n"); 1808 fprintf(stderr, 1809 "\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n"); 1810 exit(0); 1811 1812 } 1813 fprintf(stderr, 1814 "\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n"); 1815 } else { 1816 1817 if (is_clx_n_platform()) { 1818 fprintf(stderr, 1819 "\tOn this platform this command doesn't disable feature in the hardware.\n"); 1820 fprintf(stderr, 1821 "\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n"); 1822 exit(0); 1823 } 1824 fprintf(stderr, 1825 "Disable Intel Speed Select Technology base frequency feature\n"); 1826 fprintf(stderr, 1827 "\tOptional Arguments: -a|--auto : Also disable core-power associations\n"); 1828 } 1829 exit(0); 1830 } 1831 1832 isst_ctdp_display_information_start(outf); 1833 if (max_target_cpus) 1834 for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL, 1835 NULL, &enable); 1836 else 1837 for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL, 1838 NULL, &enable); 1839 isst_ctdp_display_information_end(outf); 1840 } 1841 1842 static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2, 1843 void *arg3, void *arg4) 1844 { 1845 struct isst_fact_info fact_info; 1846 int ret; 1847 1848 ret = isst_get_fact_info(cpu, tdp_level, fact_bucket, &fact_info); 1849 if (ret) { 1850 isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level); 1851 isst_ctdp_display_information_end(outf); 1852 exit(1); 1853 } else { 1854 isst_fact_display_information(cpu, outf, tdp_level, fact_bucket, 1855 fact_avx, &fact_info); 1856 } 1857 } 1858 1859 static void dump_fact_config(int arg) 1860 { 1861 if (cmd_help) { 1862 fprintf(stderr, 1863 "Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n"); 1864 fprintf(stderr, 1865 "\tArguments: -l|--level : Specify tdp level\n"); 1866 fprintf(stderr, 1867 "\tArguments: -b|--bucket : Bucket index to dump\n"); 1868 fprintf(stderr, 1869 "\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n"); 1870 exit(0); 1871 } 1872 1873 if (tdp_level == 0xff) { 1874 isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0); 1875 exit(1); 1876 } 1877 1878 isst_ctdp_display_information_start(outf); 1879 if (max_target_cpus) 1880 for_each_online_target_cpu_in_set(dump_fact_config_for_cpu, 1881 NULL, NULL, NULL, NULL); 1882 else 1883 for_each_online_package_in_set(dump_fact_config_for_cpu, NULL, 1884 NULL, NULL, NULL); 1885 isst_ctdp_display_information_end(outf); 1886 } 1887 1888 static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 1889 void *arg4) 1890 { 1891 struct isst_pkg_ctdp_level_info ctdp_level; 1892 struct isst_pkg_ctdp pkg_dev; 1893 int ret; 1894 int status = *(int *)arg4; 1895 1896 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 1897 if (ret) { 1898 isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); 1899 goto disp_results; 1900 } 1901 1902 ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level); 1903 if (ret) { 1904 isst_display_error_info_message(1, "Failed to get current level", 0, 0); 1905 goto disp_results; 1906 } 1907 1908 if (!ctdp_level.fact_support) { 1909 isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, pkg_dev.current_level); 1910 ret = -1; 1911 goto disp_results; 1912 } 1913 1914 if (status) { 1915 ret = isst_pm_qos_config(cpu, 1, 1); 1916 if (ret) 1917 goto disp_results; 1918 } 1919 1920 ret = isst_set_pbf_fact_status(cpu, 0, status); 1921 if (ret) { 1922 debug_printf("isst_set_pbf_fact_status failed"); 1923 if (auto_mode) 1924 isst_pm_qos_config(cpu, 0, 0); 1925 1926 goto disp_results; 1927 } 1928 1929 /* Set TRL */ 1930 if (status) { 1931 struct isst_pkg_ctdp pkg_dev; 1932 1933 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 1934 if (!ret) 1935 ret = isst_set_trl(cpu, fact_trl); 1936 if (ret && auto_mode) 1937 isst_pm_qos_config(cpu, 0, 0); 1938 } else { 1939 if (auto_mode) 1940 isst_pm_qos_config(cpu, 0, 0); 1941 } 1942 1943 disp_results: 1944 if (status) { 1945 isst_display_result(cpu, outf, "turbo-freq", "enable", ret); 1946 if (ret) 1947 fact_enable_fail = ret; 1948 } else { 1949 /* Since we modified TRL during Fact enable, restore it */ 1950 isst_set_trl_from_current_tdp(cpu, fact_trl); 1951 isst_display_result(cpu, outf, "turbo-freq", "disable", ret); 1952 } 1953 } 1954 1955 static void set_fact_enable(int arg) 1956 { 1957 int i, ret, enable = arg; 1958 1959 if (cmd_help) { 1960 if (enable) { 1961 fprintf(stderr, 1962 "Enable Intel Speed Select Technology Turbo frequency feature\n"); 1963 fprintf(stderr, 1964 "Optional: -t|--trl : Specify turbo ratio limit\n"); 1965 fprintf(stderr, 1966 "\tOptional Arguments: -a|--auto : Designate specified target CPUs with"); 1967 fprintf(stderr, 1968 "-C|--cpu option as as high priority using core-power feature\n"); 1969 } else { 1970 fprintf(stderr, 1971 "Disable Intel Speed Select Technology turbo frequency feature\n"); 1972 fprintf(stderr, 1973 "Optional: -t|--trl : Specify turbo ratio limit\n"); 1974 fprintf(stderr, 1975 "\tOptional Arguments: -a|--auto : Also disable core-power associations\n"); 1976 } 1977 exit(0); 1978 } 1979 1980 isst_ctdp_display_information_start(outf); 1981 if (max_target_cpus) 1982 for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL, 1983 NULL, &enable); 1984 else 1985 for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL, 1986 NULL, &enable); 1987 isst_ctdp_display_information_end(outf); 1988 1989 if (!fact_enable_fail && enable && auto_mode) { 1990 /* 1991 * When we adjust CLOS param, we have to set for siblings also. 1992 * So for the each user specified CPU, also add the sibling 1993 * in the present_cpu_mask. 1994 */ 1995 for (i = 0; i < get_topo_max_cpus(); ++i) { 1996 char buffer[128], sibling_list[128], *cpu_str; 1997 int fd, len; 1998 1999 if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask)) 2000 continue; 2001 2002 snprintf(buffer, sizeof(buffer), 2003 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i); 2004 2005 fd = open(buffer, O_RDONLY); 2006 if (fd < 0) 2007 continue; 2008 2009 len = read(fd, sibling_list, sizeof(sibling_list)); 2010 close(fd); 2011 2012 if (len < 0) 2013 continue; 2014 2015 cpu_str = strtok(sibling_list, ","); 2016 while (cpu_str != NULL) { 2017 int cpu; 2018 2019 sscanf(cpu_str, "%d", &cpu); 2020 CPU_SET_S(cpu, target_cpumask_size, target_cpumask); 2021 cpu_str = strtok(NULL, ","); 2022 } 2023 } 2024 2025 for (i = 0; i < get_topo_max_cpus(); ++i) { 2026 int clos; 2027 2028 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 2029 continue; 2030 2031 ret = set_clos_param(i, 0, 0, 0, 0, 0xff); 2032 if (ret) 2033 goto error_disp; 2034 2035 ret = set_clos_param(i, 1, 15, 15, 0, 0xff); 2036 if (ret) 2037 goto error_disp; 2038 2039 ret = set_clos_param(i, 2, 15, 15, 0, 0xff); 2040 if (ret) 2041 goto error_disp; 2042 2043 ret = set_clos_param(i, 3, 15, 15, 0, 0xff); 2044 if (ret) 2045 goto error_disp; 2046 2047 if (CPU_ISSET_S(i, target_cpumask_size, target_cpumask)) 2048 clos = 0; 2049 else 2050 clos = 3; 2051 2052 debug_printf("Associate cpu: %d clos: %d\n", i, clos); 2053 ret = isst_clos_associate(i, clos); 2054 if (ret) 2055 goto error_disp; 2056 } 2057 isst_display_result(-1, outf, "turbo-freq --auto", "enable", 0); 2058 } 2059 2060 return; 2061 2062 error_disp: 2063 isst_display_result(i, outf, "turbo-freq --auto", "enable", ret); 2064 2065 } 2066 2067 static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3, 2068 void *arg4) 2069 { 2070 int ret; 2071 int status = *(int *)arg4; 2072 2073 if (is_skx_based_platform()) 2074 clos_priority_type = 1; 2075 2076 ret = isst_pm_qos_config(cpu, status, clos_priority_type); 2077 if (ret) 2078 isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0); 2079 2080 if (status) 2081 isst_display_result(cpu, outf, "core-power", "enable", 2082 ret); 2083 else 2084 isst_display_result(cpu, outf, "core-power", "disable", 2085 ret); 2086 } 2087 2088 static void set_clos_enable(int arg) 2089 { 2090 int enable = arg; 2091 2092 if (cmd_help) { 2093 if (enable) { 2094 fprintf(stderr, 2095 "Enable core-power for a package/die\n"); 2096 if (!is_skx_based_platform()) { 2097 fprintf(stderr, 2098 "\tClos Enable: Specify priority type with [--priority|-p]\n"); 2099 fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n"); 2100 } 2101 } else { 2102 fprintf(stderr, 2103 "Disable core-power: [No command arguments are required]\n"); 2104 } 2105 exit(0); 2106 } 2107 2108 if (enable && cpufreq_sysfs_present()) { 2109 fprintf(stderr, 2110 "cpufreq subsystem and core-power enable will interfere with each other!\n"); 2111 } 2112 2113 isst_ctdp_display_information_start(outf); 2114 if (max_target_cpus) 2115 for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL, 2116 NULL, NULL, &enable); 2117 else 2118 for_each_online_package_in_set(enable_clos_qos_config, NULL, 2119 NULL, NULL, &enable); 2120 isst_ctdp_display_information_end(outf); 2121 } 2122 2123 static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2, 2124 void *arg3, void *arg4) 2125 { 2126 struct isst_clos_config clos_config; 2127 int ret; 2128 2129 ret = isst_pm_get_clos(cpu, current_clos, &clos_config); 2130 if (ret) 2131 isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0); 2132 else 2133 isst_clos_display_information(cpu, outf, current_clos, 2134 &clos_config); 2135 } 2136 2137 static void dump_clos_config(int arg) 2138 { 2139 if (cmd_help) { 2140 fprintf(stderr, 2141 "Print Intel Speed Select Technology core power configuration\n"); 2142 fprintf(stderr, 2143 "\tArguments: [-c | --clos]: Specify clos id\n"); 2144 exit(0); 2145 } 2146 if (current_clos < 0 || current_clos > 3) { 2147 isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); 2148 isst_ctdp_display_information_end(outf); 2149 exit(0); 2150 } 2151 2152 isst_ctdp_display_information_start(outf); 2153 if (max_target_cpus) 2154 for_each_online_target_cpu_in_set(dump_clos_config_for_cpu, 2155 NULL, NULL, NULL, NULL); 2156 else 2157 for_each_online_package_in_set(dump_clos_config_for_cpu, NULL, 2158 NULL, NULL, NULL); 2159 isst_ctdp_display_information_end(outf); 2160 } 2161 2162 static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 2163 void *arg4) 2164 { 2165 int enable, ret, prio_type; 2166 2167 ret = isst_clos_get_clos_information(cpu, &enable, &prio_type); 2168 if (ret) 2169 isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0); 2170 else { 2171 int cp_state, cp_cap; 2172 2173 isst_read_pm_config(cpu, &cp_state, &cp_cap); 2174 isst_clos_display_clos_information(cpu, outf, enable, prio_type, 2175 cp_state, cp_cap); 2176 } 2177 } 2178 2179 static void dump_clos_info(int arg) 2180 { 2181 if (cmd_help) { 2182 fprintf(stderr, 2183 "Print Intel Speed Select Technology core power information\n"); 2184 fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n"); 2185 exit(0); 2186 } 2187 2188 isst_ctdp_display_information_start(outf); 2189 if (max_target_cpus) 2190 for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL, 2191 NULL, NULL, NULL); 2192 else 2193 for_each_online_package_in_set(get_clos_info_for_cpu, NULL, 2194 NULL, NULL, NULL); 2195 isst_ctdp_display_information_end(outf); 2196 2197 } 2198 2199 static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 2200 void *arg4) 2201 { 2202 struct isst_clos_config clos_config; 2203 int ret; 2204 2205 clos_config.pkg_id = get_physical_package_id(cpu); 2206 clos_config.die_id = get_physical_die_id(cpu); 2207 2208 clos_config.epp = clos_epp; 2209 clos_config.clos_prop_prio = clos_prop_prio; 2210 clos_config.clos_min = clos_min; 2211 clos_config.clos_max = clos_max; 2212 clos_config.clos_desired = clos_desired; 2213 ret = isst_set_clos(cpu, current_clos, &clos_config); 2214 if (ret) 2215 isst_display_error_info_message(1, "isst_set_clos failed", 0, 0); 2216 else 2217 isst_display_result(cpu, outf, "core-power", "config", ret); 2218 } 2219 2220 static void set_clos_config(int arg) 2221 { 2222 if (cmd_help) { 2223 fprintf(stderr, 2224 "Set core-power configuration for one of the four clos ids\n"); 2225 fprintf(stderr, 2226 "\tSpecify targeted clos id with [--clos|-c]\n"); 2227 if (!is_skx_based_platform()) { 2228 fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n"); 2229 fprintf(stderr, 2230 "\tSpecify clos Proportional Priority [--weight|-w]\n"); 2231 } 2232 fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n"); 2233 fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n"); 2234 exit(0); 2235 } 2236 2237 if (current_clos < 0 || current_clos > 3) { 2238 isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); 2239 exit(0); 2240 } 2241 if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) { 2242 fprintf(stderr, "clos epp is not specified or invalid, default: 0\n"); 2243 clos_epp = 0; 2244 } 2245 if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) { 2246 fprintf(stderr, 2247 "clos frequency weight is not specified or invalid, default: 0\n"); 2248 clos_prop_prio = 0; 2249 } 2250 if (clos_min < 0) { 2251 fprintf(stderr, "clos min is not specified, default: 0\n"); 2252 clos_min = 0; 2253 } 2254 if (clos_max < 0) { 2255 fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n"); 2256 clos_max = 0xff; 2257 } 2258 if (clos_desired) { 2259 fprintf(stderr, "clos desired is not supported on this platform\n"); 2260 clos_desired = 0x00; 2261 } 2262 2263 isst_ctdp_display_information_start(outf); 2264 if (max_target_cpus) 2265 for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL, 2266 NULL, NULL, NULL); 2267 else 2268 for_each_online_package_in_set(set_clos_config_for_cpu, NULL, 2269 NULL, NULL, NULL); 2270 isst_ctdp_display_information_end(outf); 2271 } 2272 2273 static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 2274 void *arg4) 2275 { 2276 int ret; 2277 2278 ret = isst_clos_associate(cpu, current_clos); 2279 if (ret) 2280 debug_printf("isst_clos_associate failed"); 2281 else 2282 isst_display_result(cpu, outf, "core-power", "assoc", ret); 2283 } 2284 2285 static void set_clos_assoc(int arg) 2286 { 2287 if (cmd_help) { 2288 fprintf(stderr, "Associate a clos id to a CPU\n"); 2289 fprintf(stderr, 2290 "\tSpecify targeted clos id with [--clos|-c]\n"); 2291 fprintf(stderr, 2292 "\tFor example to associate clos 1 to CPU 0: issue\n"); 2293 fprintf(stderr, 2294 "\tintel-speed-select --cpu 0 core-power assoc --clos 1\n"); 2295 exit(0); 2296 } 2297 2298 if (current_clos < 0 || current_clos > 3) { 2299 isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); 2300 exit(0); 2301 } 2302 if (max_target_cpus) 2303 for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL, 2304 NULL, NULL, NULL); 2305 else { 2306 isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0); 2307 } 2308 } 2309 2310 static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 2311 void *arg4) 2312 { 2313 int clos, ret; 2314 2315 ret = isst_clos_get_assoc_status(cpu, &clos); 2316 if (ret) 2317 isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0); 2318 else 2319 isst_clos_display_assoc_information(cpu, outf, clos); 2320 } 2321 2322 static void get_clos_assoc(int arg) 2323 { 2324 if (cmd_help) { 2325 fprintf(stderr, "Get associate clos id to a CPU\n"); 2326 fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n"); 2327 exit(0); 2328 } 2329 2330 if (!max_target_cpus) { 2331 isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0); 2332 exit(0); 2333 } 2334 2335 isst_ctdp_display_information_start(outf); 2336 for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL, 2337 NULL, NULL, NULL); 2338 isst_ctdp_display_information_end(outf); 2339 } 2340 2341 static void set_turbo_mode_for_cpu(int cpu, int status) 2342 { 2343 int base_freq; 2344 2345 if (status) { 2346 base_freq = get_cpufreq_base_freq(cpu); 2347 set_cpufreq_scaling_min_max(cpu, 1, base_freq); 2348 } else { 2349 set_scaling_max_to_cpuinfo_max(cpu); 2350 } 2351 2352 if (status) { 2353 isst_display_result(cpu, outf, "turbo-mode", "enable", 0); 2354 } else { 2355 isst_display_result(cpu, outf, "turbo-mode", "disable", 0); 2356 } 2357 } 2358 2359 static void set_turbo_mode(int arg) 2360 { 2361 int i, enable = arg; 2362 2363 if (cmd_help) { 2364 if (enable) 2365 fprintf(stderr, "Set turbo mode enable\n"); 2366 else 2367 fprintf(stderr, "Set turbo mode disable\n"); 2368 exit(0); 2369 } 2370 2371 isst_ctdp_display_information_start(outf); 2372 2373 for (i = 0; i < topo_max_cpus; ++i) { 2374 int online; 2375 2376 if (i) 2377 online = parse_int_file( 2378 1, "/sys/devices/system/cpu/cpu%d/online", i); 2379 else 2380 online = 2381 1; /* online entry for CPU 0 needs some special configs */ 2382 2383 if (online) 2384 set_turbo_mode_for_cpu(i, enable); 2385 2386 } 2387 isst_ctdp_display_information_end(outf); 2388 } 2389 2390 static void get_set_trl(int cpu, void *arg1, void *arg2, void *arg3, 2391 void *arg4) 2392 { 2393 unsigned long long trl; 2394 int set = *(int *)arg4; 2395 int ret; 2396 2397 if (set && !fact_trl) { 2398 isst_display_error_info_message(1, "Invalid TRL. Specify with [-t|--trl]", 0, 0); 2399 exit(0); 2400 } 2401 2402 if (set) { 2403 ret = isst_set_trl(cpu, fact_trl); 2404 isst_display_result(cpu, outf, "turbo-mode", "set-trl", ret); 2405 return; 2406 } 2407 2408 ret = isst_get_trl(cpu, &trl); 2409 if (ret) 2410 isst_display_result(cpu, outf, "turbo-mode", "get-trl", ret); 2411 else 2412 isst_trl_display_information(cpu, outf, trl); 2413 } 2414 2415 static void process_trl(int arg) 2416 { 2417 if (cmd_help) { 2418 if (arg) { 2419 fprintf(stderr, "Set TRL (turbo ratio limits)\n"); 2420 fprintf(stderr, "\t t|--trl: Specify turbo ratio limit for setting TRL\n"); 2421 } else { 2422 fprintf(stderr, "Get TRL (turbo ratio limits)\n"); 2423 } 2424 exit(0); 2425 } 2426 2427 isst_ctdp_display_information_start(outf); 2428 if (max_target_cpus) 2429 for_each_online_target_cpu_in_set(get_set_trl, NULL, 2430 NULL, NULL, &arg); 2431 else 2432 for_each_online_package_in_set(get_set_trl, NULL, 2433 NULL, NULL, &arg); 2434 isst_ctdp_display_information_end(outf); 2435 } 2436 2437 static struct process_cmd_struct clx_n_cmds[] = { 2438 { "perf-profile", "info", dump_isst_config, 0 }, 2439 { "base-freq", "info", dump_pbf_config, 0 }, 2440 { "base-freq", "enable", set_pbf_enable, 1 }, 2441 { "base-freq", "disable", set_pbf_enable, 0 }, 2442 { NULL, NULL, NULL, 0 } 2443 }; 2444 2445 static struct process_cmd_struct isst_cmds[] = { 2446 { "perf-profile", "get-lock-status", get_tdp_locked, 0 }, 2447 { "perf-profile", "get-config-levels", get_tdp_levels, 0 }, 2448 { "perf-profile", "get-config-version", get_tdp_version, 0 }, 2449 { "perf-profile", "get-config-enabled", get_tdp_enabled, 0 }, 2450 { "perf-profile", "get-config-current-level", get_tdp_current_level, 2451 0 }, 2452 { "perf-profile", "set-config-level", set_tdp_level, 0 }, 2453 { "perf-profile", "info", dump_isst_config, 0 }, 2454 { "base-freq", "info", dump_pbf_config, 0 }, 2455 { "base-freq", "enable", set_pbf_enable, 1 }, 2456 { "base-freq", "disable", set_pbf_enable, 0 }, 2457 { "turbo-freq", "info", dump_fact_config, 0 }, 2458 { "turbo-freq", "enable", set_fact_enable, 1 }, 2459 { "turbo-freq", "disable", set_fact_enable, 0 }, 2460 { "core-power", "info", dump_clos_info, 0 }, 2461 { "core-power", "enable", set_clos_enable, 1 }, 2462 { "core-power", "disable", set_clos_enable, 0 }, 2463 { "core-power", "config", set_clos_config, 0 }, 2464 { "core-power", "get-config", dump_clos_config, 0 }, 2465 { "core-power", "assoc", set_clos_assoc, 0 }, 2466 { "core-power", "get-assoc", get_clos_assoc, 0 }, 2467 { "turbo-mode", "enable", set_turbo_mode, 0 }, 2468 { "turbo-mode", "disable", set_turbo_mode, 1 }, 2469 { "turbo-mode", "get-trl", process_trl, 0 }, 2470 { "turbo-mode", "set-trl", process_trl, 1 }, 2471 { NULL, NULL, NULL } 2472 }; 2473 2474 /* 2475 * parse cpuset with following syntax 2476 * 1,2,4..6,8-10 and set bits in cpu_subset 2477 */ 2478 void parse_cpu_command(char *optarg) 2479 { 2480 unsigned int start, end; 2481 char *next; 2482 2483 next = optarg; 2484 2485 while (next && *next) { 2486 if (*next == '-') /* no negative cpu numbers */ 2487 goto error; 2488 2489 start = strtoul(next, &next, 10); 2490 2491 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ) 2492 target_cpus[max_target_cpus++] = start; 2493 2494 if (*next == '\0') 2495 break; 2496 2497 if (*next == ',') { 2498 next += 1; 2499 continue; 2500 } 2501 2502 if (*next == '-') { 2503 next += 1; /* start range */ 2504 } else if (*next == '.') { 2505 next += 1; 2506 if (*next == '.') 2507 next += 1; /* start range */ 2508 else 2509 goto error; 2510 } 2511 2512 end = strtoul(next, &next, 10); 2513 if (end <= start) 2514 goto error; 2515 2516 while (++start <= end) { 2517 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ) 2518 target_cpus[max_target_cpus++] = start; 2519 } 2520 2521 if (*next == ',') 2522 next += 1; 2523 else if (*next != '\0') 2524 goto error; 2525 } 2526 2527 #ifdef DEBUG 2528 { 2529 int i; 2530 2531 for (i = 0; i < max_target_cpus; ++i) 2532 printf("cpu [%d] in arg\n", target_cpus[i]); 2533 } 2534 #endif 2535 return; 2536 2537 error: 2538 fprintf(stderr, "\"--cpu %s\" malformed\n", optarg); 2539 exit(-1); 2540 } 2541 2542 static void parse_cmd_args(int argc, int start, char **argv) 2543 { 2544 int opt; 2545 int option_index; 2546 2547 static struct option long_options[] = { 2548 { "bucket", required_argument, 0, 'b' }, 2549 { "level", required_argument, 0, 'l' }, 2550 { "online", required_argument, 0, 'o' }, 2551 { "trl-type", required_argument, 0, 'r' }, 2552 { "trl", required_argument, 0, 't' }, 2553 { "help", no_argument, 0, 'h' }, 2554 { "clos", required_argument, 0, 'c' }, 2555 { "desired", required_argument, 0, 'd' }, 2556 { "epp", required_argument, 0, 'e' }, 2557 { "min", required_argument, 0, 'n' }, 2558 { "max", required_argument, 0, 'm' }, 2559 { "priority", required_argument, 0, 'p' }, 2560 { "weight", required_argument, 0, 'w' }, 2561 { "auto", no_argument, 0, 'a' }, 2562 { 0, 0, 0, 0 } 2563 }; 2564 2565 option_index = start; 2566 2567 optind = start + 1; 2568 while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa", 2569 long_options, &option_index)) != -1) { 2570 switch (opt) { 2571 case 'a': 2572 auto_mode = 1; 2573 break; 2574 case 'b': 2575 fact_bucket = atoi(optarg); 2576 break; 2577 case 'h': 2578 cmd_help = 1; 2579 break; 2580 case 'l': 2581 tdp_level = atoi(optarg); 2582 break; 2583 case 'o': 2584 force_online_offline = 1; 2585 break; 2586 case 't': 2587 sscanf(optarg, "0x%llx", &fact_trl); 2588 break; 2589 case 'r': 2590 if (!strncmp(optarg, "sse", 3)) { 2591 fact_avx = 0x01; 2592 } else if (!strncmp(optarg, "avx2", 4)) { 2593 fact_avx = 0x02; 2594 } else if (!strncmp(optarg, "avx512", 6)) { 2595 fact_avx = 0x04; 2596 } else { 2597 fprintf(outf, "Invalid sse,avx options\n"); 2598 exit(1); 2599 } 2600 break; 2601 /* CLOS related */ 2602 case 'c': 2603 current_clos = atoi(optarg); 2604 break; 2605 case 'd': 2606 clos_desired = atoi(optarg); 2607 clos_desired /= DISP_FREQ_MULTIPLIER; 2608 break; 2609 case 'e': 2610 clos_epp = atoi(optarg); 2611 if (is_skx_based_platform()) { 2612 isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0); 2613 exit(0); 2614 } 2615 break; 2616 case 'n': 2617 clos_min = atoi(optarg); 2618 clos_min /= DISP_FREQ_MULTIPLIER; 2619 break; 2620 case 'm': 2621 clos_max = atoi(optarg); 2622 clos_max /= DISP_FREQ_MULTIPLIER; 2623 break; 2624 case 'p': 2625 clos_priority_type = atoi(optarg); 2626 if (is_skx_based_platform() && !clos_priority_type) { 2627 isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0); 2628 exit(0); 2629 } 2630 break; 2631 case 'w': 2632 clos_prop_prio = atoi(optarg); 2633 if (is_skx_based_platform()) { 2634 isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0); 2635 exit(0); 2636 } 2637 break; 2638 default: 2639 printf("Unknown option: ignore\n"); 2640 } 2641 } 2642 2643 if (argv[optind]) 2644 printf("Garbage at the end of command: ignore\n"); 2645 } 2646 2647 static void isst_help(void) 2648 { 2649 printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\ 2650 performance profiles per system via static and/or dynamic\n\ 2651 adjustment of core count, workload, Tjmax, and\n\ 2652 TDP, etc.\n"); 2653 printf("\nCommands : For feature=perf-profile\n"); 2654 printf("\tinfo\n"); 2655 2656 if (!is_clx_n_platform()) { 2657 printf("\tget-lock-status\n"); 2658 printf("\tget-config-levels\n"); 2659 printf("\tget-config-version\n"); 2660 printf("\tget-config-enabled\n"); 2661 printf("\tget-config-current-level\n"); 2662 printf("\tset-config-level\n"); 2663 } 2664 } 2665 2666 static void pbf_help(void) 2667 { 2668 printf("base-freq:\tEnables users to increase guaranteed base frequency\n\ 2669 on certain cores (high priority cores) in exchange for lower\n\ 2670 base frequency on remaining cores (low priority cores).\n"); 2671 printf("\tcommand : info\n"); 2672 printf("\tcommand : enable\n"); 2673 printf("\tcommand : disable\n"); 2674 } 2675 2676 static void fact_help(void) 2677 { 2678 printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\ 2679 limits to cores based on priority.\n"); 2680 printf("\nCommand: For feature=turbo-freq\n"); 2681 printf("\tcommand : info\n"); 2682 printf("\tcommand : enable\n"); 2683 printf("\tcommand : disable\n"); 2684 } 2685 2686 static void turbo_mode_help(void) 2687 { 2688 printf("turbo-mode:\tEnables users to enable/disable turbo mode by adjusting frequency settings. Also allows to get and set turbo ratio limits (TRL).\n"); 2689 printf("\tcommand : enable\n"); 2690 printf("\tcommand : disable\n"); 2691 printf("\tcommand : get-trl\n"); 2692 printf("\tcommand : set-trl\n"); 2693 } 2694 2695 2696 static void core_power_help(void) 2697 { 2698 printf("core-power:\tInterface that allows user to define per core/tile\n\ 2699 priority.\n"); 2700 printf("\nCommands : For feature=core-power\n"); 2701 printf("\tinfo\n"); 2702 printf("\tenable\n"); 2703 printf("\tdisable\n"); 2704 printf("\tconfig\n"); 2705 printf("\tget-config\n"); 2706 printf("\tassoc\n"); 2707 printf("\tget-assoc\n"); 2708 } 2709 2710 struct process_cmd_help_struct { 2711 char *feature; 2712 void (*process_fn)(void); 2713 }; 2714 2715 static struct process_cmd_help_struct isst_help_cmds[] = { 2716 { "perf-profile", isst_help }, 2717 { "base-freq", pbf_help }, 2718 { "turbo-freq", fact_help }, 2719 { "core-power", core_power_help }, 2720 { "turbo-mode", turbo_mode_help }, 2721 { NULL, NULL } 2722 }; 2723 2724 static struct process_cmd_help_struct clx_n_help_cmds[] = { 2725 { "perf-profile", isst_help }, 2726 { "base-freq", pbf_help }, 2727 { NULL, NULL } 2728 }; 2729 2730 void process_command(int argc, char **argv, 2731 struct process_cmd_help_struct *help_cmds, 2732 struct process_cmd_struct *cmds) 2733 { 2734 int i = 0, matched = 0; 2735 char *feature = argv[optind]; 2736 char *cmd = argv[optind + 1]; 2737 2738 if (!feature || !cmd) 2739 return; 2740 2741 debug_printf("feature name [%s] command [%s]\n", feature, cmd); 2742 if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) { 2743 while (help_cmds[i].feature) { 2744 if (!strcmp(help_cmds[i].feature, feature)) { 2745 help_cmds[i].process_fn(); 2746 exit(0); 2747 } 2748 ++i; 2749 } 2750 } 2751 2752 if (!is_clx_n_platform()) 2753 create_cpu_map(); 2754 2755 i = 0; 2756 while (cmds[i].feature) { 2757 if (!strcmp(cmds[i].feature, feature) && 2758 !strcmp(cmds[i].command, cmd)) { 2759 parse_cmd_args(argc, optind + 1, argv); 2760 cmds[i].process_fn(cmds[i].arg); 2761 matched = 1; 2762 break; 2763 } 2764 ++i; 2765 } 2766 2767 if (!matched) 2768 fprintf(stderr, "Invalid command\n"); 2769 } 2770 2771 static void usage(void) 2772 { 2773 if (is_clx_n_platform()) { 2774 fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n"); 2775 fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n"); 2776 } 2777 2778 printf("\nUsage:\n"); 2779 printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n"); 2780 printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n"); 2781 if (is_clx_n_platform()) 2782 printf("\nFEATURE : [perf-profile|base-freq]\n"); 2783 else 2784 printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power|turbo-mode]\n"); 2785 printf("\nFor help on each feature, use -h|--help\n"); 2786 printf("\tFor example: intel-speed-select perf-profile -h\n"); 2787 2788 printf("\nFor additional help on each command for a feature, use --h|--help\n"); 2789 printf("\tFor example: intel-speed-select perf-profile get-lock-status -h\n"); 2790 printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n"); 2791 2792 printf("\nOPTIONS\n"); 2793 printf("\t[-c|--cpu] : logical cpu number\n"); 2794 printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n"); 2795 printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n"); 2796 printf("\t[-d|--debug] : Debug mode\n"); 2797 printf("\t[-f|--format] : output format [json|text]. Default: text\n"); 2798 printf("\t[-h|--help] : Print help\n"); 2799 printf("\t[-i|--info] : Print platform information\n"); 2800 printf("\t[-a|--all-cpus-online] : Force online every CPU in the system\n"); 2801 printf("\t[-o|--out] : Output file\n"); 2802 printf("\t\t\tDefault : stderr\n"); 2803 printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n"); 2804 printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n"); 2805 printf("\t[-v|--version] : Print version\n"); 2806 2807 printf("\nResult format\n"); 2808 printf("\tResult display uses a common format for each command:\n"); 2809 printf("\tResults are formatted in text/JSON with\n"); 2810 printf("\t\tPackage, Die, CPU, and command specific results.\n"); 2811 2812 printf("\nExamples\n"); 2813 printf("\tTo get platform information:\n"); 2814 printf("\t\tintel-speed-select --info\n"); 2815 printf("\tTo get full perf-profile information dump:\n"); 2816 printf("\t\tintel-speed-select perf-profile info\n"); 2817 printf("\tTo get full base-freq information dump:\n"); 2818 printf("\t\tintel-speed-select base-freq info -l 0\n"); 2819 if (!is_clx_n_platform()) { 2820 printf("\tTo get full turbo-freq information dump:\n"); 2821 printf("\t\tintel-speed-select turbo-freq info -l 0\n"); 2822 } 2823 exit(1); 2824 } 2825 2826 static void print_version(void) 2827 { 2828 fprintf(outf, "Version %s\n", version_str); 2829 exit(0); 2830 } 2831 2832 static void cmdline(int argc, char **argv) 2833 { 2834 const char *pathname = "/dev/isst_interface"; 2835 char *ptr; 2836 FILE *fp; 2837 int opt, force_cpus_online = 0; 2838 int option_index = 0; 2839 int ret; 2840 2841 static struct option long_options[] = { 2842 { "all-cpus-online", no_argument, 0, 'a' }, 2843 { "cpu", required_argument, 0, 'c' }, 2844 { "debug", no_argument, 0, 'd' }, 2845 { "format", required_argument, 0, 'f' }, 2846 { "help", no_argument, 0, 'h' }, 2847 { "info", no_argument, 0, 'i' }, 2848 { "pause", required_argument, 0, 'p' }, 2849 { "out", required_argument, 0, 'o' }, 2850 { "retry", required_argument, 0, 'r' }, 2851 { "version", no_argument, 0, 'v' }, 2852 { 0, 0, 0, 0 } 2853 }; 2854 2855 if (geteuid() != 0) { 2856 fprintf(stderr, "Must run as root\n"); 2857 exit(0); 2858 } 2859 2860 ret = update_cpu_model(); 2861 if (ret) 2862 err(-1, "Invalid CPU model (%d)\n", cpu_model); 2863 printf("Intel(R) Speed Select Technology\n"); 2864 printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model); 2865 2866 if (!is_clx_n_platform()) { 2867 fp = fopen(pathname, "rb"); 2868 if (!fp) { 2869 fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n"); 2870 fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n"); 2871 fprintf(stderr, "If the config is included then this is not a supported platform.\n"); 2872 exit(0); 2873 } 2874 fclose(fp); 2875 } 2876 2877 progname = argv[0]; 2878 while ((opt = getopt_long_only(argc, argv, "+c:df:hio:va", long_options, 2879 &option_index)) != -1) { 2880 switch (opt) { 2881 case 'a': 2882 force_cpus_online = 1; 2883 break; 2884 case 'c': 2885 parse_cpu_command(optarg); 2886 break; 2887 case 'd': 2888 debug_flag = 1; 2889 printf("Debug Mode ON\n"); 2890 break; 2891 case 'f': 2892 if (!strncmp(optarg, "json", 4)) 2893 out_format_json = 1; 2894 break; 2895 case 'h': 2896 usage(); 2897 break; 2898 case 'i': 2899 isst_print_platform_information(); 2900 break; 2901 case 'o': 2902 if (outf) 2903 fclose(outf); 2904 outf = fopen_or_exit(optarg, "w"); 2905 break; 2906 case 'p': 2907 ret = strtol(optarg, &ptr, 10); 2908 if (!ret) 2909 fprintf(stderr, "Invalid pause interval, ignore\n"); 2910 else 2911 mbox_delay = ret; 2912 break; 2913 case 'r': 2914 ret = strtol(optarg, &ptr, 10); 2915 if (!ret) 2916 fprintf(stderr, "Invalid retry count, ignore\n"); 2917 else 2918 mbox_retries = ret; 2919 break; 2920 case 'v': 2921 print_version(); 2922 break; 2923 default: 2924 usage(); 2925 } 2926 } 2927 2928 if (optind > (argc - 2)) { 2929 usage(); 2930 exit(0); 2931 } 2932 set_max_cpu_num(); 2933 if (force_cpus_online) 2934 force_all_cpus_online(); 2935 store_cpu_topology(); 2936 set_cpu_present_cpu_mask(); 2937 set_cpu_target_cpu_mask(); 2938 2939 if (!is_clx_n_platform()) { 2940 ret = isst_fill_platform_info(); 2941 if (ret) 2942 goto out; 2943 process_command(argc, argv, isst_help_cmds, isst_cmds); 2944 } else { 2945 process_command(argc, argv, clx_n_help_cmds, clx_n_cmds); 2946 } 2947 out: 2948 free_cpu_set(present_cpumask); 2949 free_cpu_set(target_cpumask); 2950 } 2951 2952 int main(int argc, char **argv) 2953 { 2954 outf = stderr; 2955 cmdline(argc, argv); 2956 return 0; 2957 } 2958