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