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