0001
0002
0003
0004
0005
0006
0007
0008
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;
0085 unsigned int has_hwp;
0086
0087 unsigned int has_hwp_notify;
0088 unsigned int has_hwp_activity_window;
0089 unsigned int has_hwp_epp;
0090 unsigned int has_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
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
0118
0119
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;
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
0181
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
0200
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
0219
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;
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
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
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
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
0617
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
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
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
0945
0946 int ratio_2_sysfs_khz(int ratio)
0947 {
0948 int bclk_khz = 100 * 1000;
0949
0950 return ratio * bclk_khz;
0951 }
0952
0953
0954
0955
0956
0957
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
0989
0990
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
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
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
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
1211
1212
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
1277
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
1329
1330 void verify_hwp_is_enabled(void)
1331 {
1332 unsigned long long msr;
1333
1334 if (!has_hwp)
1335 return;
1336
1337
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
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
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
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
1403
1404
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
1433
1434
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
1479
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
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;
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();
1511
1512 cmdline(argc, argv);
1513
1514 if (debug)
1515 print_version();
1516
1517 parse_cpuid();
1518
1519
1520 if ((cpu_selected_set == 0) && (pkg_selected_set == 0))
1521 cpu_selected_set = cpu_present_set;
1522
1523
1524
1525
1526
1527 if (update_hwp_enable)
1528 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, enable_hwp_on_cpu);
1529
1530
1531 verify_hwp_is_enabled();
1532
1533 if (req_update_bounds_check())
1534 return -EINVAL;
1535
1536
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
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 }