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