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