x86_energy_perf_policy.c (36737B)
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 36struct msr_hwp_cap { 37 unsigned char highest; 38 unsigned char guaranteed; 39 unsigned char efficient; 40 unsigned char lowest; 41}; 42 43struct 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 52unsigned int debug; 53unsigned int verbose; 54unsigned int force; 55char *progname; 56int base_cpu; 57unsigned char update_epb; 58unsigned long long new_epb; 59unsigned char turbo_is_enabled; 60unsigned char update_turbo; 61unsigned char turbo_update_value; 62unsigned char update_hwp_epp; 63unsigned char update_hwp_min; 64unsigned char update_hwp_max; 65unsigned char update_hwp_desired; 66unsigned char update_hwp_window; 67unsigned char update_hwp_use_pkg; 68unsigned 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) 70int max_cpu_num; 71int max_pkg_num; 72#define MAX_PACKAGES 64 73unsigned int first_cpu_in_pkg[MAX_PACKAGES]; 74unsigned long long pkg_present_set; 75unsigned long long pkg_selected_set; 76cpu_set_t *cpu_present_set; 77cpu_set_t *cpu_selected_set; 78int genuine_intel; 79 80size_t cpu_setsize; 81 82char *proc_stat = "/proc/stat"; 83 84unsigned int has_epb; /* MSR_IA32_ENERGY_PERF_BIAS */ 85unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ 86 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */ 87unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */ 88unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */ 89unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ 90unsigned int has_hwp_request_pkg; /* IA32_HWP_REQUEST_PKG */ 91 92unsigned 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 */ 100void 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 */ 121int 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} 135int 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} 152int 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 */ 183int 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 */ 202int 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 */ 221int 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 236int 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} 268int 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} 289int 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 309int 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 348void 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 362void 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 376void 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 459void 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 508void 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 518void print_version(void) 519{ 520 printf("x86_energy_perf_policy 17.05.11 (C) Len Brown <len.brown@intel.com>\n"); 521} 522 523void 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 */ 631FILE *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 640void 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 680int 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 704int 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 727static 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 748static 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 769void 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} 777void 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 789void 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} 801void 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} 812void 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 826void 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 846static 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 868static 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 892int 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 914int 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 */ 946int 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 */ 959void 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 993int 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 1013int 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 1035int 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 1077int 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} 1122int 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 1167int 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 1180int 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 1231unsigned 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 return pkg; 1245} 1246 1247int set_max_cpu_pkg_num(int cpu) 1248{ 1249 unsigned int pkg; 1250 1251 if (max_cpu_num < cpu) 1252 max_cpu_num = cpu; 1253 1254 pkg = get_pkg_num(cpu); 1255 1256 if (pkg >= MAX_PACKAGES) 1257 errx(1, "cpu%d: %d >= MAX_PACKAGES (%d)", cpu, pkg, MAX_PACKAGES); 1258 1259 if (pkg > max_pkg_num) 1260 max_pkg_num = pkg; 1261 1262 if ((pkg_present_set & (1ULL << pkg)) == 0) { 1263 pkg_present_set |= (1ULL << pkg); 1264 first_cpu_in_pkg[pkg] = cpu; 1265 } 1266 1267 return 0; 1268} 1269int mark_cpu_present(int cpu) 1270{ 1271 CPU_SET_S(cpu, cpu_setsize, cpu_present_set); 1272 return 0; 1273} 1274 1275/* 1276 * run func(cpu) on every cpu in /proc/stat 1277 * return max_cpu number 1278 */ 1279int for_all_proc_cpus(int (func)(int)) 1280{ 1281 FILE *fp; 1282 int cpu_num; 1283 int retval; 1284 1285 fp = fopen_or_die(proc_stat, "r"); 1286 1287 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); 1288 if (retval != 0) 1289 err(1, "%s: failed to parse format", proc_stat); 1290 1291 while (1) { 1292 retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num); 1293 if (retval != 1) 1294 break; 1295 1296 retval = func(cpu_num); 1297 if (retval) { 1298 fclose(fp); 1299 return retval; 1300 } 1301 } 1302 fclose(fp); 1303 return 0; 1304} 1305 1306void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func)(int)) 1307{ 1308 int cpu_num; 1309 1310 for (cpu_num = 0; cpu_num <= max_cpu_num; ++cpu_num) 1311 if (CPU_ISSET_S(cpu_num, set_size, cpu_set)) 1312 func(cpu_num); 1313} 1314 1315void init_data_structures(void) 1316{ 1317 for_all_proc_cpus(set_max_cpu_pkg_num); 1318 1319 cpu_setsize = CPU_ALLOC_SIZE((max_cpu_num + 1)); 1320 1321 cpu_present_set = CPU_ALLOC((max_cpu_num + 1)); 1322 if (cpu_present_set == NULL) 1323 err(3, "CPU_ALLOC"); 1324 CPU_ZERO_S(cpu_setsize, cpu_present_set); 1325 for_all_proc_cpus(mark_cpu_present); 1326} 1327 1328/* clear has_hwp if it is not enable (or being enabled) */ 1329 1330void verify_hwp_is_enabled(void) 1331{ 1332 unsigned long long msr; 1333 1334 if (!has_hwp) /* set in early_cpuid() */ 1335 return; 1336 1337 /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */ 1338 get_msr(base_cpu, MSR_PM_ENABLE, &msr); 1339 if ((msr & 1) == 0) { 1340 fprintf(stderr, "HWP can be enabled using '--hwp-enable'\n"); 1341 has_hwp = 0; 1342 return; 1343 } 1344} 1345 1346int req_update_bounds_check(void) 1347{ 1348 if (!hwp_update_enabled()) 1349 return 0; 1350 1351 /* fail if min > max requested */ 1352 if ((update_hwp_max && update_hwp_min) && 1353 (req_update.hwp_min > req_update.hwp_max)) { 1354 printf("hwp-min %d > hwp_max %d\n", req_update.hwp_min, req_update.hwp_max); 1355 return -EINVAL; 1356 } 1357 1358 /* fail if desired > max requestd */ 1359 if (req_update.hwp_desired && update_hwp_max && 1360 (req_update.hwp_desired > req_update.hwp_max)) { 1361 printf("hwp-desired cannot be greater than hwp_max\n"); 1362 return -EINVAL; 1363 } 1364 /* fail if desired < min requestd */ 1365 if (req_update.hwp_desired && update_hwp_min && 1366 (req_update.hwp_desired < req_update.hwp_min)) { 1367 printf("hwp-desired cannot be less than hwp_min\n"); 1368 return -EINVAL; 1369 } 1370 1371 return 0; 1372} 1373 1374void set_base_cpu(void) 1375{ 1376 base_cpu = sched_getcpu(); 1377 if (base_cpu < 0) 1378 err(-ENODEV, "No valid cpus found"); 1379} 1380 1381 1382void probe_dev_msr(void) 1383{ 1384 struct stat sb; 1385 char pathname[32]; 1386 1387 sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); 1388 if (stat(pathname, &sb)) 1389 if (system("/sbin/modprobe msr > /dev/null 2>&1")) 1390 err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" "); 1391} 1392 1393static void get_cpuid_or_exit(unsigned int leaf, 1394 unsigned int *eax, unsigned int *ebx, 1395 unsigned int *ecx, unsigned int *edx) 1396{ 1397 if (!__get_cpuid(leaf, eax, ebx, ecx, edx)) 1398 errx(1, "Processor not supported\n"); 1399} 1400 1401/* 1402 * early_cpuid() 1403 * initialize turbo_is_enabled, has_hwp, has_epb 1404 * before cmdline is parsed 1405 */ 1406void early_cpuid(void) 1407{ 1408 unsigned int eax, ebx, ecx, edx; 1409 unsigned int fms, family, model; 1410 1411 get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx); 1412 family = (fms >> 8) & 0xf; 1413 model = (fms >> 4) & 0xf; 1414 if (family == 6 || family == 0xf) 1415 model += ((fms >> 16) & 0xf) << 4; 1416 1417 if (model == 0x4F) { 1418 unsigned long long msr; 1419 1420 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr); 1421 1422 bdx_highest_ratio = msr & 0xFF; 1423 } 1424 1425 get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx); 1426 turbo_is_enabled = (eax >> 1) & 1; 1427 has_hwp = (eax >> 7) & 1; 1428 has_epb = (ecx >> 3) & 1; 1429} 1430 1431/* 1432 * parse_cpuid() 1433 * set 1434 * has_hwp, has_hwp_notify, has_hwp_activity_window, has_hwp_epp, has_hwp_request_pkg, has_epb 1435 */ 1436void parse_cpuid(void) 1437{ 1438 unsigned int eax, ebx, ecx, edx, max_level; 1439 unsigned int fms, family, model, stepping; 1440 1441 eax = ebx = ecx = edx = 0; 1442 1443 get_cpuid_or_exit(0, &max_level, &ebx, &ecx, &edx); 1444 1445 if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) 1446 genuine_intel = 1; 1447 1448 if (debug) 1449 fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", 1450 (char *)&ebx, (char *)&edx, (char *)&ecx); 1451 1452 get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx); 1453 family = (fms >> 8) & 0xf; 1454 model = (fms >> 4) & 0xf; 1455 stepping = fms & 0xf; 1456 if (family == 6 || family == 0xf) 1457 model += ((fms >> 16) & 0xf) << 4; 1458 1459 if (debug) { 1460 fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", 1461 max_level, family, model, stepping, family, model, stepping); 1462 fprintf(stderr, "CPUID(1): %s %s %s %s %s %s %s %s\n", 1463 ecx & (1 << 0) ? "SSE3" : "-", 1464 ecx & (1 << 3) ? "MONITOR" : "-", 1465 ecx & (1 << 7) ? "EIST" : "-", 1466 ecx & (1 << 8) ? "TM2" : "-", 1467 edx & (1 << 4) ? "TSC" : "-", 1468 edx & (1 << 5) ? "MSR" : "-", 1469 edx & (1 << 22) ? "ACPI-TM" : "-", 1470 edx & (1 << 29) ? "TM" : "-"); 1471 } 1472 1473 if (!(edx & (1 << 5))) 1474 errx(1, "CPUID: no MSR"); 1475 1476 1477 get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx); 1478 /* turbo_is_enabled already set */ 1479 /* has_hwp already set */ 1480 has_hwp_notify = eax & (1 << 8); 1481 has_hwp_activity_window = eax & (1 << 9); 1482 has_hwp_epp = eax & (1 << 10); 1483 has_hwp_request_pkg = eax & (1 << 11); 1484 1485 if (!has_hwp_request_pkg && update_hwp_use_pkg) 1486 errx(1, "--hwp-use-pkg is not available on this hardware"); 1487 1488 /* has_epb already set */ 1489 1490 if (debug) 1491 fprintf(stderr, 1492 "CPUID(6): %sTURBO, %sHWP, %sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n", 1493 turbo_is_enabled ? "" : "No-", 1494 has_hwp ? "" : "No-", 1495 has_hwp_notify ? "" : "No-", 1496 has_hwp_activity_window ? "" : "No-", 1497 has_hwp_epp ? "" : "No-", 1498 has_hwp_request_pkg ? "" : "No-", 1499 has_epb ? "" : "No-"); 1500 1501 return; /* success */ 1502} 1503 1504int main(int argc, char **argv) 1505{ 1506 set_base_cpu(); 1507 probe_dev_msr(); 1508 init_data_structures(); 1509 1510 early_cpuid(); /* initial cpuid parse before cmdline */ 1511 1512 cmdline(argc, argv); 1513 1514 if (debug) 1515 print_version(); 1516 1517 parse_cpuid(); 1518 1519 /* If CPU-set and PKG-set are not initialized, default to all CPUs */ 1520 if ((cpu_selected_set == 0) && (pkg_selected_set == 0)) 1521 cpu_selected_set = cpu_present_set; 1522 1523 /* 1524 * If HWP is being enabled, do it now, so that subsequent operations 1525 * that access HWP registers can work. 1526 */ 1527 if (update_hwp_enable) 1528 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, enable_hwp_on_cpu); 1529 1530 /* If HWP present, but disabled, warn and ignore from here forward */ 1531 verify_hwp_is_enabled(); 1532 1533 if (req_update_bounds_check()) 1534 return -EINVAL; 1535 1536 /* display information only, no updates to settings */ 1537 if (!update_epb && !update_turbo && !hwp_update_enabled()) { 1538 if (cpu_selected_set) 1539 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, print_cpu_msrs); 1540 1541 if (has_hwp_request_pkg) { 1542 if (pkg_selected_set == 0) 1543 pkg_selected_set = pkg_present_set; 1544 1545 for_packages(pkg_selected_set, print_pkg_msrs); 1546 } 1547 1548 return 0; 1549 } 1550 1551 /* update CPU set */ 1552 if (cpu_selected_set) { 1553 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_sysfs); 1554 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_msrs); 1555 } else if (pkg_selected_set) 1556 for_packages(pkg_selected_set, update_hwp_request_pkg); 1557 1558 return 0; 1559}