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