1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * x86_energy_perf_policy -- set the energy versus performance
4 * policy preference bias on recent X86 processors.
5 */
6/*
7 * Copyright (c) 2010 - 2017 Intel Corporation.
8 * Len Brown <len.brown@intel.com>
9 */
10
11#define _GNU_SOURCE
12#include MSRHEADER
13#include <stdio.h>
14#include <unistd.h>
15#include <sys/types.h>
16#include <sched.h>
17#include <sys/stat.h>
18#include <sys/resource.h>
19#include <getopt.h>
20#include <err.h>
21#include <fcntl.h>
22#include <signal.h>
23#include <sys/time.h>
24#include <limits.h>
25#include <stdlib.h>
26#include <string.h>
27#include <cpuid.h>
28#include <errno.h>
29
30#define	OPTARG_NORMAL			(INT_MAX - 1)
31#define	OPTARG_POWER			(INT_MAX - 2)
32#define	OPTARG_BALANCE_POWER		(INT_MAX - 3)
33#define	OPTARG_BALANCE_PERFORMANCE	(INT_MAX - 4)
34#define	OPTARG_PERFORMANCE		(INT_MAX - 5)
35
36struct msr_hwp_cap {
37	unsigned char highest;
38	unsigned char guaranteed;
39	unsigned char efficient;
40	unsigned char lowest;
41};
42
43struct msr_hwp_request {
44	unsigned char hwp_min;
45	unsigned char hwp_max;
46	unsigned char hwp_desired;
47	unsigned char hwp_epp;
48	unsigned int hwp_window;
49	unsigned char hwp_use_pkg;
50} req_update;
51
52unsigned int debug;
53unsigned int verbose;
54unsigned int force;
55char *progname;
56int base_cpu;
57unsigned char update_epb;
58unsigned long long new_epb;
59unsigned char turbo_is_enabled;
60unsigned char update_turbo;
61unsigned char turbo_update_value;
62unsigned char update_hwp_epp;
63unsigned char update_hwp_min;
64unsigned char update_hwp_max;
65unsigned char update_hwp_desired;
66unsigned char update_hwp_window;
67unsigned char update_hwp_use_pkg;
68unsigned char update_hwp_enable;
69#define hwp_update_enabled() (update_hwp_enable | update_hwp_epp | update_hwp_max | update_hwp_min | update_hwp_desired | update_hwp_window | update_hwp_use_pkg)
70int max_cpu_num;
71int max_pkg_num;
72#define MAX_PACKAGES 64
73unsigned int first_cpu_in_pkg[MAX_PACKAGES];
74unsigned long long pkg_present_set;
75unsigned long long pkg_selected_set;
76cpu_set_t *cpu_present_set;
77cpu_set_t *cpu_selected_set;
78int genuine_intel;
79
80size_t cpu_setsize;
81
82char *proc_stat = "/proc/stat";
83
84unsigned int has_epb;	/* MSR_IA32_ENERGY_PERF_BIAS */
85unsigned int has_hwp;	/* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
86			/* IA32_HWP_REQUEST, IA32_HWP_STATUS */
87unsigned int has_hwp_notify;		/* IA32_HWP_INTERRUPT */
88unsigned int has_hwp_activity_window;	/* IA32_HWP_REQUEST[bits 41:32] */
89unsigned int has_hwp_epp;	/* IA32_HWP_REQUEST[bits 31:24] */
90unsigned int has_hwp_request_pkg;	/* IA32_HWP_REQUEST_PKG */
91
92unsigned int bdx_highest_ratio;
93
94#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 */
100void 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 */
121int 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}
135int 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}
152int 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 */
183int 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 */
202int 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 */
221int 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
236int 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}
268int 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}
289int 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
309int 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
348void 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
362void 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
376void 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
459void 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
508void 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
518void print_version(void)
519{
520	printf("x86_energy_perf_policy 17.05.11 (C) Len Brown <len.brown@intel.com>\n");
521}
522
523void 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 */
631FILE *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
640void 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
680int 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
704int 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
727static 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
748static 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
769void 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}
777void 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
789void 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}
801void 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}
812void 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
826void 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
846static 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
868static 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
892int 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
914int 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 */
946int 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 */
959void 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
993int 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
1013int 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
1035int 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
1077int 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}
1122int 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
1167int 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
1180int 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
1231unsigned 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
1248int 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}
1270int 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 */
1280int 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
1307void 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
1316void 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
1331void 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
1347int 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
1375void 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
1383void 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
1394static 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 */
1407void 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 */
1437void 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
1505int 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}
1561