linux/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
<<
>>
Prefs
   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}
1560