Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 1 | /* |
| 2 | * (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc. |
| 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 <stdlib.h> |
| 11 | #include <errno.h> |
| 12 | #include <string.h> |
| 13 | #include <getopt.h> |
| 14 | |
| 15 | #include <cpufreq.h> |
| 16 | #include "helpers/helpers.h" |
| 17 | #include "helpers/sysfs.h" |
| 18 | |
| 19 | void info_help(void) |
| 20 | { |
| 21 | printf(_("Usage: cpupower info [ -b ] [ -m ] [ -s ]\n")); |
| 22 | printf(_("Options:\n")); |
| 23 | printf(_(" -b, --perf-bias Gets CPU's power vs performance policy on some\n" |
| 24 | " Intel models [0-15], see manpage for details\n")); |
| 25 | printf(_(" -m, --sched-mc Gets the kernel's multi core scheduler policy.\n")); |
| 26 | printf(_(" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n")); |
| 27 | printf(_(" -h, --help Prints out this screen\n")); |
| 28 | printf(_("\nPassing no option will show all info, by default only on core 0\n")); |
| 29 | printf("\n"); |
| 30 | } |
| 31 | |
| 32 | static struct option set_opts[] = { |
Dominik Brodowski | a1ce5ba | 2011-04-19 20:33:50 +0200 | [diff] [blame^] | 33 | { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, |
| 34 | { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'}, |
| 35 | { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'}, |
| 36 | { .name = "help", .has_arg = no_argument, .flag = NULL, .val = 'h'}, |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 37 | { }, |
| 38 | }; |
| 39 | |
| 40 | static void print_wrong_arg_exit(void) |
| 41 | { |
| 42 | printf(_("invalid or unknown argument\n")); |
| 43 | info_help(); |
| 44 | exit(EXIT_FAILURE); |
| 45 | } |
| 46 | |
| 47 | int cmd_info(int argc, char **argv) |
| 48 | { |
| 49 | extern char *optarg; |
| 50 | extern int optind, opterr, optopt; |
| 51 | unsigned int cpu; |
| 52 | |
| 53 | union { |
| 54 | struct { |
| 55 | int sched_mc:1; |
| 56 | int sched_smt:1; |
| 57 | int perf_bias:1; |
| 58 | }; |
| 59 | int params; |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 60 | } params = {}; |
| 61 | int ret = 0; |
| 62 | |
| 63 | setlocale(LC_ALL, ""); |
Dominik Brodowski | a1ce5ba | 2011-04-19 20:33:50 +0200 | [diff] [blame^] | 64 | textdomain(PACKAGE); |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 65 | |
| 66 | /* parameter parsing */ |
| 67 | while ((ret = getopt_long(argc, argv, "msbh", set_opts, NULL)) != -1) { |
| 68 | switch (ret) { |
| 69 | case 'h': |
| 70 | info_help(); |
| 71 | return 0; |
| 72 | case 'b': |
| 73 | if (params.perf_bias) |
| 74 | print_wrong_arg_exit(); |
| 75 | params.perf_bias = 1; |
| 76 | break; |
| 77 | case 'm': |
| 78 | if (params.sched_mc) |
| 79 | print_wrong_arg_exit(); |
| 80 | params.sched_mc = 1; |
| 81 | break; |
| 82 | case 's': |
| 83 | if (params.sched_smt) |
| 84 | print_wrong_arg_exit(); |
| 85 | params.sched_smt = 1; |
| 86 | break; |
| 87 | default: |
| 88 | print_wrong_arg_exit(); |
| 89 | } |
| 90 | }; |
| 91 | |
| 92 | if (!params.params) |
| 93 | params.params = 0x7; |
| 94 | |
| 95 | /* Default is: show output of CPU 0 only */ |
| 96 | if (bitmask_isallclear(cpus_chosen)) |
| 97 | bitmask_setbit(cpus_chosen, 0); |
| 98 | |
| 99 | if (params.sched_mc) { |
| 100 | ret = sysfs_get_sched("mc"); |
| 101 | printf(_("System's multi core scheduler setting: ")); |
| 102 | if (ret < 0) |
| 103 | /* if sysfs file is missing it's: errno == ENOENT */ |
| 104 | printf(_("not supported\n")); |
| 105 | else |
| 106 | printf("%d\n", ret); |
Dominik Brodowski | a1ce5ba | 2011-04-19 20:33:50 +0200 | [diff] [blame^] | 107 | } |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 108 | if (params.sched_smt) { |
| 109 | ret = sysfs_get_sched("smt"); |
| 110 | printf(_("System's thread sibling scheduler setting: ")); |
| 111 | if (ret < 0) |
| 112 | /* if sysfs file is missing it's: errno == ENOENT */ |
| 113 | printf(_("not supported\n")); |
| 114 | else |
| 115 | printf("%d\n", ret); |
| 116 | } |
| 117 | |
| 118 | /* Add more per cpu options here */ |
| 119 | if (!params.perf_bias) |
| 120 | return ret; |
| 121 | |
| 122 | if (params.perf_bias) { |
| 123 | if (!run_as_root) { |
| 124 | params.perf_bias = 0; |
Dominik Brodowski | a1ce5ba | 2011-04-19 20:33:50 +0200 | [diff] [blame^] | 125 | printf(_("Intel's performance bias setting needs root privileges\n")); |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 126 | } else if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) { |
| 127 | printf(_("System does not support Intel's performance" |
| 128 | " bias setting\n")); |
| 129 | params.perf_bias = 0; |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | /* loop over CPUs */ |
| 134 | for (cpu = bitmask_first(cpus_chosen); |
| 135 | cpu <= bitmask_last(cpus_chosen); cpu++) { |
Dominik Brodowski | a1ce5ba | 2011-04-19 20:33:50 +0200 | [diff] [blame^] | 136 | |
Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 137 | if (!bitmask_isbitset(cpus_chosen, cpu) || |
| 138 | cpufreq_cpu_exists(cpu)) |
| 139 | continue; |
| 140 | |
| 141 | printf(_("analyzing CPU %d:\n"), cpu); |
| 142 | |
| 143 | if (params.perf_bias) { |
| 144 | ret = msr_intel_get_perf_bias(cpu); |
| 145 | if (ret < 0) { |
| 146 | printf(_("Could not read perf-bias value\n")); |
| 147 | break; |
| 148 | } else |
| 149 | printf(_("perf-bias: %d\n"), ret); |
| 150 | } |
| 151 | } |
| 152 | return ret; |
| 153 | } |