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
;
141 unsigned int fms
, family
, model
, stepping
;
143 eax
= ebx
= ecx
= edx
= 0;
145 asm("cpuid" : "=a" (max_level
), "=b" (ebx
), "=c" (ecx
),
146 "=d" (edx
) : "a" (0));
148 if (ebx
!= 0x756e6547 || edx
!= 0x49656e69 || ecx
!= 0x6c65746e) {
150 fprintf(stderr
, "%.4s%.4s%.4s != GenuineIntel",
151 (char *)&ebx
, (char *)&edx
, (char *)&ecx
);
155 asm("cpuid" : "=a" (fms
), "=c" (ecx
), "=d" (edx
) : "a" (1) : "ebx");
156 family
= (fms
>> 8) & 0xf;
157 model
= (fms
>> 4) & 0xf;
158 stepping
= fms
& 0xf;
159 if (family
== 6 || family
== 0xf)
160 model
+= ((fms
>> 16) & 0xf) << 4;
163 printf("CPUID %s %d levels family:model:stepping "
164 "0x%x:%x:%x (%d:%d:%d)\n", brand
, max_level
,
165 family
, model
, stepping
, family
, model
, stepping
);
167 if (!(edx
& (1 << 5))) {
169 printf("CPUID: no MSR\n");
174 * Support for MSR_IA32_ENERGY_PERF_BIAS
175 * is indicated by CPUID.06H.ECX.bit3
177 asm("cpuid" : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
) : "a" (6));
179 printf("CPUID.06H.ECX: 0x%x\n", ecx
);
180 if (!(ecx
& (1 << 3))) {
182 printf("CPUID: No MSR_IA32_ENERGY_PERF_BIAS\n");
185 return; /* success */
188 unsigned long long get_msr(int cpu
, int offset
)
190 unsigned long long msr
;
195 sprintf(msr_path
, "/dev/cpu/%d/msr", cpu
);
196 fd
= open(msr_path
, O_RDONLY
);
198 printf("Try \"# modprobe msr\"\n");
203 retval
= pread(fd
, &msr
, sizeof msr
, offset
);
205 if (retval
!= sizeof msr
) {
206 printf("pread cpu%d 0x%x = %d\n", cpu
, offset
, retval
);
213 unsigned long long put_msr(int cpu
, unsigned long long new_msr
, int offset
)
215 unsigned long long old_msr
;
220 sprintf(msr_path
, "/dev/cpu/%d/msr", cpu
);
221 fd
= open(msr_path
, O_RDWR
);
227 retval
= pread(fd
, &old_msr
, sizeof old_msr
, offset
);
228 if (retval
!= sizeof old_msr
) {
230 printf("pread cpu%d 0x%x = %d\n", cpu
, offset
, retval
);
234 retval
= pwrite(fd
, &new_msr
, sizeof new_msr
, offset
);
235 if (retval
!= sizeof new_msr
) {
237 printf("pwrite cpu%d 0x%x = %d\n", cpu
, offset
, retval
);
246 void print_msr(int cpu
)
248 printf("cpu%d: 0x%016llx\n",
249 cpu
, get_msr(cpu
, MSR_IA32_ENERGY_PERF_BIAS
));
252 void update_msr(int cpu
)
254 unsigned long long previous_msr
;
256 previous_msr
= put_msr(cpu
, new_bias
, MSR_IA32_ENERGY_PERF_BIAS
);
259 printf("cpu%d msr0x%x 0x%016llx -> 0x%016llx\n",
260 cpu
, MSR_IA32_ENERGY_PERF_BIAS
, previous_msr
, new_bias
);
265 char *proc_stat
= "/proc/stat";
267 * run func() on every cpu in /dev/cpu
269 void for_every_cpu(void (func
)(int))
274 fp
= fopen(proc_stat
, "r");
280 retval
= fscanf(fp
, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
282 perror("/proc/stat format");
290 "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n",
300 int main(int argc
, char **argv
)
305 printf("x86_energy_perf_policy Nov 24, 2010"
306 " - Len Brown <lenb@kernel.org>\n");
307 if (verbose
> 1 && !read_only
)
308 printf("new_bias %lld\n", new_bias
);
319 for_every_cpu(print_msr
);
321 for_every_cpu(update_msr
);