1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * x86_energy_perf_policy -- set the energy versus performance 4 * policy preference bias on recent X86 processors. 5 */ 6 /* 7 * Copyright (c) 2010 - 2025 Intel Corporation. 8 * Len Brown <len.brown@intel.com> 9 */ 10 11 #define _GNU_SOURCE 12 #include MSRHEADER 13 #include <stdio.h> 14 #include <unistd.h> 15 #include <sys/types.h> 16 #include <sched.h> 17 #include <sys/stat.h> 18 #include <sys/resource.h> 19 #include <getopt.h> 20 #include <err.h> 21 #include <fcntl.h> 22 #include <signal.h> 23 #include <sys/time.h> 24 #include <limits.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <cpuid.h> 28 #include <errno.h> 29 30 #define OPTARG_NORMAL (INT_MAX - 1) 31 #define OPTARG_POWER (INT_MAX - 2) 32 #define OPTARG_BALANCE_POWER (INT_MAX - 3) 33 #define OPTARG_BALANCE_PERFORMANCE (INT_MAX - 4) 34 #define OPTARG_PERFORMANCE (INT_MAX - 5) 35 36 struct msr_hwp_cap { 37 unsigned char highest; 38 unsigned char guaranteed; 39 unsigned char efficient; 40 unsigned char lowest; 41 }; 42 43 struct msr_hwp_request { 44 unsigned char hwp_min; 45 unsigned char hwp_max; 46 unsigned char hwp_desired; 47 unsigned char hwp_epp; 48 unsigned int hwp_window; 49 unsigned char hwp_use_pkg; 50 } req_update; 51 52 unsigned int debug; 53 unsigned int verbose; 54 unsigned int force; 55 char *progname; 56 int base_cpu; 57 unsigned char update_epb; 58 unsigned long long new_epb; 59 unsigned char turbo_is_enabled; 60 unsigned char update_turbo; 61 unsigned char turbo_update_value; 62 unsigned char update_hwp_epp; 63 unsigned char update_hwp_min; 64 unsigned char update_hwp_max; 65 unsigned char hwp_limits_done_via_sysfs; 66 unsigned char update_hwp_desired; 67 unsigned char update_hwp_window; 68 unsigned char update_hwp_use_pkg; 69 unsigned char update_hwp_enable; 70 #define hwp_update_enabled() (update_hwp_enable | update_hwp_epp | update_hwp_max | update_hwp_min | update_hwp_desired | update_hwp_window | update_hwp_use_pkg) 71 int max_cpu_num; 72 int max_pkg_num; 73 #define MAX_PACKAGES 64 74 unsigned int first_cpu_in_pkg[MAX_PACKAGES]; 75 unsigned long long pkg_present_set; 76 unsigned long long pkg_selected_set; 77 cpu_set_t *cpu_present_set; 78 cpu_set_t *cpu_selected_set; 79 int genuine_intel; 80 81 size_t cpu_setsize; 82 83 char *proc_stat = "/proc/stat"; 84 85 unsigned int has_epb; /* MSR_IA32_ENERGY_PERF_BIAS */ 86 unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ 87 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */ 88 unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */ 89 unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */ 90 unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ 91 unsigned int has_hwp_request_pkg; /* IA32_HWP_REQUEST_PKG */ 92 93 unsigned int bdx_highest_ratio; 94 95 #define PATH_TO_CPU "/sys/devices/system/cpu/" 96 #define SYSFS_PATH_MAX 255 97 98 /* 99 * maintain compatibility with original implementation, but don't document it: 100 */ 101 void usage(void) 102 { 103 fprintf(stderr, "%s [options] [scope][field value]\n", progname); 104 fprintf(stderr, "scope: --cpu cpu-list [--hwp-use-pkg #] | --pkg pkg-list\n"); 105 fprintf(stderr, "field: --all | --epb | --hwp-epp | --hwp-min | --hwp-max | --hwp-desired\n"); 106 fprintf(stderr, "other: --hwp-enable | --turbo-enable (0 | 1) | --help | --force\n"); 107 fprintf(stderr, 108 "value: ( # | \"normal\" | \"performance\" | \"balance-performance\" | \"balance-power\"| \"power\")\n"); 109 fprintf(stderr, "--hwp-window usec\n"); 110 111 fprintf(stderr, "Specify only Energy Performance BIAS (legacy usage):\n"); 112 fprintf(stderr, "%s: [-c cpu] [-v] (-r | policy-value )\n", progname); 113 114 exit(1); 115 } 116 117 /* 118 * If bdx_highest_ratio is set, 119 * then we must translate between MSR format and simple ratio 120 * used on the cmdline. 121 */ 122 int ratio_2_msr_perf(int ratio) 123 { 124 int msr_perf; 125 126 if (!bdx_highest_ratio) 127 return ratio; 128 129 msr_perf = ratio * 255 / bdx_highest_ratio; 130 131 if (debug) 132 fprintf(stderr, "%d = ratio_to_msr_perf(%d)\n", msr_perf, ratio); 133 134 return msr_perf; 135 } 136 int msr_perf_2_ratio(int msr_perf) 137 { 138 int ratio; 139 double d; 140 141 if (!bdx_highest_ratio) 142 return msr_perf; 143 144 d = (double)msr_perf * (double) bdx_highest_ratio / 255.0; 145 d = d + 0.5; /* round */ 146 ratio = (int)d; 147 148 if (debug) 149 fprintf(stderr, "%d = msr_perf_ratio(%d) {%f}\n", ratio, msr_perf, d); 150 151 return ratio; 152 } 153 int parse_cmdline_epb(int i) 154 { 155 if (!has_epb) 156 errx(1, "EPB not enabled on this platform"); 157 158 update_epb = 1; 159 160 switch (i) { 161 case OPTARG_POWER: 162 return ENERGY_PERF_BIAS_POWERSAVE; 163 case OPTARG_BALANCE_POWER: 164 return ENERGY_PERF_BIAS_BALANCE_POWERSAVE; 165 case OPTARG_NORMAL: 166 return ENERGY_PERF_BIAS_NORMAL; 167 case OPTARG_BALANCE_PERFORMANCE: 168 return ENERGY_PERF_BIAS_BALANCE_PERFORMANCE; 169 case OPTARG_PERFORMANCE: 170 return ENERGY_PERF_BIAS_PERFORMANCE; 171 } 172 if (i < 0 || i > ENERGY_PERF_BIAS_POWERSAVE) 173 errx(1, "--epb must be from 0 to 15"); 174 return i; 175 } 176 177 #define HWP_CAP_LOWEST 0 178 #define HWP_CAP_HIGHEST 255 179 180 /* 181 * "performance" changes hwp_min to cap.highest 182 * All others leave it at cap.lowest 183 */ 184 int parse_cmdline_hwp_min(int i) 185 { 186 update_hwp_min = 1; 187 188 switch (i) { 189 case OPTARG_POWER: 190 case OPTARG_BALANCE_POWER: 191 case OPTARG_NORMAL: 192 case OPTARG_BALANCE_PERFORMANCE: 193 return HWP_CAP_LOWEST; 194 case OPTARG_PERFORMANCE: 195 return HWP_CAP_HIGHEST; 196 } 197 return i; 198 } 199 /* 200 * "power" changes hwp_max to cap.lowest 201 * All others leave it at cap.highest 202 */ 203 int parse_cmdline_hwp_max(int i) 204 { 205 update_hwp_max = 1; 206 207 switch (i) { 208 case OPTARG_POWER: 209 return HWP_CAP_LOWEST; 210 case OPTARG_NORMAL: 211 case OPTARG_BALANCE_POWER: 212 case OPTARG_BALANCE_PERFORMANCE: 213 case OPTARG_PERFORMANCE: 214 return HWP_CAP_HIGHEST; 215 } 216 return i; 217 } 218 /* 219 * for --hwp-des, all strings leave it in autonomous mode 220 * If you want to change it, you need to explicitly pick a value 221 */ 222 int parse_cmdline_hwp_desired(int i) 223 { 224 update_hwp_desired = 1; 225 226 switch (i) { 227 case OPTARG_POWER: 228 case OPTARG_BALANCE_POWER: 229 case OPTARG_BALANCE_PERFORMANCE: 230 case OPTARG_NORMAL: 231 case OPTARG_PERFORMANCE: 232 return 0; /* autonomous */ 233 } 234 return i; 235 } 236 237 int parse_cmdline_hwp_window(int i) 238 { 239 unsigned int exponent; 240 241 update_hwp_window = 1; 242 243 switch (i) { 244 case OPTARG_POWER: 245 case OPTARG_BALANCE_POWER: 246 case OPTARG_NORMAL: 247 case OPTARG_BALANCE_PERFORMANCE: 248 case OPTARG_PERFORMANCE: 249 return 0; 250 } 251 if (i < 0 || i > 1270000000) { 252 fprintf(stderr, "--hwp-window: 0 for auto; 1 - 1270000000 usec for window duration\n"); 253 usage(); 254 } 255 for (exponent = 0; ; ++exponent) { 256 if (debug) 257 printf("%d 10^%d\n", i, exponent); 258 259 if (i <= 127) 260 break; 261 262 i = i / 10; 263 } 264 if (debug) 265 fprintf(stderr, "%d*10^%d: 0x%x\n", i, exponent, (exponent << 7) | i); 266 267 return (exponent << 7) | i; 268 } 269 int parse_cmdline_hwp_epp(int i) 270 { 271 update_hwp_epp = 1; 272 273 switch (i) { 274 case OPTARG_POWER: 275 return HWP_EPP_POWERSAVE; 276 case OPTARG_BALANCE_POWER: 277 return HWP_EPP_BALANCE_POWERSAVE; 278 case OPTARG_NORMAL: 279 case OPTARG_BALANCE_PERFORMANCE: 280 return HWP_EPP_BALANCE_PERFORMANCE; 281 case OPTARG_PERFORMANCE: 282 return HWP_EPP_PERFORMANCE; 283 } 284 if (i < 0 || i > 0xff) { 285 fprintf(stderr, "--hwp-epp must be from 0 to 0xff\n"); 286 usage(); 287 } 288 return i; 289 } 290 int parse_cmdline_turbo(int i) 291 { 292 update_turbo = 1; 293 294 switch (i) { 295 case OPTARG_POWER: 296 return 0; 297 case OPTARG_NORMAL: 298 case OPTARG_BALANCE_POWER: 299 case OPTARG_BALANCE_PERFORMANCE: 300 case OPTARG_PERFORMANCE: 301 return 1; 302 } 303 if (i < 0 || i > 1) { 304 fprintf(stderr, "--turbo-enable: 1 to enable, 0 to disable\n"); 305 usage(); 306 } 307 return i; 308 } 309 310 int parse_optarg_string(char *s) 311 { 312 int i; 313 char *endptr; 314 315 if (!strncmp(s, "default", 7)) 316 return OPTARG_NORMAL; 317 318 if (!strncmp(s, "normal", 6)) 319 return OPTARG_NORMAL; 320 321 if (!strncmp(s, "power", 9)) 322 return OPTARG_POWER; 323 324 if (!strncmp(s, "balance-power", 17)) 325 return OPTARG_BALANCE_POWER; 326 327 if (!strncmp(s, "balance-performance", 19)) 328 return OPTARG_BALANCE_PERFORMANCE; 329 330 if (!strncmp(s, "performance", 11)) 331 return OPTARG_PERFORMANCE; 332 333 i = strtol(s, &endptr, 0); 334 if (s == endptr) { 335 fprintf(stderr, "no digits in \"%s\"\n", s); 336 usage(); 337 } 338 if (i == LONG_MIN || i == LONG_MAX) 339 errx(-1, "%s", s); 340 341 if (i > 0xFF) 342 errx(-1, "%d (0x%x) must be < 256", i, i); 343 344 if (i < 0) 345 errx(-1, "%d (0x%x) must be >= 0", i, i); 346 return i; 347 } 348 349 void parse_cmdline_all(char *s) 350 { 351 force++; 352 update_hwp_enable = 1; 353 req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(s)); 354 req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(s)); 355 req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(s)); 356 if (has_epb) 357 new_epb = parse_cmdline_epb(parse_optarg_string(s)); 358 turbo_update_value = parse_cmdline_turbo(parse_optarg_string(s)); 359 req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(s)); 360 req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(s)); 361 } 362 363 void validate_cpu_selected_set(void) 364 { 365 int cpu; 366 367 if (CPU_COUNT_S(cpu_setsize, cpu_selected_set) == 0) 368 errx(0, "no CPUs requested"); 369 370 for (cpu = 0; cpu <= max_cpu_num; ++cpu) { 371 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_selected_set)) 372 if (!CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set)) 373 errx(1, "Requested cpu% is not present", cpu); 374 } 375 } 376 377 void parse_cmdline_cpu(char *s) 378 { 379 char *startp, *endp; 380 int cpu = 0; 381 382 if (pkg_selected_set) { 383 usage(); 384 errx(1, "--cpu | --pkg"); 385 } 386 cpu_selected_set = CPU_ALLOC((max_cpu_num + 1)); 387 if (cpu_selected_set == NULL) 388 err(1, "cpu_selected_set"); 389 CPU_ZERO_S(cpu_setsize, cpu_selected_set); 390 391 for (startp = s; startp && *startp;) { 392 393 if (*startp == ',') { 394 startp++; 395 continue; 396 } 397 398 if (*startp == '-') { 399 int end_cpu; 400 401 startp++; 402 end_cpu = strtol(startp, &endp, 10); 403 if (startp == endp) 404 continue; 405 406 while (cpu <= end_cpu) { 407 if (cpu > max_cpu_num) 408 errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num); 409 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set); 410 cpu++; 411 } 412 startp = endp; 413 continue; 414 } 415 416 if (strncmp(startp, "all", 3) == 0) { 417 for (cpu = 0; cpu <= max_cpu_num; cpu += 1) { 418 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set)) 419 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set); 420 } 421 startp += 3; 422 if (*startp == 0) 423 break; 424 } 425 /* "--cpu even" is not documented */ 426 if (strncmp(startp, "even", 4) == 0) { 427 for (cpu = 0; cpu <= max_cpu_num; cpu += 2) { 428 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set)) 429 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set); 430 } 431 startp += 4; 432 if (*startp == 0) 433 break; 434 } 435 436 /* "--cpu odd" is not documented */ 437 if (strncmp(startp, "odd", 3) == 0) { 438 for (cpu = 1; cpu <= max_cpu_num; cpu += 2) { 439 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set)) 440 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set); 441 } 442 startp += 3; 443 if (*startp == 0) 444 break; 445 } 446 447 cpu = strtol(startp, &endp, 10); 448 if (startp == endp) 449 errx(1, "--cpu cpu-set: confused by '%s'", startp); 450 if (cpu > max_cpu_num) 451 errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num); 452 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set); 453 startp = endp; 454 } 455 456 validate_cpu_selected_set(); 457 458 } 459 460 void parse_cmdline_pkg(char *s) 461 { 462 char *startp, *endp; 463 int pkg = 0; 464 465 if (cpu_selected_set) { 466 usage(); 467 errx(1, "--pkg | --cpu"); 468 } 469 pkg_selected_set = 0; 470 471 for (startp = s; startp && *startp;) { 472 473 if (*startp == ',') { 474 startp++; 475 continue; 476 } 477 478 if (*startp == '-') { 479 int end_pkg; 480 481 startp++; 482 end_pkg = strtol(startp, &endp, 10); 483 if (startp == endp) 484 continue; 485 486 while (pkg <= end_pkg) { 487 if (pkg > max_pkg_num) 488 errx(1, "Requested pkg%d exceeds max pkg%d", pkg, max_pkg_num); 489 pkg_selected_set |= 1 << pkg; 490 pkg++; 491 } 492 startp = endp; 493 continue; 494 } 495 496 if (strncmp(startp, "all", 3) == 0) { 497 pkg_selected_set = pkg_present_set; 498 return; 499 } 500 501 pkg = strtol(startp, &endp, 10); 502 if (pkg > max_pkg_num) 503 errx(1, "Requested pkg%d Exceeds max pkg%d", pkg, max_pkg_num); 504 pkg_selected_set |= 1 << pkg; 505 startp = endp; 506 } 507 } 508 509 void for_packages(unsigned long long pkg_set, int (func)(int)) 510 { 511 int pkg_num; 512 513 for (pkg_num = 0; pkg_num <= max_pkg_num; ++pkg_num) { 514 if (pkg_set & (1UL << pkg_num)) 515 func(pkg_num); 516 } 517 } 518 519 void print_version(void) 520 { 521 printf("x86_energy_perf_policy 2025.9.19 Len Brown <lenb@kernel.org>\n"); 522 } 523 524 void cmdline(int argc, char **argv) 525 { 526 int opt; 527 int option_index = 0; 528 529 static struct option long_options[] = { 530 {"all", required_argument, 0, 'a'}, 531 {"cpu", required_argument, 0, 'c'}, 532 {"pkg", required_argument, 0, 'p'}, 533 {"debug", no_argument, 0, 'd'}, 534 {"hwp-desired", required_argument, 0, 'D'}, 535 {"epb", required_argument, 0, 'B'}, 536 {"force", no_argument, 0, 'f'}, 537 {"hwp-enable", no_argument, 0, 'e'}, 538 {"help", no_argument, 0, 'h'}, 539 {"hwp-epp", required_argument, 0, 'P'}, 540 {"hwp-min", required_argument, 0, 'm'}, 541 {"hwp-max", required_argument, 0, 'M'}, 542 {"read", no_argument, 0, 'r'}, 543 {"turbo-enable", required_argument, 0, 't'}, 544 {"hwp-use-pkg", required_argument, 0, 'u'}, 545 {"version", no_argument, 0, 'v'}, 546 {"hwp-window", required_argument, 0, 'w'}, 547 {0, 0, 0, 0 } 548 }; 549 550 progname = argv[0]; 551 552 while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw:", 553 long_options, &option_index)) != -1) { 554 switch (opt) { 555 case 'a': 556 parse_cmdline_all(optarg); 557 break; 558 case 'B': 559 new_epb = parse_cmdline_epb(parse_optarg_string(optarg)); 560 break; 561 case 'c': 562 parse_cmdline_cpu(optarg); 563 break; 564 case 'e': 565 update_hwp_enable = 1; 566 break; 567 case 'h': 568 usage(); 569 break; 570 case 'd': 571 debug++; 572 verbose++; 573 break; 574 case 'f': 575 force++; 576 break; 577 case 'D': 578 req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(optarg)); 579 break; 580 case 'm': 581 req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(optarg)); 582 break; 583 case 'M': 584 req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(optarg)); 585 break; 586 case 'p': 587 parse_cmdline_pkg(optarg); 588 break; 589 case 'P': 590 req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(optarg)); 591 break; 592 case 'r': 593 /* v1 used -r to specify read-only mode, now the default */ 594 break; 595 case 't': 596 turbo_update_value = parse_cmdline_turbo(parse_optarg_string(optarg)); 597 break; 598 case 'u': 599 update_hwp_use_pkg++; 600 if (atoi(optarg) == 0) 601 req_update.hwp_use_pkg = 0; 602 else 603 req_update.hwp_use_pkg = 1; 604 break; 605 case 'v': 606 print_version(); 607 exit(0); 608 break; 609 case 'w': 610 req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(optarg)); 611 break; 612 default: 613 usage(); 614 } 615 } 616 /* 617 * v1 allowed "performance"|"normal"|"power" with no policy specifier 618 * to update BIAS. Continue to support that, even though no longer documented. 619 */ 620 if (argc == optind + 1) 621 new_epb = parse_cmdline_epb(parse_optarg_string(argv[optind])); 622 623 if (argc > optind + 1) { 624 fprintf(stderr, "stray parameter '%s'\n", argv[optind + 1]); 625 usage(); 626 } 627 } 628 629 /* 630 * Open a file, and exit on failure 631 */ 632 FILE *fopen_or_die(const char *path, const char *mode) 633 { 634 FILE *filep = fopen(path, mode); 635 636 if (!filep) 637 err(1, "%s: open failed", path); 638 return filep; 639 } 640 641 void err_on_hypervisor(void) 642 { 643 FILE *cpuinfo; 644 char *flags, *hypervisor; 645 char *buffer; 646 647 /* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */ 648 cpuinfo = fopen_or_die("/proc/cpuinfo", "r"); 649 650 buffer = malloc(4096); 651 if (!buffer) { 652 fclose(cpuinfo); 653 err(-ENOMEM, "buffer malloc fail"); 654 } 655 656 if (!fread(buffer, 1024, 1, cpuinfo)) { 657 fclose(cpuinfo); 658 free(buffer); 659 err(1, "Reading /proc/cpuinfo failed"); 660 } 661 662 flags = strstr(buffer, "flags"); 663 rewind(cpuinfo); 664 fseek(cpuinfo, flags - buffer, SEEK_SET); 665 if (!fgets(buffer, 4096, cpuinfo)) { 666 fclose(cpuinfo); 667 free(buffer); 668 err(1, "Reading /proc/cpuinfo failed"); 669 } 670 fclose(cpuinfo); 671 672 hypervisor = strstr(buffer, "hypervisor"); 673 674 free(buffer); 675 676 if (hypervisor) 677 err(-1, 678 "not supported on this virtual machine"); 679 } 680 681 int get_msr(int cpu, int offset, unsigned long long *msr) 682 { 683 int retval; 684 char pathname[32]; 685 int fd; 686 687 sprintf(pathname, "/dev/cpu/%d/msr", cpu); 688 fd = open(pathname, O_RDONLY); 689 if (fd < 0) 690 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname); 691 692 retval = pread(fd, msr, sizeof(*msr), offset); 693 if (retval != sizeof(*msr)) { 694 err_on_hypervisor(); 695 err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset); 696 } 697 698 if (debug > 1) 699 fprintf(stderr, "get_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, *msr); 700 701 close(fd); 702 return 0; 703 } 704 705 int put_msr(int cpu, int offset, unsigned long long new_msr) 706 { 707 char pathname[32]; 708 int retval; 709 int fd; 710 711 sprintf(pathname, "/dev/cpu/%d/msr", cpu); 712 fd = open(pathname, O_RDWR); 713 if (fd < 0) 714 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname); 715 716 retval = pwrite(fd, &new_msr, sizeof(new_msr), offset); 717 if (retval != sizeof(new_msr)) 718 err(-2, "pwrite(cpu%d, offset 0x%x, 0x%llx) = %d", cpu, offset, new_msr, retval); 719 720 close(fd); 721 722 if (debug > 1) 723 fprintf(stderr, "put_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, new_msr); 724 725 return 0; 726 } 727 728 static unsigned int read_sysfs(const char *path, char *buf, size_t buflen) 729 { 730 ssize_t numread; 731 int fd; 732 733 fd = open(path, O_RDONLY); 734 if (fd == -1) 735 return 0; 736 737 numread = read(fd, buf, buflen - 1); 738 if (numread < 1) { 739 close(fd); 740 return 0; 741 } 742 743 buf[numread] = '\0'; 744 close(fd); 745 746 return (unsigned int) numread; 747 } 748 749 static unsigned int write_sysfs(const char *path, char *buf, size_t buflen) 750 { 751 ssize_t numwritten; 752 int fd; 753 754 fd = open(path, O_WRONLY); 755 if (fd == -1) 756 return 0; 757 758 numwritten = write(fd, buf, buflen - 1); 759 if (numwritten < 1) { 760 perror("write failed\n"); 761 close(fd); 762 return -1; 763 } 764 765 close(fd); 766 767 return (unsigned int) numwritten; 768 } 769 770 void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str) 771 { 772 if (cpu != -1) 773 printf("cpu%d: ", cpu); 774 775 printf("HWP_CAP: low %d eff %d guar %d high %d\n", 776 cap->lowest, cap->efficient, cap->guaranteed, cap->highest); 777 } 778 void read_hwp_cap(int cpu, struct msr_hwp_cap *cap, unsigned int msr_offset) 779 { 780 unsigned long long msr; 781 782 get_msr(cpu, msr_offset, &msr); 783 784 cap->highest = msr_perf_2_ratio(HWP_HIGHEST_PERF(msr)); 785 cap->guaranteed = msr_perf_2_ratio(HWP_GUARANTEED_PERF(msr)); 786 cap->efficient = msr_perf_2_ratio(HWP_MOSTEFFICIENT_PERF(msr)); 787 cap->lowest = msr_perf_2_ratio(HWP_LOWEST_PERF(msr)); 788 } 789 790 void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str) 791 { 792 if (cpu != -1) 793 printf("cpu%d: ", cpu); 794 795 if (str) 796 printf("%s", str); 797 798 printf("HWP_REQ: min %d max %d des %d epp %d window 0x%x (%d*10^%dus) use_pkg %d\n", 799 h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp, 800 h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7, h->hwp_use_pkg); 801 } 802 void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, char *str) 803 { 804 printf("pkg%d: ", pkg); 805 806 if (str) 807 printf("%s", str); 808 809 printf("HWP_REQ_PKG: min %d max %d des %d epp %d window 0x%x (%d*10^%dus)\n", 810 h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp, 811 h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7); 812 } 813 void read_hwp_request_msr(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset) 814 { 815 unsigned long long msr; 816 817 get_msr(cpu, msr_offset, &msr); 818 819 hwp_req->hwp_min = msr_perf_2_ratio((((msr) >> 0) & 0xff)); 820 hwp_req->hwp_max = msr_perf_2_ratio((((msr) >> 8) & 0xff)); 821 hwp_req->hwp_desired = msr_perf_2_ratio((((msr) >> 16) & 0xff)); 822 hwp_req->hwp_epp = (((msr) >> 24) & 0xff); 823 hwp_req->hwp_window = (((msr) >> 32) & 0x3ff); 824 hwp_req->hwp_use_pkg = (((msr) >> 42) & 0x1); 825 } 826 827 void write_hwp_request_msr(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset) 828 { 829 unsigned long long msr = 0; 830 831 if (debug > 1) 832 printf("cpu%d: requesting min %d max %d des %d epp %d window 0x%0x use_pkg %d\n", 833 cpu, hwp_req->hwp_min, hwp_req->hwp_max, 834 hwp_req->hwp_desired, hwp_req->hwp_epp, 835 hwp_req->hwp_window, hwp_req->hwp_use_pkg); 836 837 msr |= HWP_MIN_PERF(ratio_2_msr_perf(hwp_req->hwp_min)); 838 msr |= HWP_MAX_PERF(ratio_2_msr_perf(hwp_req->hwp_max)); 839 msr |= HWP_DESIRED_PERF(ratio_2_msr_perf(hwp_req->hwp_desired)); 840 msr |= HWP_ENERGY_PERF_PREFERENCE(hwp_req->hwp_epp); 841 msr |= HWP_ACTIVITY_WINDOW(hwp_req->hwp_window); 842 msr |= HWP_PACKAGE_CONTROL(hwp_req->hwp_use_pkg); 843 844 put_msr(cpu, msr_offset, msr); 845 } 846 847 static int get_epb_sysfs(int cpu) 848 { 849 char path[SYSFS_PATH_MAX]; 850 char linebuf[3]; 851 char *endp; 852 long val; 853 854 if (!has_epb) 855 return -1; 856 857 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu); 858 859 if (!read_sysfs(path, linebuf, 3)) 860 return -1; 861 862 val = strtol(linebuf, &endp, 0); 863 if (endp == linebuf || errno == ERANGE) 864 return -1; 865 866 return (int)val; 867 } 868 869 static int set_epb_sysfs(int cpu, int val) 870 { 871 char path[SYSFS_PATH_MAX]; 872 char linebuf[3]; 873 char *endp; 874 int ret; 875 876 if (!has_epb) 877 return -1; 878 879 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu); 880 snprintf(linebuf, sizeof(linebuf), "%d", val); 881 882 ret = write_sysfs(path, linebuf, 3); 883 if (ret <= 0) 884 return -1; 885 886 val = strtol(linebuf, &endp, 0); 887 if (endp == linebuf || errno == ERANGE) 888 return -1; 889 890 return (int)val; 891 } 892 893 int print_cpu_msrs(int cpu) 894 { 895 struct msr_hwp_request req; 896 struct msr_hwp_cap cap; 897 int epb; 898 899 epb = get_epb_sysfs(cpu); 900 if (epb >= 0) 901 printf("cpu%d: EPB %u\n", cpu, (unsigned int) epb); 902 903 if (!has_hwp) 904 return 0; 905 906 read_hwp_request_msr(cpu, &req, MSR_HWP_REQUEST); 907 print_hwp_request(cpu, &req, ""); 908 909 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES); 910 print_hwp_cap(cpu, &cap, ""); 911 912 return 0; 913 } 914 915 int print_pkg_msrs(int pkg) 916 { 917 struct msr_hwp_request req; 918 unsigned long long msr; 919 920 if (!has_hwp) 921 return 0; 922 923 read_hwp_request_msr(first_cpu_in_pkg[pkg], &req, MSR_HWP_REQUEST_PKG); 924 print_hwp_request_pkg(pkg, &req, ""); 925 926 if (has_hwp_notify) { 927 get_msr(first_cpu_in_pkg[pkg], MSR_HWP_INTERRUPT, &msr); 928 fprintf(stderr, 929 "pkg%d: MSR_HWP_INTERRUPT: 0x%08llx (Excursion_Min-%sabled, Guaranteed_Perf_Change-%sabled)\n", 930 pkg, msr, 931 ((msr) & 0x2) ? "EN" : "Dis", 932 ((msr) & 0x1) ? "EN" : "Dis"); 933 } 934 get_msr(first_cpu_in_pkg[pkg], MSR_HWP_STATUS, &msr); 935 fprintf(stderr, 936 "pkg%d: MSR_HWP_STATUS: 0x%08llx (%sExcursion_Min, %sGuaranteed_Perf_Change)\n", 937 pkg, msr, 938 ((msr) & 0x4) ? "" : "No-", 939 ((msr) & 0x1) ? "" : "No-"); 940 941 return 0; 942 } 943 944 /* 945 * Assumption: All HWP systems have 100 MHz bus clock 946 */ 947 int ratio_2_sysfs_khz(int ratio) 948 { 949 int bclk_khz = 100 * 1000; /* 100,000 KHz = 100 MHz */ 950 951 return ratio * bclk_khz; 952 } 953 /* 954 * If HWP is enabled and cpufreq sysfs attribtes are present, 955 * then update via sysfs. The intel_pstate driver may modify (clip) 956 * this request, say, when HWP_CAP is outside of PLATFORM_INFO limits, 957 * and the driver-chosen value takes precidence. 958 * 959 * (intel_pstate's max_perf_pct and min_perf_pct will follow cpufreq, 960 * so we don't have to touch that.) 961 */ 962 void update_cpufreq_scaling_freq(int is_max, int cpu, unsigned int ratio) 963 { 964 char pathname[64]; 965 FILE *fp; 966 int retval; 967 int khz; 968 969 sprintf(pathname, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq", 970 cpu, is_max ? "max" : "min"); 971 972 fp = fopen(pathname, "w"); 973 if (!fp) { 974 if (debug) 975 perror(pathname); 976 return; 977 } 978 979 khz = ratio_2_sysfs_khz(ratio); 980 retval = fprintf(fp, "%d", khz); 981 if (retval < 0) 982 if (debug) 983 perror("fprintf"); 984 if (debug) 985 printf("echo %d > %s\n", khz, pathname); 986 987 fclose(fp); 988 } 989 990 /* 991 * We update all sysfs before updating any MSRs because of 992 * bugs in cpufreq/intel_pstate where the sysfs writes 993 * for a CPU may change the min/max values on other CPUS. 994 */ 995 996 int update_sysfs(int cpu) 997 { 998 if (!has_hwp) 999 return 0; 1000 1001 if (!hwp_update_enabled()) 1002 return 0; 1003 1004 if (access("/sys/devices/system/cpu/cpu0/cpufreq", F_OK)) 1005 return 0; 1006 1007 if (update_hwp_min) 1008 update_cpufreq_scaling_freq(0, cpu, req_update.hwp_min); 1009 1010 if (update_hwp_max) 1011 update_cpufreq_scaling_freq(1, cpu, req_update.hwp_max); 1012 1013 hwp_limits_done_via_sysfs = 1; 1014 1015 return 0; 1016 } 1017 1018 int verify_hwp_req_self_consistency(int cpu, struct msr_hwp_request *req) 1019 { 1020 /* fail if min > max requested */ 1021 if (req->hwp_min > req->hwp_max) { 1022 errx(1, "cpu%d: requested hwp-min %d > hwp_max %d", 1023 cpu, req->hwp_min, req->hwp_max); 1024 } 1025 1026 /* fail if desired > max requestd */ 1027 if (req->hwp_desired && (req->hwp_desired > req->hwp_max)) { 1028 errx(1, "cpu%d: requested hwp-desired %d > hwp_max %d", 1029 cpu, req->hwp_desired, req->hwp_max); 1030 } 1031 /* fail if desired < min requestd */ 1032 if (req->hwp_desired && (req->hwp_desired < req->hwp_min)) { 1033 errx(1, "cpu%d: requested hwp-desired %d < requested hwp_min %d", 1034 cpu, req->hwp_desired, req->hwp_min); 1035 } 1036 1037 return 0; 1038 } 1039 1040 int check_hwp_request_v_hwp_capabilities(int cpu, struct msr_hwp_request *req, struct msr_hwp_cap *cap) 1041 { 1042 if (update_hwp_max) { 1043 if (req->hwp_max > cap->highest) 1044 errx(1, "cpu%d: requested max %d > capabilities highest %d, use --force?", 1045 cpu, req->hwp_max, cap->highest); 1046 if (req->hwp_max < cap->lowest) 1047 errx(1, "cpu%d: requested max %d < capabilities lowest %d, use --force?", 1048 cpu, req->hwp_max, cap->lowest); 1049 } 1050 1051 if (update_hwp_min) { 1052 if (req->hwp_min > cap->highest) 1053 errx(1, "cpu%d: requested min %d > capabilities highest %d, use --force?", 1054 cpu, req->hwp_min, cap->highest); 1055 if (req->hwp_min < cap->lowest) 1056 errx(1, "cpu%d: requested min %d < capabilities lowest %d, use --force?", 1057 cpu, req->hwp_min, cap->lowest); 1058 } 1059 1060 if (update_hwp_min && update_hwp_max && (req->hwp_min > req->hwp_max)) 1061 errx(1, "cpu%d: requested min %d > requested max %d", 1062 cpu, req->hwp_min, req->hwp_max); 1063 1064 if (update_hwp_desired && req->hwp_desired) { 1065 if (req->hwp_desired > req->hwp_max) 1066 errx(1, "cpu%d: requested desired %d > requested max %d, use --force?", 1067 cpu, req->hwp_desired, req->hwp_max); 1068 if (req->hwp_desired < req->hwp_min) 1069 errx(1, "cpu%d: requested desired %d < requested min %d, use --force?", 1070 cpu, req->hwp_desired, req->hwp_min); 1071 if (req->hwp_desired < cap->lowest) 1072 errx(1, "cpu%d: requested desired %d < capabilities lowest %d, use --force?", 1073 cpu, req->hwp_desired, cap->lowest); 1074 if (req->hwp_desired > cap->highest) 1075 errx(1, "cpu%d: requested desired %d > capabilities highest %d, use --force?", 1076 cpu, req->hwp_desired, cap->highest); 1077 } 1078 1079 return 0; 1080 } 1081 1082 int update_hwp_request_msr(int cpu) 1083 { 1084 struct msr_hwp_request req; 1085 struct msr_hwp_cap cap; 1086 1087 int msr_offset = MSR_HWP_REQUEST; 1088 1089 read_hwp_request_msr(cpu, &req, msr_offset); 1090 if (debug) 1091 print_hwp_request(cpu, &req, "old: "); 1092 1093 if (update_hwp_min && !hwp_limits_done_via_sysfs) 1094 req.hwp_min = req_update.hwp_min; 1095 1096 if (update_hwp_max && !hwp_limits_done_via_sysfs) 1097 req.hwp_max = req_update.hwp_max; 1098 1099 if (update_hwp_desired) 1100 req.hwp_desired = req_update.hwp_desired; 1101 1102 if (update_hwp_window) 1103 req.hwp_window = req_update.hwp_window; 1104 1105 if (update_hwp_epp) 1106 req.hwp_epp = req_update.hwp_epp; 1107 1108 req.hwp_use_pkg = req_update.hwp_use_pkg; 1109 1110 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES); 1111 if (debug) 1112 print_hwp_cap(cpu, &cap, ""); 1113 1114 if (!force) 1115 check_hwp_request_v_hwp_capabilities(cpu, &req, &cap); 1116 1117 verify_hwp_req_self_consistency(cpu, &req); 1118 1119 write_hwp_request_msr(cpu, &req, msr_offset); 1120 1121 if (debug) { 1122 read_hwp_request_msr(cpu, &req, msr_offset); 1123 print_hwp_request(cpu, &req, "new: "); 1124 } 1125 return 0; 1126 } 1127 int update_hwp_request_pkg_msr(int pkg) 1128 { 1129 struct msr_hwp_request req; 1130 struct msr_hwp_cap cap; 1131 int cpu = first_cpu_in_pkg[pkg]; 1132 1133 int msr_offset = MSR_HWP_REQUEST_PKG; 1134 1135 read_hwp_request_msr(cpu, &req, msr_offset); 1136 if (debug) 1137 print_hwp_request_pkg(pkg, &req, "old: "); 1138 1139 if (update_hwp_min) 1140 req.hwp_min = req_update.hwp_min; 1141 1142 if (update_hwp_max) 1143 req.hwp_max = req_update.hwp_max; 1144 1145 if (update_hwp_desired) 1146 req.hwp_desired = req_update.hwp_desired; 1147 1148 if (update_hwp_window) 1149 req.hwp_window = req_update.hwp_window; 1150 1151 if (update_hwp_epp) 1152 req.hwp_epp = req_update.hwp_epp; 1153 1154 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES); 1155 if (debug) 1156 print_hwp_cap(cpu, &cap, ""); 1157 1158 if (!force) 1159 check_hwp_request_v_hwp_capabilities(cpu, &req, &cap); 1160 1161 verify_hwp_req_self_consistency(cpu, &req); 1162 1163 write_hwp_request_msr(cpu, &req, msr_offset); 1164 1165 if (debug) { 1166 read_hwp_request_msr(cpu, &req, msr_offset); 1167 print_hwp_request_pkg(pkg, &req, "new: "); 1168 } 1169 return 0; 1170 } 1171 1172 int enable_hwp_on_cpu(int cpu) 1173 { 1174 unsigned long long old_msr, new_msr; 1175 1176 get_msr(cpu, MSR_PM_ENABLE, &old_msr); 1177 1178 if (old_msr & 1) 1179 return 0; /* already enabled */ 1180 1181 new_msr = old_msr | 1; 1182 put_msr(cpu, MSR_PM_ENABLE, new_msr); 1183 1184 if (verbose) 1185 printf("cpu%d: MSR_PM_ENABLE old: %llX new: %llX\n", cpu, old_msr, new_msr); 1186 1187 return 0; 1188 } 1189 1190 int update_cpu_epb_sysfs(int cpu) 1191 { 1192 int epb; 1193 1194 epb = get_epb_sysfs(cpu); 1195 set_epb_sysfs(cpu, new_epb); 1196 1197 if (verbose) 1198 printf("cpu%d: ENERGY_PERF_BIAS old: %d new: %d\n", 1199 cpu, epb, (unsigned int) new_epb); 1200 1201 return 0; 1202 } 1203 1204 int update_cpu_msrs(int cpu) 1205 { 1206 unsigned long long msr; 1207 1208 if (update_turbo) { 1209 int turbo_is_present_and_disabled; 1210 1211 get_msr(cpu, MSR_IA32_MISC_ENABLE, &msr); 1212 1213 turbo_is_present_and_disabled = ((msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE) != 0); 1214 1215 if (turbo_update_value == 1) { 1216 if (turbo_is_present_and_disabled) { 1217 msr &= ~MSR_IA32_MISC_ENABLE_TURBO_DISABLE; 1218 put_msr(cpu, MSR_IA32_MISC_ENABLE, msr); 1219 if (verbose) 1220 printf("cpu%d: turbo ENABLE\n", cpu); 1221 } 1222 } else { 1223 /* 1224 * if "turbo_is_enabled" were known to be describe this cpu 1225 * then we could use it here to skip redundant disable requests. 1226 * but cpu may be in a different package, so we always write. 1227 */ 1228 msr |= MSR_IA32_MISC_ENABLE_TURBO_DISABLE; 1229 put_msr(cpu, MSR_IA32_MISC_ENABLE, msr); 1230 if (verbose) 1231 printf("cpu%d: turbo DISABLE\n", cpu); 1232 } 1233 } 1234 1235 if (!has_hwp) 1236 return 0; 1237 1238 if (!hwp_update_enabled()) 1239 return 0; 1240 1241 update_hwp_request_msr(cpu); 1242 return 0; 1243 } 1244 1245 unsigned int get_pkg_num(int cpu) 1246 { 1247 FILE *fp; 1248 char pathname[128]; 1249 unsigned int pkg; 1250 int retval; 1251 1252 sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu); 1253 1254 fp = fopen_or_die(pathname, "r"); 1255 retval = fscanf(fp, "%d\n", &pkg); 1256 if (retval != 1) 1257 errx(1, "%s: failed to parse", pathname); 1258 fclose(fp); 1259 return pkg; 1260 } 1261 1262 int set_max_cpu_pkg_num(int cpu) 1263 { 1264 unsigned int pkg; 1265 1266 if (max_cpu_num < cpu) 1267 max_cpu_num = cpu; 1268 1269 pkg = get_pkg_num(cpu); 1270 1271 if (pkg >= MAX_PACKAGES) 1272 errx(1, "cpu%d: %d >= MAX_PACKAGES (%d)", cpu, pkg, MAX_PACKAGES); 1273 1274 if (pkg > max_pkg_num) 1275 max_pkg_num = pkg; 1276 1277 if ((pkg_present_set & (1ULL << pkg)) == 0) { 1278 pkg_present_set |= (1ULL << pkg); 1279 first_cpu_in_pkg[pkg] = cpu; 1280 } 1281 1282 return 0; 1283 } 1284 int mark_cpu_present(int cpu) 1285 { 1286 CPU_SET_S(cpu, cpu_setsize, cpu_present_set); 1287 return 0; 1288 } 1289 1290 /* 1291 * run func(cpu) on every cpu in /proc/stat 1292 * return max_cpu number 1293 */ 1294 int for_all_proc_cpus(int (func)(int)) 1295 { 1296 FILE *fp; 1297 int cpu_num; 1298 int retval; 1299 1300 fp = fopen_or_die(proc_stat, "r"); 1301 1302 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); 1303 if (retval != 0) 1304 err(1, "%s: failed to parse format", proc_stat); 1305 1306 while (1) { 1307 retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num); 1308 if (retval != 1) 1309 break; 1310 1311 retval = func(cpu_num); 1312 if (retval) { 1313 fclose(fp); 1314 return retval; 1315 } 1316 } 1317 fclose(fp); 1318 return 0; 1319 } 1320 1321 void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func)(int)) 1322 { 1323 int cpu_num; 1324 1325 for (cpu_num = 0; cpu_num <= max_cpu_num; ++cpu_num) 1326 if (CPU_ISSET_S(cpu_num, set_size, cpu_set)) 1327 func(cpu_num); 1328 } 1329 int for_all_cpus_in_set_and(size_t set_size, cpu_set_t *cpu_set, int (func)(int)) 1330 { 1331 int cpu_num; 1332 int retval = 1; 1333 1334 for (cpu_num = 0; cpu_num <= max_cpu_num; ++cpu_num) 1335 if (CPU_ISSET_S(cpu_num, set_size, cpu_set)) 1336 retval &= func(cpu_num); 1337 1338 return retval; 1339 } 1340 1341 void init_data_structures(void) 1342 { 1343 for_all_proc_cpus(set_max_cpu_pkg_num); 1344 1345 cpu_setsize = CPU_ALLOC_SIZE((max_cpu_num + 1)); 1346 1347 cpu_present_set = CPU_ALLOC((max_cpu_num + 1)); 1348 if (cpu_present_set == NULL) 1349 err(3, "CPU_ALLOC"); 1350 CPU_ZERO_S(cpu_setsize, cpu_present_set); 1351 for_all_proc_cpus(mark_cpu_present); 1352 } 1353 1354 int is_hwp_enabled_on_cpu(int cpu_num) 1355 { 1356 unsigned long long msr; 1357 int retval; 1358 1359 /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */ 1360 get_msr(cpu_num, MSR_PM_ENABLE, &msr); 1361 retval = (msr & 1); 1362 1363 if (verbose) 1364 fprintf(stderr, "cpu%d: %sHWP\n", cpu_num, retval ? "" : "No-"); 1365 1366 return retval; 1367 } 1368 1369 /* 1370 * verify_hwp_is_enabled() 1371 * 1372 * Set (has_hwp=0) if no HWP feature or any of selected CPU set does not have HWP enabled 1373 */ 1374 void verify_hwp_is_enabled(void) 1375 { 1376 int retval; 1377 1378 if (!has_hwp) /* set in early_cpuid() */ 1379 return; 1380 1381 retval = for_all_cpus_in_set_and(cpu_setsize, cpu_selected_set, is_hwp_enabled_on_cpu); 1382 1383 if (retval == 0) { 1384 fprintf(stderr, "HWP can be enabled using '--hwp-enable'\n"); 1385 has_hwp = 0; 1386 } 1387 } 1388 1389 int req_update_bounds_check(void) 1390 { 1391 if (!hwp_update_enabled()) 1392 return 0; 1393 1394 /* fail if min > max requested */ 1395 if ((update_hwp_max && update_hwp_min) && 1396 (req_update.hwp_min > req_update.hwp_max)) { 1397 printf("hwp-min %d > hwp_max %d\n", req_update.hwp_min, req_update.hwp_max); 1398 return -EINVAL; 1399 } 1400 1401 /* fail if desired > max requestd */ 1402 if (req_update.hwp_desired && update_hwp_max && 1403 (req_update.hwp_desired > req_update.hwp_max)) { 1404 printf("hwp-desired cannot be greater than hwp_max\n"); 1405 return -EINVAL; 1406 } 1407 /* fail if desired < min requestd */ 1408 if (req_update.hwp_desired && update_hwp_min && 1409 (req_update.hwp_desired < req_update.hwp_min)) { 1410 printf("hwp-desired cannot be less than hwp_min\n"); 1411 return -EINVAL; 1412 } 1413 1414 return 0; 1415 } 1416 1417 void set_base_cpu(void) 1418 { 1419 base_cpu = sched_getcpu(); 1420 if (base_cpu < 0) 1421 err(-ENODEV, "No valid cpus found"); 1422 } 1423 1424 1425 void probe_dev_msr(void) 1426 { 1427 struct stat sb; 1428 char pathname[32]; 1429 1430 sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); 1431 if (stat(pathname, &sb)) 1432 if (system("/sbin/modprobe msr > /dev/null 2>&1")) 1433 err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" "); 1434 } 1435 1436 static void get_cpuid_or_exit(unsigned int leaf, 1437 unsigned int *eax, unsigned int *ebx, 1438 unsigned int *ecx, unsigned int *edx) 1439 { 1440 if (!__get_cpuid(leaf, eax, ebx, ecx, edx)) 1441 errx(1, "Processor not supported\n"); 1442 } 1443 1444 /* 1445 * early_cpuid() 1446 * initialize turbo_is_enabled, has_hwp, has_epb 1447 * before cmdline is parsed 1448 */ 1449 void early_cpuid(void) 1450 { 1451 unsigned int eax, ebx, ecx, edx; 1452 unsigned int fms, family, model; 1453 1454 get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx); 1455 family = (fms >> 8) & 0xf; 1456 model = (fms >> 4) & 0xf; 1457 if (family == 6 || family == 0xf) 1458 model += ((fms >> 16) & 0xf) << 4; 1459 1460 if (model == 0x4F) { 1461 unsigned long long msr; 1462 1463 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr); 1464 1465 bdx_highest_ratio = msr & 0xFF; 1466 } 1467 1468 get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx); 1469 turbo_is_enabled = (eax >> 1) & 1; 1470 has_hwp = (eax >> 7) & 1; 1471 has_epb = (ecx >> 3) & 1; 1472 } 1473 1474 /* 1475 * parse_cpuid() 1476 * set 1477 * has_hwp, has_hwp_notify, has_hwp_activity_window, has_hwp_epp, has_hwp_request_pkg, has_epb 1478 */ 1479 void parse_cpuid(void) 1480 { 1481 unsigned int eax, ebx, ecx, edx, max_level; 1482 unsigned int fms, family, model, stepping; 1483 1484 eax = ebx = ecx = edx = 0; 1485 1486 get_cpuid_or_exit(0, &max_level, &ebx, &ecx, &edx); 1487 1488 if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) 1489 genuine_intel = 1; 1490 1491 if (debug) 1492 fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", 1493 (char *)&ebx, (char *)&edx, (char *)&ecx); 1494 1495 get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx); 1496 family = (fms >> 8) & 0xf; 1497 model = (fms >> 4) & 0xf; 1498 stepping = fms & 0xf; 1499 if (family == 6 || family == 0xf) 1500 model += ((fms >> 16) & 0xf) << 4; 1501 1502 if (debug) { 1503 fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", 1504 max_level, family, model, stepping, family, model, stepping); 1505 fprintf(stderr, "CPUID(1): %s %s %s %s %s %s %s %s\n", 1506 ecx & (1 << 0) ? "SSE3" : "-", 1507 ecx & (1 << 3) ? "MONITOR" : "-", 1508 ecx & (1 << 7) ? "EIST" : "-", 1509 ecx & (1 << 8) ? "TM2" : "-", 1510 edx & (1 << 4) ? "TSC" : "-", 1511 edx & (1 << 5) ? "MSR" : "-", 1512 edx & (1 << 22) ? "ACPI-TM" : "-", 1513 edx & (1 << 29) ? "TM" : "-"); 1514 } 1515 1516 if (!(edx & (1 << 5))) 1517 errx(1, "CPUID: no MSR"); 1518 1519 1520 get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx); 1521 /* turbo_is_enabled already set */ 1522 /* has_hwp already set */ 1523 has_hwp_notify = eax & (1 << 8); 1524 has_hwp_activity_window = eax & (1 << 9); 1525 has_hwp_epp = eax & (1 << 10); 1526 has_hwp_request_pkg = eax & (1 << 11); 1527 1528 if (!has_hwp_request_pkg && update_hwp_use_pkg) 1529 errx(1, "--hwp-use-pkg is not available on this hardware"); 1530 1531 /* has_epb already set */ 1532 1533 if (debug) 1534 fprintf(stderr, 1535 "CPUID(6): %sTURBO, %sHWP, %sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n", 1536 turbo_is_enabled ? "" : "No-", 1537 has_hwp ? "" : "No-", 1538 has_hwp_notify ? "" : "No-", 1539 has_hwp_activity_window ? "" : "No-", 1540 has_hwp_epp ? "" : "No-", 1541 has_hwp_request_pkg ? "" : "No-", 1542 has_epb ? "" : "No-"); 1543 1544 return; /* success */ 1545 } 1546 1547 int main(int argc, char **argv) 1548 { 1549 set_base_cpu(); 1550 probe_dev_msr(); 1551 init_data_structures(); 1552 1553 early_cpuid(); /* initial cpuid parse before cmdline */ 1554 1555 cmdline(argc, argv); 1556 1557 if (debug) 1558 print_version(); 1559 1560 parse_cpuid(); 1561 1562 /* If CPU-set and PKG-set are not initialized, default to all CPUs */ 1563 if ((cpu_selected_set == 0) && (pkg_selected_set == 0)) 1564 cpu_selected_set = cpu_present_set; 1565 1566 /* 1567 * If HWP is being enabled, do it now, so that subsequent operations 1568 * that access HWP registers can work. 1569 */ 1570 if (update_hwp_enable) 1571 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, enable_hwp_on_cpu); 1572 1573 /* If HWP present, but disabled, warn and ignore from here forward */ 1574 verify_hwp_is_enabled(); 1575 1576 if (req_update_bounds_check()) 1577 return -EINVAL; 1578 1579 /* display information only, no updates to settings */ 1580 if (!update_epb && !update_turbo && !hwp_update_enabled()) { 1581 if (cpu_selected_set) 1582 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, print_cpu_msrs); 1583 1584 if (has_hwp_request_pkg) { 1585 if (pkg_selected_set == 0) 1586 pkg_selected_set = pkg_present_set; 1587 1588 for_packages(pkg_selected_set, print_pkg_msrs); 1589 } 1590 1591 return 0; 1592 } 1593 1594 /* update CPU set */ 1595 if (cpu_selected_set) { 1596 if (update_epb) 1597 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_epb_sysfs); 1598 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_sysfs); 1599 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_msrs); 1600 1601 } else if (pkg_selected_set) 1602 for_packages(pkg_selected_set, update_hwp_request_pkg_msr); 1603 1604 return 0; 1605 } 1606