aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-05-15 21:15:27 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-05-15 21:15:27 -0400
commita32f80b30dae067357f96bc2a7f977e8a91b45ed (patch)
tree3c06a476a1923683ce97991a0a535315efeddf31
parent2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff)
parent3cedbc5a6d7f7c5539e139f89ec9f6e1ed668418 (diff)
Merge branch 'utilities' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
Pull power management utilities updates from Len Brown. * 'utilities' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux: intel_pstate: use updated msr-index.h HWP.EPP values tools/power x86_energy_perf_policy: support HWP.EPP x86: msr-index.h: fix shifts to ULL results in HWP macros. x86: msr-index.h: define HWP.EPP values x86: msr-index.h: define EPB mid-points
-rw-r--r--arch/x86/include/asm/msr-index.h18
-rw-r--r--drivers/cpufreq/intel_pstate.c34
-rw-r--r--tools/power/x86/x86_energy_perf_policy/Makefile27
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8241
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c1504
5 files changed, 1527 insertions, 297 deletions
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 673f9ac50f6d..d8638e2419cc 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -249,9 +249,13 @@
249#define HWP_MIN_PERF(x) (x & 0xff) 249#define HWP_MIN_PERF(x) (x & 0xff)
250#define HWP_MAX_PERF(x) ((x & 0xff) << 8) 250#define HWP_MAX_PERF(x) ((x & 0xff) << 8)
251#define HWP_DESIRED_PERF(x) ((x & 0xff) << 16) 251#define HWP_DESIRED_PERF(x) ((x & 0xff) << 16)
252#define HWP_ENERGY_PERF_PREFERENCE(x) ((x & 0xff) << 24) 252#define HWP_ENERGY_PERF_PREFERENCE(x) (((unsigned long long) x & 0xff) << 24)
253#define HWP_ACTIVITY_WINDOW(x) ((x & 0xff3) << 32) 253#define HWP_EPP_PERFORMANCE 0x00
254#define HWP_PACKAGE_CONTROL(x) ((x & 0x1) << 42) 254#define HWP_EPP_BALANCE_PERFORMANCE 0x80
255#define HWP_EPP_BALANCE_POWERSAVE 0xC0
256#define HWP_EPP_POWERSAVE 0xFF
257#define HWP_ACTIVITY_WINDOW(x) ((unsigned long long)(x & 0xff3) << 32)
258#define HWP_PACKAGE_CONTROL(x) ((unsigned long long)(x & 0x1) << 42)
255 259
256/* IA32_HWP_STATUS */ 260/* IA32_HWP_STATUS */
257#define HWP_GUARANTEED_CHANGE(x) (x & 0x1) 261#define HWP_GUARANTEED_CHANGE(x) (x & 0x1)
@@ -474,9 +478,11 @@
474#define MSR_MISC_PWR_MGMT 0x000001aa 478#define MSR_MISC_PWR_MGMT 0x000001aa
475 479
476#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 480#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
477#define ENERGY_PERF_BIAS_PERFORMANCE 0 481#define ENERGY_PERF_BIAS_PERFORMANCE 0
478#define ENERGY_PERF_BIAS_NORMAL 6 482#define ENERGY_PERF_BIAS_BALANCE_PERFORMANCE 4
479#define ENERGY_PERF_BIAS_POWERSAVE 15 483#define ENERGY_PERF_BIAS_NORMAL 6
484#define ENERGY_PERF_BIAS_BALANCE_POWERSAVE 8
485#define ENERGY_PERF_BIAS_POWERSAVE 15
480 486
481#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1 487#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1
482 488
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index b7de5bd76a31..36ba6082d084 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -652,6 +652,12 @@ static const char * const energy_perf_strings[] = {
652 "power", 652 "power",
653 NULL 653 NULL
654}; 654};
655static const unsigned int epp_values[] = {
656 HWP_EPP_PERFORMANCE,
657 HWP_EPP_BALANCE_PERFORMANCE,
658 HWP_EPP_BALANCE_POWERSAVE,
659 HWP_EPP_POWERSAVE
660};
655 661
656static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data) 662static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data)
657{ 663{
@@ -663,17 +669,14 @@ static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data)
663 return epp; 669 return epp;
664 670
665 if (static_cpu_has(X86_FEATURE_HWP_EPP)) { 671 if (static_cpu_has(X86_FEATURE_HWP_EPP)) {
666 /* 672 if (epp == HWP_EPP_PERFORMANCE)
667 * Range: 673 return 1;
668 * 0x00-0x3F : Performance 674 if (epp <= HWP_EPP_BALANCE_PERFORMANCE)
669 * 0x40-0x7F : Balance performance 675 return 2;
670 * 0x80-0xBF : Balance power 676 if (epp <= HWP_EPP_BALANCE_POWERSAVE)
671 * 0xC0-0xFF : Power 677 return 3;
672 * The EPP is a 8 bit value, but our ranges restrict the 678 else
673 * value which can be set. Here only using top two bits 679 return 4;
674 * effectively.
675 */
676 index = (epp >> 6) + 1;
677 } else if (static_cpu_has(X86_FEATURE_EPB)) { 680 } else if (static_cpu_has(X86_FEATURE_EPB)) {
678 /* 681 /*
679 * Range: 682 * Range:
@@ -711,15 +714,8 @@ static int intel_pstate_set_energy_pref_index(struct cpudata *cpu_data,
711 714
712 value &= ~GENMASK_ULL(31, 24); 715 value &= ~GENMASK_ULL(31, 24);
713 716
714 /*
715 * If epp is not default, convert from index into
716 * energy_perf_strings to epp value, by shifting 6
717 * bits left to use only top two bits in epp.
718 * The resultant epp need to shifted by 24 bits to
719 * epp position in MSR_HWP_REQUEST.
720 */
721 if (epp == -EINVAL) 717 if (epp == -EINVAL)
722 epp = (pref_index - 1) << 6; 718 epp = epp_values[pref_index - 1];
723 719
724 value |= (u64)epp << 24; 720 value |= (u64)epp << 24;
725 ret = wrmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, value); 721 ret = wrmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, value);
diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile
index 971c9ffdcb50..a711eec0c895 100644
--- a/tools/power/x86/x86_energy_perf_policy/Makefile
+++ b/tools/power/x86/x86_energy_perf_policy/Makefile
@@ -1,10 +1,27 @@
1DESTDIR ?= 1CC = $(CROSS_COMPILE)gcc
2BUILD_OUTPUT := $(CURDIR)
3PREFIX := /usr
4DESTDIR :=
5
6ifeq ("$(origin O)", "command line")
7 BUILD_OUTPUT := $(O)
8endif
2 9
3x86_energy_perf_policy : x86_energy_perf_policy.c 10x86_energy_perf_policy : x86_energy_perf_policy.c
11CFLAGS += -Wall
12CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
13
14%: %.c
15 @mkdir -p $(BUILD_OUTPUT)
16 $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@
4 17
18.PHONY : clean
5clean : 19clean :
6 rm -f x86_energy_perf_policy 20 @rm -f $(BUILD_OUTPUT)/x86_energy_perf_policy
21
22install : x86_energy_perf_policy
23 install -d $(DESTDIR)$(PREFIX)/bin
24 install $(BUILD_OUTPUT)/x86_energy_perf_policy $(DESTDIR)$(PREFIX)/bin/x86_energy_perf_policy
25 install -d $(DESTDIR)$(PREFIX)/share/man/man8
26 install x86_energy_perf_policy.8 $(DESTDIR)$(PREFIX)/share/man/man8
7 27
8install :
9 install x86_energy_perf_policy ${DESTDIR}/usr/bin/
10 install x86_energy_perf_policy.8 ${DESTDIR}/usr/share/man/man8/
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
index 8eaaad648cdb..17db1c3af4d0 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
@@ -1,104 +1,213 @@
1.\" This page Copyright (C) 2010 Len Brown <len.brown@intel.com> 1.\" This page Copyright (C) 2010 - 2015 Len Brown <len.brown@intel.com>
2.\" Distributed under the GPL, Copyleft 1994. 2.\" Distributed under the GPL, Copyleft 1994.
3.TH X86_ENERGY_PERF_POLICY 8 3.TH X86_ENERGY_PERF_POLICY 8
4.SH NAME 4.SH NAME
5x86_energy_perf_policy \- read or write MSR_IA32_ENERGY_PERF_BIAS 5x86_energy_perf_policy \- Manage Energy vs. Performance Policy via x86 Model Specific Registers
6.SH SYNOPSIS 6.SH SYNOPSIS
7.ft B
8.B x86_energy_perf_policy 7.B x86_energy_perf_policy
9.RB [ "\-c cpu" ] 8.RB "[ options ] [ scope ] [field \ value]"
10.RB [ "\-v" ]
11.RB "\-r"
12.br 9.br
13.B x86_energy_perf_policy 10.RB "scope: \-\-cpu\ cpu-list | \-\-pkg\ pkg-list"
14.RB [ "\-c cpu" ]
15.RB [ "\-v" ]
16.RB 'performance'
17.br 11.br
18.B x86_energy_perf_policy 12.RB "cpu-list, pkg-list: # | #,# | #-# | all"
19.RB [ "\-c cpu" ]
20.RB [ "\-v" ]
21.RB 'normal'
22.br 13.br
23.B x86_energy_perf_policy 14.RB "field: \-\-all | \-\-epb | \-\-hwp-epp | \-\-hwp-min | \-\-hwp-max | \-\-hwp-desired"
24.RB [ "\-c cpu" ]
25.RB [ "\-v" ]
26.RB 'powersave'
27.br 15.br
28.B x86_energy_perf_policy 16.RB "other: (\-\-force | \-\-hwp-enable | \-\-turbo-enable) value)"
29.RB [ "\-c cpu" ]
30.RB [ "\-v" ]
31.RB n
32.br 17.br
18.RB "value: # | default | performance | balance-performance | balance-power | power"
33.SH DESCRIPTION 19.SH DESCRIPTION
34\fBx86_energy_perf_policy\fP 20\fBx86_energy_perf_policy\fP
35allows software to convey 21displays and updates energy-performance policy settings specific to
36its policy for the relative importance of performance 22Intel Architecture Processors. Settings are accessed via Model Specific Register (MSR)
37versus energy savings to the processor. 23updates, no matter if the Linux cpufreq sub-system is enabled or not.
38 24
39The processor uses this information in model-specific ways 25Policy in MSR_IA32_ENERGY_PERF_BIAS (EPB)
40when it must select trade-offs between performance and 26may affect a wide range of hardware decisions,
41energy efficiency. 27such as how aggressively the hardware enters and exits CPU idle states (C-states)
28and Processor Performance States (P-states).
29This policy hint does not replace explicit OS C-state and P-state selection.
30Rather, it tells the hardware how aggressively to implement those selections.
31Further, it allows the OS to influence energy/performance trade-offs where there
32is no software interface, such as in the opportunistic "turbo-mode" P-state range.
33Note that MSR_IA32_ENERGY_PERF_BIAS is defined per CPU,
34but some implementations
35share a single MSR among all CPUs in each processor package.
36On those systems, a write to EPB on one processor will
37be visible, and will have an effect, on all CPUs
38in the same processor package.
42 39
43This policy hint does not supersede Processor Performance states 40Hardware P-States (HWP) are effectively an expansion of hardware
44(P-states) or CPU Idle power states (C-states), but allows 41P-state control from the opportunistic turbo-mode P-state range
45software to have influence where it would otherwise be unable 42to include the entire range of available P-states.
46to express a preference. 43On Broadwell Xeon, the initial HWP implementation, EBP influenced HWP.
44That influence was removed in subsequent generations,
45where it was moved to the
46Energy_Performance_Preference (EPP) field in
47a pair of dedicated MSRs -- MSR_IA32_HWP_REQUEST and MSR_IA32_HWP_REQUEST_PKG.
47 48
48For example, this setting may tell the hardware how 49EPP is the most commonly managed knob in HWP mode,
49aggressively or conservatively to control frequency 50but MSR_IA32_HWP_REQUEST also allows the user to specify
50in the "turbo range" above the explicitly OS-controlled 51minimum-frequency for Quality-of-Service,
51P-state frequency range. It may also tell the hardware 52and maximum-frequency for power-capping.
52how aggressively is should enter the OS requested C-states. 53MSR_IA32_HWP_REQUEST is defined per-CPU.
53 54
54Support for this feature is indicated by CPUID.06H.ECX.bit3 55MSR_IA32_HWP_REQUEST_PKG has the same capability as MSR_IA32_HWP_REQUEST,
55per the Intel Architectures Software Developer's Manual. 56but it can simultaneously set the default policy for all CPUs within a package.
57A bit in per-CPU MSR_IA32_HWP_REQUEST indicates whether it is
58over-ruled-by or exempt-from MSR_IA32_HWP_REQUEST_PKG.
56 59
57.SS Options 60MSR_HWP_CAPABILITIES shows the default values for the fields
58\fB-c\fP limits operation to a single CPU. 61in MSR_IA32_HWP_REQUEST. It is displayed when no values
59The default is to operate on all CPUs. 62are being written.
60Note that MSR_IA32_ENERGY_PERF_BIAS is defined per 63
61logical processor, but that the initial implementations 64.SS SCOPE OPTIONS
62of the MSR were shared among all processors in each package.
63.PP
64\fB-v\fP increases verbosity. By default
65x86_energy_perf_policy is silent.
66.PP
67\fB-r\fP is for "read-only" mode - the unchanged state
68is read and displayed.
69.PP 65.PP
70.I performance 66\fB-c, --cpu\fP Operate on the MSR_IA32_HWP_REQUEST for each CPU in a CPU-list.
71Set a policy where performance is paramount. 67The CPU-list may be comma-separated CPU numbers, with dash for range
72The processor will be unwilling to sacrifice any performance 68or the string "all". Eg. '--cpu 1,4,6-8' or '--cpu all'.
73for the sake of energy saving. This is the hardware default. 69When --cpu is used, \fB--hwp-use-pkg\fP is available, which specifies whether the per-cpu
70MSR_IA32_HWP_REQUEST should be over-ruled by MSR_IA32_HWP_REQUEST_PKG (1),
71or exempt from MSR_IA32_HWP_REQUEST_PKG (0).
72
73\fB-p, --pkg\fP Operate on the MSR_IA32_HWP_REQUEST_PKG for each package in the package-list.
74The list is a string of individual package numbers separated
75by commas, and or ranges of package numbers separated by a dash,
76or the string "all".
77For example '--pkg 1,3' or '--pkg all'
78
79.SS VALUE OPTIONS
74.PP 80.PP
75.I normal 81.I normal | default
76Set a policy with a normal balance between performance and energy efficiency. 82Set a policy with a normal balance between performance and energy efficiency.
77The processor will tolerate minor performance compromise 83The processor will tolerate minor performance compromise
78for potentially significant energy savings. 84for potentially significant energy savings.
79This reasonable default for most desktops and servers. 85This is a reasonable default for most desktops and servers.
86"default" is a synonym for "normal".
80.PP 87.PP
81.I powersave 88.I performance
89Set a policy for maximum performance,
90accepting no performance sacrifice for the benefit of energy efficiency.
91.PP
92.I balance-performance
93Set a policy with a high priority on performance,
94but allowing some performance loss to benefit energy efficiency.
95.PP
96.I balance-power
97Set a policy where the performance and power are balanced.
98This is the default.
99.PP
100.I power
82Set a policy where the processor can accept 101Set a policy where the processor can accept
83a measurable performance hit to maximize energy efficiency. 102a measurable performance impact to maximize energy efficiency.
103
84.PP 104.PP
85.I n 105The following table shows the mapping from the value strings above to actual MSR values.
86Set MSR_IA32_ENERGY_PERF_BIAS to the specified number. 106This mapping is defined in the Linux-kernel header, msr-index.h.
87The range of valid numbers is 0-15, where 0 is maximum
88performance and 15 is maximum energy efficiency.
89 107
108.nf
109VALUE STRING EPB EPP
110performance 0 0
111balance-performance 4 128
112normal, default 6 128
113balance-power 8 192
114power 15 255
115.fi
116.PP
117For MSR_IA32_HWP_REQUEST performance fields
118(--hwp-min, --hwp-max, --hwp-desired), the value option
119is in units of 100 MHz, Eg. 12 signifies 1200 MHz.
120
121.SS FIELD OPTIONS
122\fB-a, --all value-string\fP Sets all EPB and EPP and HWP limit fields to the value associated with
123the value-string. In addition, enables turbo-mode and HWP-mode, if they were previous disabled.
124Thus "--all normal" will set a system without cpufreq into a well known configuration.
125.PP
126\fB-B, --epb\fP set EPB per-core or per-package.
127See value strings in the table above.
128.PP
129\fB-d, --debug\fP debug increases verbosity. By default
130x86_energy_perf_policy is silent for updates,
131and verbose for read-only mode.
132.PP
133\fB-P, --hwp-epp\fP set HWP.EPP per-core or per-package.
134See value strings in the table above.
135.PP
136\fB-m, --hwp-min\fP request HWP to not go below the specified core/bus ratio.
137The "default" is the value found in IA32_HWP_CAPABILITIES.min.
138.PP
139\fB-M, --hwp-max\fP request HWP not exceed a the specified core/bus ratio.
140The "default" is the value found in IA32_HWP_CAPABILITIES.max.
141.PP
142\fB-D, --hwp-desired\fP request HWP 'desired' frequency.
143The "normal" setting is 0, which
144corresponds to 'full autonomous' HWP control.
145Non-zero performance values request a specific performance
146level on this processor, specified in multiples of 100 MHz.
147.PP
148\fB-w, --hwp-window\fP specify integer number of microsec
149in the sliding window that HWP uses to maintain average frequency.
150This parameter is meaningful only when the "desired" field above is non-zero.
151Default is 0, allowing the HW to choose.
152.SH OTHER OPTIONS
153.PP
154\fB-f, --force\fP writes the specified values without bounds checking.
155.PP
156\fB-U, --hwp-use-pkg\fP (0 | 1), when used in conjunction with --cpu,
157indicates whether the per-CPU MSR_IA32_HWP_REQUEST should be overruled (1)
158or exempt (0) from per-Package MSR_IA32_HWP_REQUEST_PKG settings.
159The default is exempt.
160.PP
161\fB-H, --hwp-enable\fP enable HardWare-P-state (HWP) mode. Once enabled, system RESET is required to disable HWP mode.
162.PP
163\fB-t, --turbo-enable\fP enable (1) or disable (0) turbo mode.
164.PP
165\fB-v, --version\fP print version and exit.
166.PP
167If no request to change policy is made,
168the default behavior is to read
169and display the current system state,
170including the default capabilities.
171.SH WARNING
172.PP
173This utility writes directly to Model Specific Registers.
174There is no locking or coordination should this utility
175be used to modify HWP limit fields at the same time that
176intel_pstate's sysfs attributes access the same MSRs.
177.PP
178Note that --hwp-desired and --hwp-window are considered experimental.
179Future versions of Linux reserve the right to access these
180fields internally -- potentially conflicting with user-space access.
181.SH EXAMPLE
182.nf
183# sudo x86_energy_perf_policy
184cpu0: EPB 6
185cpu0: HWP_REQ: min 6 max 35 des 0 epp 128 window 0x0 (0*10^0us) use_pkg 0
186cpu0: HWP_CAP: low 1 eff 8 guar 27 high 35
187cpu1: EPB 6
188cpu1: HWP_REQ: min 6 max 35 des 0 epp 128 window 0x0 (0*10^0us) use_pkg 0
189cpu1: HWP_CAP: low 1 eff 8 guar 27 high 35
190cpu2: EPB 6
191cpu2: HWP_REQ: min 6 max 35 des 0 epp 128 window 0x0 (0*10^0us) use_pkg 0
192cpu2: HWP_CAP: low 1 eff 8 guar 27 high 35
193cpu3: EPB 6
194cpu3: HWP_REQ: min 6 max 35 des 0 epp 128 window 0x0 (0*10^0us) use_pkg 0
195cpu3: HWP_CAP: low 1 eff 8 guar 27 high 35
196.fi
90.SH NOTES 197.SH NOTES
91.B "x86_energy_perf_policy " 198.B "x86_energy_perf_policy"
92runs only as root. 199runs only as root.
93.SH FILES 200.SH FILES
94.ta 201.ta
95.nf 202.nf
96/dev/cpu/*/msr 203/dev/cpu/*/msr
97.fi 204.fi
98
99.SH "SEE ALSO" 205.SH "SEE ALSO"
206.nf
100msr(4) 207msr(4)
208Intel(R) 64 and IA-32 Architectures Software Developer's Manual
209.fi
101.PP 210.PP
102.SH AUTHORS 211.SH AUTHORS
103.nf 212.nf
104Written by Len Brown <len.brown@intel.com> 213Len Brown
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
index 40b3e5482f8a..65bbe627a425 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
@@ -3,322 +3,1424 @@
3 * policy preference bias on recent X86 processors. 3 * policy preference bias on recent X86 processors.
4 */ 4 */
5/* 5/*
6 * Copyright (c) 2010, Intel Corporation. 6 * Copyright (c) 2010 - 2017 Intel Corporation.
7 * Len Brown <len.brown@intel.com> 7 * Len Brown <len.brown@intel.com>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify it 9 * This program is released under GPL v2
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 */ 10 */
22 11
12#define _GNU_SOURCE
13#include MSRHEADER
23#include <stdio.h> 14#include <stdio.h>
24#include <unistd.h> 15#include <unistd.h>
25#include <sys/types.h> 16#include <sys/types.h>
17#include <sched.h>
26#include <sys/stat.h> 18#include <sys/stat.h>
27#include <sys/resource.h> 19#include <sys/resource.h>
20#include <getopt.h>
21#include <err.h>
28#include <fcntl.h> 22#include <fcntl.h>
29#include <signal.h> 23#include <signal.h>
30#include <sys/time.h> 24#include <sys/time.h>
25#include <limits.h>
31#include <stdlib.h> 26#include <stdlib.h>
32#include <string.h> 27#include <string.h>
28#include <cpuid.h>
29#include <errno.h>
30
31#define OPTARG_NORMAL (INT_MAX - 1)
32#define OPTARG_POWER (INT_MAX - 2)
33#define OPTARG_BALANCE_POWER (INT_MAX - 3)
34#define OPTARG_BALANCE_PERFORMANCE (INT_MAX - 4)
35#define OPTARG_PERFORMANCE (INT_MAX - 5)
36
37struct msr_hwp_cap {
38 unsigned char highest;
39 unsigned char guaranteed;
40 unsigned char efficient;
41 unsigned char lowest;
42};
33 43
34unsigned int verbose; /* set with -v */ 44struct msr_hwp_request {
35unsigned int read_only; /* set with -r */ 45 unsigned char hwp_min;
46 unsigned char hwp_max;
47 unsigned char hwp_desired;
48 unsigned char hwp_epp;
49 unsigned int hwp_window;
50 unsigned char hwp_use_pkg;
51} req_update;
52
53unsigned int debug;
54unsigned int verbose;
55unsigned int force;
36char *progname; 56char *progname;
37unsigned long long new_bias; 57int base_cpu;
38int cpu = -1; 58unsigned char update_epb;
59unsigned long long new_epb;
60unsigned char turbo_is_enabled;
61unsigned char update_turbo;
62unsigned char turbo_update_value;
63unsigned char update_hwp_epp;
64unsigned char update_hwp_min;
65unsigned char update_hwp_max;
66unsigned char update_hwp_desired;
67unsigned char update_hwp_window;
68unsigned char update_hwp_use_pkg;
69unsigned 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)
71int max_cpu_num;
72int max_pkg_num;
73#define MAX_PACKAGES 64
74unsigned int first_cpu_in_pkg[MAX_PACKAGES];
75unsigned long long pkg_present_set;
76unsigned long long pkg_selected_set;
77cpu_set_t *cpu_present_set;
78cpu_set_t *cpu_selected_set;
79int genuine_intel;
80
81size_t cpu_setsize;
82
83char *proc_stat = "/proc/stat";
84
85unsigned int has_epb; /* MSR_IA32_ENERGY_PERF_BIAS */
86unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
87 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */
88unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */
89unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */
90unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
91unsigned int has_hwp_request_pkg; /* IA32_HWP_REQUEST_PKG */
92
93unsigned int bdx_highest_ratio;
39 94
40/* 95/*
41 * Usage: 96 * maintain compatibility with original implementation, but don't document it:
42 *
43 * -c cpu: limit action to a single CPU (default is all CPUs)
44 * -v: verbose output (can invoke more than once)
45 * -r: read-only, don't change any settings
46 *
47 * performance
48 * Performance is paramount.
49 * Unwilling to sacrifice any performance
50 * for the sake of energy saving. (hardware default)
51 *
52 * normal
53 * Can tolerate minor performance compromise
54 * for potentially significant energy savings.
55 * (reasonable default for most desktops and servers)
56 *
57 * powersave
58 * Can tolerate significant performance hit
59 * to maximize energy savings.
60 *
61 * n
62 * a numerical value to write to the underlying MSR.
63 */ 97 */
64void usage(void) 98void usage(void)
65{ 99{
66 printf("%s: [-c cpu] [-v] " 100 fprintf(stderr, "%s [options] [scope][field value]\n", progname);
67 "(-r | 'performance' | 'normal' | 'powersave' | n)\n", 101 fprintf(stderr, "scope: --cpu cpu-list [--hwp-use-pkg #] | --pkg pkg-list\n");
68 progname); 102 fprintf(stderr, "field: --all | --epb | --hwp-epp | --hwp-min | --hwp-max | --hwp-desired\n");
103 fprintf(stderr, "other: --hwp-enable | --turbo-enable (0 | 1) | --help | --force\n");
104 fprintf(stderr,
105 "value: ( # | \"normal\" | \"performance\" | \"balance-performance\" | \"balance-power\"| \"power\")\n");
106 fprintf(stderr, "--hwp-window usec\n");
107
108 fprintf(stderr, "Specify only Energy Performance BIAS (legacy usage):\n");
109 fprintf(stderr, "%s: [-c cpu] [-v] (-r | policy-value )\n", progname);
110
69 exit(1); 111 exit(1);
70} 112}
71 113
72#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 114/*
115 * If bdx_highest_ratio is set,
116 * then we must translate between MSR format and simple ratio
117 * used on the cmdline.
118 */
119int ratio_2_msr_perf(int ratio)
120{
121 int msr_perf;
122
123 if (!bdx_highest_ratio)
124 return ratio;
125
126 msr_perf = ratio * 255 / bdx_highest_ratio;
127
128 if (debug)
129 fprintf(stderr, "%d = ratio_to_msr_perf(%d)\n", msr_perf, ratio);
130
131 return msr_perf;
132}
133int msr_perf_2_ratio(int msr_perf)
134{
135 int ratio;
136 double d;
137
138 if (!bdx_highest_ratio)
139 return msr_perf;
140
141 d = (double)msr_perf * (double) bdx_highest_ratio / 255.0;
142 d = d + 0.5; /* round */
143 ratio = (int)d;
144
145 if (debug)
146 fprintf(stderr, "%d = msr_perf_ratio(%d) {%f}\n", ratio, msr_perf, d);
147
148 return ratio;
149}
150int parse_cmdline_epb(int i)
151{
152 if (!has_epb)
153 errx(1, "EPB not enabled on this platform");
154
155 update_epb = 1;
156
157 switch (i) {
158 case OPTARG_POWER:
159 return ENERGY_PERF_BIAS_POWERSAVE;
160 case OPTARG_BALANCE_POWER:
161 return ENERGY_PERF_BIAS_BALANCE_POWERSAVE;
162 case OPTARG_NORMAL:
163 return ENERGY_PERF_BIAS_NORMAL;
164 case OPTARG_BALANCE_PERFORMANCE:
165 return ENERGY_PERF_BIAS_BALANCE_PERFORMANCE;
166 case OPTARG_PERFORMANCE:
167 return ENERGY_PERF_BIAS_PERFORMANCE;
168 }
169 if (i < 0 || i > ENERGY_PERF_BIAS_POWERSAVE)
170 errx(1, "--epb must be from 0 to 15");
171 return i;
172}
173
174#define HWP_CAP_LOWEST 0
175#define HWP_CAP_HIGHEST 255
176
177/*
178 * "performance" changes hwp_min to cap.highest
179 * All others leave it at cap.lowest
180 */
181int parse_cmdline_hwp_min(int i)
182{
183 update_hwp_min = 1;
184
185 switch (i) {
186 case OPTARG_POWER:
187 case OPTARG_BALANCE_POWER:
188 case OPTARG_NORMAL:
189 case OPTARG_BALANCE_PERFORMANCE:
190 return HWP_CAP_LOWEST;
191 case OPTARG_PERFORMANCE:
192 return HWP_CAP_HIGHEST;
193 }
194 return i;
195}
196/*
197 * "power" changes hwp_max to cap.lowest
198 * All others leave it at cap.highest
199 */
200int parse_cmdline_hwp_max(int i)
201{
202 update_hwp_max = 1;
203
204 switch (i) {
205 case OPTARG_POWER:
206 return HWP_CAP_LOWEST;
207 case OPTARG_NORMAL:
208 case OPTARG_BALANCE_POWER:
209 case OPTARG_BALANCE_PERFORMANCE:
210 case OPTARG_PERFORMANCE:
211 return HWP_CAP_HIGHEST;
212 }
213 return i;
214}
215/*
216 * for --hwp-des, all strings leave it in autonomous mode
217 * If you want to change it, you need to explicitly pick a value
218 */
219int parse_cmdline_hwp_desired(int i)
220{
221 update_hwp_desired = 1;
222
223 switch (i) {
224 case OPTARG_POWER:
225 case OPTARG_BALANCE_POWER:
226 case OPTARG_BALANCE_PERFORMANCE:
227 case OPTARG_NORMAL:
228 case OPTARG_PERFORMANCE:
229 return 0; /* autonomous */
230 }
231 return i;
232}
233
234int parse_cmdline_hwp_window(int i)
235{
236 unsigned int exponent;
237
238 update_hwp_window = 1;
239
240 switch (i) {
241 case OPTARG_POWER:
242 case OPTARG_BALANCE_POWER:
243 case OPTARG_NORMAL:
244 case OPTARG_BALANCE_PERFORMANCE:
245 case OPTARG_PERFORMANCE:
246 return 0;
247 }
248 if (i < 0 || i > 1270000000) {
249 fprintf(stderr, "--hwp-window: 0 for auto; 1 - 1270000000 usec for window duration\n");
250 usage();
251 }
252 for (exponent = 0; ; ++exponent) {
253 if (debug)
254 printf("%d 10^%d\n", i, exponent);
255
256 if (i <= 127)
257 break;
258
259 i = i / 10;
260 }
261 if (debug)
262 fprintf(stderr, "%d*10^%d: 0x%x\n", i, exponent, (exponent << 7) | i);
263
264 return (exponent << 7) | i;
265}
266int parse_cmdline_hwp_epp(int i)
267{
268 update_hwp_epp = 1;
269
270 switch (i) {
271 case OPTARG_POWER:
272 return HWP_EPP_POWERSAVE;
273 case OPTARG_BALANCE_POWER:
274 return HWP_EPP_BALANCE_POWERSAVE;
275 case OPTARG_NORMAL:
276 case OPTARG_BALANCE_PERFORMANCE:
277 return HWP_EPP_BALANCE_PERFORMANCE;
278 case OPTARG_PERFORMANCE:
279 return HWP_EPP_PERFORMANCE;
280 }
281 if (i < 0 || i > 0xff) {
282 fprintf(stderr, "--hwp-epp must be from 0 to 0xff\n");
283 usage();
284 }
285 return i;
286}
287int parse_cmdline_turbo(int i)
288{
289 update_turbo = 1;
290
291 switch (i) {
292 case OPTARG_POWER:
293 return 0;
294 case OPTARG_NORMAL:
295 case OPTARG_BALANCE_POWER:
296 case OPTARG_BALANCE_PERFORMANCE:
297 case OPTARG_PERFORMANCE:
298 return 1;
299 }
300 if (i < 0 || i > 1) {
301 fprintf(stderr, "--turbo-enable: 1 to enable, 0 to disable\n");
302 usage();
303 }
304 return i;
305}
306
307int parse_optarg_string(char *s)
308{
309 int i;
310 char *endptr;
311
312 if (!strncmp(s, "default", 7))
313 return OPTARG_NORMAL;
314
315 if (!strncmp(s, "normal", 6))
316 return OPTARG_NORMAL;
317
318 if (!strncmp(s, "power", 9))
319 return OPTARG_POWER;
320
321 if (!strncmp(s, "balance-power", 17))
322 return OPTARG_BALANCE_POWER;
323
324 if (!strncmp(s, "balance-performance", 19))
325 return OPTARG_BALANCE_PERFORMANCE;
326
327 if (!strncmp(s, "performance", 11))
328 return OPTARG_PERFORMANCE;
329
330 i = strtol(s, &endptr, 0);
331 if (s == endptr) {
332 fprintf(stderr, "no digits in \"%s\"\n", s);
333 usage();
334 }
335 if (i == LONG_MIN || i == LONG_MAX)
336 errx(-1, "%s", s);
337
338 if (i > 0xFF)
339 errx(-1, "%d (0x%x) must be < 256", i, i);
340
341 if (i < 0)
342 errx(-1, "%d (0x%x) must be >= 0", i, i);
343 return i;
344}
345
346void parse_cmdline_all(char *s)
347{
348 force++;
349 update_hwp_enable = 1;
350 req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(s));
351 req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(s));
352 req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(s));
353 if (has_epb)
354 new_epb = parse_cmdline_epb(parse_optarg_string(s));
355 turbo_update_value = parse_cmdline_turbo(parse_optarg_string(s));
356 req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(s));
357 req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(s));
358}
359
360void validate_cpu_selected_set(void)
361{
362 int cpu;
363
364 if (CPU_COUNT_S(cpu_setsize, cpu_selected_set) == 0)
365 errx(0, "no CPUs requested");
366
367 for (cpu = 0; cpu <= max_cpu_num; ++cpu) {
368 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_selected_set))
369 if (!CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
370 errx(1, "Requested cpu% is not present", cpu);
371 }
372}
373
374void parse_cmdline_cpu(char *s)
375{
376 char *startp, *endp;
377 int cpu = 0;
378
379 if (pkg_selected_set) {
380 usage();
381 errx(1, "--cpu | --pkg");
382 }
383 cpu_selected_set = CPU_ALLOC((max_cpu_num + 1));
384 if (cpu_selected_set == NULL)
385 err(1, "cpu_selected_set");
386 CPU_ZERO_S(cpu_setsize, cpu_selected_set);
387
388 for (startp = s; startp && *startp;) {
389
390 if (*startp == ',') {
391 startp++;
392 continue;
393 }
394
395 if (*startp == '-') {
396 int end_cpu;
73 397
74#define BIAS_PERFORMANCE 0 398 startp++;
75#define BIAS_BALANCE 6 399 end_cpu = strtol(startp, &endp, 10);
76#define BIAS_POWERSAVE 15 400 if (startp == endp)
401 continue;
402
403 while (cpu <= end_cpu) {
404 if (cpu > max_cpu_num)
405 errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num);
406 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
407 cpu++;
408 }
409 startp = endp;
410 continue;
411 }
412
413 if (strncmp(startp, "all", 3) == 0) {
414 for (cpu = 0; cpu <= max_cpu_num; cpu += 1) {
415 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
416 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
417 }
418 startp += 3;
419 if (*startp == 0)
420 break;
421 }
422 /* "--cpu even" is not documented */
423 if (strncmp(startp, "even", 4) == 0) {
424 for (cpu = 0; cpu <= max_cpu_num; cpu += 2) {
425 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
426 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
427 }
428 startp += 4;
429 if (*startp == 0)
430 break;
431 }
432
433 /* "--cpu odd" is not documented */
434 if (strncmp(startp, "odd", 3) == 0) {
435 for (cpu = 1; cpu <= max_cpu_num; cpu += 2) {
436 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
437 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
438 }
439 startp += 3;
440 if (*startp == 0)
441 break;
442 }
443
444 cpu = strtol(startp, &endp, 10);
445 if (startp == endp)
446 errx(1, "--cpu cpu-set: confused by '%s'", startp);
447 if (cpu > max_cpu_num)
448 errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num);
449 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
450 startp = endp;
451 }
452
453 validate_cpu_selected_set();
454
455}
456
457void parse_cmdline_pkg(char *s)
458{
459 char *startp, *endp;
460 int pkg = 0;
461
462 if (cpu_selected_set) {
463 usage();
464 errx(1, "--pkg | --cpu");
465 }
466 pkg_selected_set = 0;
467
468 for (startp = s; startp && *startp;) {
469
470 if (*startp == ',') {
471 startp++;
472 continue;
473 }
474
475 if (*startp == '-') {
476 int end_pkg;
477
478 startp++;
479 end_pkg = strtol(startp, &endp, 10);
480 if (startp == endp)
481 continue;
482
483 while (pkg <= end_pkg) {
484 if (pkg > max_pkg_num)
485 errx(1, "Requested pkg%d exceeds max pkg%d", pkg, max_pkg_num);
486 pkg_selected_set |= 1 << pkg;
487 pkg++;
488 }
489 startp = endp;
490 continue;
491 }
492
493 if (strncmp(startp, "all", 3) == 0) {
494 pkg_selected_set = pkg_present_set;
495 return;
496 }
497
498 pkg = strtol(startp, &endp, 10);
499 if (pkg > max_pkg_num)
500 errx(1, "Requested pkg%d Exceeds max pkg%d", pkg, max_pkg_num);
501 pkg_selected_set |= 1 << pkg;
502 startp = endp;
503 }
504}
505
506void for_packages(unsigned long long pkg_set, int (func)(int))
507{
508 int pkg_num;
509
510 for (pkg_num = 0; pkg_num <= max_pkg_num; ++pkg_num) {
511 if (pkg_set & (1UL << pkg_num))
512 func(pkg_num);
513 }
514}
515
516void print_version(void)
517{
518 printf("x86_energy_perf_policy 17.05.11 (C) Len Brown <len.brown@intel.com>\n");
519}
77 520
78void cmdline(int argc, char **argv) 521void cmdline(int argc, char **argv)
79{ 522{
80 int opt; 523 int opt;
524 int option_index = 0;
525
526 static struct option long_options[] = {
527 {"all", required_argument, 0, 'a'},
528 {"cpu", required_argument, 0, 'c'},
529 {"pkg", required_argument, 0, 'p'},
530 {"debug", no_argument, 0, 'd'},
531 {"hwp-desired", required_argument, 0, 'D'},
532 {"epb", required_argument, 0, 'B'},
533 {"force", no_argument, 0, 'f'},
534 {"hwp-enable", no_argument, 0, 'e'},
535 {"help", no_argument, 0, 'h'},
536 {"hwp-epp", required_argument, 0, 'P'},
537 {"hwp-min", required_argument, 0, 'm'},
538 {"hwp-max", required_argument, 0, 'M'},
539 {"read", no_argument, 0, 'r'},
540 {"turbo-enable", required_argument, 0, 't'},
541 {"hwp-use-pkg", required_argument, 0, 'u'},
542 {"version", no_argument, 0, 'v'},
543 {"hwp-window", required_argument, 0, 'w'},
544 {0, 0, 0, 0 }
545 };
81 546
82 progname = argv[0]; 547 progname = argv[0];
83 548
84 while ((opt = getopt(argc, argv, "+rvc:")) != -1) { 549 while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw",
550 long_options, &option_index)) != -1) {
85 switch (opt) { 551 switch (opt) {
552 case 'a':
553 parse_cmdline_all(optarg);
554 break;
555 case 'B':
556 new_epb = parse_cmdline_epb(parse_optarg_string(optarg));
557 break;
86 case 'c': 558 case 'c':
87 cpu = atoi(optarg); 559 parse_cmdline_cpu(optarg);
560 break;
561 case 'e':
562 update_hwp_enable = 1;
563 break;
564 case 'h':
565 usage();
566 break;
567 case 'd':
568 debug++;
569 verbose++;
570 break;
571 case 'f':
572 force++;
573 break;
574 case 'D':
575 req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(optarg));
576 break;
577 case 'm':
578 req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(optarg));
579 break;
580 case 'M':
581 req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(optarg));
582 break;
583 case 'p':
584 parse_cmdline_pkg(optarg);
585 break;
586 case 'P':
587 req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(optarg));
88 break; 588 break;
89 case 'r': 589 case 'r':
90 read_only = 1; 590 /* v1 used -r to specify read-only mode, now the default */
591 break;
592 case 't':
593 turbo_update_value = parse_cmdline_turbo(parse_optarg_string(optarg));
594 break;
595 case 'u':
596 update_hwp_use_pkg++;
597 if (atoi(optarg) == 0)
598 req_update.hwp_use_pkg = 0;
599 else
600 req_update.hwp_use_pkg = 1;
91 break; 601 break;
92 case 'v': 602 case 'v':
93 verbose++; 603 print_version();
604 exit(0);
605 break;
606 case 'w':
607 req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(optarg));
94 break; 608 break;
95 default: 609 default:
96 usage(); 610 usage();
97 } 611 }
98 } 612 }
99 /* if -r, then should be no additional optind */
100 if (read_only && (argc > optind))
101 usage();
102
103 /* 613 /*
104 * if no -r , then must be one additional optind 614 * v1 allowed "performance"|"normal"|"power" with no policy specifier
615 * to update BIAS. Continue to support that, even though no longer documented.
105 */ 616 */
106 if (!read_only) { 617 if (argc == optind + 1)
618 new_epb = parse_cmdline_epb(parse_optarg_string(argv[optind]));
107 619
108 if (argc != optind + 1) { 620 if (argc > optind + 1) {
109 printf("must supply -r or policy param\n"); 621 fprintf(stderr, "stray parameter '%s'\n", argv[optind + 1]);
110 usage(); 622 usage();
111 } 623 }
624}
112 625
113 if (!strcmp("performance", argv[optind])) { 626
114 new_bias = BIAS_PERFORMANCE; 627int get_msr(int cpu, int offset, unsigned long long *msr)
115 } else if (!strcmp("normal", argv[optind])) { 628{
116 new_bias = BIAS_BALANCE; 629 int retval;
117 } else if (!strcmp("powersave", argv[optind])) { 630 char pathname[32];
118 new_bias = BIAS_POWERSAVE; 631 int fd;
119 } else { 632
120 char *endptr; 633 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
121 634 fd = open(pathname, O_RDONLY);
122 new_bias = strtoull(argv[optind], &endptr, 0); 635 if (fd < 0)
123 if (endptr == argv[optind] || 636 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
124 new_bias > BIAS_POWERSAVE) { 637
125 fprintf(stderr, "invalid value: %s\n", 638 retval = pread(fd, msr, sizeof(*msr), offset);
126 argv[optind]); 639 if (retval != sizeof(*msr))
127 usage(); 640 err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
128 } 641
129 } 642 if (debug > 1)
643 fprintf(stderr, "get_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, *msr);
644
645 close(fd);
646 return 0;
647}
648
649int put_msr(int cpu, int offset, unsigned long long new_msr)
650{
651 char pathname[32];
652 int retval;
653 int fd;
654
655 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
656 fd = open(pathname, O_RDWR);
657 if (fd < 0)
658 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
659
660 retval = pwrite(fd, &new_msr, sizeof(new_msr), offset);
661 if (retval != sizeof(new_msr))
662 err(-2, "pwrite(cpu%d, offset 0x%x, 0x%llx) = %d", cpu, offset, new_msr, retval);
663
664 close(fd);
665
666 if (debug > 1)
667 fprintf(stderr, "put_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, new_msr);
668
669 return 0;
670}
671
672void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str)
673{
674 if (cpu != -1)
675 printf("cpu%d: ", cpu);
676
677 printf("HWP_CAP: low %d eff %d guar %d high %d\n",
678 cap->lowest, cap->efficient, cap->guaranteed, cap->highest);
679}
680void read_hwp_cap(int cpu, struct msr_hwp_cap *cap, unsigned int msr_offset)
681{
682 unsigned long long msr;
683
684 get_msr(cpu, msr_offset, &msr);
685
686 cap->highest = msr_perf_2_ratio(HWP_HIGHEST_PERF(msr));
687 cap->guaranteed = msr_perf_2_ratio(HWP_GUARANTEED_PERF(msr));
688 cap->efficient = msr_perf_2_ratio(HWP_MOSTEFFICIENT_PERF(msr));
689 cap->lowest = msr_perf_2_ratio(HWP_LOWEST_PERF(msr));
690}
691
692void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str)
693{
694 if (cpu != -1)
695 printf("cpu%d: ", cpu);
696
697 if (str)
698 printf("%s", str);
699
700 printf("HWP_REQ: min %d max %d des %d epp %d window 0x%x (%d*10^%dus) use_pkg %d\n",
701 h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp,
702 h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7, h->hwp_use_pkg);
703}
704void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, char *str)
705{
706 printf("pkg%d: ", pkg);
707
708 if (str)
709 printf("%s", str);
710
711 printf("HWP_REQ_PKG: min %d max %d des %d epp %d window 0x%x (%d*10^%dus)\n",
712 h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp,
713 h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7);
714}
715void read_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset)
716{
717 unsigned long long msr;
718
719 get_msr(cpu, msr_offset, &msr);
720
721 hwp_req->hwp_min = msr_perf_2_ratio((((msr) >> 0) & 0xff));
722 hwp_req->hwp_max = msr_perf_2_ratio((((msr) >> 8) & 0xff));
723 hwp_req->hwp_desired = msr_perf_2_ratio((((msr) >> 16) & 0xff));
724 hwp_req->hwp_epp = (((msr) >> 24) & 0xff);
725 hwp_req->hwp_window = (((msr) >> 32) & 0x3ff);
726 hwp_req->hwp_use_pkg = (((msr) >> 42) & 0x1);
727}
728
729void write_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset)
730{
731 unsigned long long msr = 0;
732
733 if (debug > 1)
734 printf("cpu%d: requesting min %d max %d des %d epp %d window 0x%0x use_pkg %d\n",
735 cpu, hwp_req->hwp_min, hwp_req->hwp_max,
736 hwp_req->hwp_desired, hwp_req->hwp_epp,
737 hwp_req->hwp_window, hwp_req->hwp_use_pkg);
738
739 msr |= HWP_MIN_PERF(ratio_2_msr_perf(hwp_req->hwp_min));
740 msr |= HWP_MAX_PERF(ratio_2_msr_perf(hwp_req->hwp_max));
741 msr |= HWP_DESIRED_PERF(ratio_2_msr_perf(hwp_req->hwp_desired));
742 msr |= HWP_ENERGY_PERF_PREFERENCE(hwp_req->hwp_epp);
743 msr |= HWP_ACTIVITY_WINDOW(hwp_req->hwp_window);
744 msr |= HWP_PACKAGE_CONTROL(hwp_req->hwp_use_pkg);
745
746 put_msr(cpu, msr_offset, msr);
747}
748
749int print_cpu_msrs(int cpu)
750{
751 unsigned long long msr;
752 struct msr_hwp_request req;
753 struct msr_hwp_cap cap;
754
755 if (has_epb) {
756 get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);
757
758 printf("cpu%d: EPB %u\n", cpu, (unsigned int) msr);
130 } 759 }
760
761 if (!has_hwp)
762 return 0;
763
764 read_hwp_request(cpu, &req, MSR_HWP_REQUEST);
765 print_hwp_request(cpu, &req, "");
766
767 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
768 print_hwp_cap(cpu, &cap, "");
769
770 return 0;
771}
772
773int print_pkg_msrs(int pkg)
774{
775 struct msr_hwp_request req;
776 unsigned long long msr;
777
778 if (!has_hwp)
779 return 0;
780
781 read_hwp_request(first_cpu_in_pkg[pkg], &req, MSR_HWP_REQUEST_PKG);
782 print_hwp_request_pkg(pkg, &req, "");
783
784 if (has_hwp_notify) {
785 get_msr(first_cpu_in_pkg[pkg], MSR_HWP_INTERRUPT, &msr);
786 fprintf(stderr,
787 "pkg%d: MSR_HWP_INTERRUPT: 0x%08llx (Excursion_Min-%sabled, Guaranteed_Perf_Change-%sabled)\n",
788 pkg, msr,
789 ((msr) & 0x2) ? "EN" : "Dis",
790 ((msr) & 0x1) ? "EN" : "Dis");
791 }
792 get_msr(first_cpu_in_pkg[pkg], MSR_HWP_STATUS, &msr);
793 fprintf(stderr,
794 "pkg%d: MSR_HWP_STATUS: 0x%08llx (%sExcursion_Min, %sGuaranteed_Perf_Change)\n",
795 pkg, msr,
796 ((msr) & 0x4) ? "" : "No-",
797 ((msr) & 0x1) ? "" : "No-");
798
799 return 0;
131} 800}
132 801
133/* 802/*
134 * validate_cpuid() 803 * Assumption: All HWP systems have 100 MHz bus clock
135 * returns on success, quietly exits on failure (make verbose with -v)
136 */ 804 */
137void validate_cpuid(void) 805int ratio_2_sysfs_khz(int ratio)
138{ 806{
139 unsigned int eax, ebx, ecx, edx, max_level; 807 int bclk_khz = 100 * 1000; /* 100,000 KHz = 100 MHz */
140 unsigned int fms, family, model, stepping;
141 808
142 eax = ebx = ecx = edx = 0; 809 return ratio * bclk_khz;
810}
811/*
812 * If HWP is enabled and cpufreq sysfs attribtes are present,
813 * then update sysfs, so that it will not become
814 * stale when we write to MSRs.
815 * (intel_pstate's max_perf_pct and min_perf_pct will follow cpufreq,
816 * so we don't have to touch that.)
817 */
818void update_cpufreq_scaling_freq(int is_max, int cpu, unsigned int ratio)
819{
820 char pathname[64];
821 FILE *fp;
822 int retval;
823 int khz;
143 824
144 asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), 825 sprintf(pathname, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq",
145 "=d" (edx) : "a" (0)); 826 cpu, is_max ? "max" : "min");
146 827
147 if (ebx != 0x756e6547 || edx != 0x49656e69 || ecx != 0x6c65746e) { 828 fp = fopen(pathname, "w");
148 if (verbose) 829 if (!fp) {
149 fprintf(stderr, "%.4s%.4s%.4s != GenuineIntel", 830 if (debug)
150 (char *)&ebx, (char *)&edx, (char *)&ecx); 831 perror(pathname);
151 exit(1); 832 return;
152 } 833 }
153 834
154 asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx"); 835 khz = ratio_2_sysfs_khz(ratio);
155 family = (fms >> 8) & 0xf; 836 retval = fprintf(fp, "%d", khz);
156 model = (fms >> 4) & 0xf; 837 if (retval < 0)
157 stepping = fms & 0xf; 838 if (debug)
158 if (family == 6 || family == 0xf) 839 perror("fprintf");
159 model += ((fms >> 16) & 0xf) << 4; 840 if (debug)
841 printf("echo %d > %s\n", khz, pathname);
160 842
161 if (verbose > 1) 843 fclose(fp);
162 printf("CPUID %d levels family:model:stepping " 844}
163 "0x%x:%x:%x (%d:%d:%d)\n", max_level,
164 family, model, stepping, family, model, stepping);
165 845
166 if (!(edx & (1 << 5))) { 846/*
167 if (verbose) 847 * We update all sysfs before updating any MSRs because of
168 printf("CPUID: no MSR\n"); 848 * bugs in cpufreq/intel_pstate where the sysfs writes
169 exit(1); 849 * for a CPU may change the min/max values on other CPUS.
850 */
851
852int update_sysfs(int cpu)
853{
854 if (!has_hwp)
855 return 0;
856
857 if (!hwp_update_enabled())
858 return 0;
859
860 if (access("/sys/devices/system/cpu/cpu0/cpufreq", F_OK))
861 return 0;
862
863 if (update_hwp_min)
864 update_cpufreq_scaling_freq(0, cpu, req_update.hwp_min);
865
866 if (update_hwp_max)
867 update_cpufreq_scaling_freq(1, cpu, req_update.hwp_max);
868
869 return 0;
870}
871
872int verify_hwp_req_self_consistency(int cpu, struct msr_hwp_request *req)
873{
874 /* fail if min > max requested */
875 if (req->hwp_min > req->hwp_max) {
876 errx(1, "cpu%d: requested hwp-min %d > hwp_max %d",
877 cpu, req->hwp_min, req->hwp_max);
170 } 878 }
171 879
172 /* 880 /* fail if desired > max requestd */
173 * Support for MSR_IA32_ENERGY_PERF_BIAS 881 if (req->hwp_desired && (req->hwp_desired > req->hwp_max)) {
174 * is indicated by CPUID.06H.ECX.bit3 882 errx(1, "cpu%d: requested hwp-desired %d > hwp_max %d",
175 */ 883 cpu, req->hwp_desired, req->hwp_max);
176 asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (6));
177 if (verbose)
178 printf("CPUID.06H.ECX: 0x%x\n", ecx);
179 if (!(ecx & (1 << 3))) {
180 if (verbose)
181 printf("CPUID: No MSR_IA32_ENERGY_PERF_BIAS\n");
182 exit(1);
183 } 884 }
184 return; /* success */ 885 /* fail if desired < min requestd */
886 if (req->hwp_desired && (req->hwp_desired < req->hwp_min)) {
887 errx(1, "cpu%d: requested hwp-desired %d < requested hwp_min %d",
888 cpu, req->hwp_desired, req->hwp_min);
889 }
890
891 return 0;
185} 892}
186 893
187unsigned long long get_msr(int cpu, int offset) 894int check_hwp_request_v_hwp_capabilities(int cpu, struct msr_hwp_request *req, struct msr_hwp_cap *cap)
188{ 895{
189 unsigned long long msr; 896 if (update_hwp_max) {
190 char msr_path[32]; 897 if (req->hwp_max > cap->highest)
191 int retval; 898 errx(1, "cpu%d: requested max %d > capabilities highest %d, use --force?",
192 int fd; 899 cpu, req->hwp_max, cap->highest);
900 if (req->hwp_max < cap->lowest)
901 errx(1, "cpu%d: requested max %d < capabilities lowest %d, use --force?",
902 cpu, req->hwp_max, cap->lowest);
903 }
193 904
194 sprintf(msr_path, "/dev/cpu/%d/msr", cpu); 905 if (update_hwp_min) {
195 fd = open(msr_path, O_RDONLY); 906 if (req->hwp_min > cap->highest)
196 if (fd < 0) { 907 errx(1, "cpu%d: requested min %d > capabilities highest %d, use --force?",
197 printf("Try \"# modprobe msr\"\n"); 908 cpu, req->hwp_min, cap->highest);
198 perror(msr_path); 909 if (req->hwp_min < cap->lowest)
199 exit(1); 910 errx(1, "cpu%d: requested min %d < capabilities lowest %d, use --force?",
911 cpu, req->hwp_min, cap->lowest);
200 } 912 }
201 913
202 retval = pread(fd, &msr, sizeof msr, offset); 914 if (update_hwp_min && update_hwp_max && (req->hwp_min > req->hwp_max))
915 errx(1, "cpu%d: requested min %d > requested max %d",
916 cpu, req->hwp_min, req->hwp_max);
203 917
204 if (retval != sizeof msr) { 918 if (update_hwp_desired && req->hwp_desired) {
205 printf("pread cpu%d 0x%x = %d\n", cpu, offset, retval); 919 if (req->hwp_desired > req->hwp_max)
206 exit(-2); 920 errx(1, "cpu%d: requested desired %d > requested max %d, use --force?",
921 cpu, req->hwp_desired, req->hwp_max);
922 if (req->hwp_desired < req->hwp_min)
923 errx(1, "cpu%d: requested desired %d < requested min %d, use --force?",
924 cpu, req->hwp_desired, req->hwp_min);
925 if (req->hwp_desired < cap->lowest)
926 errx(1, "cpu%d: requested desired %d < capabilities lowest %d, use --force?",
927 cpu, req->hwp_desired, cap->lowest);
928 if (req->hwp_desired > cap->highest)
929 errx(1, "cpu%d: requested desired %d > capabilities highest %d, use --force?",
930 cpu, req->hwp_desired, cap->highest);
207 } 931 }
208 close(fd); 932
209 return msr; 933 return 0;
210} 934}
211 935
212unsigned long long put_msr(int cpu, unsigned long long new_msr, int offset) 936int update_hwp_request(int cpu)
213{ 937{
214 unsigned long long old_msr; 938 struct msr_hwp_request req;
215 char msr_path[32]; 939 struct msr_hwp_cap cap;
216 int retval; 940
217 int fd; 941 int msr_offset = MSR_HWP_REQUEST;
942
943 read_hwp_request(cpu, &req, msr_offset);
944 if (debug)
945 print_hwp_request(cpu, &req, "old: ");
946
947 if (update_hwp_min)
948 req.hwp_min = req_update.hwp_min;
949
950 if (update_hwp_max)
951 req.hwp_max = req_update.hwp_max;
952
953 if (update_hwp_desired)
954 req.hwp_desired = req_update.hwp_desired;
955
956 if (update_hwp_window)
957 req.hwp_window = req_update.hwp_window;
958
959 if (update_hwp_epp)
960 req.hwp_epp = req_update.hwp_epp;
961
962 req.hwp_use_pkg = req_update.hwp_use_pkg;
963
964 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
965 if (debug)
966 print_hwp_cap(cpu, &cap, "");
967
968 if (!force)
969 check_hwp_request_v_hwp_capabilities(cpu, &req, &cap);
970
971 verify_hwp_req_self_consistency(cpu, &req);
218 972
219 sprintf(msr_path, "/dev/cpu/%d/msr", cpu); 973 write_hwp_request(cpu, &req, msr_offset);
220 fd = open(msr_path, O_RDWR); 974
221 if (fd < 0) { 975 if (debug) {
222 perror(msr_path); 976 read_hwp_request(cpu, &req, msr_offset);
223 exit(1); 977 print_hwp_request(cpu, &req, "new: ");
224 } 978 }
979 return 0;
980}
981int update_hwp_request_pkg(int pkg)
982{
983 struct msr_hwp_request req;
984 struct msr_hwp_cap cap;
985 int cpu = first_cpu_in_pkg[pkg];
986
987 int msr_offset = MSR_HWP_REQUEST_PKG;
988
989 read_hwp_request(cpu, &req, msr_offset);
990 if (debug)
991 print_hwp_request_pkg(pkg, &req, "old: ");
992
993 if (update_hwp_min)
994 req.hwp_min = req_update.hwp_min;
995
996 if (update_hwp_max)
997 req.hwp_max = req_update.hwp_max;
998
999 if (update_hwp_desired)
1000 req.hwp_desired = req_update.hwp_desired;
1001
1002 if (update_hwp_window)
1003 req.hwp_window = req_update.hwp_window;
1004
1005 if (update_hwp_epp)
1006 req.hwp_epp = req_update.hwp_epp;
1007
1008 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
1009 if (debug)
1010 print_hwp_cap(cpu, &cap, "");
1011
1012 if (!force)
1013 check_hwp_request_v_hwp_capabilities(cpu, &req, &cap);
1014
1015 verify_hwp_req_self_consistency(cpu, &req);
1016
1017 write_hwp_request(cpu, &req, msr_offset);
225 1018
226 retval = pread(fd, &old_msr, sizeof old_msr, offset); 1019 if (debug) {
227 if (retval != sizeof old_msr) { 1020 read_hwp_request(cpu, &req, msr_offset);
228 perror("pwrite"); 1021 print_hwp_request_pkg(pkg, &req, "new: ");
229 printf("pread cpu%d 0x%x = %d\n", cpu, offset, retval);
230 exit(-2);
231 } 1022 }
1023 return 0;
1024}
1025
1026int enable_hwp_on_cpu(int cpu)
1027{
1028 unsigned long long msr;
1029
1030 get_msr(cpu, MSR_PM_ENABLE, &msr);
1031 put_msr(cpu, MSR_PM_ENABLE, 1);
1032
1033 if (verbose)
1034 printf("cpu%d: MSR_PM_ENABLE old: %d new: %d\n", cpu, (unsigned int) msr, 1);
1035
1036 return 0;
1037}
1038
1039int update_cpu_msrs(int cpu)
1040{
1041 unsigned long long msr;
1042
232 1043
233 retval = pwrite(fd, &new_msr, sizeof new_msr, offset); 1044 if (update_epb) {
234 if (retval != sizeof new_msr) { 1045 get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);
235 perror("pwrite"); 1046 put_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, new_epb);
236 printf("pwrite cpu%d 0x%x = %d\n", cpu, offset, retval); 1047
237 exit(-2); 1048 if (verbose)
1049 printf("cpu%d: ENERGY_PERF_BIAS old: %d new: %d\n",
1050 cpu, (unsigned int) msr, (unsigned int) new_epb);
238 } 1051 }
239 1052
240 close(fd); 1053 if (update_turbo) {
1054 int turbo_is_present_and_disabled;
1055
1056 get_msr(cpu, MSR_IA32_MISC_ENABLE, &msr);
1057
1058 turbo_is_present_and_disabled = ((msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE) != 0);
1059
1060 if (turbo_update_value == 1) {
1061 if (turbo_is_present_and_disabled) {
1062 msr &= ~MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
1063 put_msr(cpu, MSR_IA32_MISC_ENABLE, msr);
1064 if (verbose)
1065 printf("cpu%d: turbo ENABLE\n", cpu);
1066 }
1067 } else {
1068 /*
1069 * if "turbo_is_enabled" were known to be describe this cpu
1070 * then we could use it here to skip redundant disable requests.
1071 * but cpu may be in a different package, so we always write.
1072 */
1073 msr |= MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
1074 put_msr(cpu, MSR_IA32_MISC_ENABLE, msr);
1075 if (verbose)
1076 printf("cpu%d: turbo DISABLE\n", cpu);
1077 }
1078 }
1079
1080 if (!has_hwp)
1081 return 0;
1082
1083 if (!hwp_update_enabled())
1084 return 0;
1085
1086 update_hwp_request(cpu);
1087 return 0;
1088}
1089
1090/*
1091 * Open a file, and exit on failure
1092 */
1093FILE *fopen_or_die(const char *path, const char *mode)
1094{
1095 FILE *filep = fopen(path, "r");
241 1096
242 return old_msr; 1097 if (!filep)
1098 err(1, "%s: open failed", path);
1099 return filep;
243} 1100}
244 1101
245void print_msr(int cpu) 1102unsigned int get_pkg_num(int cpu)
246{ 1103{
247 printf("cpu%d: 0x%016llx\n", 1104 FILE *fp;
248 cpu, get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS)); 1105 char pathname[128];
1106 unsigned int pkg;
1107 int retval;
1108
1109 sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);
1110
1111 fp = fopen_or_die(pathname, "r");
1112 retval = fscanf(fp, "%d\n", &pkg);
1113 if (retval != 1)
1114 errx(1, "%s: failed to parse", pathname);
1115 return pkg;
249} 1116}
250 1117
251void update_msr(int cpu) 1118int set_max_cpu_pkg_num(int cpu)
252{ 1119{
253 unsigned long long previous_msr; 1120 unsigned int pkg;
254 1121
255 previous_msr = put_msr(cpu, new_bias, MSR_IA32_ENERGY_PERF_BIAS); 1122 if (max_cpu_num < cpu)
1123 max_cpu_num = cpu;
256 1124
257 if (verbose) 1125 pkg = get_pkg_num(cpu);
258 printf("cpu%d msr0x%x 0x%016llx -> 0x%016llx\n", 1126
259 cpu, MSR_IA32_ENERGY_PERF_BIAS, previous_msr, new_bias); 1127 if (pkg >= MAX_PACKAGES)
1128 errx(1, "cpu%d: %d >= MAX_PACKAGES (%d)", cpu, pkg, MAX_PACKAGES);
1129
1130 if (pkg > max_pkg_num)
1131 max_pkg_num = pkg;
260 1132
261 return; 1133 if ((pkg_present_set & (1ULL << pkg)) == 0) {
1134 pkg_present_set |= (1ULL << pkg);
1135 first_cpu_in_pkg[pkg] = cpu;
1136 }
1137
1138 return 0;
1139}
1140int mark_cpu_present(int cpu)
1141{
1142 CPU_SET_S(cpu, cpu_setsize, cpu_present_set);
1143 return 0;
262} 1144}
263 1145
264char *proc_stat = "/proc/stat";
265/* 1146/*
266 * run func() on every cpu in /dev/cpu 1147 * run func(cpu) on every cpu in /proc/stat
1148 * return max_cpu number
267 */ 1149 */
268void for_every_cpu(void (func)(int)) 1150int for_all_proc_cpus(int (func)(int))
269{ 1151{
270 FILE *fp; 1152 FILE *fp;
1153 int cpu_num;
271 int retval; 1154 int retval;
272 1155
273 fp = fopen(proc_stat, "r"); 1156 fp = fopen_or_die(proc_stat, "r");
274 if (fp == NULL) {
275 perror(proc_stat);
276 exit(1);
277 }
278 1157
279 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); 1158 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
280 if (retval != 0) { 1159 if (retval != 0)
281 perror("/proc/stat format"); 1160 err(1, "%s: failed to parse format", proc_stat);
282 exit(1);
283 }
284 1161
285 while (1) { 1162 while (1) {
286 int cpu; 1163 retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
287
288 retval = fscanf(fp,
289 "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n",
290 &cpu);
291 if (retval != 1) 1164 if (retval != 1)
292 break; 1165 break;
293 1166
294 func(cpu); 1167 retval = func(cpu_num);
1168 if (retval) {
1169 fclose(fp);
1170 return retval;
1171 }
295 } 1172 }
296 fclose(fp); 1173 fclose(fp);
1174 return 0;
1175}
1176
1177void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func)(int))
1178{
1179 int cpu_num;
1180
1181 for (cpu_num = 0; cpu_num <= max_cpu_num; ++cpu_num)
1182 if (CPU_ISSET_S(cpu_num, set_size, cpu_set))
1183 func(cpu_num);
1184}
1185
1186void init_data_structures(void)
1187{
1188 for_all_proc_cpus(set_max_cpu_pkg_num);
1189
1190 cpu_setsize = CPU_ALLOC_SIZE((max_cpu_num + 1));
1191
1192 cpu_present_set = CPU_ALLOC((max_cpu_num + 1));
1193 if (cpu_present_set == NULL)
1194 err(3, "CPU_ALLOC");
1195 CPU_ZERO_S(cpu_setsize, cpu_present_set);
1196 for_all_proc_cpus(mark_cpu_present);
1197}
1198
1199/* clear has_hwp if it is not enable (or being enabled) */
1200
1201void verify_hwp_is_enabled(void)
1202{
1203 unsigned long long msr;
1204
1205 if (!has_hwp) /* set in early_cpuid() */
1206 return;
1207
1208 /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
1209 get_msr(base_cpu, MSR_PM_ENABLE, &msr);
1210 if ((msr & 1) == 0) {
1211 fprintf(stderr, "HWP can be enabled using '--hwp-enable'\n");
1212 has_hwp = 0;
1213 return;
1214 }
1215}
1216
1217int req_update_bounds_check(void)
1218{
1219 if (!hwp_update_enabled())
1220 return 0;
1221
1222 /* fail if min > max requested */
1223 if ((update_hwp_max && update_hwp_min) &&
1224 (req_update.hwp_min > req_update.hwp_max)) {
1225 printf("hwp-min %d > hwp_max %d\n", req_update.hwp_min, req_update.hwp_max);
1226 return -EINVAL;
1227 }
1228
1229 /* fail if desired > max requestd */
1230 if (req_update.hwp_desired && update_hwp_max &&
1231 (req_update.hwp_desired > req_update.hwp_max)) {
1232 printf("hwp-desired cannot be greater than hwp_max\n");
1233 return -EINVAL;
1234 }
1235 /* fail if desired < min requestd */
1236 if (req_update.hwp_desired && update_hwp_min &&
1237 (req_update.hwp_desired < req_update.hwp_min)) {
1238 printf("hwp-desired cannot be less than hwp_min\n");
1239 return -EINVAL;
1240 }
1241
1242 return 0;
1243}
1244
1245void set_base_cpu(void)
1246{
1247 base_cpu = sched_getcpu();
1248 if (base_cpu < 0)
1249 err(-ENODEV, "No valid cpus found");
1250}
1251
1252
1253void probe_dev_msr(void)
1254{
1255 struct stat sb;
1256 char pathname[32];
1257
1258 sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
1259 if (stat(pathname, &sb))
1260 if (system("/sbin/modprobe msr > /dev/null 2>&1"))
1261 err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
1262}
1263/*
1264 * early_cpuid()
1265 * initialize turbo_is_enabled, has_hwp, has_epb
1266 * before cmdline is parsed
1267 */
1268void early_cpuid(void)
1269{
1270 unsigned int eax, ebx, ecx, edx, max_level;
1271 unsigned int fms, family, model;
1272
1273 __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
1274
1275 if (max_level < 6)
1276 errx(1, "Processor not supported\n");
1277
1278 __get_cpuid(1, &fms, &ebx, &ecx, &edx);
1279 family = (fms >> 8) & 0xf;
1280 model = (fms >> 4) & 0xf;
1281 if (family == 6 || family == 0xf)
1282 model += ((fms >> 16) & 0xf) << 4;
1283
1284 if (model == 0x4F) {
1285 unsigned long long msr;
1286
1287 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
1288
1289 bdx_highest_ratio = msr & 0xFF;
1290 }
1291
1292 __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
1293 turbo_is_enabled = (eax >> 1) & 1;
1294 has_hwp = (eax >> 7) & 1;
1295 has_epb = (ecx >> 3) & 1;
1296}
1297
1298/*
1299 * parse_cpuid()
1300 * set
1301 * has_hwp, has_hwp_notify, has_hwp_activity_window, has_hwp_epp, has_hwp_request_pkg, has_epb
1302 */
1303void parse_cpuid(void)
1304{
1305 unsigned int eax, ebx, ecx, edx, max_level;
1306 unsigned int fms, family, model, stepping;
1307
1308 eax = ebx = ecx = edx = 0;
1309
1310 __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
1311
1312 if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
1313 genuine_intel = 1;
1314
1315 if (debug)
1316 fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
1317 (char *)&ebx, (char *)&edx, (char *)&ecx);
1318
1319 __get_cpuid(1, &fms, &ebx, &ecx, &edx);
1320 family = (fms >> 8) & 0xf;
1321 model = (fms >> 4) & 0xf;
1322 stepping = fms & 0xf;
1323 if (family == 6 || family == 0xf)
1324 model += ((fms >> 16) & 0xf) << 4;
1325
1326 if (debug) {
1327 fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
1328 max_level, family, model, stepping, family, model, stepping);
1329 fprintf(stderr, "CPUID(1): %s %s %s %s %s %s %s %s\n",
1330 ecx & (1 << 0) ? "SSE3" : "-",
1331 ecx & (1 << 3) ? "MONITOR" : "-",
1332 ecx & (1 << 7) ? "EIST" : "-",
1333 ecx & (1 << 8) ? "TM2" : "-",
1334 edx & (1 << 4) ? "TSC" : "-",
1335 edx & (1 << 5) ? "MSR" : "-",
1336 edx & (1 << 22) ? "ACPI-TM" : "-",
1337 edx & (1 << 29) ? "TM" : "-");
1338 }
1339
1340 if (!(edx & (1 << 5)))
1341 errx(1, "CPUID: no MSR");
1342
1343
1344 __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
1345 /* turbo_is_enabled already set */
1346 /* has_hwp already set */
1347 has_hwp_notify = eax & (1 << 8);
1348 has_hwp_activity_window = eax & (1 << 9);
1349 has_hwp_epp = eax & (1 << 10);
1350 has_hwp_request_pkg = eax & (1 << 11);
1351
1352 if (!has_hwp_request_pkg && update_hwp_use_pkg)
1353 errx(1, "--hwp-use-pkg is not available on this hardware");
1354
1355 /* has_epb already set */
1356
1357 if (debug)
1358 fprintf(stderr,
1359 "CPUID(6): %sTURBO, %sHWP, %sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
1360 turbo_is_enabled ? "" : "No-",
1361 has_hwp ? "" : "No-",
1362 has_hwp_notify ? "" : "No-",
1363 has_hwp_activity_window ? "" : "No-",
1364 has_hwp_epp ? "" : "No-",
1365 has_hwp_request_pkg ? "" : "No-",
1366 has_epb ? "" : "No-");
1367
1368 return; /* success */
297} 1369}
298 1370
299int main(int argc, char **argv) 1371int main(int argc, char **argv)
300{ 1372{
1373 set_base_cpu();
1374 probe_dev_msr();
1375 init_data_structures();
1376
1377 early_cpuid(); /* initial cpuid parse before cmdline */
1378
301 cmdline(argc, argv); 1379 cmdline(argc, argv);
302 1380
303 if (verbose > 1) 1381 if (debug)
304 printf("x86_energy_perf_policy Nov 24, 2010" 1382 print_version();
305 " - Len Brown <lenb@kernel.org>\n"); 1383
306 if (verbose > 1 && !read_only) 1384 parse_cpuid();
307 printf("new_bias %lld\n", new_bias); 1385
308 1386 /* If CPU-set and PKG-set are not initialized, default to all CPUs */
309 validate_cpuid(); 1387 if ((cpu_selected_set == 0) && (pkg_selected_set == 0))
310 1388 cpu_selected_set = cpu_present_set;
311 if (cpu != -1) { 1389
312 if (read_only) 1390 /*
313 print_msr(cpu); 1391 * If HWP is being enabled, do it now, so that subsequent operations
314 else 1392 * that access HWP registers can work.
315 update_msr(cpu); 1393 */
316 } else { 1394 if (update_hwp_enable)
317 if (read_only) 1395 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, enable_hwp_on_cpu);
318 for_every_cpu(print_msr); 1396
319 else 1397 /* If HWP present, but disabled, warn and ignore from here forward */
320 for_every_cpu(update_msr); 1398 verify_hwp_is_enabled();
1399
1400 if (req_update_bounds_check())
1401 return -EINVAL;
1402
1403 /* display information only, no updates to settings */
1404 if (!update_epb && !update_turbo && !hwp_update_enabled()) {
1405 if (cpu_selected_set)
1406 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, print_cpu_msrs);
1407
1408 if (has_hwp_request_pkg) {
1409 if (pkg_selected_set == 0)
1410 pkg_selected_set = pkg_present_set;
1411
1412 for_packages(pkg_selected_set, print_pkg_msrs);
1413 }
1414
1415 return 0;
321 } 1416 }
322 1417
1418 /* update CPU set */
1419 if (cpu_selected_set) {
1420 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_sysfs);
1421 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_msrs);
1422 } else if (pkg_selected_set)
1423 for_packages(pkg_selected_set, update_hwp_request_pkg);
1424
323 return 0; 1425 return 0;
324} 1426}