Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools/power/cpupower: allow running without cpu0

Linux-3.7 added CONFIG_BOOTPARAM_HOTPLUG_CPU0,
allowing systems to offline cpu0.

But when cpu0 is offline, cpupower monitor will not display all
processor and Mperf information:

[root@intel-skylake-dh-03 cpupower]# ./cpupower monitor
WARNING: at least one cpu is offline
|Idle_Stats
CPU | POLL | C1-S | C1E- | C3-S | C6-S | C7s- | C8-S
4| 0.00| 0.00| 0.00| 0.00| 0.90| 0.00| 96.13
1| 0.00| 0.00| 5.49| 0.00| 0.01| 0.00| 92.26
5| 0.00| 0.00| 0.00| 0.00| 0.46| 0.00| 99.50
2| 45.42| 0.00| 0.00| 0.00| 22.94| 0.00| 28.84
6| 0.00| 37.54| 0.00| 0.00| 0.00| 0.00| 0.00
3| 0.00| 0.00| 0.00| 0.00| 0.30| 0.00| 91.99
7| 0.00| 0.00| 0.00| 0.00| 4.70| 0.00| 0.70

This patch replaces the hard-coded use of cpu0 in cpupower with the
current cpu, allowing it to run without a cpu0.

After the patch is applied,

[root@intel-skylake-dh-03 cpupower]# ./cpupower monitor
WARNING: at least one cpu is offline
|Nehalem || Mperf || Idle_Stats
CPU | C3 | C6 | PC3 | PC6 || C0 | Cx | Freq || POLL | C1-S | C1E- | C3-S | C6-S | C7s- | C8-S
4| 0.01| 1.27| 0.00| 0.00|| 0.04| 99.96| 3957|| 0.00| 0.00| 0.00| 0.00| 1.43| 0.00| 98.52
1| 0.00| 98.82| 0.00| 0.00|| 0.05| 99.95| 3361|| 0.00| 0.00| 0.01| 0.00| 0.03| 0.00| 99.88
5| 0.00| 98.82| 0.00| 0.00|| 0.09| 99.91| 3917|| 0.00| 0.00| 0.00| 0.00| 99.38| 0.00| 0.50
2| 0.33| 0.00| 0.00| 0.00|| 0.00|100.00| 3890|| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00|100.00
6| 0.33| 0.00| 0.00| 0.00|| 0.01| 99.99| 3903|| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 99.99
3| 0.01| 0.71| 0.00| 0.00|| 0.06| 99.94| 3678|| 0.00| 0.00| 0.00| 0.00| 0.80| 0.00| 99.13
7| 0.01| 0.71| 0.00| 0.00|| 0.03| 99.97| 3538|| 0.00| 0.69| 11.70| 0.00| 0.00| 0.00| 87.57

There are some minor cleanups included in this patch.

Signed-off-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: Thomas Renninger <trenn@suse.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Prarit Bhargava and committed by
Rafael J. Wysocki
d0e4a193 2158e724

+28 -17
+12 -3
tools/power/cpupower/utils/cpupower.c
··· 12 12 #include <string.h> 13 13 #include <unistd.h> 14 14 #include <errno.h> 15 + #include <sched.h> 15 16 #include <sys/types.h> 16 17 #include <sys/stat.h> 17 18 #include <sys/utsname.h> ··· 32 31 */ 33 32 struct cpupower_cpu_info cpupower_cpu_info; 34 33 int run_as_root; 34 + int base_cpu; 35 35 /* Affected cpus chosen by -c/--cpu param */ 36 36 struct bitmask *cpus_chosen; 37 37 ··· 176 174 unsigned int i, ret; 177 175 struct stat statbuf; 178 176 struct utsname uts; 177 + char pathname[32]; 179 178 180 179 cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); 181 180 ··· 201 198 argv[0] = cmd = "help"; 202 199 } 203 200 204 - get_cpu_info(0, &cpupower_cpu_info); 201 + base_cpu = sched_getcpu(); 202 + if (base_cpu < 0) { 203 + fprintf(stderr, _("No valid cpus found.\n")); 204 + return EXIT_FAILURE; 205 + } 206 + 207 + get_cpu_info(&cpupower_cpu_info); 205 208 run_as_root = !geteuid(); 206 209 if (run_as_root) { 207 210 ret = uname(&uts); 211 + sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); 208 212 if (!ret && !strcmp(uts.machine, "x86_64") && 209 - stat("/dev/cpu/0/msr", &statbuf) != 0) { 213 + stat(pathname, &statbuf) != 0) { 210 214 if (system("modprobe msr") == -1) 211 215 fprintf(stderr, _("MSR access not available.\n")); 212 216 } 213 217 } 214 - 215 218 216 219 for (i = 0; i < ARRAY_SIZE(commands); i++) { 217 220 struct cmd_struct *p = commands + i;
+2 -2
tools/power/cpupower/utils/helpers/cpuid.c
··· 42 42 * 43 43 * TBD: Should there be a cpuid alternative for this if /proc is not mounted? 44 44 */ 45 - int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info) 45 + int get_cpu_info(struct cpupower_cpu_info *cpu_info) 46 46 { 47 47 FILE *fp; 48 48 char value[64]; ··· 70 70 if (!strncmp(value, "processor\t: ", 12)) 71 71 sscanf(value, "processor\t: %u", &proc); 72 72 73 - if (proc != cpu) 73 + if (proc != (unsigned int)base_cpu) 74 74 continue; 75 75 76 76 /* Get CPU vendor */
+3 -2
tools/power/cpupower/utils/helpers/helpers.h
··· 34 34 /* Internationalization ****************************/ 35 35 36 36 extern int run_as_root; 37 + extern int base_cpu; 37 38 extern struct bitmask *cpus_chosen; 38 39 39 40 /* Global verbose (-d) stuff *********************************/ ··· 88 87 * 89 88 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo 90 89 * 91 - * Returns 0 on success or a negativ error code 90 + * Returns 0 on success or a negative error code 92 91 * Only used on x86, below global's struct values are zero/unknown on 93 92 * other archs 94 93 */ 95 - extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info); 94 + extern int get_cpu_info(struct cpupower_cpu_info *cpu_info); 96 95 extern struct cpupower_cpu_info cpupower_cpu_info; 97 96 /* cpuid and cpuinfo helpers **************************/ 98 97
+1 -1
tools/power/cpupower/utils/helpers/misc.c
··· 13 13 14 14 *support = *active = *states = 0; 15 15 16 - ret = get_cpu_info(0, &cpu_info); 16 + ret = get_cpu_info(&cpu_info); 17 17 if (ret) 18 18 return ret; 19 19
+2 -2
tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
··· 123 123 previous_count[num][cpu] = val; 124 124 } 125 125 } 126 - hsw_ext_get_count(TSC, &tsc_at_measure_start, 0); 126 + hsw_ext_get_count(TSC, &tsc_at_measure_start, base_cpu); 127 127 return 0; 128 128 } 129 129 ··· 132 132 unsigned long long val; 133 133 int num, cpu; 134 134 135 - hsw_ext_get_count(TSC, &tsc_at_measure_end, 0); 135 + hsw_ext_get_count(TSC, &tsc_at_measure_end, base_cpu); 136 136 137 137 for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) { 138 138 for (cpu = 0; cpu < cpu_count; cpu++) {
+2 -1
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
··· 80 80 static int mperf_get_tsc(unsigned long long *tsc) 81 81 { 82 82 int ret; 83 - ret = read_msr(0, MSR_TSC, tsc); 83 + 84 + ret = read_msr(base_cpu, MSR_TSC, tsc); 84 85 if (ret) 85 86 dprint("Reading TSC MSR failed, returning %llu\n", *tsc); 86 87 return ret;
+4 -4
tools/power/cpupower/utils/idle_monitor/nhm_idle.c
··· 129 129 int num, cpu; 130 130 unsigned long long dbg, val; 131 131 132 - nhm_get_count(TSC, &tsc_at_measure_start, 0); 132 + nhm_get_count(TSC, &tsc_at_measure_start, base_cpu); 133 133 134 134 for (num = 0; num < NHM_CSTATE_COUNT; num++) { 135 135 for (cpu = 0; cpu < cpu_count; cpu++) { ··· 137 137 previous_count[num][cpu] = val; 138 138 } 139 139 } 140 - nhm_get_count(TSC, &dbg, 0); 140 + nhm_get_count(TSC, &dbg, base_cpu); 141 141 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start); 142 142 return 0; 143 143 } ··· 148 148 unsigned long long dbg; 149 149 int num, cpu; 150 150 151 - nhm_get_count(TSC, &tsc_at_measure_end, 0); 151 + nhm_get_count(TSC, &tsc_at_measure_end, base_cpu); 152 152 153 153 for (num = 0; num < NHM_CSTATE_COUNT; num++) { 154 154 for (cpu = 0; cpu < cpu_count; cpu++) { ··· 156 156 current_count[num][cpu] = val; 157 157 } 158 158 } 159 - nhm_get_count(TSC, &dbg, 0); 159 + nhm_get_count(TSC, &dbg, base_cpu); 160 160 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end); 161 161 162 162 return 0;
+2 -2
tools/power/cpupower/utils/idle_monitor/snb_idle.c
··· 120 120 previous_count[num][cpu] = val; 121 121 } 122 122 } 123 - snb_get_count(TSC, &tsc_at_measure_start, 0); 123 + snb_get_count(TSC, &tsc_at_measure_start, base_cpu); 124 124 return 0; 125 125 } 126 126 ··· 129 129 unsigned long long val; 130 130 int num, cpu; 131 131 132 - snb_get_count(TSC, &tsc_at_measure_end, 0); 132 + snb_get_count(TSC, &tsc_at_measure_end, base_cpu); 133 133 134 134 for (num = 0; num < SNB_CSTATE_COUNT; num++) { 135 135 for (cpu = 0; cpu < cpu_count; cpu++) {