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