2 * x86_energy_perf_policy -- set the energy versus performance
3 * policy preference bias on recent X86 processors.
6 * Copyright (c) 2010, Intel Corporation.
7 * Len Brown <len.brown@intel.com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
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
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.
25 #include <sys/types.h>
27 #include <sys/resource.h>
34 unsigned int verbose
; /* set with -v */
35 unsigned int read_only
; /* set with -r */
37 unsigned long long new_bias
;
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
48 * Performance is paramount.
49 * Unwilling to sacrifice any performance
50 * for the sake of energy saving. (hardware default)
53 * Can tolerate minor performance compromise
54 * for potentially significant energy savings.
55 * (reasonable default for most desktops and servers)
58 * Can tolerate significant performance hit
59 * to maximize energy savings.
62 * a numerical value to write to the underlying MSR.
66 printf("%s: [-c cpu] [-v] "
67 "(-r | 'performance' | 'normal' | 'powersave' | n)\n",
72 #define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
74 #define BIAS_PERFORMANCE 0
75 #define BIAS_BALANCE 6
76 #define BIAS_POWERSAVE 15
78 void cmdline(int argc
, char **argv
)
84 while ((opt
= getopt(argc
, argv
, "+rvc:")) != -1) {
99 /* if -r, then should be no additional optind */
100 if (read_only
&& (argc
> optind
))
104 * if no -r , then must be one additional optind
108 if (argc
!= optind
+ 1) {
109 printf("must supply -r or policy param\n");
113 if (!strcmp("performance", argv
[optind
])) {
114 new_bias
= BIAS_PERFORMANCE
;
115 } else if (!strcmp("normal", argv
[optind
])) {
116 new_bias
= BIAS_BALANCE
;
117 } else if (!strcmp("powersave", argv
[optind
])) {
118 new_bias
= BIAS_POWERSAVE
;
122 new_bias
= strtoull(argv
[optind
], &endptr
, 0);
123 if (endptr
== argv
[optind
] ||
124 new_bias
> BIAS_POWERSAVE
) {
125 fprintf(stderr
, "invalid value: %s\n",
135 * returns on success, quietly exits on failure (make verbose with -v)
137 void validate_cpuid(void)
139 unsigned int eax
, ebx
, ecx
, edx
, max_level
;
140 unsigned int fms
, family
, model
, stepping
;
142 eax
= ebx
= ecx
= edx
= 0;
144 asm("cpuid" : "=a" (max_level
), "=b" (ebx
), "=c" (ecx
),
145 "=d" (edx
) : "a" (0));
147 if (ebx
!= 0x756e6547 || edx
!= 0x49656e69 || ecx
!= 0x6c65746e) {
149 fprintf(stderr
, "%.4s%.4s%.4s != GenuineIntel",
150 (char *)&ebx
, (char *)&edx
, (char *)&ecx
);
154 asm("cpuid" : "=a" (fms
), "=c" (ecx
), "=d" (edx
) : "a" (1) : "ebx");
155 family
= (fms
>> 8) & 0xf;
156 model
= (fms
>> 4) & 0xf;
157 stepping
= fms
& 0xf;
158 if (family
== 6 || family
== 0xf)
159 model
+= ((fms
>> 16) & 0xf) << 4;
162 printf("CPUID %d levels family:model:stepping "
163 "0x%x:%x:%x (%d:%d:%d)\n", max_level
,
164 family
, model
, stepping
, family
, model
, stepping
);
166 if (!(edx
& (1 << 5))) {
168 printf("CPUID: no MSR\n");
173 * Support for MSR_IA32_ENERGY_PERF_BIAS
174 * is indicated by CPUID.06H.ECX.bit3
176 asm("cpuid" : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
) : "a" (6));
178 printf("CPUID.06H.ECX: 0x%x\n", ecx
);
179 if (!(ecx
& (1 << 3))) {
181 printf("CPUID: No MSR_IA32_ENERGY_PERF_BIAS\n");
184 return; /* success */
187 unsigned long long get_msr(int cpu
, int offset
)
189 unsigned long long msr
;
194 sprintf(msr_path
, "/dev/cpu/%d/msr", cpu
);
195 fd
= open(msr_path
, O_RDONLY
);
197 printf("Try \"# modprobe msr\"\n");
202 retval
= pread(fd
, &msr
, sizeof msr
, offset
);
204 if (retval
!= sizeof msr
) {
205 printf("pread cpu%d 0x%x = %d\n", cpu
, offset
, retval
);
212 unsigned long long put_msr(int cpu
, unsigned long long new_msr
, int offset
)
214 unsigned long long old_msr
;
219 sprintf(msr_path
, "/dev/cpu/%d/msr", cpu
);
220 fd
= open(msr_path
, O_RDWR
);
226 retval
= pread(fd
, &old_msr
, sizeof old_msr
, offset
);
227 if (retval
!= sizeof old_msr
) {
229 printf("pread cpu%d 0x%x = %d\n", cpu
, offset
, retval
);
233 retval
= pwrite(fd
, &new_msr
, sizeof new_msr
, offset
);
234 if (retval
!= sizeof new_msr
) {
236 printf("pwrite cpu%d 0x%x = %d\n", cpu
, offset
, retval
);
245 void print_msr(int cpu
)
247 printf("cpu%d: 0x%016llx\n",
248 cpu
, get_msr(cpu
, MSR_IA32_ENERGY_PERF_BIAS
));
251 void update_msr(int cpu
)
253 unsigned long long previous_msr
;
255 previous_msr
= put_msr(cpu
, new_bias
, MSR_IA32_ENERGY_PERF_BIAS
);
258 printf("cpu%d msr0x%x 0x%016llx -> 0x%016llx\n",
259 cpu
, MSR_IA32_ENERGY_PERF_BIAS
, previous_msr
, new_bias
);
264 char *proc_stat
= "/proc/stat";
266 * run func() on every cpu in /dev/cpu
268 void for_every_cpu(void (func
)(int))
273 fp
= fopen(proc_stat
, "r");
279 retval
= fscanf(fp
, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
281 perror("/proc/stat format");
289 "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n",
299 int main(int argc
, char **argv
)
304 printf("x86_energy_perf_policy Nov 24, 2010"
305 " - Len Brown <lenb@kernel.org>\n");
306 if (verbose
> 1 && !read_only
)
307 printf("new_bias %lld\n", new_bias
);
318 for_every_cpu(print_msr
);
320 for_every_cpu(update_msr
);