diff options
| author | Len Brown <len.brown@intel.com> | 2015-01-23 01:33:58 -0500 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2015-02-09 18:28:18 -0500 |
| commit | a729617c58529be0be8faa22c5d45748bb0f12e5 (patch) | |
| tree | f50255767f07a7bc8ccbc0abcd3e097b7ea7cef8 | |
| parent | d7899447535929b3672442b7b42a09ae4e48fa91 (diff) | |
tools/power turbostat: relax dependency on APERF_MSR
While turbostat is significantly less useful on systems
with no APERF_MSR, it seems more friendly
to run on such systems and report what we can,
rather than refusing to run.
Update man page to reflect recent changes.
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | tools/power/x86/turbostat/turbostat.8 | 66 | ||||
| -rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 47 |
2 files changed, 68 insertions, 45 deletions
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 56bfb523c5bb..9b950699e63d 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 | |||
| @@ -12,16 +12,16 @@ turbostat \- Report processor frequency and idle statistics | |||
| 12 | .RB [ "\-i interval_sec" ] | 12 | .RB [ "\-i interval_sec" ] |
| 13 | .SH DESCRIPTION | 13 | .SH DESCRIPTION |
| 14 | \fBturbostat \fP reports processor topology, frequency, | 14 | \fBturbostat \fP reports processor topology, frequency, |
| 15 | idle power-state statistics, temperature and power on modern X86 processors. | 15 | idle power-state statistics, temperature and power on X86 processors. |
| 16 | Either \fBcommand\fP is forked and statistics are printed | 16 | There are two ways to invoke turbostat. |
| 17 | upon its completion, or statistics are printed periodically. | 17 | The first method is to supply a |
| 18 | 18 | \fBcommand\fP, which is forked and statistics are printed | |
| 19 | \fBturbostat \fP | 19 | upon its completion. |
| 20 | must be run on root, and | 20 | The second method is to omit the command, |
| 21 | minimally requires that the processor | 21 | and turbodstat will print statistics every 5 seconds. |
| 22 | supports an "invariant" TSC, plus the APERF and MPERF MSRs. | 22 | The 5-second interval can changed using the -i option. |
| 23 | Additional information is reported depending on hardware counter support. | 23 | |
| 24 | 24 | Some information is not availalbe on older processors. | |
| 25 | .SS Options | 25 | .SS Options |
| 26 | The \fB-p\fP option limits output to the 1st thread in 1st core of each package. | 26 | The \fB-p\fP option limits output to the 1st thread in 1st core of each package. |
| 27 | .PP | 27 | .PP |
| @@ -130,12 +130,13 @@ cpu3: MSR_IA32_THERM_STATUS: 0x884e0000 (27 C +/- 1) | |||
| 130 | ... | 130 | ... |
| 131 | .fi | 131 | .fi |
| 132 | The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency | 132 | The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency |
| 133 | available at the minimum package voltage. The \fBTSC frequency\fP is the nominal | 133 | available at the minimum package voltage. The \fBTSC frequency\fP is the base |
| 134 | maximum frequency of the processor if turbo-mode were not available. This frequency | 134 | frequency of the processor -- this should match the brand string |
| 135 | in /proc/cpuinfo. This base frequency | ||
| 135 | should be sustainable on all CPUs indefinitely, given nominal power and cooling. | 136 | should be sustainable on all CPUs indefinitely, given nominal power and cooling. |
| 136 | The remaining rows show what maximum turbo frequency is possible | 137 | The remaining rows show what maximum turbo frequency is possible |
| 137 | depending on the number of idle cores. Note that this information is | 138 | depending on the number of idle cores. Note that not all information is |
| 138 | not available on all processors. | 139 | available on all processors. |
| 139 | .SH FORK EXAMPLE | 140 | .SH FORK EXAMPLE |
| 140 | If turbostat is invoked with a command, it will fork that command | 141 | If turbostat is invoked with a command, it will fork that command |
| 141 | and output the statistics gathered when the command exits. | 142 | and output the statistics gathered when the command exits. |
| @@ -176,6 +177,11 @@ not including any non-busy idle time. | |||
| 176 | 177 | ||
| 177 | .B "turbostat " | 178 | .B "turbostat " |
| 178 | must be run as root. | 179 | must be run as root. |
| 180 | Alternatively, non-root users can be enabled to run turbostat this way: | ||
| 181 | |||
| 182 | # setcap cap_sys_rawio=ep ./turbostat | ||
| 183 | |||
| 184 | # chmod +r /dev/cpu/*/msr | ||
| 179 | 185 | ||
| 180 | .B "turbostat " | 186 | .B "turbostat " |
| 181 | reads hardware counters, but doesn't write them. | 187 | reads hardware counters, but doesn't write them. |
| @@ -184,15 +190,33 @@ multiple invocations of itself. | |||
| 184 | 190 | ||
| 185 | \fBturbostat \fP | 191 | \fBturbostat \fP |
| 186 | may work poorly on Linux-2.6.20 through 2.6.29, | 192 | may work poorly on Linux-2.6.20 through 2.6.29, |
| 187 | as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF | 193 | as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF MSRs |
| 188 | in those kernels. | 194 | in those kernels. |
| 189 | 195 | ||
| 190 | If the TSC column does not make sense, then | 196 | AVG_MHz = APERF_delta/measurement_interval. This is the actual |
| 191 | the other numbers will also make no sense. | 197 | number of elapsed cycles divided by the entire sample interval -- |
| 192 | Turbostat is lightweight, and its data collection is not atomic. | 198 | including idle time. Note that this calculation is resiliant |
| 193 | These issues are usually caused by an extremely short measurement | 199 | to systems lacking a non-stop TSC. |
| 194 | interval (much less than 1 second), or system activity that prevents | 200 | |
| 195 | turbostat from being able to run on all CPUS to quickly collect data. | 201 | TSC_MHz = TSC_delta/measurement_interval. |
| 202 | On a system with an invariant TSC, this value will be constant | ||
| 203 | and will closely match the base frequency value shown | ||
| 204 | in the brand string in /proc/cpuinfo. On a system where | ||
| 205 | the TSC stops in idle, TSC_MHz will drop | ||
| 206 | below the processor's base frequency. | ||
| 207 | |||
| 208 | %Busy = MPERF_delta/TSC_delta | ||
| 209 | |||
| 210 | Bzy_MHz = TSC_delta/APERF_delta/MPERF_delta/measurement_interval | ||
| 211 | |||
| 212 | Note that these calculations depend on TSC_delta, so they | ||
| 213 | are not reliable during intervals when TSC_MHz is not running at the base frequency. | ||
| 214 | |||
| 215 | Turbostat data collection is not atomic. | ||
| 216 | Extremely short measurement intervals (much less than 1 second), | ||
| 217 | or system activity that prevents turbostat from being able | ||
| 218 | to run on all CPUS to quickly collect data, will result in | ||
| 219 | inconsistent results. | ||
| 196 | 220 | ||
| 197 | The APERF, MPERF MSRs are defined to count non-halted cycles. | 221 | The APERF, MPERF MSRs are defined to count non-halted cycles. |
| 198 | Although it is not guaranteed by the architecture, turbostat assumes | 222 | Although it is not guaranteed by the architecture, turbostat assumes |
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index b654b641d4c3..a02c02f25e88 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
| @@ -673,24 +673,26 @@ delta_thread(struct thread_data *new, struct thread_data *old, | |||
| 673 | 673 | ||
| 674 | old->c1 = new->c1 - old->c1; | 674 | old->c1 = new->c1 - old->c1; |
| 675 | 675 | ||
| 676 | if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) { | 676 | if (has_aperf) { |
| 677 | old->aperf = new->aperf - old->aperf; | 677 | if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) { |
| 678 | old->mperf = new->mperf - old->mperf; | 678 | old->aperf = new->aperf - old->aperf; |
| 679 | } else { | 679 | old->mperf = new->mperf - old->mperf; |
| 680 | } else { | ||
| 680 | 681 | ||
| 681 | if (!aperf_mperf_unstable) { | 682 | if (!aperf_mperf_unstable) { |
| 682 | fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname); | 683 | fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname); |
| 683 | fprintf(stderr, "* Frequency results do not cover entire interval *\n"); | 684 | fprintf(stderr, "* Frequency results do not cover entire interval *\n"); |
| 684 | fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n"); | 685 | fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n"); |
| 685 | 686 | ||
| 686 | aperf_mperf_unstable = 1; | 687 | aperf_mperf_unstable = 1; |
| 688 | } | ||
| 689 | /* | ||
| 690 | * mperf delta is likely a huge "positive" number | ||
| 691 | * can not use it for calculating c0 time | ||
| 692 | */ | ||
| 693 | skip_c0 = 1; | ||
| 694 | skip_c1 = 1; | ||
| 687 | } | 695 | } |
| 688 | /* | ||
| 689 | * mperf delta is likely a huge "positive" number | ||
| 690 | * can not use it for calculating c0 time | ||
| 691 | */ | ||
| 692 | skip_c0 = 1; | ||
| 693 | skip_c1 = 1; | ||
| 694 | } | 696 | } |
| 695 | 697 | ||
| 696 | 698 | ||
| @@ -2244,14 +2246,11 @@ void check_cpuid() | |||
| 2244 | has_epb = ecx & (1 << 3); | 2246 | has_epb = ecx & (1 << 3); |
| 2245 | 2247 | ||
| 2246 | if (verbose) | 2248 | if (verbose) |
| 2247 | fprintf(stderr, "CPUID(6): %s%s%s%s\n", | 2249 | fprintf(stderr, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sEPB\n", |
| 2248 | has_aperf ? "APERF" : "No APERF!", | 2250 | has_aperf ? "" : "No ", |
| 2249 | do_dts ? ", DTS" : "", | 2251 | do_dts ? "" : "No ", |
| 2250 | do_ptm ? ", PTM": "", | 2252 | do_ptm ? "" : "No ", |
| 2251 | has_epb ? ", EPB": ""); | 2253 | has_epb ? "" : "No "); |
| 2252 | |||
| 2253 | if (!has_aperf) | ||
| 2254 | errx(-1, "No APERF"); | ||
| 2255 | 2254 | ||
| 2256 | do_nhm_platform_info = do_nhm_cstates = do_smi = has_nhm_msrs(family, model); | 2255 | do_nhm_platform_info = do_nhm_cstates = do_smi = has_nhm_msrs(family, model); |
| 2257 | do_snb_cstates = has_snb_msrs(family, model); | 2256 | do_snb_cstates = has_snb_msrs(family, model); |
| @@ -2632,7 +2631,7 @@ int main(int argc, char **argv) | |||
| 2632 | cmdline(argc, argv); | 2631 | cmdline(argc, argv); |
| 2633 | 2632 | ||
| 2634 | if (verbose) | 2633 | if (verbose) |
| 2635 | fprintf(stderr, "turbostat v3.8 14-Aug 2014" | 2634 | fprintf(stderr, "turbostat v3.9 23-Jan, 2015" |
| 2636 | " - Len Brown <lenb@kernel.org>\n"); | 2635 | " - Len Brown <lenb@kernel.org>\n"); |
| 2637 | 2636 | ||
| 2638 | turbostat_init(); | 2637 | turbostat_init(); |
