mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 21:57:43 +00:00
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>
This commit is contained in:
parent
d789944753
commit
a729617c58
2 changed files with 67 additions and 44 deletions
|
@ -12,16 +12,16 @@ turbostat \- Report processor frequency and idle statistics
|
||||||
.RB [ "\-i interval_sec" ]
|
.RB [ "\-i interval_sec" ]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBturbostat \fP reports processor topology, frequency,
|
\fBturbostat \fP reports processor topology, frequency,
|
||||||
idle power-state statistics, temperature and power on modern X86 processors.
|
idle power-state statistics, temperature and power on X86 processors.
|
||||||
Either \fBcommand\fP is forked and statistics are printed
|
There are two ways to invoke turbostat.
|
||||||
upon its completion, or statistics are printed periodically.
|
The first method is to supply a
|
||||||
|
\fBcommand\fP, which is forked and statistics are printed
|
||||||
\fBturbostat \fP
|
upon its completion.
|
||||||
must be run on root, and
|
The second method is to omit the command,
|
||||||
minimally requires that the processor
|
and turbodstat will print statistics every 5 seconds.
|
||||||
supports an "invariant" TSC, plus the APERF and MPERF MSRs.
|
The 5-second interval can changed using the -i option.
|
||||||
Additional information is reported depending on hardware counter support.
|
|
||||||
|
|
||||||
|
Some information is not availalbe on older processors.
|
||||||
.SS Options
|
.SS Options
|
||||||
The \fB-p\fP option limits output to the 1st thread in 1st core of each package.
|
The \fB-p\fP option limits output to the 1st thread in 1st core of each package.
|
||||||
.PP
|
.PP
|
||||||
|
@ -130,12 +130,13 @@ cpu3: MSR_IA32_THERM_STATUS: 0x884e0000 (27 C +/- 1)
|
||||||
...
|
...
|
||||||
.fi
|
.fi
|
||||||
The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency
|
The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency
|
||||||
available at the minimum package voltage. The \fBTSC frequency\fP is the nominal
|
available at the minimum package voltage. The \fBTSC frequency\fP is the base
|
||||||
maximum frequency of the processor if turbo-mode were not available. This frequency
|
frequency of the processor -- this should match the brand string
|
||||||
|
in /proc/cpuinfo. This base frequency
|
||||||
should be sustainable on all CPUs indefinitely, given nominal power and cooling.
|
should be sustainable on all CPUs indefinitely, given nominal power and cooling.
|
||||||
The remaining rows show what maximum turbo frequency is possible
|
The remaining rows show what maximum turbo frequency is possible
|
||||||
depending on the number of idle cores. Note that this information is
|
depending on the number of idle cores. Note that not all information is
|
||||||
not available on all processors.
|
available on all processors.
|
||||||
.SH FORK EXAMPLE
|
.SH FORK EXAMPLE
|
||||||
If turbostat is invoked with a command, it will fork that command
|
If turbostat is invoked with a command, it will fork that command
|
||||||
and output the statistics gathered when the command exits.
|
and output the statistics gathered when the command exits.
|
||||||
|
@ -176,6 +177,11 @@ not including any non-busy idle time.
|
||||||
|
|
||||||
.B "turbostat "
|
.B "turbostat "
|
||||||
must be run as root.
|
must be run as root.
|
||||||
|
Alternatively, non-root users can be enabled to run turbostat this way:
|
||||||
|
|
||||||
|
# setcap cap_sys_rawio=ep ./turbostat
|
||||||
|
|
||||||
|
# chmod +r /dev/cpu/*/msr
|
||||||
|
|
||||||
.B "turbostat "
|
.B "turbostat "
|
||||||
reads hardware counters, but doesn't write them.
|
reads hardware counters, but doesn't write them.
|
||||||
|
@ -184,15 +190,33 @@ multiple invocations of itself.
|
||||||
|
|
||||||
\fBturbostat \fP
|
\fBturbostat \fP
|
||||||
may work poorly on Linux-2.6.20 through 2.6.29,
|
may work poorly on Linux-2.6.20 through 2.6.29,
|
||||||
as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF
|
as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF MSRs
|
||||||
in those kernels.
|
in those kernels.
|
||||||
|
|
||||||
If the TSC column does not make sense, then
|
AVG_MHz = APERF_delta/measurement_interval. This is the actual
|
||||||
the other numbers will also make no sense.
|
number of elapsed cycles divided by the entire sample interval --
|
||||||
Turbostat is lightweight, and its data collection is not atomic.
|
including idle time. Note that this calculation is resiliant
|
||||||
These issues are usually caused by an extremely short measurement
|
to systems lacking a non-stop TSC.
|
||||||
interval (much less than 1 second), or system activity that prevents
|
|
||||||
turbostat from being able to run on all CPUS to quickly collect data.
|
TSC_MHz = TSC_delta/measurement_interval.
|
||||||
|
On a system with an invariant TSC, this value will be constant
|
||||||
|
and will closely match the base frequency value shown
|
||||||
|
in the brand string in /proc/cpuinfo. On a system where
|
||||||
|
the TSC stops in idle, TSC_MHz will drop
|
||||||
|
below the processor's base frequency.
|
||||||
|
|
||||||
|
%Busy = MPERF_delta/TSC_delta
|
||||||
|
|
||||||
|
Bzy_MHz = TSC_delta/APERF_delta/MPERF_delta/measurement_interval
|
||||||
|
|
||||||
|
Note that these calculations depend on TSC_delta, so they
|
||||||
|
are not reliable during intervals when TSC_MHz is not running at the base frequency.
|
||||||
|
|
||||||
|
Turbostat data collection is not atomic.
|
||||||
|
Extremely short measurement intervals (much less than 1 second),
|
||||||
|
or system activity that prevents turbostat from being able
|
||||||
|
to run on all CPUS to quickly collect data, will result in
|
||||||
|
inconsistent results.
|
||||||
|
|
||||||
The APERF, MPERF MSRs are defined to count non-halted cycles.
|
The APERF, MPERF MSRs are defined to count non-halted cycles.
|
||||||
Although it is not guaranteed by the architecture, turbostat assumes
|
Although it is not guaranteed by the architecture, turbostat assumes
|
||||||
|
|
|
@ -673,24 +673,26 @@ delta_thread(struct thread_data *new, struct thread_data *old,
|
||||||
|
|
||||||
old->c1 = new->c1 - old->c1;
|
old->c1 = new->c1 - old->c1;
|
||||||
|
|
||||||
if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
|
if (has_aperf) {
|
||||||
old->aperf = new->aperf - old->aperf;
|
if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
|
||||||
old->mperf = new->mperf - old->mperf;
|
old->aperf = new->aperf - old->aperf;
|
||||||
} else {
|
old->mperf = new->mperf - old->mperf;
|
||||||
|
} else {
|
||||||
|
|
||||||
if (!aperf_mperf_unstable) {
|
if (!aperf_mperf_unstable) {
|
||||||
fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname);
|
fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname);
|
||||||
fprintf(stderr, "* Frequency results do not cover entire interval *\n");
|
fprintf(stderr, "* Frequency results do not cover entire interval *\n");
|
||||||
fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n");
|
fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n");
|
||||||
|
|
||||||
aperf_mperf_unstable = 1;
|
aperf_mperf_unstable = 1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* mperf delta is likely a huge "positive" number
|
||||||
|
* can not use it for calculating c0 time
|
||||||
|
*/
|
||||||
|
skip_c0 = 1;
|
||||||
|
skip_c1 = 1;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* mperf delta is likely a huge "positive" number
|
|
||||||
* can not use it for calculating c0 time
|
|
||||||
*/
|
|
||||||
skip_c0 = 1;
|
|
||||||
skip_c1 = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2244,14 +2246,11 @@ void check_cpuid()
|
||||||
has_epb = ecx & (1 << 3);
|
has_epb = ecx & (1 << 3);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "CPUID(6): %s%s%s%s\n",
|
fprintf(stderr, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sEPB\n",
|
||||||
has_aperf ? "APERF" : "No APERF!",
|
has_aperf ? "" : "No ",
|
||||||
do_dts ? ", DTS" : "",
|
do_dts ? "" : "No ",
|
||||||
do_ptm ? ", PTM": "",
|
do_ptm ? "" : "No ",
|
||||||
has_epb ? ", EPB": "");
|
has_epb ? "" : "No ");
|
||||||
|
|
||||||
if (!has_aperf)
|
|
||||||
errx(-1, "No APERF");
|
|
||||||
|
|
||||||
do_nhm_platform_info = do_nhm_cstates = do_smi = has_nhm_msrs(family, model);
|
do_nhm_platform_info = do_nhm_cstates = do_smi = has_nhm_msrs(family, model);
|
||||||
do_snb_cstates = has_snb_msrs(family, model);
|
do_snb_cstates = has_snb_msrs(family, model);
|
||||||
|
@ -2632,7 +2631,7 @@ int main(int argc, char **argv)
|
||||||
cmdline(argc, argv);
|
cmdline(argc, argv);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "turbostat v3.8 14-Aug 2014"
|
fprintf(stderr, "turbostat v3.9 23-Jan, 2015"
|
||||||
" - Len Brown <lenb@kernel.org>\n");
|
" - Len Brown <lenb@kernel.org>\n");
|
||||||
|
|
||||||
turbostat_init();
|
turbostat_init();
|
||||||
|
|
Loading…
Reference in a new issue