~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c

Version: ~ [ linux-5.1-rc5 ] ~ [ linux-5.0.7 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.34 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.111 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.168 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.178 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.138 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.65 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * x86_energy_perf_policy -- set the energy versus performance
  3  * policy preference bias on recent X86 processors.
  4  */
  5 /*
  6  * Copyright (c) 2010, Intel Corporation.
  7  * Len Brown <len.brown@intel.com>
  8  *
  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.
 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  */
 22 
 23 #include <stdio.h>
 24 #include <unistd.h>
 25 #include <sys/types.h>
 26 #include <sys/stat.h>
 27 #include <sys/resource.h>
 28 #include <fcntl.h>
 29 #include <signal.h>
 30 #include <sys/time.h>
 31 #include <stdlib.h>
 32 #include <string.h>
 33 
 34 unsigned int verbose;           /* set with -v */
 35 unsigned int read_only;         /* set with -r */
 36 char *progname;
 37 unsigned long long new_bias;
 38 int cpu = -1;
 39 
 40 /*
 41  * Usage:
 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  */
 64 void usage(void)
 65 {
 66         printf("%s: [-c cpu] [-v] "
 67                 "(-r | 'performance' | 'normal' | 'powersave' | n)\n",
 68                 progname);
 69         exit(1);
 70 }
 71 
 72 #define MSR_IA32_ENERGY_PERF_BIAS       0x000001b0
 73 
 74 #define BIAS_PERFORMANCE                0
 75 #define BIAS_BALANCE                    6
 76 #define BIAS_POWERSAVE                  15
 77 
 78 void cmdline(int argc, char **argv)
 79 {
 80         int opt;
 81 
 82         progname = argv[0];
 83 
 84         while ((opt = getopt(argc, argv, "+rvc:")) != -1) {
 85                 switch (opt) {
 86                 case 'c':
 87                         cpu = atoi(optarg);
 88                         break;
 89                 case 'r':
 90                         read_only = 1;
 91                         break;
 92                 case 'v':
 93                         verbose++;
 94                         break;
 95                 default:
 96                         usage();
 97                 }
 98         }
 99         /* if -r, then should be no additional optind */
100         if (read_only && (argc > optind))
101                 usage();
102 
103         /*
104          * if no -r , then must be one additional optind
105          */
106         if (!read_only) {
107 
108                 if (argc != optind + 1) {
109                         printf("must supply -r or policy param\n");
110                         usage();
111                         }
112 
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;
119                 } else {
120                         char *endptr;
121 
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",
126                                                 argv[optind]);
127                                 usage();
128                         }
129                 }
130         }
131 }
132 
133 /*
134  * validate_cpuid()
135  * returns on success, quietly exits on failure (make verbose with -v)
136  */
137 void validate_cpuid(void)
138 {
139         unsigned int eax, ebx, ecx, edx, max_level;
140         char brand[16];
141         unsigned int fms, family, model, stepping;
142 
143         eax = ebx = ecx = edx = 0;
144 
145         asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx),
146                 "=d" (edx) : "a" (0));
147 
148         if (ebx != 0x756e6547 || edx != 0x49656e69 || ecx != 0x6c65746e) {
149                 if (verbose)
150                         fprintf(stderr, "%.4s%.4s%.4s != GenuineIntel",
151                                 (char *)&ebx, (char *)&edx, (char *)&ecx);
152                 exit(1);
153         }
154 
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;
161 
162         if (verbose > 1)
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);
166 
167         if (!(edx & (1 << 5))) {
168                 if (verbose)
169                         printf("CPUID: no MSR\n");
170                 exit(1);
171         }
172 
173         /*
174          * Support for MSR_IA32_ENERGY_PERF_BIAS
175          * is indicated by CPUID.06H.ECX.bit3
176          */
177         asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (6));
178         if (verbose)
179                 printf("CPUID.06H.ECX: 0x%x\n", ecx);
180         if (!(ecx & (1 << 3))) {
181                 if (verbose)
182                         printf("CPUID: No MSR_IA32_ENERGY_PERF_BIAS\n");
183                 exit(1);
184         }
185         return; /* success */
186 }
187 
188 unsigned long long get_msr(int cpu, int offset)
189 {
190         unsigned long long msr;
191         char msr_path[32];
192         int retval;
193         int fd;
194 
195         sprintf(msr_path, "/dev/cpu/%d/msr", cpu);
196         fd = open(msr_path, O_RDONLY);
197         if (fd < 0) {
198                 printf("Try \"# modprobe msr\"\n");
199                 perror(msr_path);
200                 exit(1);
201         }
202 
203         retval = pread(fd, &msr, sizeof msr, offset);
204 
205         if (retval != sizeof msr) {
206                 printf("pread cpu%d 0x%x = %d\n", cpu, offset, retval);
207                 exit(-2);
208         }
209         close(fd);
210         return msr;
211 }
212 
213 unsigned long long  put_msr(int cpu, unsigned long long new_msr, int offset)
214 {
215         unsigned long long old_msr;
216         char msr_path[32];
217         int retval;
218         int fd;
219 
220         sprintf(msr_path, "/dev/cpu/%d/msr", cpu);
221         fd = open(msr_path, O_RDWR);
222         if (fd < 0) {
223                 perror(msr_path);
224                 exit(1);
225         }
226 
227         retval = pread(fd, &old_msr, sizeof old_msr, offset);
228         if (retval != sizeof old_msr) {
229                 perror("pwrite");
230                 printf("pread cpu%d 0x%x = %d\n", cpu, offset, retval);
231                 exit(-2);
232         }
233 
234         retval = pwrite(fd, &new_msr, sizeof new_msr, offset);
235         if (retval != sizeof new_msr) {
236                 perror("pwrite");
237                 printf("pwrite cpu%d 0x%x = %d\n", cpu, offset, retval);
238                 exit(-2);
239         }
240 
241         close(fd);
242 
243         return old_msr;
244 }
245 
246 void print_msr(int cpu)
247 {
248         printf("cpu%d: 0x%016llx\n",
249                 cpu, get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS));
250 }
251 
252 void update_msr(int cpu)
253 {
254         unsigned long long previous_msr;
255 
256         previous_msr = put_msr(cpu, new_bias, MSR_IA32_ENERGY_PERF_BIAS);
257 
258         if (verbose)
259                 printf("cpu%d  msr0x%x 0x%016llx -> 0x%016llx\n",
260                         cpu, MSR_IA32_ENERGY_PERF_BIAS, previous_msr, new_bias);
261 
262         return;
263 }
264 
265 char *proc_stat = "/proc/stat";
266 /*
267  * run func() on every cpu in /dev/cpu
268  */
269 void for_every_cpu(void (func)(int))
270 {
271         FILE *fp;
272         int retval;
273 
274         fp = fopen(proc_stat, "r");
275         if (fp == NULL) {
276                 perror(proc_stat);
277                 exit(1);
278         }
279 
280         retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
281         if (retval != 0) {
282                 perror("/proc/stat format");
283                 exit(1);
284         }
285 
286         while (1) {
287                 int cpu;
288 
289                 retval = fscanf(fp,
290                         "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n",
291                         &cpu);
292                 if (retval != 1)
293                         return;
294 
295                 func(cpu);
296         }
297         fclose(fp);
298 }
299 
300 int main(int argc, char **argv)
301 {
302         cmdline(argc, argv);
303 
304         if (verbose > 1)
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);
309 
310         validate_cpuid();
311 
312         if (cpu != -1) {
313                 if (read_only)
314                         print_msr(cpu);
315                 else
316                         update_msr(cpu);
317         } else {
318                 if (read_only)
319                         for_every_cpu(print_msr);
320                 else
321                         for_every_cpu(update_msr);
322         }
323 
324         return 0;
325 }
326 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp