Linux 6.9-rc1
[linux-2.6-microblaze.git] / tools / power / x86 / x86_energy_perf_policy / x86_energy_perf_policy.c
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
36 struct msr_hwp_cap {
37         unsigned char highest;
38         unsigned char guaranteed;
39         unsigned char efficient;
40         unsigned char lowest;
41 };
42
43 struct 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
52 unsigned int debug;
53 unsigned int verbose;
54 unsigned int force;
55 char *progname;
56 int base_cpu;
57 unsigned char update_epb;
58 unsigned long long new_epb;
59 unsigned char turbo_is_enabled;
60 unsigned char update_turbo;
61 unsigned char turbo_update_value;
62 unsigned char update_hwp_epp;
63 unsigned char update_hwp_min;
64 unsigned char update_hwp_max;
65 unsigned char update_hwp_desired;
66 unsigned char update_hwp_window;
67 unsigned char update_hwp_use_pkg;
68 unsigned 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)
70 int max_cpu_num;
71 int max_pkg_num;
72 #define MAX_PACKAGES 64
73 unsigned int first_cpu_in_pkg[MAX_PACKAGES];
74 unsigned long long pkg_present_set;
75 unsigned long long pkg_selected_set;
76 cpu_set_t *cpu_present_set;
77 cpu_set_t *cpu_selected_set;
78 int genuine_intel;
79
80 size_t cpu_setsize;
81
82 char *proc_stat = "/proc/stat";
83
84 unsigned int has_epb;   /* MSR_IA32_ENERGY_PERF_BIAS */
85 unsigned int has_hwp;   /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
86                         /* IA32_HWP_REQUEST, IA32_HWP_STATUS */
87 unsigned int has_hwp_notify;            /* IA32_HWP_INTERRUPT */
88 unsigned int has_hwp_activity_window;   /* IA32_HWP_REQUEST[bits 41:32] */
89 unsigned int has_hwp_epp;       /* IA32_HWP_REQUEST[bits 31:24] */
90 unsigned int has_hwp_request_pkg;       /* IA32_HWP_REQUEST_PKG */
91
92 unsigned int bdx_highest_ratio;
93
94 #define PATH_TO_CPU "/sys/devices/system/cpu/"
95 #define SYSFS_PATH_MAX 255
96
97 /*
98  * maintain compatibility with original implementation, but don't document it:
99  */
100 void usage(void)
101 {
102         fprintf(stderr, "%s [options] [scope][field value]\n", progname);
103         fprintf(stderr, "scope: --cpu cpu-list [--hwp-use-pkg #] | --pkg pkg-list\n");
104         fprintf(stderr, "field: --all | --epb | --hwp-epp | --hwp-min | --hwp-max | --hwp-desired\n");
105         fprintf(stderr, "other: --hwp-enable | --turbo-enable (0 | 1) | --help | --force\n");
106         fprintf(stderr,
107                 "value: ( # | \"normal\" | \"performance\" | \"balance-performance\" | \"balance-power\"| \"power\")\n");
108         fprintf(stderr, "--hwp-window usec\n");
109
110         fprintf(stderr, "Specify only Energy Performance BIAS (legacy usage):\n");
111         fprintf(stderr, "%s: [-c cpu] [-v] (-r | policy-value )\n", progname);
112
113         exit(1);
114 }
115
116 /*
117  * If bdx_highest_ratio is set,
118  * then we must translate between MSR format and simple ratio
119  * used on the cmdline.
120  */
121 int ratio_2_msr_perf(int ratio)
122 {
123         int msr_perf;
124
125         if (!bdx_highest_ratio)
126                 return ratio;
127
128         msr_perf = ratio * 255 / bdx_highest_ratio;
129
130         if (debug)
131                 fprintf(stderr, "%d = ratio_to_msr_perf(%d)\n", msr_perf, ratio);
132
133         return msr_perf;
134 }
135 int msr_perf_2_ratio(int msr_perf)
136 {
137         int ratio;
138         double d;
139
140         if (!bdx_highest_ratio)
141                 return msr_perf;
142
143         d = (double)msr_perf * (double) bdx_highest_ratio / 255.0;
144         d = d + 0.5;    /* round */
145         ratio = (int)d;
146
147         if (debug)
148                 fprintf(stderr, "%d = msr_perf_ratio(%d) {%f}\n", ratio, msr_perf, d);
149
150         return ratio;
151 }
152 int parse_cmdline_epb(int i)
153 {
154         if (!has_epb)
155                 errx(1, "EPB not enabled on this platform");
156
157         update_epb = 1;
158
159         switch (i) {
160         case OPTARG_POWER:
161                 return ENERGY_PERF_BIAS_POWERSAVE;
162         case OPTARG_BALANCE_POWER:
163                 return ENERGY_PERF_BIAS_BALANCE_POWERSAVE;
164         case OPTARG_NORMAL:
165                 return ENERGY_PERF_BIAS_NORMAL;
166         case OPTARG_BALANCE_PERFORMANCE:
167                 return ENERGY_PERF_BIAS_BALANCE_PERFORMANCE;
168         case OPTARG_PERFORMANCE:
169                 return ENERGY_PERF_BIAS_PERFORMANCE;
170         }
171         if (i < 0 || i > ENERGY_PERF_BIAS_POWERSAVE)
172                 errx(1, "--epb must be from 0 to 15");
173         return i;
174 }
175
176 #define HWP_CAP_LOWEST 0
177 #define HWP_CAP_HIGHEST 255
178
179 /*
180  * "performance" changes hwp_min to cap.highest
181  * All others leave it at cap.lowest
182  */
183 int parse_cmdline_hwp_min(int i)
184 {
185         update_hwp_min = 1;
186
187         switch (i) {
188         case OPTARG_POWER:
189         case OPTARG_BALANCE_POWER:
190         case OPTARG_NORMAL:
191         case OPTARG_BALANCE_PERFORMANCE:
192                 return HWP_CAP_LOWEST;
193         case OPTARG_PERFORMANCE:
194                 return HWP_CAP_HIGHEST;
195         }
196         return i;
197 }
198 /*
199  * "power" changes hwp_max to cap.lowest
200  * All others leave it at cap.highest
201  */
202 int parse_cmdline_hwp_max(int i)
203 {
204         update_hwp_max = 1;
205
206         switch (i) {
207         case OPTARG_POWER:
208                 return HWP_CAP_LOWEST;
209         case OPTARG_NORMAL:
210         case OPTARG_BALANCE_POWER:
211         case OPTARG_BALANCE_PERFORMANCE:
212         case OPTARG_PERFORMANCE:
213                 return HWP_CAP_HIGHEST;
214         }
215         return i;
216 }
217 /*
218  * for --hwp-des, all strings leave it in autonomous mode
219  * If you want to change it, you need to explicitly pick a value
220  */
221 int parse_cmdline_hwp_desired(int i)
222 {
223         update_hwp_desired = 1;
224
225         switch (i) {
226         case OPTARG_POWER:
227         case OPTARG_BALANCE_POWER:
228         case OPTARG_BALANCE_PERFORMANCE:
229         case OPTARG_NORMAL:
230         case OPTARG_PERFORMANCE:
231                 return 0;       /* autonomous */
232         }
233         return i;
234 }
235
236 int parse_cmdline_hwp_window(int i)
237 {
238         unsigned int exponent;
239
240         update_hwp_window = 1;
241
242         switch (i) {
243         case OPTARG_POWER:
244         case OPTARG_BALANCE_POWER:
245         case OPTARG_NORMAL:
246         case OPTARG_BALANCE_PERFORMANCE:
247         case OPTARG_PERFORMANCE:
248                 return 0;
249         }
250         if (i < 0 || i > 1270000000) {
251                 fprintf(stderr, "--hwp-window: 0 for auto; 1 - 1270000000 usec for window duration\n");
252                 usage();
253         }
254         for (exponent = 0; ; ++exponent) {
255                 if (debug)
256                         printf("%d 10^%d\n", i, exponent);
257
258                 if (i <= 127)
259                         break;
260
261                 i = i / 10;
262         }
263         if (debug)
264                 fprintf(stderr, "%d*10^%d: 0x%x\n", i, exponent, (exponent << 7) | i);
265
266         return (exponent << 7) | i;
267 }
268 int parse_cmdline_hwp_epp(int i)
269 {
270         update_hwp_epp = 1;
271
272         switch (i) {
273         case OPTARG_POWER:
274                 return HWP_EPP_POWERSAVE;
275         case OPTARG_BALANCE_POWER:
276                 return HWP_EPP_BALANCE_POWERSAVE;
277         case OPTARG_NORMAL:
278         case OPTARG_BALANCE_PERFORMANCE:
279                 return HWP_EPP_BALANCE_PERFORMANCE;
280         case OPTARG_PERFORMANCE:
281                 return HWP_EPP_PERFORMANCE;
282         }
283         if (i < 0 || i > 0xff) {
284                 fprintf(stderr, "--hwp-epp must be from 0 to 0xff\n");
285                 usage();
286         }
287         return i;
288 }
289 int parse_cmdline_turbo(int i)
290 {
291         update_turbo = 1;
292
293         switch (i) {
294         case OPTARG_POWER:
295                 return 0;
296         case OPTARG_NORMAL:
297         case OPTARG_BALANCE_POWER:
298         case OPTARG_BALANCE_PERFORMANCE:
299         case OPTARG_PERFORMANCE:
300                 return 1;
301         }
302         if (i < 0 || i > 1) {
303                 fprintf(stderr, "--turbo-enable: 1 to enable, 0 to disable\n");
304                 usage();
305         }
306         return i;
307 }
308
309 int parse_optarg_string(char *s)
310 {
311         int i;
312         char *endptr;
313
314         if (!strncmp(s, "default", 7))
315                 return OPTARG_NORMAL;
316
317         if (!strncmp(s, "normal", 6))
318                 return OPTARG_NORMAL;
319
320         if (!strncmp(s, "power", 9))
321                 return OPTARG_POWER;
322
323         if (!strncmp(s, "balance-power", 17))
324                 return OPTARG_BALANCE_POWER;
325
326         if (!strncmp(s, "balance-performance", 19))
327                 return OPTARG_BALANCE_PERFORMANCE;
328
329         if (!strncmp(s, "performance", 11))
330                 return OPTARG_PERFORMANCE;
331
332         i = strtol(s, &endptr, 0);
333         if (s == endptr) {
334                 fprintf(stderr, "no digits in \"%s\"\n", s);
335                 usage();
336         }
337         if (i == LONG_MIN || i == LONG_MAX)
338                 errx(-1, "%s", s);
339
340         if (i > 0xFF)
341                 errx(-1, "%d (0x%x) must be < 256", i, i);
342
343         if (i < 0)
344                 errx(-1, "%d (0x%x) must be >= 0", i, i);
345         return i;
346 }
347
348 void parse_cmdline_all(char *s)
349 {
350         force++;
351         update_hwp_enable = 1;
352         req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(s));
353         req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(s));
354         req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(s));
355         if (has_epb)
356                 new_epb = parse_cmdline_epb(parse_optarg_string(s));
357         turbo_update_value = parse_cmdline_turbo(parse_optarg_string(s));
358         req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(s));
359         req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(s));
360 }
361
362 void validate_cpu_selected_set(void)
363 {
364         int cpu;
365
366         if (CPU_COUNT_S(cpu_setsize, cpu_selected_set) == 0)
367                 errx(0, "no CPUs requested");
368
369         for (cpu = 0; cpu <= max_cpu_num; ++cpu) {
370                 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_selected_set))
371                         if (!CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
372                                 errx(1, "Requested cpu% is not present", cpu);
373         }
374 }
375
376 void parse_cmdline_cpu(char *s)
377 {
378         char *startp, *endp;
379         int cpu = 0;
380
381         if (pkg_selected_set) {
382                 usage();
383                 errx(1, "--cpu | --pkg");
384         }
385         cpu_selected_set = CPU_ALLOC((max_cpu_num + 1));
386         if (cpu_selected_set == NULL)
387                 err(1, "cpu_selected_set");
388         CPU_ZERO_S(cpu_setsize, cpu_selected_set);
389
390         for (startp = s; startp && *startp;) {
391
392                 if (*startp == ',') {
393                         startp++;
394                         continue;
395                 }
396
397                 if (*startp == '-') {
398                         int end_cpu;
399
400                         startp++;
401                         end_cpu = strtol(startp, &endp, 10);
402                         if (startp == endp)
403                                 continue;
404
405                         while (cpu <= end_cpu) {
406                                 if (cpu > max_cpu_num)
407                                         errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num);
408                                 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
409                                 cpu++;
410                         }
411                         startp = endp;
412                         continue;
413                 }
414
415                 if (strncmp(startp, "all", 3) == 0) {
416                         for (cpu = 0; cpu <= max_cpu_num; cpu += 1) {
417                                 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
418                                         CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
419                         }
420                         startp += 3;
421                         if (*startp == 0)
422                                 break;
423                 }
424                 /* "--cpu even" is not documented */
425                 if (strncmp(startp, "even", 4) == 0) {
426                         for (cpu = 0; cpu <= max_cpu_num; cpu += 2) {
427                                 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
428                                         CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
429                         }
430                         startp += 4;
431                         if (*startp == 0)
432                                 break;
433                 }
434
435                 /* "--cpu odd" is not documented */
436                 if (strncmp(startp, "odd", 3) == 0) {
437                         for (cpu = 1; cpu <= max_cpu_num; cpu += 2) {
438                                 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
439                                         CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
440                         }
441                         startp += 3;
442                         if (*startp == 0)
443                                 break;
444                 }
445
446                 cpu = strtol(startp, &endp, 10);
447                 if (startp == endp)
448                         errx(1, "--cpu cpu-set: confused by '%s'", startp);
449                 if (cpu > max_cpu_num)
450                         errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num);
451                 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
452                 startp = endp;
453         }
454
455         validate_cpu_selected_set();
456
457 }
458
459 void parse_cmdline_pkg(char *s)
460 {
461         char *startp, *endp;
462         int pkg = 0;
463
464         if (cpu_selected_set) {
465                 usage();
466                 errx(1, "--pkg | --cpu");
467         }
468         pkg_selected_set = 0;
469
470         for (startp = s; startp && *startp;) {
471
472                 if (*startp == ',') {
473                         startp++;
474                         continue;
475                 }
476
477                 if (*startp == '-') {
478                         int end_pkg;
479
480                         startp++;
481                         end_pkg = strtol(startp, &endp, 10);
482                         if (startp == endp)
483                                 continue;
484
485                         while (pkg <= end_pkg) {
486                                 if (pkg > max_pkg_num)
487                                         errx(1, "Requested pkg%d exceeds max pkg%d", pkg, max_pkg_num);
488                                 pkg_selected_set |= 1 << pkg;
489                                 pkg++;
490                         }
491                         startp = endp;
492                         continue;
493                 }
494
495                 if (strncmp(startp, "all", 3) == 0) {
496                         pkg_selected_set = pkg_present_set;
497                         return;
498                 }
499
500                 pkg = strtol(startp, &endp, 10);
501                 if (pkg > max_pkg_num)
502                         errx(1, "Requested pkg%d Exceeds max pkg%d", pkg, max_pkg_num);
503                 pkg_selected_set |= 1 << pkg;
504                 startp = endp;
505         }
506 }
507
508 void for_packages(unsigned long long pkg_set, int (func)(int))
509 {
510         int pkg_num;
511
512         for (pkg_num = 0; pkg_num <= max_pkg_num; ++pkg_num) {
513                 if (pkg_set & (1UL << pkg_num))
514                         func(pkg_num);
515         }
516 }
517
518 void print_version(void)
519 {
520         printf("x86_energy_perf_policy 17.05.11 (C) Len Brown <len.brown@intel.com>\n");
521 }
522
523 void cmdline(int argc, char **argv)
524 {
525         int opt;
526         int option_index = 0;
527
528         static struct option long_options[] = {
529                 {"all",         required_argument,      0, 'a'},
530                 {"cpu",         required_argument,      0, 'c'},
531                 {"pkg",         required_argument,      0, 'p'},
532                 {"debug",       no_argument,            0, 'd'},
533                 {"hwp-desired", required_argument,      0, 'D'},
534                 {"epb", required_argument,      0, 'B'},
535                 {"force",       no_argument,    0, 'f'},
536                 {"hwp-enable",  no_argument,    0, 'e'},
537                 {"help",        no_argument,    0, 'h'},
538                 {"hwp-epp",     required_argument,      0, 'P'},
539                 {"hwp-min",     required_argument,      0, 'm'},
540                 {"hwp-max",     required_argument,      0, 'M'},
541                 {"read",        no_argument,            0, 'r'},
542                 {"turbo-enable",        required_argument,      0, 't'},
543                 {"hwp-use-pkg", required_argument,      0, 'u'},
544                 {"version",     no_argument,            0, 'v'},
545                 {"hwp-window",  required_argument,      0, 'w'},
546                 {0,             0,                      0, 0 }
547         };
548
549         progname = argv[0];
550
551         while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw:",
552                                 long_options, &option_index)) != -1) {
553                 switch (opt) {
554                 case 'a':
555                         parse_cmdline_all(optarg);
556                         break;
557                 case 'B':
558                         new_epb = parse_cmdline_epb(parse_optarg_string(optarg));
559                         break;
560                 case 'c':
561                         parse_cmdline_cpu(optarg);
562                         break;
563                 case 'e':
564                         update_hwp_enable = 1;
565                         break;
566                 case 'h':
567                         usage();
568                         break;
569                 case 'd':
570                         debug++;
571                         verbose++;
572                         break;
573                 case 'f':
574                         force++;
575                         break;
576                 case 'D':
577                         req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(optarg));
578                         break;
579                 case 'm':
580                         req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(optarg));
581                         break;
582                 case 'M':
583                         req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(optarg));
584                         break;
585                 case 'p':
586                         parse_cmdline_pkg(optarg);
587                         break;
588                 case 'P':
589                         req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(optarg));
590                         break;
591                 case 'r':
592                         /* v1 used -r to specify read-only mode, now the default */
593                         break;
594                 case 't':
595                         turbo_update_value = parse_cmdline_turbo(parse_optarg_string(optarg));
596                         break;
597                 case 'u':
598                         update_hwp_use_pkg++;
599                         if (atoi(optarg) == 0)
600                                 req_update.hwp_use_pkg = 0;
601                         else
602                                 req_update.hwp_use_pkg = 1;
603                         break;
604                 case 'v':
605                         print_version();
606                         exit(0);
607                         break;
608                 case 'w':
609                         req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(optarg));
610                         break;
611                 default:
612                         usage();
613                 }
614         }
615         /*
616          * v1 allowed "performance"|"normal"|"power" with no policy specifier
617          * to update BIAS.  Continue to support that, even though no longer documented.
618          */
619         if (argc == optind + 1)
620                 new_epb = parse_cmdline_epb(parse_optarg_string(argv[optind]));
621
622         if (argc > optind + 1) {
623                 fprintf(stderr, "stray parameter '%s'\n", argv[optind + 1]);
624                 usage();
625         }
626 }
627
628 /*
629  * Open a file, and exit on failure
630  */
631 FILE *fopen_or_die(const char *path, const char *mode)
632 {
633         FILE *filep = fopen(path, "r");
634
635         if (!filep)
636                 err(1, "%s: open failed", path);
637         return filep;
638 }
639
640 void err_on_hypervisor(void)
641 {
642         FILE *cpuinfo;
643         char *flags, *hypervisor;
644         char *buffer;
645
646         /* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */
647         cpuinfo = fopen_or_die("/proc/cpuinfo", "ro");
648
649         buffer = malloc(4096);
650         if (!buffer) {
651                 fclose(cpuinfo);
652                 err(-ENOMEM, "buffer malloc fail");
653         }
654
655         if (!fread(buffer, 1024, 1, cpuinfo)) {
656                 fclose(cpuinfo);
657                 free(buffer);
658                 err(1, "Reading /proc/cpuinfo failed");
659         }
660
661         flags = strstr(buffer, "flags");
662         rewind(cpuinfo);
663         fseek(cpuinfo, flags - buffer, SEEK_SET);
664         if (!fgets(buffer, 4096, cpuinfo)) {
665                 fclose(cpuinfo);
666                 free(buffer);
667                 err(1, "Reading /proc/cpuinfo failed");
668         }
669         fclose(cpuinfo);
670
671         hypervisor = strstr(buffer, "hypervisor");
672
673         free(buffer);
674
675         if (hypervisor)
676                 err(-1,
677                     "not supported on this virtual machine");
678 }
679
680 int get_msr(int cpu, int offset, unsigned long long *msr)
681 {
682         int retval;
683         char pathname[32];
684         int fd;
685
686         sprintf(pathname, "/dev/cpu/%d/msr", cpu);
687         fd = open(pathname, O_RDONLY);
688         if (fd < 0)
689                 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
690
691         retval = pread(fd, msr, sizeof(*msr), offset);
692         if (retval != sizeof(*msr)) {
693                 err_on_hypervisor();
694                 err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
695         }
696
697         if (debug > 1)
698                 fprintf(stderr, "get_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, *msr);
699
700         close(fd);
701         return 0;
702 }
703
704 int put_msr(int cpu, int offset, unsigned long long new_msr)
705 {
706         char pathname[32];
707         int retval;
708         int fd;
709
710         sprintf(pathname, "/dev/cpu/%d/msr", cpu);
711         fd = open(pathname, O_RDWR);
712         if (fd < 0)
713                 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
714
715         retval = pwrite(fd, &new_msr, sizeof(new_msr), offset);
716         if (retval != sizeof(new_msr))
717                 err(-2, "pwrite(cpu%d, offset 0x%x, 0x%llx) = %d", cpu, offset, new_msr, retval);
718
719         close(fd);
720
721         if (debug > 1)
722                 fprintf(stderr, "put_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, new_msr);
723
724         return 0;
725 }
726
727 static unsigned int read_sysfs(const char *path, char *buf, size_t buflen)
728 {
729         ssize_t numread;
730         int fd;
731
732         fd = open(path, O_RDONLY);
733         if (fd == -1)
734                 return 0;
735
736         numread = read(fd, buf, buflen - 1);
737         if (numread < 1) {
738                 close(fd);
739                 return 0;
740         }
741
742         buf[numread] = '\0';
743         close(fd);
744
745         return (unsigned int) numread;
746 }
747
748 static unsigned int write_sysfs(const char *path, char *buf, size_t buflen)
749 {
750         ssize_t numwritten;
751         int fd;
752
753         fd = open(path, O_WRONLY);
754         if (fd == -1)
755                 return 0;
756
757         numwritten = write(fd, buf, buflen - 1);
758         if (numwritten < 1) {
759                 perror("write failed\n");
760                 close(fd);
761                 return -1;
762         }
763
764         close(fd);
765
766         return (unsigned int) numwritten;
767 }
768
769 void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str)
770 {
771         if (cpu != -1)
772                 printf("cpu%d: ", cpu);
773
774         printf("HWP_CAP: low %d eff %d guar %d high %d\n",
775                 cap->lowest, cap->efficient, cap->guaranteed, cap->highest);
776 }
777 void read_hwp_cap(int cpu, struct msr_hwp_cap *cap, unsigned int msr_offset)
778 {
779         unsigned long long msr;
780
781         get_msr(cpu, msr_offset, &msr);
782
783         cap->highest = msr_perf_2_ratio(HWP_HIGHEST_PERF(msr));
784         cap->guaranteed = msr_perf_2_ratio(HWP_GUARANTEED_PERF(msr));
785         cap->efficient = msr_perf_2_ratio(HWP_MOSTEFFICIENT_PERF(msr));
786         cap->lowest = msr_perf_2_ratio(HWP_LOWEST_PERF(msr));
787 }
788
789 void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str)
790 {
791         if (cpu != -1)
792                 printf("cpu%d: ", cpu);
793
794         if (str)
795                 printf("%s", str);
796
797         printf("HWP_REQ: min %d max %d des %d epp %d window 0x%x (%d*10^%dus) use_pkg %d\n",
798                 h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp,
799                 h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7, h->hwp_use_pkg);
800 }
801 void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, char *str)
802 {
803         printf("pkg%d: ", pkg);
804
805         if (str)
806                 printf("%s", str);
807
808         printf("HWP_REQ_PKG: min %d max %d des %d epp %d window 0x%x (%d*10^%dus)\n",
809                 h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp,
810                 h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7);
811 }
812 void read_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset)
813 {
814         unsigned long long msr;
815
816         get_msr(cpu, msr_offset, &msr);
817
818         hwp_req->hwp_min = msr_perf_2_ratio((((msr) >> 0) & 0xff));
819         hwp_req->hwp_max = msr_perf_2_ratio((((msr) >> 8) & 0xff));
820         hwp_req->hwp_desired = msr_perf_2_ratio((((msr) >> 16) & 0xff));
821         hwp_req->hwp_epp = (((msr) >> 24) & 0xff);
822         hwp_req->hwp_window = (((msr) >> 32) & 0x3ff);
823         hwp_req->hwp_use_pkg = (((msr) >> 42) & 0x1);
824 }
825
826 void write_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset)
827 {
828         unsigned long long msr = 0;
829
830         if (debug > 1)
831                 printf("cpu%d: requesting min %d max %d des %d epp %d window 0x%0x use_pkg %d\n",
832                         cpu, hwp_req->hwp_min, hwp_req->hwp_max,
833                         hwp_req->hwp_desired, hwp_req->hwp_epp,
834                         hwp_req->hwp_window, hwp_req->hwp_use_pkg);
835
836         msr |= HWP_MIN_PERF(ratio_2_msr_perf(hwp_req->hwp_min));
837         msr |= HWP_MAX_PERF(ratio_2_msr_perf(hwp_req->hwp_max));
838         msr |= HWP_DESIRED_PERF(ratio_2_msr_perf(hwp_req->hwp_desired));
839         msr |= HWP_ENERGY_PERF_PREFERENCE(hwp_req->hwp_epp);
840         msr |= HWP_ACTIVITY_WINDOW(hwp_req->hwp_window);
841         msr |= HWP_PACKAGE_CONTROL(hwp_req->hwp_use_pkg);
842
843         put_msr(cpu, msr_offset, msr);
844 }
845
846 static int get_epb(int cpu)
847 {
848         char path[SYSFS_PATH_MAX];
849         char linebuf[3];
850         char *endp;
851         long val;
852
853         if (!has_epb)
854                 return -1;
855
856         snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
857
858         if (!read_sysfs(path, linebuf, 3))
859                 return -1;
860
861         val = strtol(linebuf, &endp, 0);
862         if (endp == linebuf || errno == ERANGE)
863                 return -1;
864
865         return (int)val;
866 }
867
868 static int set_epb(int cpu, int val)
869 {
870         char path[SYSFS_PATH_MAX];
871         char linebuf[3];
872         char *endp;
873         int ret;
874
875         if (!has_epb)
876                 return -1;
877
878         snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
879         snprintf(linebuf, sizeof(linebuf), "%d", val);
880
881         ret = write_sysfs(path, linebuf, 3);
882         if (ret <= 0)
883                 return -1;
884
885         val = strtol(linebuf, &endp, 0);
886         if (endp == linebuf || errno == ERANGE)
887                 return -1;
888
889         return (int)val;
890 }
891
892 int print_cpu_msrs(int cpu)
893 {
894         struct msr_hwp_request req;
895         struct msr_hwp_cap cap;
896         int epb;
897
898         epb = get_epb(cpu);
899         if (epb >= 0)
900                 printf("cpu%d: EPB %u\n", cpu, (unsigned int) epb);
901
902         if (!has_hwp)
903                 return 0;
904
905         read_hwp_request(cpu, &req, MSR_HWP_REQUEST);
906         print_hwp_request(cpu, &req, "");
907
908         read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
909         print_hwp_cap(cpu, &cap, "");
910
911         return 0;
912 }
913
914 int print_pkg_msrs(int pkg)
915 {
916         struct msr_hwp_request req;
917         unsigned long long msr;
918
919         if (!has_hwp)
920                 return 0;
921
922         read_hwp_request(first_cpu_in_pkg[pkg], &req, MSR_HWP_REQUEST_PKG);
923         print_hwp_request_pkg(pkg, &req, "");
924
925         if (has_hwp_notify) {
926                 get_msr(first_cpu_in_pkg[pkg], MSR_HWP_INTERRUPT, &msr);
927                 fprintf(stderr,
928                 "pkg%d: MSR_HWP_INTERRUPT: 0x%08llx (Excursion_Min-%sabled, Guaranteed_Perf_Change-%sabled)\n",
929                 pkg, msr,
930                 ((msr) & 0x2) ? "EN" : "Dis",
931                 ((msr) & 0x1) ? "EN" : "Dis");
932         }
933         get_msr(first_cpu_in_pkg[pkg], MSR_HWP_STATUS, &msr);
934         fprintf(stderr,
935                 "pkg%d: MSR_HWP_STATUS: 0x%08llx (%sExcursion_Min, %sGuaranteed_Perf_Change)\n",
936                 pkg, msr,
937                 ((msr) & 0x4) ? "" : "No-",
938                 ((msr) & 0x1) ? "" : "No-");
939
940         return 0;
941 }
942
943 /*
944  * Assumption: All HWP systems have 100 MHz bus clock
945  */
946 int ratio_2_sysfs_khz(int ratio)
947 {
948         int bclk_khz = 100 * 1000;      /* 100,000 KHz = 100 MHz */
949
950         return ratio * bclk_khz;
951 }
952 /*
953  * If HWP is enabled and cpufreq sysfs attribtes are present,
954  * then update sysfs, so that it will not become
955  * stale when we write to MSRs.
956  * (intel_pstate's max_perf_pct and min_perf_pct will follow cpufreq,
957  *  so we don't have to touch that.)
958  */
959 void update_cpufreq_scaling_freq(int is_max, int cpu, unsigned int ratio)
960 {
961         char pathname[64];
962         FILE *fp;
963         int retval;
964         int khz;
965
966         sprintf(pathname, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq",
967                 cpu, is_max ? "max" : "min");
968
969         fp = fopen(pathname, "w");
970         if (!fp) {
971                 if (debug)
972                         perror(pathname);
973                 return;
974         }
975
976         khz = ratio_2_sysfs_khz(ratio);
977         retval = fprintf(fp, "%d", khz);
978         if (retval < 0)
979                 if (debug)
980                         perror("fprintf");
981         if (debug)
982                 printf("echo %d > %s\n", khz, pathname);
983
984         fclose(fp);
985 }
986
987 /*
988  * We update all sysfs before updating any MSRs because of
989  * bugs in cpufreq/intel_pstate where the sysfs writes
990  * for a CPU may change the min/max values on other CPUS.
991  */
992
993 int update_sysfs(int cpu)
994 {
995         if (!has_hwp)
996                 return 0;
997
998         if (!hwp_update_enabled())
999                 return 0;
1000
1001         if (access("/sys/devices/system/cpu/cpu0/cpufreq", F_OK))
1002                 return 0;
1003
1004         if (update_hwp_min)
1005                 update_cpufreq_scaling_freq(0, cpu, req_update.hwp_min);
1006
1007         if (update_hwp_max)
1008                 update_cpufreq_scaling_freq(1, cpu, req_update.hwp_max);
1009
1010         return 0;
1011 }
1012
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         fclose(fp);
1245         return pkg;
1246 }
1247
1248 int set_max_cpu_pkg_num(int cpu)
1249 {
1250         unsigned int pkg;
1251
1252         if (max_cpu_num < cpu)
1253                 max_cpu_num = cpu;
1254
1255         pkg = get_pkg_num(cpu);
1256
1257         if (pkg >= MAX_PACKAGES)
1258                 errx(1, "cpu%d: %d >= MAX_PACKAGES (%d)", cpu, pkg, MAX_PACKAGES);
1259
1260         if (pkg > max_pkg_num)
1261                 max_pkg_num = pkg;
1262
1263         if ((pkg_present_set & (1ULL << pkg)) == 0) {
1264                 pkg_present_set |= (1ULL << pkg);
1265                 first_cpu_in_pkg[pkg] = cpu;
1266         }
1267
1268         return 0;
1269 }
1270 int mark_cpu_present(int cpu)
1271 {
1272         CPU_SET_S(cpu, cpu_setsize, cpu_present_set);
1273         return 0;
1274 }
1275
1276 /*
1277  * run func(cpu) on every cpu in /proc/stat
1278  * return max_cpu number
1279  */
1280 int for_all_proc_cpus(int (func)(int))
1281 {
1282         FILE *fp;
1283         int cpu_num;
1284         int retval;
1285
1286         fp = fopen_or_die(proc_stat, "r");
1287
1288         retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
1289         if (retval != 0)
1290                 err(1, "%s: failed to parse format", proc_stat);
1291
1292         while (1) {
1293                 retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
1294                 if (retval != 1)
1295                         break;
1296
1297                 retval = func(cpu_num);
1298                 if (retval) {
1299                         fclose(fp);
1300                         return retval;
1301                 }
1302         }
1303         fclose(fp);
1304         return 0;
1305 }
1306
1307 void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func)(int))
1308 {
1309         int cpu_num;
1310
1311         for (cpu_num = 0; cpu_num <= max_cpu_num; ++cpu_num)
1312                 if (CPU_ISSET_S(cpu_num, set_size, cpu_set))
1313                         func(cpu_num);
1314 }
1315
1316 void init_data_structures(void)
1317 {
1318         for_all_proc_cpus(set_max_cpu_pkg_num);
1319
1320         cpu_setsize = CPU_ALLOC_SIZE((max_cpu_num + 1));
1321
1322         cpu_present_set = CPU_ALLOC((max_cpu_num + 1));
1323         if (cpu_present_set == NULL)
1324                 err(3, "CPU_ALLOC");
1325         CPU_ZERO_S(cpu_setsize, cpu_present_set);
1326         for_all_proc_cpus(mark_cpu_present);
1327 }
1328
1329 /* clear has_hwp if it is not enable (or being enabled) */
1330
1331 void verify_hwp_is_enabled(void)
1332 {
1333         unsigned long long msr;
1334
1335         if (!has_hwp)   /* set in early_cpuid() */
1336                 return;
1337
1338         /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
1339         get_msr(base_cpu, MSR_PM_ENABLE, &msr);
1340         if ((msr & 1) == 0) {
1341                 fprintf(stderr, "HWP can be enabled using '--hwp-enable'\n");
1342                 has_hwp = 0;
1343                 return;
1344         }
1345 }
1346
1347 int req_update_bounds_check(void)
1348 {
1349         if (!hwp_update_enabled())
1350                 return 0;
1351
1352         /* fail if min > max requested */
1353         if ((update_hwp_max && update_hwp_min) &&
1354             (req_update.hwp_min > req_update.hwp_max)) {
1355                 printf("hwp-min %d > hwp_max %d\n", req_update.hwp_min, req_update.hwp_max);
1356                 return -EINVAL;
1357         }
1358
1359         /* fail if desired > max requestd */
1360         if (req_update.hwp_desired && update_hwp_max &&
1361             (req_update.hwp_desired > req_update.hwp_max)) {
1362                 printf("hwp-desired cannot be greater than hwp_max\n");
1363                 return -EINVAL;
1364         }
1365         /* fail if desired < min requestd */
1366         if (req_update.hwp_desired && update_hwp_min &&
1367             (req_update.hwp_desired < req_update.hwp_min)) {
1368                 printf("hwp-desired cannot be less than hwp_min\n");
1369                 return -EINVAL;
1370         }
1371
1372         return 0;
1373 }
1374
1375 void set_base_cpu(void)
1376 {
1377         base_cpu = sched_getcpu();
1378         if (base_cpu < 0)
1379                 err(-ENODEV, "No valid cpus found");
1380 }
1381
1382
1383 void probe_dev_msr(void)
1384 {
1385         struct stat sb;
1386         char pathname[32];
1387
1388         sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
1389         if (stat(pathname, &sb))
1390                 if (system("/sbin/modprobe msr > /dev/null 2>&1"))
1391                         err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
1392 }
1393
1394 static void get_cpuid_or_exit(unsigned int leaf,
1395                              unsigned int *eax, unsigned int *ebx,
1396                              unsigned int *ecx, unsigned int *edx)
1397 {
1398         if (!__get_cpuid(leaf, eax, ebx, ecx, edx))
1399                 errx(1, "Processor not supported\n");
1400 }
1401
1402 /*
1403  * early_cpuid()
1404  * initialize turbo_is_enabled, has_hwp, has_epb
1405  * before cmdline is parsed
1406  */
1407 void early_cpuid(void)
1408 {
1409         unsigned int eax, ebx, ecx, edx;
1410         unsigned int fms, family, model;
1411
1412         get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
1413         family = (fms >> 8) & 0xf;
1414         model = (fms >> 4) & 0xf;
1415         if (family == 6 || family == 0xf)
1416                 model += ((fms >> 16) & 0xf) << 4;
1417
1418         if (model == 0x4F) {
1419                 unsigned long long msr;
1420
1421                 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
1422
1423                 bdx_highest_ratio = msr & 0xFF;
1424         }
1425
1426         get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
1427         turbo_is_enabled = (eax >> 1) & 1;
1428         has_hwp = (eax >> 7) & 1;
1429         has_epb = (ecx >> 3) & 1;
1430 }
1431
1432 /*
1433  * parse_cpuid()
1434  * set
1435  * has_hwp, has_hwp_notify, has_hwp_activity_window, has_hwp_epp, has_hwp_request_pkg, has_epb
1436  */
1437 void parse_cpuid(void)
1438 {
1439         unsigned int eax, ebx, ecx, edx, max_level;
1440         unsigned int fms, family, model, stepping;
1441
1442         eax = ebx = ecx = edx = 0;
1443
1444         get_cpuid_or_exit(0, &max_level, &ebx, &ecx, &edx);
1445
1446         if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
1447                 genuine_intel = 1;
1448
1449         if (debug)
1450                 fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
1451                         (char *)&ebx, (char *)&edx, (char *)&ecx);
1452
1453         get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
1454         family = (fms >> 8) & 0xf;
1455         model = (fms >> 4) & 0xf;
1456         stepping = fms & 0xf;
1457         if (family == 6 || family == 0xf)
1458                 model += ((fms >> 16) & 0xf) << 4;
1459
1460         if (debug) {
1461                 fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
1462                         max_level, family, model, stepping, family, model, stepping);
1463                 fprintf(stderr, "CPUID(1): %s %s %s %s %s %s %s %s\n",
1464                         ecx & (1 << 0) ? "SSE3" : "-",
1465                         ecx & (1 << 3) ? "MONITOR" : "-",
1466                         ecx & (1 << 7) ? "EIST" : "-",
1467                         ecx & (1 << 8) ? "TM2" : "-",
1468                         edx & (1 << 4) ? "TSC" : "-",
1469                         edx & (1 << 5) ? "MSR" : "-",
1470                         edx & (1 << 22) ? "ACPI-TM" : "-",
1471                         edx & (1 << 29) ? "TM" : "-");
1472         }
1473
1474         if (!(edx & (1 << 5)))
1475                 errx(1, "CPUID: no MSR");
1476
1477
1478         get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
1479         /* turbo_is_enabled already set */
1480         /* has_hwp already set */
1481         has_hwp_notify = eax & (1 << 8);
1482         has_hwp_activity_window = eax & (1 << 9);
1483         has_hwp_epp = eax & (1 << 10);
1484         has_hwp_request_pkg = eax & (1 << 11);
1485
1486         if (!has_hwp_request_pkg && update_hwp_use_pkg)
1487                 errx(1, "--hwp-use-pkg is not available on this hardware");
1488
1489         /* has_epb already set */
1490
1491         if (debug)
1492                 fprintf(stderr,
1493                         "CPUID(6): %sTURBO, %sHWP, %sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
1494                         turbo_is_enabled ? "" : "No-",
1495                         has_hwp ? "" : "No-",
1496                         has_hwp_notify ? "" : "No-",
1497                         has_hwp_activity_window ? "" : "No-",
1498                         has_hwp_epp ? "" : "No-",
1499                         has_hwp_request_pkg ? "" : "No-",
1500                         has_epb ? "" : "No-");
1501
1502         return; /* success */
1503 }
1504
1505 int main(int argc, char **argv)
1506 {
1507         set_base_cpu();
1508         probe_dev_msr();
1509         init_data_structures();
1510
1511         early_cpuid();  /* initial cpuid parse before cmdline */
1512
1513         cmdline(argc, argv);
1514
1515         if (debug)
1516                 print_version();
1517
1518         parse_cpuid();
1519
1520          /* If CPU-set and PKG-set are not initialized, default to all CPUs */
1521         if ((cpu_selected_set == 0) && (pkg_selected_set == 0))
1522                 cpu_selected_set = cpu_present_set;
1523
1524         /*
1525          * If HWP is being enabled, do it now, so that subsequent operations
1526          * that access HWP registers can work.
1527          */
1528         if (update_hwp_enable)
1529                 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, enable_hwp_on_cpu);
1530
1531         /* If HWP present, but disabled, warn and ignore from here forward */
1532         verify_hwp_is_enabled();
1533
1534         if (req_update_bounds_check())
1535                 return -EINVAL;
1536
1537         /* display information only, no updates to settings */
1538         if (!update_epb && !update_turbo && !hwp_update_enabled()) {
1539                 if (cpu_selected_set)
1540                         for_all_cpus_in_set(cpu_setsize, cpu_selected_set, print_cpu_msrs);
1541
1542                 if (has_hwp_request_pkg) {
1543                         if (pkg_selected_set == 0)
1544                                 pkg_selected_set = pkg_present_set;
1545
1546                         for_packages(pkg_selected_set, print_pkg_msrs);
1547                 }
1548
1549                 return 0;
1550         }
1551
1552         /* update CPU set */
1553         if (cpu_selected_set) {
1554                 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_sysfs);
1555                 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_msrs);
1556         } else if (pkg_selected_set)
1557                 for_packages(pkg_selected_set, update_hwp_request_pkg);
1558
1559         return 0;
1560 }