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

TOMOYO Linux Cross Reference
Linux/tools/power/cpupower/utils/cpufreq-info.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ 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-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  *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
  3  *
  4  *  Licensed under the terms of the GNU GPL License version 2.
  5  */
  6 
  7 
  8 #include <unistd.h>
  9 #include <stdio.h>
 10 #include <errno.h>
 11 #include <stdlib.h>
 12 #include <string.h>
 13 #include <limits.h>
 14 
 15 #include <getopt.h>
 16 
 17 #include "cpufreq.h"
 18 #include "helpers/sysfs.h"
 19 #include "helpers/helpers.h"
 20 #include "helpers/bitmask.h"
 21 
 22 #define LINE_LEN 10
 23 
 24 static unsigned int count_cpus(void)
 25 {
 26         FILE *fp;
 27         char value[LINE_LEN];
 28         unsigned int ret = 0;
 29         unsigned int cpunr = 0;
 30 
 31         fp = fopen("/proc/stat", "r");
 32         if (!fp) {
 33                 printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
 34                 return 1;
 35         }
 36 
 37         while (!feof(fp)) {
 38                 if (!fgets(value, LINE_LEN, fp))
 39                         continue;
 40                 value[LINE_LEN - 1] = '\0';
 41                 if (strlen(value) < (LINE_LEN - 2))
 42                         continue;
 43                 if (strstr(value, "cpu "))
 44                         continue;
 45                 if (sscanf(value, "cpu%d ", &cpunr) != 1)
 46                         continue;
 47                 if (cpunr > ret)
 48                         ret = cpunr;
 49         }
 50         fclose(fp);
 51 
 52         /* cpu count starts from 0, on error return 1 (UP) */
 53         return ret + 1;
 54 }
 55 
 56 
 57 static void proc_cpufreq_output(void)
 58 {
 59         unsigned int cpu, nr_cpus;
 60         struct cpufreq_policy *policy;
 61         unsigned int min_pctg = 0;
 62         unsigned int max_pctg = 0;
 63         unsigned long min, max;
 64 
 65         printf(_("          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"));
 66 
 67         nr_cpus = count_cpus();
 68         for (cpu = 0; cpu < nr_cpus; cpu++) {
 69                 policy = cpufreq_get_policy(cpu);
 70                 if (!policy)
 71                         continue;
 72 
 73                 if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
 74                         max = 0;
 75                 } else {
 76                         min_pctg = (policy->min * 100) / max;
 77                         max_pctg = (policy->max * 100) / max;
 78                 }
 79                 printf("CPU%3d    %9lu kHz (%3d %%)  -  %9lu kHz (%3d %%)  -  %s\n",
 80                         cpu , policy->min, max ? min_pctg : 0, policy->max,
 81                         max ? max_pctg : 0, policy->governor);
 82 
 83                 cpufreq_put_policy(policy);
 84         }
 85 }
 86 
 87 static int no_rounding;
 88 static void print_speed(unsigned long speed)
 89 {
 90         unsigned long tmp;
 91 
 92         if (no_rounding) {
 93                 if (speed > 1000000)
 94                         printf("%u.%06u GHz", ((unsigned int) speed/1000000),
 95                                 ((unsigned int) speed%1000000));
 96                 else if (speed > 100000)
 97                         printf("%u MHz", (unsigned int) speed);
 98                 else if (speed > 1000)
 99                         printf("%u.%03u MHz", ((unsigned int) speed/1000),
100                                 (unsigned int) (speed%1000));
101                 else
102                         printf("%lu kHz", speed);
103         } else {
104                 if (speed > 1000000) {
105                         tmp = speed%10000;
106                         if (tmp >= 5000)
107                                 speed += 10000;
108                         printf("%u.%02u GHz", ((unsigned int) speed/1000000),
109                                 ((unsigned int) (speed%1000000)/10000));
110                 } else if (speed > 100000) {
111                         tmp = speed%1000;
112                         if (tmp >= 500)
113                                 speed += 1000;
114                         printf("%u MHz", ((unsigned int) speed/1000));
115                 } else if (speed > 1000) {
116                         tmp = speed%100;
117                         if (tmp >= 50)
118                                 speed += 100;
119                         printf("%u.%01u MHz", ((unsigned int) speed/1000),
120                                 ((unsigned int) (speed%1000)/100));
121                 }
122         }
123 
124         return;
125 }
126 
127 static void print_duration(unsigned long duration)
128 {
129         unsigned long tmp;
130 
131         if (no_rounding) {
132                 if (duration > 1000000)
133                         printf("%u.%06u ms", ((unsigned int) duration/1000000),
134                                 ((unsigned int) duration%1000000));
135                 else if (duration > 100000)
136                         printf("%u us", ((unsigned int) duration/1000));
137                 else if (duration > 1000)
138                         printf("%u.%03u us", ((unsigned int) duration/1000),
139                                 ((unsigned int) duration%1000));
140                 else
141                         printf("%lu ns", duration);
142         } else {
143                 if (duration > 1000000) {
144                         tmp = duration%10000;
145                         if (tmp >= 5000)
146                                 duration += 10000;
147                         printf("%u.%02u ms", ((unsigned int) duration/1000000),
148                                 ((unsigned int) (duration%1000000)/10000));
149                 } else if (duration > 100000) {
150                         tmp = duration%1000;
151                         if (tmp >= 500)
152                                 duration += 1000;
153                         printf("%u us", ((unsigned int) duration / 1000));
154                 } else if (duration > 1000) {
155                         tmp = duration%100;
156                         if (tmp >= 50)
157                                 duration += 100;
158                         printf("%u.%01u us", ((unsigned int) duration/1000),
159                                 ((unsigned int) (duration%1000)/100));
160                 } else
161                         printf("%lu ns", duration);
162         }
163         return;
164 }
165 
166 /* --boost / -b */
167 
168 static int get_boost_mode(unsigned int cpu)
169 {
170         int support, active, b_states = 0, ret, pstate_no, i;
171         /* ToDo: Make this more global */
172         unsigned long pstates[MAX_HW_PSTATES] = {0,};
173 
174         if (cpupower_cpu_info.vendor != X86_VENDOR_AMD &&
175             cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
176                 return 0;
177 
178         ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states);
179         if (ret) {
180                 printf(_("Error while evaluating Boost Capabilities"
181                                 " on CPU %d -- are you root?\n"), cpu);
182                 return ret;
183         }
184         /* P state changes via MSR are identified via cpuid 80000007
185            on Intel and AMD, but we assume boost capable machines can do that
186            if (cpuid_eax(0x80000000) >= 0x80000007
187            && (cpuid_edx(0x80000007) & (1 << 7)))
188         */
189 
190         printf(_("  boost state support:\n"));
191 
192         printf(_("    Supported: %s\n"), support ? _("yes") : _("no"));
193         printf(_("    Active: %s\n"), active ? _("yes") : _("no"));
194 
195         if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
196             cpupower_cpu_info.family >= 0x10) {
197                 ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
198                                      pstates, &pstate_no);
199                 if (ret)
200                         return ret;
201 
202                 printf(_("    Boost States: %d\n"), b_states);
203                 printf(_("    Total States: %d\n"), pstate_no);
204                 for (i = 0; i < pstate_no; i++) {
205                         if (i < b_states)
206                                 printf(_("    Pstate-Pb%d: %luMHz (boost state)"
207                                          "\n"), i, pstates[i]);
208                         else
209                                 printf(_("    Pstate-P%d:  %luMHz\n"),
210                                        i - b_states, pstates[i]);
211                 }
212         } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) {
213                 double bclk;
214                 unsigned long long intel_turbo_ratio = 0;
215                 unsigned int ratio;
216 
217                 /* Any way to autodetect this ? */
218                 if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB)
219                         bclk = 100.00;
220                 else
221                         bclk = 133.33;
222                 intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu);
223                 dprint ("    Ratio: 0x%llx - bclk: %f\n",
224                         intel_turbo_ratio, bclk);
225 
226                 ratio = (intel_turbo_ratio >> 24) & 0xFF;
227                 if (ratio)
228                         printf(_("    %.0f MHz max turbo 4 active cores\n"),
229                                ratio * bclk);
230 
231                 ratio = (intel_turbo_ratio >> 16) & 0xFF;
232                 if (ratio)
233                         printf(_("    %.0f MHz max turbo 3 active cores\n"),
234                                ratio * bclk);
235 
236                 ratio = (intel_turbo_ratio >> 8) & 0xFF;
237                 if (ratio)
238                         printf(_("    %.0f MHz max turbo 2 active cores\n"),
239                                ratio * bclk);
240 
241                 ratio = (intel_turbo_ratio >> 0) & 0xFF;
242                 if (ratio)
243                         printf(_("    %.0f MHz max turbo 1 active cores\n"),
244                                ratio * bclk);
245         }
246         return 0;
247 }
248 
249 /* --freq / -f */
250 
251 static int get_freq_kernel(unsigned int cpu, unsigned int human)
252 {
253         unsigned long freq = cpufreq_get_freq_kernel(cpu);
254         printf(_("  current CPU frequency: "));
255         if (!freq) {
256                 printf(_(" Unable to call to kernel\n"));
257                 return -EINVAL;
258         }
259         if (human) {
260                 print_speed(freq);
261         } else
262                 printf("%lu", freq);
263         printf(_(" (asserted by call to kernel)\n"));
264         return 0;
265 }
266 
267 
268 /* --hwfreq / -w */
269 
270 static int get_freq_hardware(unsigned int cpu, unsigned int human)
271 {
272         unsigned long freq = cpufreq_get_freq_hardware(cpu);
273         printf(_("  current CPU frequency: "));
274         if (!freq) {
275                 printf("Unable to call hardware\n");
276                 return -EINVAL;
277         }
278         if (human) {
279                 print_speed(freq);
280         } else
281                 printf("%lu", freq);
282         printf(_(" (asserted by call to hardware)\n"));
283         return 0;
284 }
285 
286 /* --hwlimits / -l */
287 
288 static int get_hardware_limits(unsigned int cpu)
289 {
290         unsigned long min, max;
291 
292         printf(_("  hardware limits: "));
293         if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
294                 printf(_("Not Available\n"));
295                 return -EINVAL;
296         }
297 
298         print_speed(min);
299         printf(" - ");
300         print_speed(max);
301         printf("\n");
302         return 0;
303 }
304 
305 /* --driver / -d */
306 
307 static int get_driver(unsigned int cpu)
308 {
309         char *driver = cpufreq_get_driver(cpu);
310         if (!driver) {
311                 printf(_("  no or unknown cpufreq driver is active on this CPU\n"));
312                 return -EINVAL;
313         }
314         printf("  driver: %s\n", driver);
315         cpufreq_put_driver(driver);
316         return 0;
317 }
318 
319 /* --policy / -p */
320 
321 static int get_policy(unsigned int cpu)
322 {
323         struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
324         if (!policy) {
325                 printf(_("  Unable to determine current policy\n"));
326                 return -EINVAL;
327         }
328         printf(_("  current policy: frequency should be within "));
329         print_speed(policy->min);
330         printf(_(" and "));
331         print_speed(policy->max);
332 
333         printf(".\n                  ");
334         printf(_("The governor \"%s\" may decide which speed to use\n"
335                "                  within this range.\n"),
336                policy->governor);
337         cpufreq_put_policy(policy);
338         return 0;
339 }
340 
341 /* --governors / -g */
342 
343 static int get_available_governors(unsigned int cpu)
344 {
345         struct cpufreq_available_governors *governors =
346                 cpufreq_get_available_governors(cpu);
347 
348         printf(_("  available cpufreq governors: "));
349         if (!governors) {
350                 printf(_("Not Available\n"));
351                 return -EINVAL;
352         }
353 
354         while (governors->next) {
355                 printf("%s ", governors->governor);
356                 governors = governors->next;
357         }
358         printf("%s\n", governors->governor);
359         cpufreq_put_available_governors(governors);
360         return 0;
361 }
362 
363 
364 /* --affected-cpus  / -a */
365 
366 static int get_affected_cpus(unsigned int cpu)
367 {
368         struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
369 
370         printf(_("  CPUs which need to have their frequency coordinated by software: "));
371         if (!cpus) {
372                 printf(_("Not Available\n"));
373                 return -EINVAL;
374         }
375 
376         while (cpus->next) {
377                 printf("%d ", cpus->cpu);
378                 cpus = cpus->next;
379         }
380         printf("%d\n", cpus->cpu);
381         cpufreq_put_affected_cpus(cpus);
382         return 0;
383 }
384 
385 /* --related-cpus  / -r */
386 
387 static int get_related_cpus(unsigned int cpu)
388 {
389         struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
390 
391         printf(_("  CPUs which run at the same hardware frequency: "));
392         if (!cpus) {
393                 printf(_("Not Available\n"));
394                 return -EINVAL;
395         }
396 
397         while (cpus->next) {
398                 printf("%d ", cpus->cpu);
399                 cpus = cpus->next;
400         }
401         printf("%d\n", cpus->cpu);
402         cpufreq_put_related_cpus(cpus);
403         return 0;
404 }
405 
406 /* --stats / -s */
407 
408 static int get_freq_stats(unsigned int cpu, unsigned int human)
409 {
410         unsigned long total_trans = cpufreq_get_transitions(cpu);
411         unsigned long long total_time;
412         struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
413         while (stats) {
414                 if (human) {
415                         print_speed(stats->frequency);
416                         printf(":%.2f%%",
417                                 (100.0 * stats->time_in_state) / total_time);
418                 } else
419                         printf("%lu:%llu",
420                                 stats->frequency, stats->time_in_state);
421                 stats = stats->next;
422                 if (stats)
423                         printf(", ");
424         }
425         cpufreq_put_stats(stats);
426         if (total_trans)
427                 printf("  (%lu)\n", total_trans);
428         return 0;
429 }
430 
431 /* --latency / -y */
432 
433 static int get_latency(unsigned int cpu, unsigned int human)
434 {
435         unsigned long latency = cpufreq_get_transition_latency(cpu);
436 
437         printf(_("  maximum transition latency: "));
438         if (!latency || latency == UINT_MAX) {
439                 printf(_(" Cannot determine or is not supported.\n"));
440                 return -EINVAL;
441         }
442 
443         if (human) {
444                 print_duration(latency);
445                 printf("\n");
446         } else
447                 printf("%lu\n", latency);
448         return 0;
449 }
450 
451 static void debug_output_one(unsigned int cpu)
452 {
453         struct cpufreq_available_frequencies *freqs;
454 
455         get_driver(cpu);
456         get_related_cpus(cpu);
457         get_affected_cpus(cpu);
458         get_latency(cpu, 1);
459         get_hardware_limits(cpu);
460 
461         freqs = cpufreq_get_available_frequencies(cpu);
462         if (freqs) {
463                 printf(_("  available frequency steps:  "));
464                 while (freqs->next) {
465                         print_speed(freqs->frequency);
466                         printf(", ");
467                         freqs = freqs->next;
468                 }
469                 print_speed(freqs->frequency);
470                 printf("\n");
471                 cpufreq_put_available_frequencies(freqs);
472         }
473 
474         get_available_governors(cpu);
475         get_policy(cpu);
476         if (get_freq_hardware(cpu, 1) < 0)
477                 get_freq_kernel(cpu, 1);
478         get_boost_mode(cpu);
479 }
480 
481 static struct option info_opts[] = {
482         {"debug",        no_argument,            NULL,   'e'},
483         {"boost",        no_argument,            NULL,   'b'},
484         {"freq",         no_argument,            NULL,   'f'},
485         {"hwfreq",       no_argument,            NULL,   'w'},
486         {"hwlimits",     no_argument,            NULL,   'l'},
487         {"driver",       no_argument,            NULL,   'd'},
488         {"policy",       no_argument,            NULL,   'p'},
489         {"governors",    no_argument,            NULL,   'g'},
490         {"related-cpus",  no_argument,   NULL,   'r'},
491         {"affected-cpus", no_argument,   NULL,   'a'},
492         {"stats",        no_argument,            NULL,   's'},
493         {"latency",      no_argument,            NULL,   'y'},
494         {"proc",         no_argument,            NULL,   'o'},
495         {"human",        no_argument,            NULL,   'm'},
496         {"no-rounding", no_argument,     NULL,   'n'},
497         { },
498 };
499 
500 int cmd_freq_info(int argc, char **argv)
501 {
502         extern char *optarg;
503         extern int optind, opterr, optopt;
504         int ret = 0, cont = 1;
505         unsigned int cpu = 0;
506         unsigned int human = 0;
507         int output_param = 0;
508 
509         do {
510                 ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts,
511                                   NULL);
512                 switch (ret) {
513                 case '?':
514                         output_param = '?';
515                         cont = 0;
516                         break;
517                 case -1:
518                         cont = 0;
519                         break;
520                 case 'b':
521                 case 'o':
522                 case 'a':
523                 case 'r':
524                 case 'g':
525                 case 'p':
526                 case 'd':
527                 case 'l':
528                 case 'w':
529                 case 'f':
530                 case 'e':
531                 case 's':
532                 case 'y':
533                         if (output_param) {
534                                 output_param = -1;
535                                 cont = 0;
536                                 break;
537                         }
538                         output_param = ret;
539                         break;
540                 case 'm':
541                         if (human) {
542                                 output_param = -1;
543                                 cont = 0;
544                                 break;
545                         }
546                         human = 1;
547                         break;
548                 case 'n':
549                         no_rounding = 1;
550                         break;
551                 default:
552                         fprintf(stderr, "invalid or unknown argument\n");
553                         return EXIT_FAILURE;
554                 }
555         } while (cont);
556 
557         switch (output_param) {
558         case 'o':
559                 if (!bitmask_isallclear(cpus_chosen)) {
560                         printf(_("The argument passed to this tool can't be "
561                                  "combined with passing a --cpu argument\n"));
562                         return -EINVAL;
563                 }
564                 break;
565         case 0:
566                 output_param = 'e';
567         }
568 
569         ret = 0;
570 
571         /* Default is: show output of CPU 0 only */
572         if (bitmask_isallclear(cpus_chosen))
573                 bitmask_setbit(cpus_chosen, 0);
574 
575         switch (output_param) {
576         case -1:
577                 printf(_("You can't specify more than one --cpu parameter and/or\n"
578                        "more than one output-specific argument\n"));
579                 return -EINVAL;
580         case '?':
581                 printf(_("invalid or unknown argument\n"));
582                 return -EINVAL;
583         case 'o':
584                 proc_cpufreq_output();
585                 return EXIT_SUCCESS;
586         }
587 
588         for (cpu = bitmask_first(cpus_chosen);
589              cpu <= bitmask_last(cpus_chosen); cpu++) {
590 
591                 if (!bitmask_isbitset(cpus_chosen, cpu))
592                         continue;
593 
594                 printf(_("analyzing CPU %d:\n"), cpu);
595 
596                 if (sysfs_is_cpu_online(cpu) != 1) {
597                         printf(_(" *is offline\n"));
598                         printf("\n");
599                         continue;
600                 }
601 
602                 switch (output_param) {
603                 case 'b':
604                         get_boost_mode(cpu);
605                         break;
606                 case 'e':
607                         debug_output_one(cpu);
608                         break;
609                 case 'a':
610                         ret = get_affected_cpus(cpu);
611                         break;
612                 case 'r':
613                         ret = get_related_cpus(cpu);
614                         break;
615                 case 'g':
616                         ret = get_available_governors(cpu);
617                         break;
618                 case 'p':
619                         ret = get_policy(cpu);
620                         break;
621                 case 'd':
622                         ret = get_driver(cpu);
623                         break;
624                 case 'l':
625                         ret = get_hardware_limits(cpu);
626                         break;
627                 case 'w':
628                         ret = get_freq_hardware(cpu, human);
629                         break;
630                 case 'f':
631                         ret = get_freq_kernel(cpu, human);
632                         break;
633                 case 's':
634                         ret = get_freq_stats(cpu, human);
635                         break;
636                 case 'y':
637                         ret = get_latency(cpu, human);
638                         break;
639                 }
640                 if (ret)
641                         return ret;
642                 printf("\n");
643         }
644         return ret;
645 }
646 

~ [ 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