cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

x86_energy_perf_policy.c (36737B)


      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	return pkg;
   1245}
   1246
   1247int set_max_cpu_pkg_num(int cpu)
   1248{
   1249	unsigned int pkg;
   1250
   1251	if (max_cpu_num < cpu)
   1252		max_cpu_num = cpu;
   1253
   1254	pkg = get_pkg_num(cpu);
   1255
   1256	if (pkg >= MAX_PACKAGES)
   1257		errx(1, "cpu%d: %d >= MAX_PACKAGES (%d)", cpu, pkg, MAX_PACKAGES);
   1258
   1259	if (pkg > max_pkg_num)
   1260		max_pkg_num = pkg;
   1261
   1262	if ((pkg_present_set & (1ULL << pkg)) == 0) {
   1263		pkg_present_set |= (1ULL << pkg);
   1264		first_cpu_in_pkg[pkg] = cpu;
   1265	}
   1266
   1267	return 0;
   1268}
   1269int mark_cpu_present(int cpu)
   1270{
   1271	CPU_SET_S(cpu, cpu_setsize, cpu_present_set);
   1272	return 0;
   1273}
   1274
   1275/*
   1276 * run func(cpu) on every cpu in /proc/stat
   1277 * return max_cpu number
   1278 */
   1279int for_all_proc_cpus(int (func)(int))
   1280{
   1281	FILE *fp;
   1282	int cpu_num;
   1283	int retval;
   1284
   1285	fp = fopen_or_die(proc_stat, "r");
   1286
   1287	retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
   1288	if (retval != 0)
   1289		err(1, "%s: failed to parse format", proc_stat);
   1290
   1291	while (1) {
   1292		retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
   1293		if (retval != 1)
   1294			break;
   1295
   1296		retval = func(cpu_num);
   1297		if (retval) {
   1298			fclose(fp);
   1299			return retval;
   1300		}
   1301	}
   1302	fclose(fp);
   1303	return 0;
   1304}
   1305
   1306void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func)(int))
   1307{
   1308	int cpu_num;
   1309
   1310	for (cpu_num = 0; cpu_num <= max_cpu_num; ++cpu_num)
   1311		if (CPU_ISSET_S(cpu_num, set_size, cpu_set))
   1312			func(cpu_num);
   1313}
   1314
   1315void init_data_structures(void)
   1316{
   1317	for_all_proc_cpus(set_max_cpu_pkg_num);
   1318
   1319	cpu_setsize = CPU_ALLOC_SIZE((max_cpu_num + 1));
   1320
   1321	cpu_present_set = CPU_ALLOC((max_cpu_num + 1));
   1322	if (cpu_present_set == NULL)
   1323		err(3, "CPU_ALLOC");
   1324	CPU_ZERO_S(cpu_setsize, cpu_present_set);
   1325	for_all_proc_cpus(mark_cpu_present);
   1326}
   1327
   1328/* clear has_hwp if it is not enable (or being enabled) */
   1329
   1330void verify_hwp_is_enabled(void)
   1331{
   1332	unsigned long long msr;
   1333
   1334	if (!has_hwp)	/* set in early_cpuid() */
   1335		return;
   1336
   1337	/* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
   1338	get_msr(base_cpu, MSR_PM_ENABLE, &msr);
   1339	if ((msr & 1) == 0) {
   1340		fprintf(stderr, "HWP can be enabled using '--hwp-enable'\n");
   1341		has_hwp = 0;
   1342		return;
   1343	}
   1344}
   1345
   1346int req_update_bounds_check(void)
   1347{
   1348	if (!hwp_update_enabled())
   1349		return 0;
   1350
   1351	/* fail if min > max requested */
   1352	if ((update_hwp_max && update_hwp_min) &&
   1353	    (req_update.hwp_min > req_update.hwp_max)) {
   1354		printf("hwp-min %d > hwp_max %d\n", req_update.hwp_min, req_update.hwp_max);
   1355		return -EINVAL;
   1356	}
   1357
   1358	/* fail if desired > max requestd */
   1359	if (req_update.hwp_desired && update_hwp_max &&
   1360	    (req_update.hwp_desired > req_update.hwp_max)) {
   1361		printf("hwp-desired cannot be greater than hwp_max\n");
   1362		return -EINVAL;
   1363	}
   1364	/* fail if desired < min requestd */
   1365	if (req_update.hwp_desired && update_hwp_min &&
   1366	    (req_update.hwp_desired < req_update.hwp_min)) {
   1367		printf("hwp-desired cannot be less than hwp_min\n");
   1368		return -EINVAL;
   1369	}
   1370
   1371	return 0;
   1372}
   1373
   1374void set_base_cpu(void)
   1375{
   1376	base_cpu = sched_getcpu();
   1377	if (base_cpu < 0)
   1378		err(-ENODEV, "No valid cpus found");
   1379}
   1380
   1381
   1382void probe_dev_msr(void)
   1383{
   1384	struct stat sb;
   1385	char pathname[32];
   1386
   1387	sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
   1388	if (stat(pathname, &sb))
   1389		if (system("/sbin/modprobe msr > /dev/null 2>&1"))
   1390			err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
   1391}
   1392
   1393static void get_cpuid_or_exit(unsigned int leaf,
   1394			     unsigned int *eax, unsigned int *ebx,
   1395			     unsigned int *ecx, unsigned int *edx)
   1396{
   1397	if (!__get_cpuid(leaf, eax, ebx, ecx, edx))
   1398		errx(1, "Processor not supported\n");
   1399}
   1400
   1401/*
   1402 * early_cpuid()
   1403 * initialize turbo_is_enabled, has_hwp, has_epb
   1404 * before cmdline is parsed
   1405 */
   1406void early_cpuid(void)
   1407{
   1408	unsigned int eax, ebx, ecx, edx;
   1409	unsigned int fms, family, model;
   1410
   1411	get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
   1412	family = (fms >> 8) & 0xf;
   1413	model = (fms >> 4) & 0xf;
   1414	if (family == 6 || family == 0xf)
   1415		model += ((fms >> 16) & 0xf) << 4;
   1416
   1417	if (model == 0x4F) {
   1418		unsigned long long msr;
   1419
   1420		get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
   1421
   1422		bdx_highest_ratio = msr & 0xFF;
   1423	}
   1424
   1425	get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
   1426	turbo_is_enabled = (eax >> 1) & 1;
   1427	has_hwp = (eax >> 7) & 1;
   1428	has_epb = (ecx >> 3) & 1;
   1429}
   1430
   1431/*
   1432 * parse_cpuid()
   1433 * set
   1434 * has_hwp, has_hwp_notify, has_hwp_activity_window, has_hwp_epp, has_hwp_request_pkg, has_epb
   1435 */
   1436void parse_cpuid(void)
   1437{
   1438	unsigned int eax, ebx, ecx, edx, max_level;
   1439	unsigned int fms, family, model, stepping;
   1440
   1441	eax = ebx = ecx = edx = 0;
   1442
   1443	get_cpuid_or_exit(0, &max_level, &ebx, &ecx, &edx);
   1444
   1445	if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
   1446		genuine_intel = 1;
   1447
   1448	if (debug)
   1449		fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
   1450			(char *)&ebx, (char *)&edx, (char *)&ecx);
   1451
   1452	get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
   1453	family = (fms >> 8) & 0xf;
   1454	model = (fms >> 4) & 0xf;
   1455	stepping = fms & 0xf;
   1456	if (family == 6 || family == 0xf)
   1457		model += ((fms >> 16) & 0xf) << 4;
   1458
   1459	if (debug) {
   1460		fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
   1461			max_level, family, model, stepping, family, model, stepping);
   1462		fprintf(stderr, "CPUID(1): %s %s %s %s %s %s %s %s\n",
   1463			ecx & (1 << 0) ? "SSE3" : "-",
   1464			ecx & (1 << 3) ? "MONITOR" : "-",
   1465			ecx & (1 << 7) ? "EIST" : "-",
   1466			ecx & (1 << 8) ? "TM2" : "-",
   1467			edx & (1 << 4) ? "TSC" : "-",
   1468			edx & (1 << 5) ? "MSR" : "-",
   1469			edx & (1 << 22) ? "ACPI-TM" : "-",
   1470			edx & (1 << 29) ? "TM" : "-");
   1471	}
   1472
   1473	if (!(edx & (1 << 5)))
   1474		errx(1, "CPUID: no MSR");
   1475
   1476
   1477	get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
   1478	/* turbo_is_enabled already set */
   1479	/* has_hwp already set */
   1480	has_hwp_notify = eax & (1 << 8);
   1481	has_hwp_activity_window = eax & (1 << 9);
   1482	has_hwp_epp = eax & (1 << 10);
   1483	has_hwp_request_pkg = eax & (1 << 11);
   1484
   1485	if (!has_hwp_request_pkg && update_hwp_use_pkg)
   1486		errx(1, "--hwp-use-pkg is not available on this hardware");
   1487
   1488	/* has_epb already set */
   1489
   1490	if (debug)
   1491		fprintf(stderr,
   1492			"CPUID(6): %sTURBO, %sHWP, %sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
   1493			turbo_is_enabled ? "" : "No-",
   1494			has_hwp ? "" : "No-",
   1495			has_hwp_notify ? "" : "No-",
   1496			has_hwp_activity_window ? "" : "No-",
   1497			has_hwp_epp ? "" : "No-",
   1498			has_hwp_request_pkg ? "" : "No-",
   1499			has_epb ? "" : "No-");
   1500
   1501	return;	/* success */
   1502}
   1503
   1504int main(int argc, char **argv)
   1505{
   1506	set_base_cpu();
   1507	probe_dev_msr();
   1508	init_data_structures();
   1509
   1510	early_cpuid();	/* initial cpuid parse before cmdline */
   1511
   1512	cmdline(argc, argv);
   1513
   1514	if (debug)
   1515		print_version();
   1516
   1517	parse_cpuid();
   1518
   1519	 /* If CPU-set and PKG-set are not initialized, default to all CPUs */
   1520	if ((cpu_selected_set == 0) && (pkg_selected_set == 0))
   1521		cpu_selected_set = cpu_present_set;
   1522
   1523	/*
   1524	 * If HWP is being enabled, do it now, so that subsequent operations
   1525	 * that access HWP registers can work.
   1526	 */
   1527	if (update_hwp_enable)
   1528		for_all_cpus_in_set(cpu_setsize, cpu_selected_set, enable_hwp_on_cpu);
   1529
   1530	/* If HWP present, but disabled, warn and ignore from here forward */
   1531	verify_hwp_is_enabled();
   1532
   1533	if (req_update_bounds_check())
   1534		return -EINVAL;
   1535
   1536	/* display information only, no updates to settings */
   1537	if (!update_epb && !update_turbo && !hwp_update_enabled()) {
   1538		if (cpu_selected_set)
   1539			for_all_cpus_in_set(cpu_setsize, cpu_selected_set, print_cpu_msrs);
   1540
   1541		if (has_hwp_request_pkg) {
   1542			if (pkg_selected_set == 0)
   1543				pkg_selected_set = pkg_present_set;
   1544
   1545			for_packages(pkg_selected_set, print_pkg_msrs);
   1546		}
   1547
   1548		return 0;
   1549	}
   1550
   1551	/* update CPU set */
   1552	if (cpu_selected_set) {
   1553		for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_sysfs);
   1554		for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_msrs);
   1555	} else if (pkg_selected_set)
   1556		for_packages(pkg_selected_set, update_hwp_request_pkg);
   1557
   1558	return 0;
   1559}