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