Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * x86_energy_perf_policy -- set the energy versus performance
0004  * policy preference bias on recent X86 processors.
0005  */
0006 /*
0007  * Copyright (c) 2010 - 2017 Intel Corporation.
0008  * Len Brown <len.brown@intel.com>
0009  */
0010 
0011 #define _GNU_SOURCE
0012 #include MSRHEADER
0013 #include <stdio.h>
0014 #include <unistd.h>
0015 #include <sys/types.h>
0016 #include <sched.h>
0017 #include <sys/stat.h>
0018 #include <sys/resource.h>
0019 #include <getopt.h>
0020 #include <err.h>
0021 #include <fcntl.h>
0022 #include <signal.h>
0023 #include <sys/time.h>
0024 #include <limits.h>
0025 #include <stdlib.h>
0026 #include <string.h>
0027 #include <cpuid.h>
0028 #include <errno.h>
0029 
0030 #define OPTARG_NORMAL           (INT_MAX - 1)
0031 #define OPTARG_POWER            (INT_MAX - 2)
0032 #define OPTARG_BALANCE_POWER        (INT_MAX - 3)
0033 #define OPTARG_BALANCE_PERFORMANCE  (INT_MAX - 4)
0034 #define OPTARG_PERFORMANCE      (INT_MAX - 5)
0035 
0036 struct msr_hwp_cap {
0037     unsigned char highest;
0038     unsigned char guaranteed;
0039     unsigned char efficient;
0040     unsigned char lowest;
0041 };
0042 
0043 struct msr_hwp_request {
0044     unsigned char hwp_min;
0045     unsigned char hwp_max;
0046     unsigned char hwp_desired;
0047     unsigned char hwp_epp;
0048     unsigned int hwp_window;
0049     unsigned char hwp_use_pkg;
0050 } req_update;
0051 
0052 unsigned int debug;
0053 unsigned int verbose;
0054 unsigned int force;
0055 char *progname;
0056 int base_cpu;
0057 unsigned char update_epb;
0058 unsigned long long new_epb;
0059 unsigned char turbo_is_enabled;
0060 unsigned char update_turbo;
0061 unsigned char turbo_update_value;
0062 unsigned char update_hwp_epp;
0063 unsigned char update_hwp_min;
0064 unsigned char update_hwp_max;
0065 unsigned char update_hwp_desired;
0066 unsigned char update_hwp_window;
0067 unsigned char update_hwp_use_pkg;
0068 unsigned char update_hwp_enable;
0069 #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)
0070 int max_cpu_num;
0071 int max_pkg_num;
0072 #define MAX_PACKAGES 64
0073 unsigned int first_cpu_in_pkg[MAX_PACKAGES];
0074 unsigned long long pkg_present_set;
0075 unsigned long long pkg_selected_set;
0076 cpu_set_t *cpu_present_set;
0077 cpu_set_t *cpu_selected_set;
0078 int genuine_intel;
0079 
0080 size_t cpu_setsize;
0081 
0082 char *proc_stat = "/proc/stat";
0083 
0084 unsigned int has_epb;   /* MSR_IA32_ENERGY_PERF_BIAS */
0085 unsigned int has_hwp;   /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
0086             /* IA32_HWP_REQUEST, IA32_HWP_STATUS */
0087 unsigned int has_hwp_notify;        /* IA32_HWP_INTERRUPT */
0088 unsigned int has_hwp_activity_window;   /* IA32_HWP_REQUEST[bits 41:32] */
0089 unsigned int has_hwp_epp;   /* IA32_HWP_REQUEST[bits 31:24] */
0090 unsigned int has_hwp_request_pkg;   /* IA32_HWP_REQUEST_PKG */
0091 
0092 unsigned int bdx_highest_ratio;
0093 
0094 #define PATH_TO_CPU "/sys/devices/system/cpu/"
0095 #define SYSFS_PATH_MAX 255
0096 
0097 /*
0098  * maintain compatibility with original implementation, but don't document it:
0099  */
0100 void usage(void)
0101 {
0102     fprintf(stderr, "%s [options] [scope][field value]\n", progname);
0103     fprintf(stderr, "scope: --cpu cpu-list [--hwp-use-pkg #] | --pkg pkg-list\n");
0104     fprintf(stderr, "field: --all | --epb | --hwp-epp | --hwp-min | --hwp-max | --hwp-desired\n");
0105     fprintf(stderr, "other: --hwp-enable | --turbo-enable (0 | 1) | --help | --force\n");
0106     fprintf(stderr,
0107         "value: ( # | \"normal\" | \"performance\" | \"balance-performance\" | \"balance-power\"| \"power\")\n");
0108     fprintf(stderr, "--hwp-window usec\n");
0109 
0110     fprintf(stderr, "Specify only Energy Performance BIAS (legacy usage):\n");
0111     fprintf(stderr, "%s: [-c cpu] [-v] (-r | policy-value )\n", progname);
0112 
0113     exit(1);
0114 }
0115 
0116 /*
0117  * If bdx_highest_ratio is set,
0118  * then we must translate between MSR format and simple ratio
0119  * used on the cmdline.
0120  */
0121 int ratio_2_msr_perf(int ratio)
0122 {
0123     int msr_perf;
0124 
0125     if (!bdx_highest_ratio)
0126         return ratio;
0127 
0128     msr_perf = ratio * 255 / bdx_highest_ratio;
0129 
0130     if (debug)
0131         fprintf(stderr, "%d = ratio_to_msr_perf(%d)\n", msr_perf, ratio);
0132 
0133     return msr_perf;
0134 }
0135 int msr_perf_2_ratio(int msr_perf)
0136 {
0137     int ratio;
0138     double d;
0139 
0140     if (!bdx_highest_ratio)
0141         return msr_perf;
0142 
0143     d = (double)msr_perf * (double) bdx_highest_ratio / 255.0;
0144     d = d + 0.5;    /* round */
0145     ratio = (int)d;
0146 
0147     if (debug)
0148         fprintf(stderr, "%d = msr_perf_ratio(%d) {%f}\n", ratio, msr_perf, d);
0149 
0150     return ratio;
0151 }
0152 int parse_cmdline_epb(int i)
0153 {
0154     if (!has_epb)
0155         errx(1, "EPB not enabled on this platform");
0156 
0157     update_epb = 1;
0158 
0159     switch (i) {
0160     case OPTARG_POWER:
0161         return ENERGY_PERF_BIAS_POWERSAVE;
0162     case OPTARG_BALANCE_POWER:
0163         return ENERGY_PERF_BIAS_BALANCE_POWERSAVE;
0164     case OPTARG_NORMAL:
0165         return ENERGY_PERF_BIAS_NORMAL;
0166     case OPTARG_BALANCE_PERFORMANCE:
0167         return ENERGY_PERF_BIAS_BALANCE_PERFORMANCE;
0168     case OPTARG_PERFORMANCE:
0169         return ENERGY_PERF_BIAS_PERFORMANCE;
0170     }
0171     if (i < 0 || i > ENERGY_PERF_BIAS_POWERSAVE)
0172         errx(1, "--epb must be from 0 to 15");
0173     return i;
0174 }
0175 
0176 #define HWP_CAP_LOWEST 0
0177 #define HWP_CAP_HIGHEST 255
0178 
0179 /*
0180  * "performance" changes hwp_min to cap.highest
0181  * All others leave it at cap.lowest
0182  */
0183 int parse_cmdline_hwp_min(int i)
0184 {
0185     update_hwp_min = 1;
0186 
0187     switch (i) {
0188     case OPTARG_POWER:
0189     case OPTARG_BALANCE_POWER:
0190     case OPTARG_NORMAL:
0191     case OPTARG_BALANCE_PERFORMANCE:
0192         return HWP_CAP_LOWEST;
0193     case OPTARG_PERFORMANCE:
0194         return HWP_CAP_HIGHEST;
0195     }
0196     return i;
0197 }
0198 /*
0199  * "power" changes hwp_max to cap.lowest
0200  * All others leave it at cap.highest
0201  */
0202 int parse_cmdline_hwp_max(int i)
0203 {
0204     update_hwp_max = 1;
0205 
0206     switch (i) {
0207     case OPTARG_POWER:
0208         return HWP_CAP_LOWEST;
0209     case OPTARG_NORMAL:
0210     case OPTARG_BALANCE_POWER:
0211     case OPTARG_BALANCE_PERFORMANCE:
0212     case OPTARG_PERFORMANCE:
0213         return HWP_CAP_HIGHEST;
0214     }
0215     return i;
0216 }
0217 /*
0218  * for --hwp-des, all strings leave it in autonomous mode
0219  * If you want to change it, you need to explicitly pick a value
0220  */
0221 int parse_cmdline_hwp_desired(int i)
0222 {
0223     update_hwp_desired = 1;
0224 
0225     switch (i) {
0226     case OPTARG_POWER:
0227     case OPTARG_BALANCE_POWER:
0228     case OPTARG_BALANCE_PERFORMANCE:
0229     case OPTARG_NORMAL:
0230     case OPTARG_PERFORMANCE:
0231         return 0;   /* autonomous */
0232     }
0233     return i;
0234 }
0235 
0236 int parse_cmdline_hwp_window(int i)
0237 {
0238     unsigned int exponent;
0239 
0240     update_hwp_window = 1;
0241 
0242     switch (i) {
0243     case OPTARG_POWER:
0244     case OPTARG_BALANCE_POWER:
0245     case OPTARG_NORMAL:
0246     case OPTARG_BALANCE_PERFORMANCE:
0247     case OPTARG_PERFORMANCE:
0248         return 0;
0249     }
0250     if (i < 0 || i > 1270000000) {
0251         fprintf(stderr, "--hwp-window: 0 for auto; 1 - 1270000000 usec for window duration\n");
0252         usage();
0253     }
0254     for (exponent = 0; ; ++exponent) {
0255         if (debug)
0256             printf("%d 10^%d\n", i, exponent);
0257 
0258         if (i <= 127)
0259             break;
0260 
0261         i = i / 10;
0262     }
0263     if (debug)
0264         fprintf(stderr, "%d*10^%d: 0x%x\n", i, exponent, (exponent << 7) | i);
0265 
0266     return (exponent << 7) | i;
0267 }
0268 int parse_cmdline_hwp_epp(int i)
0269 {
0270     update_hwp_epp = 1;
0271 
0272     switch (i) {
0273     case OPTARG_POWER:
0274         return HWP_EPP_POWERSAVE;
0275     case OPTARG_BALANCE_POWER:
0276         return HWP_EPP_BALANCE_POWERSAVE;
0277     case OPTARG_NORMAL:
0278     case OPTARG_BALANCE_PERFORMANCE:
0279         return HWP_EPP_BALANCE_PERFORMANCE;
0280     case OPTARG_PERFORMANCE:
0281         return HWP_EPP_PERFORMANCE;
0282     }
0283     if (i < 0 || i > 0xff) {
0284         fprintf(stderr, "--hwp-epp must be from 0 to 0xff\n");
0285         usage();
0286     }
0287     return i;
0288 }
0289 int parse_cmdline_turbo(int i)
0290 {
0291     update_turbo = 1;
0292 
0293     switch (i) {
0294     case OPTARG_POWER:
0295         return 0;
0296     case OPTARG_NORMAL:
0297     case OPTARG_BALANCE_POWER:
0298     case OPTARG_BALANCE_PERFORMANCE:
0299     case OPTARG_PERFORMANCE:
0300         return 1;
0301     }
0302     if (i < 0 || i > 1) {
0303         fprintf(stderr, "--turbo-enable: 1 to enable, 0 to disable\n");
0304         usage();
0305     }
0306     return i;
0307 }
0308 
0309 int parse_optarg_string(char *s)
0310 {
0311     int i;
0312     char *endptr;
0313 
0314     if (!strncmp(s, "default", 7))
0315         return OPTARG_NORMAL;
0316 
0317     if (!strncmp(s, "normal", 6))
0318         return OPTARG_NORMAL;
0319 
0320     if (!strncmp(s, "power", 9))
0321         return OPTARG_POWER;
0322 
0323     if (!strncmp(s, "balance-power", 17))
0324         return OPTARG_BALANCE_POWER;
0325 
0326     if (!strncmp(s, "balance-performance", 19))
0327         return OPTARG_BALANCE_PERFORMANCE;
0328 
0329     if (!strncmp(s, "performance", 11))
0330         return OPTARG_PERFORMANCE;
0331 
0332     i = strtol(s, &endptr, 0);
0333     if (s == endptr) {
0334         fprintf(stderr, "no digits in \"%s\"\n", s);
0335         usage();
0336     }
0337     if (i == LONG_MIN || i == LONG_MAX)
0338         errx(-1, "%s", s);
0339 
0340     if (i > 0xFF)
0341         errx(-1, "%d (0x%x) must be < 256", i, i);
0342 
0343     if (i < 0)
0344         errx(-1, "%d (0x%x) must be >= 0", i, i);
0345     return i;
0346 }
0347 
0348 void parse_cmdline_all(char *s)
0349 {
0350     force++;
0351     update_hwp_enable = 1;
0352     req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(s));
0353     req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(s));
0354     req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(s));
0355     if (has_epb)
0356         new_epb = parse_cmdline_epb(parse_optarg_string(s));
0357     turbo_update_value = parse_cmdline_turbo(parse_optarg_string(s));
0358     req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(s));
0359     req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(s));
0360 }
0361 
0362 void validate_cpu_selected_set(void)
0363 {
0364     int cpu;
0365 
0366     if (CPU_COUNT_S(cpu_setsize, cpu_selected_set) == 0)
0367         errx(0, "no CPUs requested");
0368 
0369     for (cpu = 0; cpu <= max_cpu_num; ++cpu) {
0370         if (CPU_ISSET_S(cpu, cpu_setsize, cpu_selected_set))
0371             if (!CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
0372                 errx(1, "Requested cpu% is not present", cpu);
0373     }
0374 }
0375 
0376 void parse_cmdline_cpu(char *s)
0377 {
0378     char *startp, *endp;
0379     int cpu = 0;
0380 
0381     if (pkg_selected_set) {
0382         usage();
0383         errx(1, "--cpu | --pkg");
0384     }
0385     cpu_selected_set = CPU_ALLOC((max_cpu_num + 1));
0386     if (cpu_selected_set == NULL)
0387         err(1, "cpu_selected_set");
0388     CPU_ZERO_S(cpu_setsize, cpu_selected_set);
0389 
0390     for (startp = s; startp && *startp;) {
0391 
0392         if (*startp == ',') {
0393             startp++;
0394             continue;
0395         }
0396 
0397         if (*startp == '-') {
0398             int end_cpu;
0399 
0400             startp++;
0401             end_cpu = strtol(startp, &endp, 10);
0402             if (startp == endp)
0403                 continue;
0404 
0405             while (cpu <= end_cpu) {
0406                 if (cpu > max_cpu_num)
0407                     errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num);
0408                 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
0409                 cpu++;
0410             }
0411             startp = endp;
0412             continue;
0413         }
0414 
0415         if (strncmp(startp, "all", 3) == 0) {
0416             for (cpu = 0; cpu <= max_cpu_num; cpu += 1) {
0417                 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
0418                     CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
0419             }
0420             startp += 3;
0421             if (*startp == 0)
0422                 break;
0423         }
0424         /* "--cpu even" is not documented */
0425         if (strncmp(startp, "even", 4) == 0) {
0426             for (cpu = 0; cpu <= max_cpu_num; cpu += 2) {
0427                 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
0428                     CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
0429             }
0430             startp += 4;
0431             if (*startp == 0)
0432                 break;
0433         }
0434 
0435         /* "--cpu odd" is not documented */
0436         if (strncmp(startp, "odd", 3) == 0) {
0437             for (cpu = 1; cpu <= max_cpu_num; cpu += 2) {
0438                 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
0439                     CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
0440             }
0441             startp += 3;
0442             if (*startp == 0)
0443                 break;
0444         }
0445 
0446         cpu = strtol(startp, &endp, 10);
0447         if (startp == endp)
0448             errx(1, "--cpu cpu-set: confused by '%s'", startp);
0449         if (cpu > max_cpu_num)
0450             errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num);
0451         CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
0452         startp = endp;
0453     }
0454 
0455     validate_cpu_selected_set();
0456 
0457 }
0458 
0459 void parse_cmdline_pkg(char *s)
0460 {
0461     char *startp, *endp;
0462     int pkg = 0;
0463 
0464     if (cpu_selected_set) {
0465         usage();
0466         errx(1, "--pkg | --cpu");
0467     }
0468     pkg_selected_set = 0;
0469 
0470     for (startp = s; startp && *startp;) {
0471 
0472         if (*startp == ',') {
0473             startp++;
0474             continue;
0475         }
0476 
0477         if (*startp == '-') {
0478             int end_pkg;
0479 
0480             startp++;
0481             end_pkg = strtol(startp, &endp, 10);
0482             if (startp == endp)
0483                 continue;
0484 
0485             while (pkg <= end_pkg) {
0486                 if (pkg > max_pkg_num)
0487                     errx(1, "Requested pkg%d exceeds max pkg%d", pkg, max_pkg_num);
0488                 pkg_selected_set |= 1 << pkg;
0489                 pkg++;
0490             }
0491             startp = endp;
0492             continue;
0493         }
0494 
0495         if (strncmp(startp, "all", 3) == 0) {
0496             pkg_selected_set = pkg_present_set;
0497             return;
0498         }
0499 
0500         pkg = strtol(startp, &endp, 10);
0501         if (pkg > max_pkg_num)
0502             errx(1, "Requested pkg%d Exceeds max pkg%d", pkg, max_pkg_num);
0503         pkg_selected_set |= 1 << pkg;
0504         startp = endp;
0505     }
0506 }
0507 
0508 void for_packages(unsigned long long pkg_set, int (func)(int))
0509 {
0510     int pkg_num;
0511 
0512     for (pkg_num = 0; pkg_num <= max_pkg_num; ++pkg_num) {
0513         if (pkg_set & (1UL << pkg_num))
0514             func(pkg_num);
0515     }
0516 }
0517 
0518 void print_version(void)
0519 {
0520     printf("x86_energy_perf_policy 17.05.11 (C) Len Brown <len.brown@intel.com>\n");
0521 }
0522 
0523 void cmdline(int argc, char **argv)
0524 {
0525     int opt;
0526     int option_index = 0;
0527 
0528     static struct option long_options[] = {
0529         {"all",     required_argument,  0, 'a'},
0530         {"cpu",     required_argument,  0, 'c'},
0531         {"pkg",     required_argument,  0, 'p'},
0532         {"debug",   no_argument,        0, 'd'},
0533         {"hwp-desired", required_argument,  0, 'D'},
0534         {"epb", required_argument,  0, 'B'},
0535         {"force",   no_argument,    0, 'f'},
0536         {"hwp-enable",  no_argument,    0, 'e'},
0537         {"help",    no_argument,    0, 'h'},
0538         {"hwp-epp", required_argument,  0, 'P'},
0539         {"hwp-min", required_argument,  0, 'm'},
0540         {"hwp-max", required_argument,  0, 'M'},
0541         {"read",    no_argument,        0, 'r'},
0542         {"turbo-enable",    required_argument,  0, 't'},
0543         {"hwp-use-pkg", required_argument,  0, 'u'},
0544         {"version", no_argument,        0, 'v'},
0545         {"hwp-window",  required_argument,  0, 'w'},
0546         {0,     0,          0, 0 }
0547     };
0548 
0549     progname = argv[0];
0550 
0551     while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw:",
0552                 long_options, &option_index)) != -1) {
0553         switch (opt) {
0554         case 'a':
0555             parse_cmdline_all(optarg);
0556             break;
0557         case 'B':
0558             new_epb = parse_cmdline_epb(parse_optarg_string(optarg));
0559             break;
0560         case 'c':
0561             parse_cmdline_cpu(optarg);
0562             break;
0563         case 'e':
0564             update_hwp_enable = 1;
0565             break;
0566         case 'h':
0567             usage();
0568             break;
0569         case 'd':
0570             debug++;
0571             verbose++;
0572             break;
0573         case 'f':
0574             force++;
0575             break;
0576         case 'D':
0577             req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(optarg));
0578             break;
0579         case 'm':
0580             req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(optarg));
0581             break;
0582         case 'M':
0583             req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(optarg));
0584             break;
0585         case 'p':
0586             parse_cmdline_pkg(optarg);
0587             break;
0588         case 'P':
0589             req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(optarg));
0590             break;
0591         case 'r':
0592             /* v1 used -r to specify read-only mode, now the default */
0593             break;
0594         case 't':
0595             turbo_update_value = parse_cmdline_turbo(parse_optarg_string(optarg));
0596             break;
0597         case 'u':
0598             update_hwp_use_pkg++;
0599             if (atoi(optarg) == 0)
0600                 req_update.hwp_use_pkg = 0;
0601             else
0602                 req_update.hwp_use_pkg = 1;
0603             break;
0604         case 'v':
0605             print_version();
0606             exit(0);
0607             break;
0608         case 'w':
0609             req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(optarg));
0610             break;
0611         default:
0612             usage();
0613         }
0614     }
0615     /*
0616      * v1 allowed "performance"|"normal"|"power" with no policy specifier
0617      * to update BIAS.  Continue to support that, even though no longer documented.
0618      */
0619     if (argc == optind + 1)
0620         new_epb = parse_cmdline_epb(parse_optarg_string(argv[optind]));
0621 
0622     if (argc > optind + 1) {
0623         fprintf(stderr, "stray parameter '%s'\n", argv[optind + 1]);
0624         usage();
0625     }
0626 }
0627 
0628 /*
0629  * Open a file, and exit on failure
0630  */
0631 FILE *fopen_or_die(const char *path, const char *mode)
0632 {
0633     FILE *filep = fopen(path, "r");
0634 
0635     if (!filep)
0636         err(1, "%s: open failed", path);
0637     return filep;
0638 }
0639 
0640 void err_on_hypervisor(void)
0641 {
0642     FILE *cpuinfo;
0643     char *flags, *hypervisor;
0644     char *buffer;
0645 
0646     /* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */
0647     cpuinfo = fopen_or_die("/proc/cpuinfo", "ro");
0648 
0649     buffer = malloc(4096);
0650     if (!buffer) {
0651         fclose(cpuinfo);
0652         err(-ENOMEM, "buffer malloc fail");
0653     }
0654 
0655     if (!fread(buffer, 1024, 1, cpuinfo)) {
0656         fclose(cpuinfo);
0657         free(buffer);
0658         err(1, "Reading /proc/cpuinfo failed");
0659     }
0660 
0661     flags = strstr(buffer, "flags");
0662     rewind(cpuinfo);
0663     fseek(cpuinfo, flags - buffer, SEEK_SET);
0664     if (!fgets(buffer, 4096, cpuinfo)) {
0665         fclose(cpuinfo);
0666         free(buffer);
0667         err(1, "Reading /proc/cpuinfo failed");
0668     }
0669     fclose(cpuinfo);
0670 
0671     hypervisor = strstr(buffer, "hypervisor");
0672 
0673     free(buffer);
0674 
0675     if (hypervisor)
0676         err(-1,
0677             "not supported on this virtual machine");
0678 }
0679 
0680 int get_msr(int cpu, int offset, unsigned long long *msr)
0681 {
0682     int retval;
0683     char pathname[32];
0684     int fd;
0685 
0686     sprintf(pathname, "/dev/cpu/%d/msr", cpu);
0687     fd = open(pathname, O_RDONLY);
0688     if (fd < 0)
0689         err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
0690 
0691     retval = pread(fd, msr, sizeof(*msr), offset);
0692     if (retval != sizeof(*msr)) {
0693         err_on_hypervisor();
0694         err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
0695     }
0696 
0697     if (debug > 1)
0698         fprintf(stderr, "get_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, *msr);
0699 
0700     close(fd);
0701     return 0;
0702 }
0703 
0704 int put_msr(int cpu, int offset, unsigned long long new_msr)
0705 {
0706     char pathname[32];
0707     int retval;
0708     int fd;
0709 
0710     sprintf(pathname, "/dev/cpu/%d/msr", cpu);
0711     fd = open(pathname, O_RDWR);
0712     if (fd < 0)
0713         err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
0714 
0715     retval = pwrite(fd, &new_msr, sizeof(new_msr), offset);
0716     if (retval != sizeof(new_msr))
0717         err(-2, "pwrite(cpu%d, offset 0x%x, 0x%llx) = %d", cpu, offset, new_msr, retval);
0718 
0719     close(fd);
0720 
0721     if (debug > 1)
0722         fprintf(stderr, "put_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, new_msr);
0723 
0724     return 0;
0725 }
0726 
0727 static unsigned int read_sysfs(const char *path, char *buf, size_t buflen)
0728 {
0729     ssize_t numread;
0730     int fd;
0731 
0732     fd = open(path, O_RDONLY);
0733     if (fd == -1)
0734         return 0;
0735 
0736     numread = read(fd, buf, buflen - 1);
0737     if (numread < 1) {
0738         close(fd);
0739         return 0;
0740     }
0741 
0742     buf[numread] = '\0';
0743     close(fd);
0744 
0745     return (unsigned int) numread;
0746 }
0747 
0748 static unsigned int write_sysfs(const char *path, char *buf, size_t buflen)
0749 {
0750     ssize_t numwritten;
0751     int fd;
0752 
0753     fd = open(path, O_WRONLY);
0754     if (fd == -1)
0755         return 0;
0756 
0757     numwritten = write(fd, buf, buflen - 1);
0758     if (numwritten < 1) {
0759         perror("write failed\n");
0760         close(fd);
0761         return -1;
0762     }
0763 
0764     close(fd);
0765 
0766     return (unsigned int) numwritten;
0767 }
0768 
0769 void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str)
0770 {
0771     if (cpu != -1)
0772         printf("cpu%d: ", cpu);
0773 
0774     printf("HWP_CAP: low %d eff %d guar %d high %d\n",
0775         cap->lowest, cap->efficient, cap->guaranteed, cap->highest);
0776 }
0777 void read_hwp_cap(int cpu, struct msr_hwp_cap *cap, unsigned int msr_offset)
0778 {
0779     unsigned long long msr;
0780 
0781     get_msr(cpu, msr_offset, &msr);
0782 
0783     cap->highest = msr_perf_2_ratio(HWP_HIGHEST_PERF(msr));
0784     cap->guaranteed = msr_perf_2_ratio(HWP_GUARANTEED_PERF(msr));
0785     cap->efficient = msr_perf_2_ratio(HWP_MOSTEFFICIENT_PERF(msr));
0786     cap->lowest = msr_perf_2_ratio(HWP_LOWEST_PERF(msr));
0787 }
0788 
0789 void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str)
0790 {
0791     if (cpu != -1)
0792         printf("cpu%d: ", cpu);
0793 
0794     if (str)
0795         printf("%s", str);
0796 
0797     printf("HWP_REQ: min %d max %d des %d epp %d window 0x%x (%d*10^%dus) use_pkg %d\n",
0798         h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp,
0799         h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7, h->hwp_use_pkg);
0800 }
0801 void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, char *str)
0802 {
0803     printf("pkg%d: ", pkg);
0804 
0805     if (str)
0806         printf("%s", str);
0807 
0808     printf("HWP_REQ_PKG: min %d max %d des %d epp %d window 0x%x (%d*10^%dus)\n",
0809         h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp,
0810         h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7);
0811 }
0812 void read_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset)
0813 {
0814     unsigned long long msr;
0815 
0816     get_msr(cpu, msr_offset, &msr);
0817 
0818     hwp_req->hwp_min = msr_perf_2_ratio((((msr) >> 0) & 0xff));
0819     hwp_req->hwp_max = msr_perf_2_ratio((((msr) >> 8) & 0xff));
0820     hwp_req->hwp_desired = msr_perf_2_ratio((((msr) >> 16) & 0xff));
0821     hwp_req->hwp_epp = (((msr) >> 24) & 0xff);
0822     hwp_req->hwp_window = (((msr) >> 32) & 0x3ff);
0823     hwp_req->hwp_use_pkg = (((msr) >> 42) & 0x1);
0824 }
0825 
0826 void write_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset)
0827 {
0828     unsigned long long msr = 0;
0829 
0830     if (debug > 1)
0831         printf("cpu%d: requesting min %d max %d des %d epp %d window 0x%0x use_pkg %d\n",
0832             cpu, hwp_req->hwp_min, hwp_req->hwp_max,
0833             hwp_req->hwp_desired, hwp_req->hwp_epp,
0834             hwp_req->hwp_window, hwp_req->hwp_use_pkg);
0835 
0836     msr |= HWP_MIN_PERF(ratio_2_msr_perf(hwp_req->hwp_min));
0837     msr |= HWP_MAX_PERF(ratio_2_msr_perf(hwp_req->hwp_max));
0838     msr |= HWP_DESIRED_PERF(ratio_2_msr_perf(hwp_req->hwp_desired));
0839     msr |= HWP_ENERGY_PERF_PREFERENCE(hwp_req->hwp_epp);
0840     msr |= HWP_ACTIVITY_WINDOW(hwp_req->hwp_window);
0841     msr |= HWP_PACKAGE_CONTROL(hwp_req->hwp_use_pkg);
0842 
0843     put_msr(cpu, msr_offset, msr);
0844 }
0845 
0846 static int get_epb(int cpu)
0847 {
0848     char path[SYSFS_PATH_MAX];
0849     char linebuf[3];
0850     char *endp;
0851     long val;
0852 
0853     if (!has_epb)
0854         return -1;
0855 
0856     snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
0857 
0858     if (!read_sysfs(path, linebuf, 3))
0859         return -1;
0860 
0861     val = strtol(linebuf, &endp, 0);
0862     if (endp == linebuf || errno == ERANGE)
0863         return -1;
0864 
0865     return (int)val;
0866 }
0867 
0868 static int set_epb(int cpu, int val)
0869 {
0870     char path[SYSFS_PATH_MAX];
0871     char linebuf[3];
0872     char *endp;
0873     int ret;
0874 
0875     if (!has_epb)
0876         return -1;
0877 
0878     snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
0879     snprintf(linebuf, sizeof(linebuf), "%d", val);
0880 
0881     ret = write_sysfs(path, linebuf, 3);
0882     if (ret <= 0)
0883         return -1;
0884 
0885     val = strtol(linebuf, &endp, 0);
0886     if (endp == linebuf || errno == ERANGE)
0887         return -1;
0888 
0889     return (int)val;
0890 }
0891 
0892 int print_cpu_msrs(int cpu)
0893 {
0894     struct msr_hwp_request req;
0895     struct msr_hwp_cap cap;
0896     int epb;
0897 
0898     epb = get_epb(cpu);
0899     if (epb >= 0)
0900         printf("cpu%d: EPB %u\n", cpu, (unsigned int) epb);
0901 
0902     if (!has_hwp)
0903         return 0;
0904 
0905     read_hwp_request(cpu, &req, MSR_HWP_REQUEST);
0906     print_hwp_request(cpu, &req, "");
0907 
0908     read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
0909     print_hwp_cap(cpu, &cap, "");
0910 
0911     return 0;
0912 }
0913 
0914 int print_pkg_msrs(int pkg)
0915 {
0916     struct msr_hwp_request req;
0917     unsigned long long msr;
0918 
0919     if (!has_hwp)
0920         return 0;
0921 
0922     read_hwp_request(first_cpu_in_pkg[pkg], &req, MSR_HWP_REQUEST_PKG);
0923     print_hwp_request_pkg(pkg, &req, "");
0924 
0925     if (has_hwp_notify) {
0926         get_msr(first_cpu_in_pkg[pkg], MSR_HWP_INTERRUPT, &msr);
0927         fprintf(stderr,
0928         "pkg%d: MSR_HWP_INTERRUPT: 0x%08llx (Excursion_Min-%sabled, Guaranteed_Perf_Change-%sabled)\n",
0929         pkg, msr,
0930         ((msr) & 0x2) ? "EN" : "Dis",
0931         ((msr) & 0x1) ? "EN" : "Dis");
0932     }
0933     get_msr(first_cpu_in_pkg[pkg], MSR_HWP_STATUS, &msr);
0934     fprintf(stderr,
0935         "pkg%d: MSR_HWP_STATUS: 0x%08llx (%sExcursion_Min, %sGuaranteed_Perf_Change)\n",
0936         pkg, msr,
0937         ((msr) & 0x4) ? "" : "No-",
0938         ((msr) & 0x1) ? "" : "No-");
0939 
0940     return 0;
0941 }
0942 
0943 /*
0944  * Assumption: All HWP systems have 100 MHz bus clock
0945  */
0946 int ratio_2_sysfs_khz(int ratio)
0947 {
0948     int bclk_khz = 100 * 1000;  /* 100,000 KHz = 100 MHz */
0949 
0950     return ratio * bclk_khz;
0951 }
0952 /*
0953  * If HWP is enabled and cpufreq sysfs attribtes are present,
0954  * then update sysfs, so that it will not become
0955  * stale when we write to MSRs.
0956  * (intel_pstate's max_perf_pct and min_perf_pct will follow cpufreq,
0957  *  so we don't have to touch that.)
0958  */
0959 void update_cpufreq_scaling_freq(int is_max, int cpu, unsigned int ratio)
0960 {
0961     char pathname[64];
0962     FILE *fp;
0963     int retval;
0964     int khz;
0965 
0966     sprintf(pathname, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq",
0967         cpu, is_max ? "max" : "min");
0968 
0969     fp = fopen(pathname, "w");
0970     if (!fp) {
0971         if (debug)
0972             perror(pathname);
0973         return;
0974     }
0975 
0976     khz = ratio_2_sysfs_khz(ratio);
0977     retval = fprintf(fp, "%d", khz);
0978     if (retval < 0)
0979         if (debug)
0980             perror("fprintf");
0981     if (debug)
0982         printf("echo %d > %s\n", khz, pathname);
0983 
0984     fclose(fp);
0985 }
0986 
0987 /*
0988  * We update all sysfs before updating any MSRs because of
0989  * bugs in cpufreq/intel_pstate where the sysfs writes
0990  * for a CPU may change the min/max values on other CPUS.
0991  */
0992 
0993 int update_sysfs(int cpu)
0994 {
0995     if (!has_hwp)
0996         return 0;
0997 
0998     if (!hwp_update_enabled())
0999         return 0;
1000 
1001     if (access("/sys/devices/system/cpu/cpu0/cpufreq", F_OK))
1002         return 0;
1003 
1004     if (update_hwp_min)
1005         update_cpufreq_scaling_freq(0, cpu, req_update.hwp_min);
1006 
1007     if (update_hwp_max)
1008         update_cpufreq_scaling_freq(1, cpu, req_update.hwp_max);
1009 
1010     return 0;
1011 }
1012 
1013 int verify_hwp_req_self_consistency(int cpu, struct msr_hwp_request *req)
1014 {
1015     /* fail if min > max requested */
1016     if (req->hwp_min > req->hwp_max) {
1017         errx(1, "cpu%d: requested hwp-min %d > hwp_max %d",
1018             cpu, req->hwp_min, req->hwp_max);
1019     }
1020 
1021     /* fail if desired > max requestd */
1022     if (req->hwp_desired && (req->hwp_desired > req->hwp_max)) {
1023         errx(1, "cpu%d: requested hwp-desired %d > hwp_max %d",
1024             cpu, req->hwp_desired, req->hwp_max);
1025     }
1026     /* fail if desired < min requestd */
1027     if (req->hwp_desired && (req->hwp_desired < req->hwp_min)) {
1028         errx(1, "cpu%d: requested hwp-desired %d < requested hwp_min %d",
1029             cpu, req->hwp_desired, req->hwp_min);
1030     }
1031 
1032     return 0;
1033 }
1034 
1035 int check_hwp_request_v_hwp_capabilities(int cpu, struct msr_hwp_request *req, struct msr_hwp_cap *cap)
1036 {
1037     if (update_hwp_max) {
1038         if (req->hwp_max > cap->highest)
1039             errx(1, "cpu%d: requested max %d > capabilities highest %d, use --force?",
1040                 cpu, req->hwp_max, cap->highest);
1041         if (req->hwp_max < cap->lowest)
1042             errx(1, "cpu%d: requested max %d < capabilities lowest %d, use --force?",
1043                 cpu, req->hwp_max, cap->lowest);
1044     }
1045 
1046     if (update_hwp_min) {
1047         if (req->hwp_min > cap->highest)
1048             errx(1, "cpu%d: requested min %d > capabilities highest %d, use --force?",
1049                 cpu, req->hwp_min, cap->highest);
1050         if (req->hwp_min < cap->lowest)
1051             errx(1, "cpu%d: requested min %d < capabilities lowest %d, use --force?",
1052                 cpu, req->hwp_min, cap->lowest);
1053     }
1054 
1055     if (update_hwp_min && update_hwp_max && (req->hwp_min > req->hwp_max))
1056         errx(1, "cpu%d: requested min %d > requested max %d",
1057             cpu, req->hwp_min, req->hwp_max);
1058 
1059     if (update_hwp_desired && req->hwp_desired) {
1060         if (req->hwp_desired > req->hwp_max)
1061             errx(1, "cpu%d: requested desired %d > requested max %d, use --force?",
1062                 cpu, req->hwp_desired, req->hwp_max);
1063         if (req->hwp_desired < req->hwp_min)
1064             errx(1, "cpu%d: requested desired %d < requested min %d, use --force?",
1065                 cpu, req->hwp_desired, req->hwp_min);
1066         if (req->hwp_desired < cap->lowest)
1067             errx(1, "cpu%d: requested desired %d < capabilities lowest %d, use --force?",
1068                 cpu, req->hwp_desired, cap->lowest);
1069         if (req->hwp_desired > cap->highest)
1070             errx(1, "cpu%d: requested desired %d > capabilities highest %d, use --force?",
1071                 cpu, req->hwp_desired, cap->highest);
1072     }
1073 
1074     return 0;
1075 }
1076 
1077 int update_hwp_request(int cpu)
1078 {
1079     struct msr_hwp_request req;
1080     struct msr_hwp_cap cap;
1081 
1082     int msr_offset = MSR_HWP_REQUEST;
1083 
1084     read_hwp_request(cpu, &req, msr_offset);
1085     if (debug)
1086         print_hwp_request(cpu, &req, "old: ");
1087 
1088     if (update_hwp_min)
1089         req.hwp_min = req_update.hwp_min;
1090 
1091     if (update_hwp_max)
1092         req.hwp_max = req_update.hwp_max;
1093 
1094     if (update_hwp_desired)
1095         req.hwp_desired = req_update.hwp_desired;
1096 
1097     if (update_hwp_window)
1098         req.hwp_window = req_update.hwp_window;
1099 
1100     if (update_hwp_epp)
1101         req.hwp_epp = req_update.hwp_epp;
1102 
1103     req.hwp_use_pkg = req_update.hwp_use_pkg;
1104 
1105     read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
1106     if (debug)
1107         print_hwp_cap(cpu, &cap, "");
1108 
1109     if (!force)
1110         check_hwp_request_v_hwp_capabilities(cpu, &req, &cap);
1111 
1112     verify_hwp_req_self_consistency(cpu, &req);
1113 
1114     write_hwp_request(cpu, &req, msr_offset);
1115 
1116     if (debug) {
1117         read_hwp_request(cpu, &req, msr_offset);
1118         print_hwp_request(cpu, &req, "new: ");
1119     }
1120     return 0;
1121 }
1122 int update_hwp_request_pkg(int pkg)
1123 {
1124     struct msr_hwp_request req;
1125     struct msr_hwp_cap cap;
1126     int cpu = first_cpu_in_pkg[pkg];
1127 
1128     int msr_offset = MSR_HWP_REQUEST_PKG;
1129 
1130     read_hwp_request(cpu, &req, msr_offset);
1131     if (debug)
1132         print_hwp_request_pkg(pkg, &req, "old: ");
1133 
1134     if (update_hwp_min)
1135         req.hwp_min = req_update.hwp_min;
1136 
1137     if (update_hwp_max)
1138         req.hwp_max = req_update.hwp_max;
1139 
1140     if (update_hwp_desired)
1141         req.hwp_desired = req_update.hwp_desired;
1142 
1143     if (update_hwp_window)
1144         req.hwp_window = req_update.hwp_window;
1145 
1146     if (update_hwp_epp)
1147         req.hwp_epp = req_update.hwp_epp;
1148 
1149     read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
1150     if (debug)
1151         print_hwp_cap(cpu, &cap, "");
1152 
1153     if (!force)
1154         check_hwp_request_v_hwp_capabilities(cpu, &req, &cap);
1155 
1156     verify_hwp_req_self_consistency(cpu, &req);
1157 
1158     write_hwp_request(cpu, &req, msr_offset);
1159 
1160     if (debug) {
1161         read_hwp_request(cpu, &req, msr_offset);
1162         print_hwp_request_pkg(pkg, &req, "new: ");
1163     }
1164     return 0;
1165 }
1166 
1167 int enable_hwp_on_cpu(int cpu)
1168 {
1169     unsigned long long msr;
1170 
1171     get_msr(cpu, MSR_PM_ENABLE, &msr);
1172     put_msr(cpu, MSR_PM_ENABLE, 1);
1173 
1174     if (verbose)
1175         printf("cpu%d: MSR_PM_ENABLE old: %d new: %d\n", cpu, (unsigned int) msr, 1);
1176 
1177     return 0;
1178 }
1179 
1180 int update_cpu_msrs(int cpu)
1181 {
1182     unsigned long long msr;
1183     int epb;
1184 
1185     if (update_epb) {
1186         epb = get_epb(cpu);
1187         set_epb(cpu, new_epb);
1188 
1189         if (verbose)
1190             printf("cpu%d: ENERGY_PERF_BIAS old: %d new: %d\n",
1191                 cpu, epb, (unsigned int) new_epb);
1192     }
1193 
1194     if (update_turbo) {
1195         int turbo_is_present_and_disabled;
1196 
1197         get_msr(cpu, MSR_IA32_MISC_ENABLE, &msr);
1198 
1199         turbo_is_present_and_disabled = ((msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE) != 0);
1200 
1201         if (turbo_update_value == 1)    {
1202             if (turbo_is_present_and_disabled) {
1203                 msr &= ~MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
1204                 put_msr(cpu, MSR_IA32_MISC_ENABLE, msr);
1205                 if (verbose)
1206                     printf("cpu%d: turbo ENABLE\n", cpu);
1207             }
1208         } else {
1209             /*
1210              * if "turbo_is_enabled" were known to be describe this cpu
1211              * then we could use it here to skip redundant disable requests.
1212              * but cpu may be in a different package, so we always write.
1213              */
1214             msr |= MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
1215             put_msr(cpu, MSR_IA32_MISC_ENABLE, msr);
1216             if (verbose)
1217                 printf("cpu%d: turbo DISABLE\n", cpu);
1218         }
1219     }
1220 
1221     if (!has_hwp)
1222         return 0;
1223 
1224     if (!hwp_update_enabled())
1225         return 0;
1226 
1227     update_hwp_request(cpu);
1228     return 0;
1229 }
1230 
1231 unsigned int get_pkg_num(int cpu)
1232 {
1233     FILE *fp;
1234     char pathname[128];
1235     unsigned int pkg;
1236     int retval;
1237 
1238     sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);
1239 
1240     fp = fopen_or_die(pathname, "r");
1241     retval = fscanf(fp, "%d\n", &pkg);
1242     if (retval != 1)
1243         errx(1, "%s: failed to parse", pathname);
1244     return pkg;
1245 }
1246 
1247 int set_max_cpu_pkg_num(int cpu)
1248 {
1249     unsigned int pkg;
1250 
1251     if (max_cpu_num < cpu)
1252         max_cpu_num = cpu;
1253 
1254     pkg = get_pkg_num(cpu);
1255 
1256     if (pkg >= MAX_PACKAGES)
1257         errx(1, "cpu%d: %d >= MAX_PACKAGES (%d)", cpu, pkg, MAX_PACKAGES);
1258 
1259     if (pkg > max_pkg_num)
1260         max_pkg_num = pkg;
1261 
1262     if ((pkg_present_set & (1ULL << pkg)) == 0) {
1263         pkg_present_set |= (1ULL << pkg);
1264         first_cpu_in_pkg[pkg] = cpu;
1265     }
1266 
1267     return 0;
1268 }
1269 int mark_cpu_present(int cpu)
1270 {
1271     CPU_SET_S(cpu, cpu_setsize, cpu_present_set);
1272     return 0;
1273 }
1274 
1275 /*
1276  * run func(cpu) on every cpu in /proc/stat
1277  * return max_cpu number
1278  */
1279 int for_all_proc_cpus(int (func)(int))
1280 {
1281     FILE *fp;
1282     int cpu_num;
1283     int retval;
1284 
1285     fp = fopen_or_die(proc_stat, "r");
1286 
1287     retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
1288     if (retval != 0)
1289         err(1, "%s: failed to parse format", proc_stat);
1290 
1291     while (1) {
1292         retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
1293         if (retval != 1)
1294             break;
1295 
1296         retval = func(cpu_num);
1297         if (retval) {
1298             fclose(fp);
1299             return retval;
1300         }
1301     }
1302     fclose(fp);
1303     return 0;
1304 }
1305 
1306 void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func)(int))
1307 {
1308     int cpu_num;
1309 
1310     for (cpu_num = 0; cpu_num <= max_cpu_num; ++cpu_num)
1311         if (CPU_ISSET_S(cpu_num, set_size, cpu_set))
1312             func(cpu_num);
1313 }
1314 
1315 void init_data_structures(void)
1316 {
1317     for_all_proc_cpus(set_max_cpu_pkg_num);
1318 
1319     cpu_setsize = CPU_ALLOC_SIZE((max_cpu_num + 1));
1320 
1321     cpu_present_set = CPU_ALLOC((max_cpu_num + 1));
1322     if (cpu_present_set == NULL)
1323         err(3, "CPU_ALLOC");
1324     CPU_ZERO_S(cpu_setsize, cpu_present_set);
1325     for_all_proc_cpus(mark_cpu_present);
1326 }
1327 
1328 /* clear has_hwp if it is not enable (or being enabled) */
1329 
1330 void verify_hwp_is_enabled(void)
1331 {
1332     unsigned long long msr;
1333 
1334     if (!has_hwp)   /* set in early_cpuid() */
1335         return;
1336 
1337     /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
1338     get_msr(base_cpu, MSR_PM_ENABLE, &msr);
1339     if ((msr & 1) == 0) {
1340         fprintf(stderr, "HWP can be enabled using '--hwp-enable'\n");
1341         has_hwp = 0;
1342         return;
1343     }
1344 }
1345 
1346 int req_update_bounds_check(void)
1347 {
1348     if (!hwp_update_enabled())
1349         return 0;
1350 
1351     /* fail if min > max requested */
1352     if ((update_hwp_max && update_hwp_min) &&
1353         (req_update.hwp_min > req_update.hwp_max)) {
1354         printf("hwp-min %d > hwp_max %d\n", req_update.hwp_min, req_update.hwp_max);
1355         return -EINVAL;
1356     }
1357 
1358     /* fail if desired > max requestd */
1359     if (req_update.hwp_desired && update_hwp_max &&
1360         (req_update.hwp_desired > req_update.hwp_max)) {
1361         printf("hwp-desired cannot be greater than hwp_max\n");
1362         return -EINVAL;
1363     }
1364     /* fail if desired < min requestd */
1365     if (req_update.hwp_desired && update_hwp_min &&
1366         (req_update.hwp_desired < req_update.hwp_min)) {
1367         printf("hwp-desired cannot be less than hwp_min\n");
1368         return -EINVAL;
1369     }
1370 
1371     return 0;
1372 }
1373 
1374 void set_base_cpu(void)
1375 {
1376     base_cpu = sched_getcpu();
1377     if (base_cpu < 0)
1378         err(-ENODEV, "No valid cpus found");
1379 }
1380 
1381 
1382 void probe_dev_msr(void)
1383 {
1384     struct stat sb;
1385     char pathname[32];
1386 
1387     sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
1388     if (stat(pathname, &sb))
1389         if (system("/sbin/modprobe msr > /dev/null 2>&1"))
1390             err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
1391 }
1392 
1393 static void get_cpuid_or_exit(unsigned int leaf,
1394                  unsigned int *eax, unsigned int *ebx,
1395                  unsigned int *ecx, unsigned int *edx)
1396 {
1397     if (!__get_cpuid(leaf, eax, ebx, ecx, edx))
1398         errx(1, "Processor not supported\n");
1399 }
1400 
1401 /*
1402  * early_cpuid()
1403  * initialize turbo_is_enabled, has_hwp, has_epb
1404  * before cmdline is parsed
1405  */
1406 void early_cpuid(void)
1407 {
1408     unsigned int eax, ebx, ecx, edx;
1409     unsigned int fms, family, model;
1410 
1411     get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
1412     family = (fms >> 8) & 0xf;
1413     model = (fms >> 4) & 0xf;
1414     if (family == 6 || family == 0xf)
1415         model += ((fms >> 16) & 0xf) << 4;
1416 
1417     if (model == 0x4F) {
1418         unsigned long long msr;
1419 
1420         get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
1421 
1422         bdx_highest_ratio = msr & 0xFF;
1423     }
1424 
1425     get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
1426     turbo_is_enabled = (eax >> 1) & 1;
1427     has_hwp = (eax >> 7) & 1;
1428     has_epb = (ecx >> 3) & 1;
1429 }
1430 
1431 /*
1432  * parse_cpuid()
1433  * set
1434  * has_hwp, has_hwp_notify, has_hwp_activity_window, has_hwp_epp, has_hwp_request_pkg, has_epb
1435  */
1436 void parse_cpuid(void)
1437 {
1438     unsigned int eax, ebx, ecx, edx, max_level;
1439     unsigned int fms, family, model, stepping;
1440 
1441     eax = ebx = ecx = edx = 0;
1442 
1443     get_cpuid_or_exit(0, &max_level, &ebx, &ecx, &edx);
1444 
1445     if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
1446         genuine_intel = 1;
1447 
1448     if (debug)
1449         fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
1450             (char *)&ebx, (char *)&edx, (char *)&ecx);
1451 
1452     get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
1453     family = (fms >> 8) & 0xf;
1454     model = (fms >> 4) & 0xf;
1455     stepping = fms & 0xf;
1456     if (family == 6 || family == 0xf)
1457         model += ((fms >> 16) & 0xf) << 4;
1458 
1459     if (debug) {
1460         fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
1461             max_level, family, model, stepping, family, model, stepping);
1462         fprintf(stderr, "CPUID(1): %s %s %s %s %s %s %s %s\n",
1463             ecx & (1 << 0) ? "SSE3" : "-",
1464             ecx & (1 << 3) ? "MONITOR" : "-",
1465             ecx & (1 << 7) ? "EIST" : "-",
1466             ecx & (1 << 8) ? "TM2" : "-",
1467             edx & (1 << 4) ? "TSC" : "-",
1468             edx & (1 << 5) ? "MSR" : "-",
1469             edx & (1 << 22) ? "ACPI-TM" : "-",
1470             edx & (1 << 29) ? "TM" : "-");
1471     }
1472 
1473     if (!(edx & (1 << 5)))
1474         errx(1, "CPUID: no MSR");
1475 
1476 
1477     get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
1478     /* turbo_is_enabled already set */
1479     /* has_hwp already set */
1480     has_hwp_notify = eax & (1 << 8);
1481     has_hwp_activity_window = eax & (1 << 9);
1482     has_hwp_epp = eax & (1 << 10);
1483     has_hwp_request_pkg = eax & (1 << 11);
1484 
1485     if (!has_hwp_request_pkg && update_hwp_use_pkg)
1486         errx(1, "--hwp-use-pkg is not available on this hardware");
1487 
1488     /* has_epb already set */
1489 
1490     if (debug)
1491         fprintf(stderr,
1492             "CPUID(6): %sTURBO, %sHWP, %sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
1493             turbo_is_enabled ? "" : "No-",
1494             has_hwp ? "" : "No-",
1495             has_hwp_notify ? "" : "No-",
1496             has_hwp_activity_window ? "" : "No-",
1497             has_hwp_epp ? "" : "No-",
1498             has_hwp_request_pkg ? "" : "No-",
1499             has_epb ? "" : "No-");
1500 
1501     return; /* success */
1502 }
1503 
1504 int main(int argc, char **argv)
1505 {
1506     set_base_cpu();
1507     probe_dev_msr();
1508     init_data_structures();
1509 
1510     early_cpuid();  /* initial cpuid parse before cmdline */
1511 
1512     cmdline(argc, argv);
1513 
1514     if (debug)
1515         print_version();
1516 
1517     parse_cpuid();
1518 
1519      /* If CPU-set and PKG-set are not initialized, default to all CPUs */
1520     if ((cpu_selected_set == 0) && (pkg_selected_set == 0))
1521         cpu_selected_set = cpu_present_set;
1522 
1523     /*
1524      * If HWP is being enabled, do it now, so that subsequent operations
1525      * that access HWP registers can work.
1526      */
1527     if (update_hwp_enable)
1528         for_all_cpus_in_set(cpu_setsize, cpu_selected_set, enable_hwp_on_cpu);
1529 
1530     /* If HWP present, but disabled, warn and ignore from here forward */
1531     verify_hwp_is_enabled();
1532 
1533     if (req_update_bounds_check())
1534         return -EINVAL;
1535 
1536     /* display information only, no updates to settings */
1537     if (!update_epb && !update_turbo && !hwp_update_enabled()) {
1538         if (cpu_selected_set)
1539             for_all_cpus_in_set(cpu_setsize, cpu_selected_set, print_cpu_msrs);
1540 
1541         if (has_hwp_request_pkg) {
1542             if (pkg_selected_set == 0)
1543                 pkg_selected_set = pkg_present_set;
1544 
1545             for_packages(pkg_selected_set, print_pkg_msrs);
1546         }
1547 
1548         return 0;
1549     }
1550 
1551     /* update CPU set */
1552     if (cpu_selected_set) {
1553         for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_sysfs);
1554         for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_msrs);
1555     } else if (pkg_selected_set)
1556         for_packages(pkg_selected_set, update_hwp_request_pkg);
1557 
1558     return 0;
1559 }