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.10"; 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 set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0); 1603 adjust_scaling_min_from_base_freq(i); 1604 } 1605 } 1606 1607 static void set_scaling_min_to_cpuinfo_min(int cpu) 1608 { 1609 int i, pkg_id, die_id; 1610 1611 pkg_id = get_physical_package_id(cpu); 1612 die_id = get_physical_die_id(cpu); 1613 for (i = 0; i < get_topo_max_cpus(); ++i) { 1614 if (pkg_id != get_physical_package_id(i) || 1615 die_id != get_physical_die_id(i)) 1616 continue; 1617 1618 set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0); 1619 } 1620 } 1621 1622 static void set_scaling_max_to_cpuinfo_max(int cpu) 1623 { 1624 int i, pkg_id, die_id; 1625 1626 pkg_id = get_physical_package_id(cpu); 1627 die_id = get_physical_die_id(cpu); 1628 for (i = 0; i < get_topo_max_cpus(); ++i) { 1629 if (pkg_id != get_physical_package_id(i) || 1630 die_id != get_physical_die_id(i)) 1631 continue; 1632 1633 set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1); 1634 } 1635 } 1636 1637 static int set_core_priority_and_min(int cpu, int mask_size, 1638 cpu_set_t *cpu_mask, int min_high, 1639 int min_low) 1640 { 1641 int pkg_id, die_id, ret, i; 1642 1643 if (!CPU_COUNT_S(mask_size, cpu_mask)) 1644 return -1; 1645 1646 ret = set_clos_param(cpu, 0, 0, 0, min_high, 0xff); 1647 if (ret) 1648 return ret; 1649 1650 ret = set_clos_param(cpu, 1, 15, 15, min_low, 0xff); 1651 if (ret) 1652 return ret; 1653 1654 ret = set_clos_param(cpu, 2, 15, 15, min_low, 0xff); 1655 if (ret) 1656 return ret; 1657 1658 ret = set_clos_param(cpu, 3, 15, 15, min_low, 0xff); 1659 if (ret) 1660 return ret; 1661 1662 pkg_id = get_physical_package_id(cpu); 1663 die_id = get_physical_die_id(cpu); 1664 for (i = 0; i < get_topo_max_cpus(); ++i) { 1665 int clos; 1666 1667 if (pkg_id != get_physical_package_id(i) || 1668 die_id != get_physical_die_id(i)) 1669 continue; 1670 1671 if (CPU_ISSET_S(i, mask_size, cpu_mask)) 1672 clos = 0; 1673 else 1674 clos = 3; 1675 1676 debug_printf("Associate cpu: %d clos: %d\n", i, clos); 1677 ret = isst_clos_associate(i, clos); 1678 if (ret) { 1679 isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0); 1680 return ret; 1681 } 1682 } 1683 1684 return 0; 1685 } 1686 1687 static int set_pbf_core_power(int cpu) 1688 { 1689 struct isst_pbf_info pbf_info; 1690 struct isst_pkg_ctdp pkg_dev; 1691 int ret; 1692 1693 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 1694 if (ret) { 1695 debug_printf("isst_get_ctdp_levels failed"); 1696 return ret; 1697 } 1698 debug_printf("Current_level: %d\n", pkg_dev.current_level); 1699 1700 ret = isst_get_pbf_info(cpu, pkg_dev.current_level, &pbf_info); 1701 if (ret) { 1702 debug_printf("isst_get_pbf_info failed"); 1703 return ret; 1704 } 1705 debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high, 1706 pbf_info.p1_low); 1707 1708 ret = set_core_priority_and_min(cpu, pbf_info.core_cpumask_size, 1709 pbf_info.core_cpumask, 1710 pbf_info.p1_high, pbf_info.p1_low); 1711 if (ret) { 1712 debug_printf("set_core_priority_and_min failed"); 1713 return ret; 1714 } 1715 1716 ret = isst_pm_qos_config(cpu, 1, 1); 1717 if (ret) { 1718 debug_printf("isst_pm_qos_config failed"); 1719 return ret; 1720 } 1721 1722 return 0; 1723 } 1724 1725 static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 1726 void *arg4) 1727 { 1728 struct isst_pkg_ctdp_level_info ctdp_level; 1729 struct isst_pkg_ctdp pkg_dev; 1730 int ret; 1731 int status = *(int *)arg4; 1732 1733 if (is_clx_n_platform()) { 1734 ret = 0; 1735 if (status) { 1736 set_clx_pbf_cpufreq_scaling_min_max(cpu); 1737 1738 } else { 1739 set_scaling_max_to_cpuinfo_max(cpu); 1740 set_scaling_min_to_cpuinfo_min(cpu); 1741 } 1742 goto disp_result; 1743 } 1744 1745 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 1746 if (ret) { 1747 isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); 1748 goto disp_result; 1749 } 1750 1751 ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level); 1752 if (ret) { 1753 isst_display_error_info_message(1, "Failed to get current level", 0, 0); 1754 goto disp_result; 1755 } 1756 1757 if (!ctdp_level.pbf_support) { 1758 isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, pkg_dev.current_level); 1759 ret = -1; 1760 goto disp_result; 1761 } 1762 1763 if (auto_mode && status) { 1764 ret = set_pbf_core_power(cpu); 1765 if (ret) 1766 goto disp_result; 1767 } 1768 1769 ret = isst_set_pbf_fact_status(cpu, 1, status); 1770 if (ret) { 1771 debug_printf("isst_set_pbf_fact_status failed"); 1772 if (auto_mode) 1773 isst_pm_qos_config(cpu, 0, 0); 1774 } else { 1775 if (auto_mode) { 1776 if (status) 1777 set_scaling_min_to_cpuinfo_max(cpu); 1778 else 1779 set_scaling_min_to_cpuinfo_min(cpu); 1780 } 1781 } 1782 1783 if (auto_mode && !status) 1784 isst_pm_qos_config(cpu, 0, 1); 1785 1786 disp_result: 1787 if (status) 1788 isst_display_result(cpu, outf, "base-freq", "enable", 1789 ret); 1790 else 1791 isst_display_result(cpu, outf, "base-freq", "disable", 1792 ret); 1793 } 1794 1795 static void set_pbf_enable(int arg) 1796 { 1797 int enable = arg; 1798 1799 if (cmd_help) { 1800 if (enable) { 1801 fprintf(stderr, 1802 "Enable Intel Speed Select Technology base frequency feature\n"); 1803 if (is_clx_n_platform()) { 1804 fprintf(stderr, 1805 "\tOn this platform this command doesn't enable feature in the hardware.\n"); 1806 fprintf(stderr, 1807 "\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n"); 1808 exit(0); 1809 1810 } 1811 fprintf(stderr, 1812 "\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n"); 1813 } else { 1814 1815 if (is_clx_n_platform()) { 1816 fprintf(stderr, 1817 "\tOn this platform this command doesn't disable feature in the hardware.\n"); 1818 fprintf(stderr, 1819 "\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n"); 1820 exit(0); 1821 } 1822 fprintf(stderr, 1823 "Disable Intel Speed Select Technology base frequency feature\n"); 1824 fprintf(stderr, 1825 "\tOptional Arguments: -a|--auto : Also disable core-power associations\n"); 1826 } 1827 exit(0); 1828 } 1829 1830 isst_ctdp_display_information_start(outf); 1831 if (max_target_cpus) 1832 for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL, 1833 NULL, &enable); 1834 else 1835 for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL, 1836 NULL, &enable); 1837 isst_ctdp_display_information_end(outf); 1838 } 1839 1840 static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2, 1841 void *arg3, void *arg4) 1842 { 1843 struct isst_fact_info fact_info; 1844 int ret; 1845 1846 ret = isst_get_fact_info(cpu, tdp_level, fact_bucket, &fact_info); 1847 if (ret) { 1848 isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level); 1849 isst_ctdp_display_information_end(outf); 1850 exit(1); 1851 } else { 1852 isst_fact_display_information(cpu, outf, tdp_level, fact_bucket, 1853 fact_avx, &fact_info); 1854 } 1855 } 1856 1857 static void dump_fact_config(int arg) 1858 { 1859 if (cmd_help) { 1860 fprintf(stderr, 1861 "Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n"); 1862 fprintf(stderr, 1863 "\tArguments: -l|--level : Specify tdp level\n"); 1864 fprintf(stderr, 1865 "\tArguments: -b|--bucket : Bucket index to dump\n"); 1866 fprintf(stderr, 1867 "\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n"); 1868 exit(0); 1869 } 1870 1871 if (tdp_level == 0xff) { 1872 isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0); 1873 exit(1); 1874 } 1875 1876 isst_ctdp_display_information_start(outf); 1877 if (max_target_cpus) 1878 for_each_online_target_cpu_in_set(dump_fact_config_for_cpu, 1879 NULL, NULL, NULL, NULL); 1880 else 1881 for_each_online_package_in_set(dump_fact_config_for_cpu, NULL, 1882 NULL, NULL, NULL); 1883 isst_ctdp_display_information_end(outf); 1884 } 1885 1886 static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 1887 void *arg4) 1888 { 1889 struct isst_pkg_ctdp_level_info ctdp_level; 1890 struct isst_pkg_ctdp pkg_dev; 1891 int ret; 1892 int status = *(int *)arg4; 1893 1894 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 1895 if (ret) { 1896 isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); 1897 goto disp_results; 1898 } 1899 1900 ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level); 1901 if (ret) { 1902 isst_display_error_info_message(1, "Failed to get current level", 0, 0); 1903 goto disp_results; 1904 } 1905 1906 if (!ctdp_level.fact_support) { 1907 isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, pkg_dev.current_level); 1908 ret = -1; 1909 goto disp_results; 1910 } 1911 1912 if (status) { 1913 ret = isst_pm_qos_config(cpu, 1, 1); 1914 if (ret) 1915 goto disp_results; 1916 } 1917 1918 ret = isst_set_pbf_fact_status(cpu, 0, status); 1919 if (ret) { 1920 debug_printf("isst_set_pbf_fact_status failed"); 1921 if (auto_mode) 1922 isst_pm_qos_config(cpu, 0, 0); 1923 1924 goto disp_results; 1925 } 1926 1927 /* Set TRL */ 1928 if (status) { 1929 struct isst_pkg_ctdp pkg_dev; 1930 1931 ret = isst_get_ctdp_levels(cpu, &pkg_dev); 1932 if (!ret) 1933 ret = isst_set_trl(cpu, fact_trl); 1934 if (ret && auto_mode) 1935 isst_pm_qos_config(cpu, 0, 0); 1936 } else { 1937 if (auto_mode) 1938 isst_pm_qos_config(cpu, 0, 0); 1939 } 1940 1941 disp_results: 1942 if (status) { 1943 isst_display_result(cpu, outf, "turbo-freq", "enable", ret); 1944 if (ret) 1945 fact_enable_fail = ret; 1946 } else { 1947 /* Since we modified TRL during Fact enable, restore it */ 1948 isst_set_trl_from_current_tdp(cpu, fact_trl); 1949 isst_display_result(cpu, outf, "turbo-freq", "disable", ret); 1950 } 1951 } 1952 1953 static void set_fact_enable(int arg) 1954 { 1955 int i, ret, enable = arg; 1956 1957 if (cmd_help) { 1958 if (enable) { 1959 fprintf(stderr, 1960 "Enable Intel Speed Select Technology Turbo frequency feature\n"); 1961 fprintf(stderr, 1962 "Optional: -t|--trl : Specify turbo ratio limit\n"); 1963 fprintf(stderr, 1964 "\tOptional Arguments: -a|--auto : Designate specified target CPUs with"); 1965 fprintf(stderr, 1966 "-C|--cpu option as as high priority using core-power feature\n"); 1967 } else { 1968 fprintf(stderr, 1969 "Disable Intel Speed Select Technology turbo frequency feature\n"); 1970 fprintf(stderr, 1971 "Optional: -t|--trl : Specify turbo ratio limit\n"); 1972 fprintf(stderr, 1973 "\tOptional Arguments: -a|--auto : Also disable core-power associations\n"); 1974 } 1975 exit(0); 1976 } 1977 1978 isst_ctdp_display_information_start(outf); 1979 if (max_target_cpus) 1980 for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL, 1981 NULL, &enable); 1982 else 1983 for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL, 1984 NULL, &enable); 1985 isst_ctdp_display_information_end(outf); 1986 1987 if (!fact_enable_fail && enable && auto_mode) { 1988 /* 1989 * When we adjust CLOS param, we have to set for siblings also. 1990 * So for the each user specified CPU, also add the sibling 1991 * in the present_cpu_mask. 1992 */ 1993 for (i = 0; i < get_topo_max_cpus(); ++i) { 1994 char buffer[128], sibling_list[128], *cpu_str; 1995 int fd, len; 1996 1997 if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask)) 1998 continue; 1999 2000 snprintf(buffer, sizeof(buffer), 2001 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i); 2002 2003 fd = open(buffer, O_RDONLY); 2004 if (fd < 0) 2005 continue; 2006 2007 len = read(fd, sibling_list, sizeof(sibling_list)); 2008 close(fd); 2009 2010 if (len < 0) 2011 continue; 2012 2013 cpu_str = strtok(sibling_list, ","); 2014 while (cpu_str != NULL) { 2015 int cpu; 2016 2017 sscanf(cpu_str, "%d", &cpu); 2018 CPU_SET_S(cpu, target_cpumask_size, target_cpumask); 2019 cpu_str = strtok(NULL, ","); 2020 } 2021 } 2022 2023 for (i = 0; i < get_topo_max_cpus(); ++i) { 2024 int clos; 2025 2026 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 2027 continue; 2028 2029 ret = set_clos_param(i, 0, 0, 0, 0, 0xff); 2030 if (ret) 2031 goto error_disp; 2032 2033 ret = set_clos_param(i, 1, 15, 15, 0, 0xff); 2034 if (ret) 2035 goto error_disp; 2036 2037 ret = set_clos_param(i, 2, 15, 15, 0, 0xff); 2038 if (ret) 2039 goto error_disp; 2040 2041 ret = set_clos_param(i, 3, 15, 15, 0, 0xff); 2042 if (ret) 2043 goto error_disp; 2044 2045 if (CPU_ISSET_S(i, target_cpumask_size, target_cpumask)) 2046 clos = 0; 2047 else 2048 clos = 3; 2049 2050 debug_printf("Associate cpu: %d clos: %d\n", i, clos); 2051 ret = isst_clos_associate(i, clos); 2052 if (ret) 2053 goto error_disp; 2054 } 2055 isst_display_result(-1, outf, "turbo-freq --auto", "enable", 0); 2056 } 2057 2058 return; 2059 2060 error_disp: 2061 isst_display_result(i, outf, "turbo-freq --auto", "enable", ret); 2062 2063 } 2064 2065 static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3, 2066 void *arg4) 2067 { 2068 int ret; 2069 int status = *(int *)arg4; 2070 2071 if (is_skx_based_platform()) 2072 clos_priority_type = 1; 2073 2074 ret = isst_pm_qos_config(cpu, status, clos_priority_type); 2075 if (ret) 2076 isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0); 2077 2078 if (status) 2079 isst_display_result(cpu, outf, "core-power", "enable", 2080 ret); 2081 else 2082 isst_display_result(cpu, outf, "core-power", "disable", 2083 ret); 2084 } 2085 2086 static void set_clos_enable(int arg) 2087 { 2088 int enable = arg; 2089 2090 if (cmd_help) { 2091 if (enable) { 2092 fprintf(stderr, 2093 "Enable core-power for a package/die\n"); 2094 if (!is_skx_based_platform()) { 2095 fprintf(stderr, 2096 "\tClos Enable: Specify priority type with [--priority|-p]\n"); 2097 fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n"); 2098 } 2099 } else { 2100 fprintf(stderr, 2101 "Disable core-power: [No command arguments are required]\n"); 2102 } 2103 exit(0); 2104 } 2105 2106 if (enable && cpufreq_sysfs_present()) { 2107 fprintf(stderr, 2108 "cpufreq subsystem and core-power enable will interfere with each other!\n"); 2109 } 2110 2111 isst_ctdp_display_information_start(outf); 2112 if (max_target_cpus) 2113 for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL, 2114 NULL, NULL, &enable); 2115 else 2116 for_each_online_package_in_set(enable_clos_qos_config, NULL, 2117 NULL, NULL, &enable); 2118 isst_ctdp_display_information_end(outf); 2119 } 2120 2121 static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2, 2122 void *arg3, void *arg4) 2123 { 2124 struct isst_clos_config clos_config; 2125 int ret; 2126 2127 ret = isst_pm_get_clos(cpu, current_clos, &clos_config); 2128 if (ret) 2129 isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0); 2130 else 2131 isst_clos_display_information(cpu, outf, current_clos, 2132 &clos_config); 2133 } 2134 2135 static void dump_clos_config(int arg) 2136 { 2137 if (cmd_help) { 2138 fprintf(stderr, 2139 "Print Intel Speed Select Technology core power configuration\n"); 2140 fprintf(stderr, 2141 "\tArguments: [-c | --clos]: Specify clos id\n"); 2142 exit(0); 2143 } 2144 if (current_clos < 0 || current_clos > 3) { 2145 isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); 2146 isst_ctdp_display_information_end(outf); 2147 exit(0); 2148 } 2149 2150 isst_ctdp_display_information_start(outf); 2151 if (max_target_cpus) 2152 for_each_online_target_cpu_in_set(dump_clos_config_for_cpu, 2153 NULL, NULL, NULL, NULL); 2154 else 2155 for_each_online_package_in_set(dump_clos_config_for_cpu, NULL, 2156 NULL, NULL, NULL); 2157 isst_ctdp_display_information_end(outf); 2158 } 2159 2160 static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 2161 void *arg4) 2162 { 2163 int enable, ret, prio_type; 2164 2165 ret = isst_clos_get_clos_information(cpu, &enable, &prio_type); 2166 if (ret) 2167 isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0); 2168 else { 2169 int cp_state, cp_cap; 2170 2171 isst_read_pm_config(cpu, &cp_state, &cp_cap); 2172 isst_clos_display_clos_information(cpu, outf, enable, prio_type, 2173 cp_state, cp_cap); 2174 } 2175 } 2176 2177 static void dump_clos_info(int arg) 2178 { 2179 if (cmd_help) { 2180 fprintf(stderr, 2181 "Print Intel Speed Select Technology core power information\n"); 2182 fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n"); 2183 exit(0); 2184 } 2185 2186 isst_ctdp_display_information_start(outf); 2187 if (max_target_cpus) 2188 for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL, 2189 NULL, NULL, NULL); 2190 else 2191 for_each_online_package_in_set(get_clos_info_for_cpu, NULL, 2192 NULL, NULL, NULL); 2193 isst_ctdp_display_information_end(outf); 2194 2195 } 2196 2197 static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 2198 void *arg4) 2199 { 2200 struct isst_clos_config clos_config; 2201 int ret; 2202 2203 clos_config.pkg_id = get_physical_package_id(cpu); 2204 clos_config.die_id = get_physical_die_id(cpu); 2205 2206 clos_config.epp = clos_epp; 2207 clos_config.clos_prop_prio = clos_prop_prio; 2208 clos_config.clos_min = clos_min; 2209 clos_config.clos_max = clos_max; 2210 clos_config.clos_desired = clos_desired; 2211 ret = isst_set_clos(cpu, current_clos, &clos_config); 2212 if (ret) 2213 isst_display_error_info_message(1, "isst_set_clos failed", 0, 0); 2214 else 2215 isst_display_result(cpu, outf, "core-power", "config", ret); 2216 } 2217 2218 static void set_clos_config(int arg) 2219 { 2220 if (cmd_help) { 2221 fprintf(stderr, 2222 "Set core-power configuration for one of the four clos ids\n"); 2223 fprintf(stderr, 2224 "\tSpecify targeted clos id with [--clos|-c]\n"); 2225 if (!is_skx_based_platform()) { 2226 fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n"); 2227 fprintf(stderr, 2228 "\tSpecify clos Proportional Priority [--weight|-w]\n"); 2229 } 2230 fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n"); 2231 fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n"); 2232 exit(0); 2233 } 2234 2235 if (current_clos < 0 || current_clos > 3) { 2236 isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); 2237 exit(0); 2238 } 2239 if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) { 2240 fprintf(stderr, "clos epp is not specified or invalid, default: 0\n"); 2241 clos_epp = 0; 2242 } 2243 if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) { 2244 fprintf(stderr, 2245 "clos frequency weight is not specified or invalid, default: 0\n"); 2246 clos_prop_prio = 0; 2247 } 2248 if (clos_min < 0) { 2249 fprintf(stderr, "clos min is not specified, default: 0\n"); 2250 clos_min = 0; 2251 } 2252 if (clos_max < 0) { 2253 fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n"); 2254 clos_max = 0xff; 2255 } 2256 if (clos_desired) { 2257 fprintf(stderr, "clos desired is not supported on this platform\n"); 2258 clos_desired = 0x00; 2259 } 2260 2261 isst_ctdp_display_information_start(outf); 2262 if (max_target_cpus) 2263 for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL, 2264 NULL, NULL, NULL); 2265 else 2266 for_each_online_package_in_set(set_clos_config_for_cpu, NULL, 2267 NULL, NULL, NULL); 2268 isst_ctdp_display_information_end(outf); 2269 } 2270 2271 static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 2272 void *arg4) 2273 { 2274 int ret; 2275 2276 ret = isst_clos_associate(cpu, current_clos); 2277 if (ret) 2278 debug_printf("isst_clos_associate failed"); 2279 else 2280 isst_display_result(cpu, outf, "core-power", "assoc", ret); 2281 } 2282 2283 static void set_clos_assoc(int arg) 2284 { 2285 if (cmd_help) { 2286 fprintf(stderr, "Associate a clos id to a CPU\n"); 2287 fprintf(stderr, 2288 "\tSpecify targeted clos id with [--clos|-c]\n"); 2289 fprintf(stderr, 2290 "\tFor example to associate clos 1 to CPU 0: issue\n"); 2291 fprintf(stderr, 2292 "\tintel-speed-select --cpu 0 core-power assoc --clos 1\n"); 2293 exit(0); 2294 } 2295 2296 if (current_clos < 0 || current_clos > 3) { 2297 isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); 2298 exit(0); 2299 } 2300 if (max_target_cpus) 2301 for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL, 2302 NULL, NULL, NULL); 2303 else { 2304 isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0); 2305 } 2306 } 2307 2308 static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3, 2309 void *arg4) 2310 { 2311 int clos, ret; 2312 2313 ret = isst_clos_get_assoc_status(cpu, &clos); 2314 if (ret) 2315 isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0); 2316 else 2317 isst_clos_display_assoc_information(cpu, outf, clos); 2318 } 2319 2320 static void get_clos_assoc(int arg) 2321 { 2322 if (cmd_help) { 2323 fprintf(stderr, "Get associate clos id to a CPU\n"); 2324 fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n"); 2325 exit(0); 2326 } 2327 2328 if (!max_target_cpus) { 2329 isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0); 2330 exit(0); 2331 } 2332 2333 isst_ctdp_display_information_start(outf); 2334 for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL, 2335 NULL, NULL, NULL); 2336 isst_ctdp_display_information_end(outf); 2337 } 2338 2339 static void set_turbo_mode_for_cpu(int cpu, int status) 2340 { 2341 int base_freq; 2342 2343 if (status) { 2344 base_freq = get_cpufreq_base_freq(cpu); 2345 set_cpufreq_scaling_min_max(cpu, 1, base_freq); 2346 } else { 2347 set_scaling_max_to_cpuinfo_max(cpu); 2348 } 2349 2350 if (status) { 2351 isst_display_result(cpu, outf, "turbo-mode", "enable", 0); 2352 } else { 2353 isst_display_result(cpu, outf, "turbo-mode", "disable", 0); 2354 } 2355 } 2356 2357 static void set_turbo_mode(int arg) 2358 { 2359 int i, enable = arg; 2360 2361 if (cmd_help) { 2362 if (enable) 2363 fprintf(stderr, "Set turbo mode enable\n"); 2364 else 2365 fprintf(stderr, "Set turbo mode disable\n"); 2366 exit(0); 2367 } 2368 2369 isst_ctdp_display_information_start(outf); 2370 2371 for (i = 0; i < topo_max_cpus; ++i) { 2372 int online; 2373 2374 if (i) 2375 online = parse_int_file( 2376 1, "/sys/devices/system/cpu/cpu%d/online", i); 2377 else 2378 online = 2379 1; /* online entry for CPU 0 needs some special configs */ 2380 2381 if (online) 2382 set_turbo_mode_for_cpu(i, enable); 2383 2384 } 2385 isst_ctdp_display_information_end(outf); 2386 } 2387 2388 static void get_set_trl(int cpu, void *arg1, void *arg2, void *arg3, 2389 void *arg4) 2390 { 2391 unsigned long long trl; 2392 int set = *(int *)arg4; 2393 int ret; 2394 2395 if (set && !fact_trl) { 2396 isst_display_error_info_message(1, "Invalid TRL. Specify with [-t|--trl]", 0, 0); 2397 exit(0); 2398 } 2399 2400 if (set) { 2401 ret = isst_set_trl(cpu, fact_trl); 2402 isst_display_result(cpu, outf, "turbo-mode", "set-trl", ret); 2403 return; 2404 } 2405 2406 ret = isst_get_trl(cpu, &trl); 2407 if (ret) 2408 isst_display_result(cpu, outf, "turbo-mode", "get-trl", ret); 2409 else 2410 isst_trl_display_information(cpu, outf, trl); 2411 } 2412 2413 static void process_trl(int arg) 2414 { 2415 if (cmd_help) { 2416 if (arg) { 2417 fprintf(stderr, "Set TRL (turbo ratio limits)\n"); 2418 fprintf(stderr, "\t t|--trl: Specify turbo ratio limit for setting TRL\n"); 2419 } else { 2420 fprintf(stderr, "Get TRL (turbo ratio limits)\n"); 2421 } 2422 exit(0); 2423 } 2424 2425 isst_ctdp_display_information_start(outf); 2426 if (max_target_cpus) 2427 for_each_online_target_cpu_in_set(get_set_trl, NULL, 2428 NULL, NULL, &arg); 2429 else 2430 for_each_online_package_in_set(get_set_trl, NULL, 2431 NULL, NULL, &arg); 2432 isst_ctdp_display_information_end(outf); 2433 } 2434 2435 static struct process_cmd_struct clx_n_cmds[] = { 2436 { "perf-profile", "info", dump_isst_config, 0 }, 2437 { "base-freq", "info", dump_pbf_config, 0 }, 2438 { "base-freq", "enable", set_pbf_enable, 1 }, 2439 { "base-freq", "disable", set_pbf_enable, 0 }, 2440 { NULL, NULL, NULL, 0 } 2441 }; 2442 2443 static struct process_cmd_struct isst_cmds[] = { 2444 { "perf-profile", "get-lock-status", get_tdp_locked, 0 }, 2445 { "perf-profile", "get-config-levels", get_tdp_levels, 0 }, 2446 { "perf-profile", "get-config-version", get_tdp_version, 0 }, 2447 { "perf-profile", "get-config-enabled", get_tdp_enabled, 0 }, 2448 { "perf-profile", "get-config-current-level", get_tdp_current_level, 2449 0 }, 2450 { "perf-profile", "set-config-level", set_tdp_level, 0 }, 2451 { "perf-profile", "info", dump_isst_config, 0 }, 2452 { "base-freq", "info", dump_pbf_config, 0 }, 2453 { "base-freq", "enable", set_pbf_enable, 1 }, 2454 { "base-freq", "disable", set_pbf_enable, 0 }, 2455 { "turbo-freq", "info", dump_fact_config, 0 }, 2456 { "turbo-freq", "enable", set_fact_enable, 1 }, 2457 { "turbo-freq", "disable", set_fact_enable, 0 }, 2458 { "core-power", "info", dump_clos_info, 0 }, 2459 { "core-power", "enable", set_clos_enable, 1 }, 2460 { "core-power", "disable", set_clos_enable, 0 }, 2461 { "core-power", "config", set_clos_config, 0 }, 2462 { "core-power", "get-config", dump_clos_config, 0 }, 2463 { "core-power", "assoc", set_clos_assoc, 0 }, 2464 { "core-power", "get-assoc", get_clos_assoc, 0 }, 2465 { "turbo-mode", "enable", set_turbo_mode, 0 }, 2466 { "turbo-mode", "disable", set_turbo_mode, 1 }, 2467 { "turbo-mode", "get-trl", process_trl, 0 }, 2468 { "turbo-mode", "set-trl", process_trl, 1 }, 2469 { NULL, NULL, NULL } 2470 }; 2471 2472 /* 2473 * parse cpuset with following syntax 2474 * 1,2,4..6,8-10 and set bits in cpu_subset 2475 */ 2476 void parse_cpu_command(char *optarg) 2477 { 2478 unsigned int start, end; 2479 char *next; 2480 2481 next = optarg; 2482 2483 while (next && *next) { 2484 if (*next == '-') /* no negative cpu numbers */ 2485 goto error; 2486 2487 start = strtoul(next, &next, 10); 2488 2489 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ) 2490 target_cpus[max_target_cpus++] = start; 2491 2492 if (*next == '\0') 2493 break; 2494 2495 if (*next == ',') { 2496 next += 1; 2497 continue; 2498 } 2499 2500 if (*next == '-') { 2501 next += 1; /* start range */ 2502 } else if (*next == '.') { 2503 next += 1; 2504 if (*next == '.') 2505 next += 1; /* start range */ 2506 else 2507 goto error; 2508 } 2509 2510 end = strtoul(next, &next, 10); 2511 if (end <= start) 2512 goto error; 2513 2514 while (++start <= end) { 2515 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ) 2516 target_cpus[max_target_cpus++] = start; 2517 } 2518 2519 if (*next == ',') 2520 next += 1; 2521 else if (*next != '\0') 2522 goto error; 2523 } 2524 2525 #ifdef DEBUG 2526 { 2527 int i; 2528 2529 for (i = 0; i < max_target_cpus; ++i) 2530 printf("cpu [%d] in arg\n", target_cpus[i]); 2531 } 2532 #endif 2533 return; 2534 2535 error: 2536 fprintf(stderr, "\"--cpu %s\" malformed\n", optarg); 2537 exit(-1); 2538 } 2539 2540 static void parse_cmd_args(int argc, int start, char **argv) 2541 { 2542 int opt; 2543 int option_index; 2544 2545 static struct option long_options[] = { 2546 { "bucket", required_argument, 0, 'b' }, 2547 { "level", required_argument, 0, 'l' }, 2548 { "online", required_argument, 0, 'o' }, 2549 { "trl-type", required_argument, 0, 'r' }, 2550 { "trl", required_argument, 0, 't' }, 2551 { "help", no_argument, 0, 'h' }, 2552 { "clos", required_argument, 0, 'c' }, 2553 { "desired", required_argument, 0, 'd' }, 2554 { "epp", required_argument, 0, 'e' }, 2555 { "min", required_argument, 0, 'n' }, 2556 { "max", required_argument, 0, 'm' }, 2557 { "priority", required_argument, 0, 'p' }, 2558 { "weight", required_argument, 0, 'w' }, 2559 { "auto", no_argument, 0, 'a' }, 2560 { 0, 0, 0, 0 } 2561 }; 2562 2563 option_index = start; 2564 2565 optind = start + 1; 2566 while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa", 2567 long_options, &option_index)) != -1) { 2568 switch (opt) { 2569 case 'a': 2570 auto_mode = 1; 2571 break; 2572 case 'b': 2573 fact_bucket = atoi(optarg); 2574 break; 2575 case 'h': 2576 cmd_help = 1; 2577 break; 2578 case 'l': 2579 tdp_level = atoi(optarg); 2580 break; 2581 case 'o': 2582 force_online_offline = 1; 2583 break; 2584 case 't': 2585 sscanf(optarg, "0x%llx", &fact_trl); 2586 break; 2587 case 'r': 2588 if (!strncmp(optarg, "sse", 3)) { 2589 fact_avx = 0x01; 2590 } else if (!strncmp(optarg, "avx2", 4)) { 2591 fact_avx = 0x02; 2592 } else if (!strncmp(optarg, "avx512", 6)) { 2593 fact_avx = 0x04; 2594 } else { 2595 fprintf(outf, "Invalid sse,avx options\n"); 2596 exit(1); 2597 } 2598 break; 2599 /* CLOS related */ 2600 case 'c': 2601 current_clos = atoi(optarg); 2602 break; 2603 case 'd': 2604 clos_desired = atoi(optarg); 2605 clos_desired /= DISP_FREQ_MULTIPLIER; 2606 break; 2607 case 'e': 2608 clos_epp = atoi(optarg); 2609 if (is_skx_based_platform()) { 2610 isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0); 2611 exit(0); 2612 } 2613 break; 2614 case 'n': 2615 clos_min = atoi(optarg); 2616 clos_min /= DISP_FREQ_MULTIPLIER; 2617 break; 2618 case 'm': 2619 clos_max = atoi(optarg); 2620 clos_max /= DISP_FREQ_MULTIPLIER; 2621 break; 2622 case 'p': 2623 clos_priority_type = atoi(optarg); 2624 if (is_skx_based_platform() && !clos_priority_type) { 2625 isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0); 2626 exit(0); 2627 } 2628 break; 2629 case 'w': 2630 clos_prop_prio = atoi(optarg); 2631 if (is_skx_based_platform()) { 2632 isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0); 2633 exit(0); 2634 } 2635 break; 2636 default: 2637 printf("Unknown option: ignore\n"); 2638 } 2639 } 2640 2641 if (argv[optind]) 2642 printf("Garbage at the end of command: ignore\n"); 2643 } 2644 2645 static void isst_help(void) 2646 { 2647 printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\ 2648 performance profiles per system via static and/or dynamic\n\ 2649 adjustment of core count, workload, Tjmax, and\n\ 2650 TDP, etc.\n"); 2651 printf("\nCommands : For feature=perf-profile\n"); 2652 printf("\tinfo\n"); 2653 2654 if (!is_clx_n_platform()) { 2655 printf("\tget-lock-status\n"); 2656 printf("\tget-config-levels\n"); 2657 printf("\tget-config-version\n"); 2658 printf("\tget-config-enabled\n"); 2659 printf("\tget-config-current-level\n"); 2660 printf("\tset-config-level\n"); 2661 } 2662 } 2663 2664 static void pbf_help(void) 2665 { 2666 printf("base-freq:\tEnables users to increase guaranteed base frequency\n\ 2667 on certain cores (high priority cores) in exchange for lower\n\ 2668 base frequency on remaining cores (low priority cores).\n"); 2669 printf("\tcommand : info\n"); 2670 printf("\tcommand : enable\n"); 2671 printf("\tcommand : disable\n"); 2672 } 2673 2674 static void fact_help(void) 2675 { 2676 printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\ 2677 limits to cores based on priority.\n"); 2678 printf("\nCommand: For feature=turbo-freq\n"); 2679 printf("\tcommand : info\n"); 2680 printf("\tcommand : enable\n"); 2681 printf("\tcommand : disable\n"); 2682 } 2683 2684 static void turbo_mode_help(void) 2685 { 2686 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"); 2687 printf("\tcommand : enable\n"); 2688 printf("\tcommand : disable\n"); 2689 printf("\tcommand : get-trl\n"); 2690 printf("\tcommand : set-trl\n"); 2691 } 2692 2693 2694 static void core_power_help(void) 2695 { 2696 printf("core-power:\tInterface that allows user to define per core/tile\n\ 2697 priority.\n"); 2698 printf("\nCommands : For feature=core-power\n"); 2699 printf("\tinfo\n"); 2700 printf("\tenable\n"); 2701 printf("\tdisable\n"); 2702 printf("\tconfig\n"); 2703 printf("\tget-config\n"); 2704 printf("\tassoc\n"); 2705 printf("\tget-assoc\n"); 2706 } 2707 2708 struct process_cmd_help_struct { 2709 char *feature; 2710 void (*process_fn)(void); 2711 }; 2712 2713 static struct process_cmd_help_struct isst_help_cmds[] = { 2714 { "perf-profile", isst_help }, 2715 { "base-freq", pbf_help }, 2716 { "turbo-freq", fact_help }, 2717 { "core-power", core_power_help }, 2718 { "turbo-mode", turbo_mode_help }, 2719 { NULL, NULL } 2720 }; 2721 2722 static struct process_cmd_help_struct clx_n_help_cmds[] = { 2723 { "perf-profile", isst_help }, 2724 { "base-freq", pbf_help }, 2725 { NULL, NULL } 2726 }; 2727 2728 void process_command(int argc, char **argv, 2729 struct process_cmd_help_struct *help_cmds, 2730 struct process_cmd_struct *cmds) 2731 { 2732 int i = 0, matched = 0; 2733 char *feature = argv[optind]; 2734 char *cmd = argv[optind + 1]; 2735 2736 if (!feature || !cmd) 2737 return; 2738 2739 debug_printf("feature name [%s] command [%s]\n", feature, cmd); 2740 if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) { 2741 while (help_cmds[i].feature) { 2742 if (!strcmp(help_cmds[i].feature, feature)) { 2743 help_cmds[i].process_fn(); 2744 exit(0); 2745 } 2746 ++i; 2747 } 2748 } 2749 2750 if (!is_clx_n_platform()) 2751 create_cpu_map(); 2752 2753 i = 0; 2754 while (cmds[i].feature) { 2755 if (!strcmp(cmds[i].feature, feature) && 2756 !strcmp(cmds[i].command, cmd)) { 2757 parse_cmd_args(argc, optind + 1, argv); 2758 cmds[i].process_fn(cmds[i].arg); 2759 matched = 1; 2760 break; 2761 } 2762 ++i; 2763 } 2764 2765 if (!matched) 2766 fprintf(stderr, "Invalid command\n"); 2767 } 2768 2769 static void usage(void) 2770 { 2771 if (is_clx_n_platform()) { 2772 fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n"); 2773 fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n"); 2774 } 2775 2776 printf("\nUsage:\n"); 2777 printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n"); 2778 printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n"); 2779 if (is_clx_n_platform()) 2780 printf("\nFEATURE : [perf-profile|base-freq]\n"); 2781 else 2782 printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power|turbo-mode]\n"); 2783 printf("\nFor help on each feature, use -h|--help\n"); 2784 printf("\tFor example: intel-speed-select perf-profile -h\n"); 2785 2786 printf("\nFor additional help on each command for a feature, use --h|--help\n"); 2787 printf("\tFor example: intel-speed-select perf-profile get-lock-status -h\n"); 2788 printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n"); 2789 2790 printf("\nOPTIONS\n"); 2791 printf("\t[-c|--cpu] : logical cpu number\n"); 2792 printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n"); 2793 printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n"); 2794 printf("\t[-d|--debug] : Debug mode\n"); 2795 printf("\t[-f|--format] : output format [json|text]. Default: text\n"); 2796 printf("\t[-h|--help] : Print help\n"); 2797 printf("\t[-i|--info] : Print platform information\n"); 2798 printf("\t[-a|--all-cpus-online] : Force online every CPU in the system\n"); 2799 printf("\t[-o|--out] : Output file\n"); 2800 printf("\t\t\tDefault : stderr\n"); 2801 printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n"); 2802 printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n"); 2803 printf("\t[-v|--version] : Print version\n"); 2804 2805 printf("\nResult format\n"); 2806 printf("\tResult display uses a common format for each command:\n"); 2807 printf("\tResults are formatted in text/JSON with\n"); 2808 printf("\t\tPackage, Die, CPU, and command specific results.\n"); 2809 2810 printf("\nExamples\n"); 2811 printf("\tTo get platform information:\n"); 2812 printf("\t\tintel-speed-select --info\n"); 2813 printf("\tTo get full perf-profile information dump:\n"); 2814 printf("\t\tintel-speed-select perf-profile info\n"); 2815 printf("\tTo get full base-freq information dump:\n"); 2816 printf("\t\tintel-speed-select base-freq info -l 0\n"); 2817 if (!is_clx_n_platform()) { 2818 printf("\tTo get full turbo-freq information dump:\n"); 2819 printf("\t\tintel-speed-select turbo-freq info -l 0\n"); 2820 } 2821 exit(1); 2822 } 2823 2824 static void print_version(void) 2825 { 2826 fprintf(outf, "Version %s\n", version_str); 2827 exit(0); 2828 } 2829 2830 static void cmdline(int argc, char **argv) 2831 { 2832 const char *pathname = "/dev/isst_interface"; 2833 char *ptr; 2834 FILE *fp; 2835 int opt, force_cpus_online = 0; 2836 int option_index = 0; 2837 int ret; 2838 2839 static struct option long_options[] = { 2840 { "all-cpus-online", no_argument, 0, 'a' }, 2841 { "cpu", required_argument, 0, 'c' }, 2842 { "debug", no_argument, 0, 'd' }, 2843 { "format", required_argument, 0, 'f' }, 2844 { "help", no_argument, 0, 'h' }, 2845 { "info", no_argument, 0, 'i' }, 2846 { "pause", required_argument, 0, 'p' }, 2847 { "out", required_argument, 0, 'o' }, 2848 { "retry", required_argument, 0, 'r' }, 2849 { "version", no_argument, 0, 'v' }, 2850 { 0, 0, 0, 0 } 2851 }; 2852 2853 if (geteuid() != 0) { 2854 fprintf(stderr, "Must run as root\n"); 2855 exit(0); 2856 } 2857 2858 ret = update_cpu_model(); 2859 if (ret) 2860 err(-1, "Invalid CPU model (%d)\n", cpu_model); 2861 printf("Intel(R) Speed Select Technology\n"); 2862 printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model); 2863 2864 if (!is_clx_n_platform()) { 2865 fp = fopen(pathname, "rb"); 2866 if (!fp) { 2867 fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n"); 2868 fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n"); 2869 fprintf(stderr, "If the config is included then this is not a supported platform.\n"); 2870 exit(0); 2871 } 2872 fclose(fp); 2873 } 2874 2875 progname = argv[0]; 2876 while ((opt = getopt_long_only(argc, argv, "+c:df:hio:va", long_options, 2877 &option_index)) != -1) { 2878 switch (opt) { 2879 case 'a': 2880 force_cpus_online = 1; 2881 break; 2882 case 'c': 2883 parse_cpu_command(optarg); 2884 break; 2885 case 'd': 2886 debug_flag = 1; 2887 printf("Debug Mode ON\n"); 2888 break; 2889 case 'f': 2890 if (!strncmp(optarg, "json", 4)) 2891 out_format_json = 1; 2892 break; 2893 case 'h': 2894 usage(); 2895 break; 2896 case 'i': 2897 isst_print_platform_information(); 2898 break; 2899 case 'o': 2900 if (outf) 2901 fclose(outf); 2902 outf = fopen_or_exit(optarg, "w"); 2903 break; 2904 case 'p': 2905 ret = strtol(optarg, &ptr, 10); 2906 if (!ret) 2907 fprintf(stderr, "Invalid pause interval, ignore\n"); 2908 else 2909 mbox_delay = ret; 2910 break; 2911 case 'r': 2912 ret = strtol(optarg, &ptr, 10); 2913 if (!ret) 2914 fprintf(stderr, "Invalid retry count, ignore\n"); 2915 else 2916 mbox_retries = ret; 2917 break; 2918 case 'v': 2919 print_version(); 2920 break; 2921 default: 2922 usage(); 2923 } 2924 } 2925 2926 if (optind > (argc - 2)) { 2927 usage(); 2928 exit(0); 2929 } 2930 set_max_cpu_num(); 2931 if (force_cpus_online) 2932 force_all_cpus_online(); 2933 store_cpu_topology(); 2934 set_cpu_present_cpu_mask(); 2935 set_cpu_target_cpu_mask(); 2936 2937 if (!is_clx_n_platform()) { 2938 ret = isst_fill_platform_info(); 2939 if (ret) 2940 goto out; 2941 process_command(argc, argv, isst_help_cmds, isst_cmds); 2942 } else { 2943 process_command(argc, argv, clx_n_help_cmds, clx_n_cmds); 2944 } 2945 out: 2946 free_cpu_set(present_cpumask); 2947 free_cpu_set(target_cpumask); 2948 } 2949 2950 int main(int argc, char **argv) 2951 { 2952 outf = stderr; 2953 cmdline(argc, argv); 2954 return 0; 2955 } 2956