Hi Rafael,
Please pull these turbostat-related patches.
This patch series updates turbostat in the Linux kernel tree to
to the latest out-of-tree version -- 17.02.24.
There are several significant changes since the version that
shipped in the Linux-4.10 tree.
Default output is now verbose, --debug is no longer required
to get all counters. As a result, some options have
been added to specify exactly what output is wanted.
Added --quiet to skip system configuration output
Added --list, --show and --hide parameters
Added --cpu parameter
Enhanced Baytrail SOC support
Added Gemini Lake SOC support
Added sysfs C-state columns
These changes are detailed on the updated turbostat.8 man page.
thanks!
Len Brown, Intel Open Source Technology Center
The following changes since commit c470abd4fde40ea6a0846a2beab642a578c0b8cd:
Linux 4.10 (2017-02-19 14:34:00 -0800)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git turbostat
for you to fetch changes up to e3942ed8c66bcff496abee5182422cd542962d9e:
tools/power turbostat: version 17.02.24 (2017-03-01 00:14:26 -0500)
----------------------------------------------------------------
Len Brown (44):
tools/power turbostat: fix bugs in --add option
tools/power turbostat: Add --show and --hide parameters
tools/power turbostat: BYT does not have MSR_MISC_PWR_MGMT
tools/power turbostat: decode Baytrail CC6 and MC6 demotion configuration
tools/power turbostat: Baytrail: remove debug line in quiet mode
tools/power turbostat: update MSR_PKG_CST_CONFIG_CONTROL decoding
x86: msr-index.h: Define MSR_PKG_CST_CONFIG_CONTROL
intel_idle: use new name for MSR_PKG_CST_CONFIG_CONTROL
tools/power turbostat: use new name for MSR_PKG_CST_CONFIG_CONTROL
x86: msr-index.h: Remove unused MSR_NHM_SNB_PKG_CST_CFG_CTL
tools/power turbostat: Baytrail c-state support
tools/power turbostat: add precision to --debug frequency output
tools/power turbostat: further decode MSR_IA32_MISC_ENABLE
x86 msr-index.h: Define Atom specific core ratio MSR locations
intel_pstate: use MSR_ATOM_RATIOS definitions from msr-index.h
tools/power turbostat: dump Atom P-states correctly
tools/power turbostat: decode CPUID(6).TURBO
x86 msr_index.h: Define MSR_MISC_FEATURE_CONTROL
tools/power turbostat: decode MSR_MISC_FEATURE_CONTROL
tools/power turbostat: show all columns, independent of --debug
tools/power turbostat: print system config, unless --quiet
tools/power turbostat: use tsc_tweak everwhere it is needed
tools/power turbostat: bug fixes to --add, --show/--hide features
x86: intel-family.h: Add GEMINI_LAKE SOC
tools/power turbostat: initial Gemini Lake SOC support
tools/power turbostat: Denverton: use HW CC1 counter, skip C3, C7
tools/power turbostat: skip unused counters on SKX
tools/power turbostat: fix decoding for GLM, DNV, SKX turbo-ratio limits
tools/power turbostat: skip unused counters on BDX
tools/power turbostat: extend --add option to accept /sys path
tools/power turbostat: print sysfs C-state stats
tools/power turbostat: add --cpu parameter
tools/power turbostat: fix zero IRQ count shown in one-shot command mode
tools/power turbostat: Add --list option to show available header names
tools/power turbostat: use wide columns to display large numbers
tools/power turbostat: update --list feature
tools/power turbostat: turbostat.8 update
tools/power turbostat: move --Package and --processor into the --cpu option
tools/power turbostat: support "--hide C1" etc.
tools/power turbostat: show package number, even without --debug
tools/power turbostat: dump p-state software config
tools/power turbostat: show error on exec
tools/power turbostat: bugfix: --add u32 was printed as u64
tools/power turbostat: version 17.02.24
arch/x86/include/asm/intel-family.h | 1 +
arch/x86/include/asm/msr-index.h | 11 +-
drivers/cpufreq/intel_pstate.c | 15 +-
drivers/idle/intel_idle.c | 6 +-
tools/power/x86/turbostat/turbostat.8 | 253 +++--
tools/power/x86/turbostat/turbostat.c | 1880 ++++++++++++++++++++++++---------
6 files changed, 1570 insertions(+), 596 deletions(-)
From: Len Brown <[email protected]>
--Package is now "--cpu package",
which will display just the 1st CPU in each package
--processor is not "--cpu core"
which will display just the 1st CPU in each core
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.8 | 6 +-----
tools/power/x86/turbostat/turbostat.c | 31 ++++++++++++++++++++-----------
2 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index b1b1ab80102c..5189d9d982fe 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -52,7 +52,7 @@ name as necessary to disambiguate it from others is necessary. Note that option
as the column header.
.fi
.PP
-\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. cpu-set is a comma delimited list of cpu ranges. cpu ranges can be individual cpu numbers or start and end numbers, separated by ".." or '-'. eg. 1,2,8,14..17,21-44
+\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. If cpu-set is the string "core", then the system summary plus the first CPU in each core are printed -- eg. subsequent HT siblings are not printed. Or if cpu-set is the string "package", then the system summary plus the first CPU in each package is printed. Otherwise, the system summary plus the specified set of CPUs are printed. The cpu-set is ordered from low to high, comma delimited with ".." and "-" permitted to denote a range. eg. 1,2,8,14..17,21-44
.PP
\fB--hide column\fP do not show the specified columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
.PP
@@ -71,12 +71,8 @@ The file is truncated if it already exists, and it is created if it does not exi
.PP
\fB--Joules\fP displays energy in Joules, rather than dividing Joules by time to print power in Watts.
.PP
-\fB--Package\fP limits output to the system summary plus the 1st thread in each Package.
-.PP
\fB--list\fP display column header names available for use by --show and --hide, then exit.
.PP
-\fB--processor\fP limits output to the system summary plus the 1st thread in each processor of each package. Ie. it skips hyper-threaded siblings.
-.PP
\fB--Summary\fP limits output to a 1-line System Summary for each interval.
.PP
\fB--TCC temperature\fP sets the Thermal Control Circuit temperature for systems which do not export that value. This is used for making sense of the Digital Thermal Sensor outputs, as they return degrees Celsius below the TCC activation temperature.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 851eaf06f358..c005d9052679 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -4153,7 +4153,8 @@ void help()
"to print statistics, until interrupted.\n"
"--add add a counter\n"
" eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
- "--cpu cpu-set limit output to summary plus cpu-set cpu-set\n"
+ "--cpu cpu-set limit output to summary plus cpu-set:\n"
+ " {core | package | j,k,l..m,n-p }\n"
"--quiet skip decoding system configuration header\n"
"--interval sec Override default 5-second measurement interval\n"
"--help print this help message\n"
@@ -4756,6 +4757,21 @@ void parse_cpu_command(char *optarg)
unsigned int start, end;
char *next;
+ if (!strcmp(optarg, "core")) {
+ if (cpu_subset)
+ goto error;
+ show_core_only++;
+ return;
+ }
+ if (!strcmp(optarg, "package")) {
+ if (cpu_subset)
+ goto error;
+ show_pkg_only++;
+ return;
+ }
+ if (show_core_only || show_pkg_only)
+ goto error;
+
cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS);
if (cpu_subset == NULL)
err(3, "CPU_ALLOC");
@@ -4813,7 +4829,8 @@ void parse_cpu_command(char *optarg)
return;
error:
- fprintf(stderr, "'--cpu %s' malformed\n", optarg);
+ fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
+ help();
exit(-1);
}
@@ -4867,8 +4884,6 @@ void cmdline(int argc, char **argv)
{"Joules", no_argument, 0, 'J'},
{"list", no_argument, 0, 'l'},
{"out", required_argument, 0, 'o'},
- {"Package", no_argument, 0, 'p'},
- {"processor", no_argument, 0, 'p'},
{"quiet", no_argument, 0, 'q'},
{"show", required_argument, 0, 's'},
{"Summary", no_argument, 0, 'S'},
@@ -4879,7 +4894,7 @@ void cmdline(int argc, char **argv)
progname = argv[0];
- while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:PpqST:v",
+ while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:qST:v",
long_options, &option_index)) != -1) {
switch (opt) {
case 'a':
@@ -4925,12 +4940,6 @@ void cmdline(int argc, char **argv)
case 'o':
outf = fopen_or_die(optarg, "w");
break;
- case 'P':
- show_pkg_only++;
- break;
- case 'p':
- show_core_only++;
- break;
case 'q':
quiet = 1;
break;
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Make it possible to take the entire un-edited output
from `turbostat --list` and feed it to "turbostat --show"
or "turbostat --hide".
To do this, the leading comma was removed
(no mater what columns are active)
and also they dynamic C-state "C1, C2, C3" etc are replaced
by the string "sysfs", which refers to them as a group.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 219 ++++++++++++++++++----------------
1 file changed, 113 insertions(+), 106 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index cafc6bba6539..851eaf06f358 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -474,33 +474,38 @@ unsigned long long bic_lookup(char *name_list)
void print_header(char *delim)
{
struct msr_counter *mp;
+ int printed = 0;
if (DO_BIC(BIC_Package))
- outp += sprintf(outp, "%sPackage", delim);
+ outp += sprintf(outp, "%sPackage", (printed++ ? delim : ""));
if (DO_BIC(BIC_Core))
- outp += sprintf(outp, "%sCore", delim);
+ outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));
if (DO_BIC(BIC_CPU))
- outp += sprintf(outp, "%sCPU", delim);
+ outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));
if (DO_BIC(BIC_Avg_MHz))
- outp += sprintf(outp, "%sAvg_MHz", delim);
+ outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));
if (DO_BIC(BIC_Busy))
- outp += sprintf(outp, "%sBusy%%", delim);
+ outp += sprintf(outp, "%sBusy%%", (printed++ ? delim : ""));
if (DO_BIC(BIC_Bzy_MHz))
- outp += sprintf(outp, "%sBzy_MHz", delim);
+ outp += sprintf(outp, "%sBzy_MHz", (printed++ ? delim : ""));
if (DO_BIC(BIC_TSC_MHz))
- outp += sprintf(outp, "%sTSC_MHz", delim);
+ outp += sprintf(outp, "%sTSC_MHz", (printed++ ? delim : ""));
if (DO_BIC(BIC_IRQ)) {
if (sums_need_wide_columns)
- outp += sprintf(outp, "%s IRQ", delim);
+ outp += sprintf(outp, "%s IRQ", (printed++ ? delim : ""));
else
- outp += sprintf(outp, "%sIRQ", delim);
+ outp += sprintf(outp, "%sIRQ", (printed++ ? delim : ""));
}
if (DO_BIC(BIC_SMI))
- outp += sprintf(outp, "%sSMI", delim);
+ outp += sprintf(outp, "%sSMI", (printed++ ? delim : ""));
for (mp = sys.tp; mp; mp = mp->next) {
+ if (*delim == ',') {
+ outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), "sysfs");
+ break;
+ }
if (mp->format == FORMAT_RAW) {
if (mp->width == 64)
outp += sprintf(outp, "%s%18.18s", delim, mp->name);
@@ -515,19 +520,19 @@ void print_header(char *delim)
}
if (DO_BIC(BIC_CPU_c1))
- outp += sprintf(outp, "%sCPU%%c1", delim);
+ outp += sprintf(outp, "%sCPU%%c1", (printed++ ? delim : ""));
if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates)
- outp += sprintf(outp, "%sCPU%%c3", delim);
+ outp += sprintf(outp, "%sCPU%%c3", (printed++ ? delim : ""));
if (DO_BIC(BIC_CPU_c6))
- outp += sprintf(outp, "%sCPU%%c6", delim);
+ outp += sprintf(outp, "%sCPU%%c6", (printed++ ? delim : ""));
if (DO_BIC(BIC_CPU_c7))
- outp += sprintf(outp, "%sCPU%%c7", delim);
+ outp += sprintf(outp, "%sCPU%%c7", (printed++ ? delim : ""));
if (DO_BIC(BIC_Mod_c6))
- outp += sprintf(outp, "%sMod%%c6", delim);
+ outp += sprintf(outp, "%sMod%%c6", (printed++ ? delim : ""));
if (DO_BIC(BIC_CoreTmp))
- outp += sprintf(outp, "%sCoreTmp", delim);
+ outp += sprintf(outp, "%sCoreTmp", (printed++ ? delim : ""));
for (mp = sys.cp; mp; mp = mp->next) {
if (mp->format == FORMAT_RAW) {
@@ -544,62 +549,62 @@ void print_header(char *delim)
}
if (DO_BIC(BIC_PkgTmp))
- outp += sprintf(outp, "%sPkgTmp", delim);
+ outp += sprintf(outp, "%sPkgTmp", (printed++ ? delim : ""));
if (DO_BIC(BIC_GFX_rc6))
- outp += sprintf(outp, "%sGFX%%rc6", delim);
+ outp += sprintf(outp, "%sGFX%%rc6", (printed++ ? delim : ""));
if (DO_BIC(BIC_GFXMHz))
- outp += sprintf(outp, "%sGFXMHz", delim);
+ outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));
if (do_skl_residency) {
- outp += sprintf(outp, "%sTotl%%C0", delim);
- outp += sprintf(outp, "%sAny%%C0", delim);
- outp += sprintf(outp, "%sGFX%%C0", delim);
- outp += sprintf(outp, "%sCPUGFX%%", delim);
+ outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));
+ outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : ""));
+ outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : ""));
+ outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : ""));
}
if (DO_BIC(BIC_Pkgpc2))
- outp += sprintf(outp, "%sPkg%%pc2", delim);
+ outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : ""));
if (DO_BIC(BIC_Pkgpc3))
- outp += sprintf(outp, "%sPkg%%pc3", delim);
+ outp += sprintf(outp, "%sPkg%%pc3", (printed++ ? delim : ""));
if (DO_BIC(BIC_Pkgpc6))
- outp += sprintf(outp, "%sPkg%%pc6", delim);
+ outp += sprintf(outp, "%sPkg%%pc6", (printed++ ? delim : ""));
if (DO_BIC(BIC_Pkgpc7))
- outp += sprintf(outp, "%sPkg%%pc7", delim);
+ outp += sprintf(outp, "%sPkg%%pc7", (printed++ ? delim : ""));
if (DO_BIC(BIC_Pkgpc8))
- outp += sprintf(outp, "%sPkg%%pc8", delim);
+ outp += sprintf(outp, "%sPkg%%pc8", (printed++ ? delim : ""));
if (DO_BIC(BIC_Pkgpc9))
- outp += sprintf(outp, "%sPkg%%pc9", delim);
+ outp += sprintf(outp, "%sPkg%%pc9", (printed++ ? delim : ""));
if (DO_BIC(BIC_Pkgpc10))
- outp += sprintf(outp, "%sPk%%pc10", delim);
+ outp += sprintf(outp, "%sPk%%pc10", (printed++ ? delim : ""));
if (do_rapl && !rapl_joules) {
if (DO_BIC(BIC_PkgWatt))
- outp += sprintf(outp, "%sPkgWatt", delim);
+ outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : ""));
if (DO_BIC(BIC_CorWatt))
- outp += sprintf(outp, "%sCorWatt", delim);
+ outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));
if (DO_BIC(BIC_GFXWatt))
- outp += sprintf(outp, "%sGFXWatt", delim);
+ outp += sprintf(outp, "%sGFXWatt", (printed++ ? delim : ""));
if (DO_BIC(BIC_RAMWatt))
- outp += sprintf(outp, "%sRAMWatt", delim);
+ outp += sprintf(outp, "%sRAMWatt", (printed++ ? delim : ""));
if (DO_BIC(BIC_PKG__))
- outp += sprintf(outp, "%sPKG_%%", delim);
+ outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
if (DO_BIC(BIC_RAM__))
- outp += sprintf(outp, "%sRAM_%%", delim);
+ outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
} else if (do_rapl && rapl_joules) {
if (DO_BIC(BIC_Pkg_J))
- outp += sprintf(outp, "%sPkg_J", delim);
+ outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : ""));
if (DO_BIC(BIC_Cor_J))
- outp += sprintf(outp, "%sCor_J", delim);
+ outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));
if (DO_BIC(BIC_GFX_J))
- outp += sprintf(outp, "%sGFX_J", delim);
+ outp += sprintf(outp, "%sGFX_J", (printed++ ? delim : ""));
if (DO_BIC(BIC_RAM_J))
- outp += sprintf(outp, "%sRAM_J", delim);
+ outp += sprintf(outp, "%sRAM_J", (printed++ ? delim : ""));
if (DO_BIC(BIC_PKG__))
- outp += sprintf(outp, "%sPKG_%%", delim);
+ outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
if (DO_BIC(BIC_RAM__))
- outp += sprintf(outp, "%sRAM_%%", delim);
+ outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
}
for (mp = sys.pp; mp; mp = mp->next) {
if (mp->format == FORMAT_RAW) {
@@ -708,6 +713,8 @@ int format_counters(struct thread_data *t, struct core_data *c,
char *fmt8;
int i;
struct msr_counter *mp;
+ char *delim = "\t";
+ int printed = 0;
/* if showing only 1st thread in core and this isn't one, bail out */
if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
@@ -729,81 +736,81 @@ int format_counters(struct thread_data *t, struct core_data *c,
/* topo columns, print blanks on 1st (average) line */
if (t == &average.threads) {
if (DO_BIC(BIC_Package))
- outp += sprintf(outp, "\t-");
+ outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
if (DO_BIC(BIC_Core))
- outp += sprintf(outp, "\t-");
+ outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
if (DO_BIC(BIC_CPU))
- outp += sprintf(outp, "\t-");
+ outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
} else {
if (DO_BIC(BIC_Package)) {
if (p)
- outp += sprintf(outp, "\t%d", p->package_id);
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->package_id);
else
- outp += sprintf(outp, "\t-");
+ outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
}
if (DO_BIC(BIC_Core)) {
if (c)
- outp += sprintf(outp, "\t%d", c->core_id);
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_id);
else
- outp += sprintf(outp, "\t-");
+ outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
}
if (DO_BIC(BIC_CPU))
- outp += sprintf(outp, "\t%d", t->cpu_id);
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);
}
if (DO_BIC(BIC_Avg_MHz))
- outp += sprintf(outp, "\t%.0f",
+ outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
1.0 / units * t->aperf / interval_float);
if (DO_BIC(BIC_Busy))
- outp += sprintf(outp, "\t%.2f", 100.0 * t->mperf/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->mperf/tsc);
if (DO_BIC(BIC_Bzy_MHz)) {
if (has_base_hz)
- outp += sprintf(outp, "\t%.0f", base_hz / units * t->aperf / t->mperf);
+ outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf);
else
- outp += sprintf(outp, "\t%.0f",
+ outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
tsc / units * t->aperf / t->mperf / interval_float);
}
if (DO_BIC(BIC_TSC_MHz))
- outp += sprintf(outp, "\t%.0f", 1.0 * t->tsc/units/interval_float);
+ outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc/units/interval_float);
/* IRQ */
if (DO_BIC(BIC_IRQ)) {
if (sums_need_wide_columns)
- outp += sprintf(outp, "\t%8lld", t->irq_count);
+ outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->irq_count);
else
- outp += sprintf(outp, "\t%lld", t->irq_count);
+ outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->irq_count);
}
/* SMI */
if (DO_BIC(BIC_SMI))
- outp += sprintf(outp, "\t%d", t->smi_count);
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->smi_count);
/* Added counters */
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
- outp += sprintf(outp, "\t0x%08lx", (unsigned long) t->counter[i]);
+ outp += sprintf(outp, "%s0x%08lx", (printed++ ? delim : ""), (unsigned long) t->counter[i]);
else
- outp += sprintf(outp, "\t0x%016llx", t->counter[i]);
+ outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
- outp += sprintf(outp, "\t%8lld", t->counter[i]);
+ outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->counter[i]);
else
- outp += sprintf(outp, "\t%lld", t->counter[i]);
+ outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
if (mp->type == COUNTER_USEC)
- outp += sprintf(outp, "\t%.2f", t->counter[i]/interval_float/10000);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), t->counter[i]/interval_float/10000);
else
- outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->counter[i]/tsc);
}
}
/* C1 */
if (DO_BIC(BIC_CPU_c1))
- outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->c1/tsc);
/* print per-core data only for 1st thread in core */
@@ -811,32 +818,32 @@ int format_counters(struct thread_data *t, struct core_data *c,
goto done;
if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates)
- outp += sprintf(outp, "\t%.2f", 100.0 * c->c3/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c3/tsc);
if (DO_BIC(BIC_CPU_c6))
- outp += sprintf(outp, "\t%.2f", 100.0 * c->c6/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c6/tsc);
if (DO_BIC(BIC_CPU_c7))
- outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c7/tsc);
/* Mod%c6 */
if (DO_BIC(BIC_Mod_c6))
- outp += sprintf(outp, "\t%.2f", 100.0 * c->mc6_us / tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->mc6_us / tsc);
if (DO_BIC(BIC_CoreTmp))
- outp += sprintf(outp, "\t%d", c->core_temp_c);
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c);
for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
- outp += sprintf(outp, "\t0x%08lx", (unsigned long) c->counter[i]);
+ outp += sprintf(outp, "%s0x%08lx", (printed++ ? delim : ""), (unsigned long) c->counter[i]);
else
- outp += sprintf(outp, "\t0x%016llx", c->counter[i]);
+ outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
- outp += sprintf(outp, "\t%8lld", c->counter[i]);
+ outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), c->counter[i]);
else
- outp += sprintf(outp, "\t%lld", c->counter[i]);
+ outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
- outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->counter[i]/tsc);
}
}
@@ -846,88 +853,88 @@ int format_counters(struct thread_data *t, struct core_data *c,
/* PkgTmp */
if (DO_BIC(BIC_PkgTmp))
- outp += sprintf(outp, "\t%d", p->pkg_temp_c);
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->pkg_temp_c);
/* GFXrc6 */
if (DO_BIC(BIC_GFX_rc6)) {
if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */
- outp += sprintf(outp, "\t**.**");
+ outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));
} else {
- outp += sprintf(outp, "\t%.2f",
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
p->gfx_rc6_ms / 10.0 / interval_float);
}
}
/* GFXMHz */
if (DO_BIC(BIC_GFXMHz))
- outp += sprintf(outp, "\t%d", p->gfx_mhz);
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);
/* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
if (do_skl_residency) {
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_wtd_core_c0/tsc);
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_core_c0/tsc);
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_gfxe_c0/tsc);
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_both_core_gfxe_c0/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0/tsc);
}
if (DO_BIC(BIC_Pkgpc2))
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc2/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2/tsc);
if (DO_BIC(BIC_Pkgpc3))
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc3/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc3/tsc);
if (DO_BIC(BIC_Pkgpc6))
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc6/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc6/tsc);
if (DO_BIC(BIC_Pkgpc7))
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc7/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc7/tsc);
if (DO_BIC(BIC_Pkgpc8))
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc8/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc8/tsc);
if (DO_BIC(BIC_Pkgpc9))
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc9/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc9/tsc);
if (DO_BIC(BIC_Pkgpc10))
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc10/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10/tsc);
/*
* If measurement interval exceeds minimum RAPL Joule Counter range,
* indicate that results are suspect by printing "**" in fraction place.
*/
if (interval_float < rapl_joule_counter_range)
- fmt8 = "\t%.2f";
+ fmt8 = "%s%.2f";
else
fmt8 = "%6.0f**";
if (DO_BIC(BIC_PkgWatt))
- outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units / interval_float);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units / interval_float);
if (DO_BIC(BIC_CorWatt))
- outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units / interval_float);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units / interval_float);
if (DO_BIC(BIC_GFXWatt))
- outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units / interval_float);
if (DO_BIC(BIC_RAMWatt))
- outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units / interval_float);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units / interval_float);
if (DO_BIC(BIC_Pkg_J))
- outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units);
if (DO_BIC(BIC_Cor_J))
- outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units);
if (DO_BIC(BIC_GFX_J))
- outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units);
if (DO_BIC(BIC_RAM_J))
- outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units);
if (DO_BIC(BIC_PKG__))
- outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
if (DO_BIC(BIC_RAM__))
- outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
- outp += sprintf(outp, "\t0x%08lx", (unsigned long) p->counter[i]);
+ outp += sprintf(outp, "%s0x%08lx", (printed++ ? delim : ""), (unsigned long) p->counter[i]);
else
- outp += sprintf(outp, "\t0x%016llx", p->counter[i]);
+ outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
- outp += sprintf(outp, "\t%8lld", p->counter[i]);
+ outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), p->counter[i]);
else
- outp += sprintf(outp, "\t%lld", p->counter[i]);
+ outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), p->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
- outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->counter[i]/tsc);
}
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
update examples to show recently updated features.
In particular
--add
--show
--hide
--cpu
--list
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.8 | 238 ++++++++++++++++++++--------------
1 file changed, 140 insertions(+), 98 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index efe6a7147ff2..b1b1ab80102c 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -16,9 +16,9 @@ idle power-state statistics, temperature and power on X86 processors.
There are two ways to invoke turbostat.
The first method is to supply a
\fBcommand\fP, which is forked and statistics are printed
-upon its completion.
+in one-shot upon its completion.
The second method is to omit the command,
-and turbostat displays statistics every 5 seconds.
+and turbostat displays statistics every 5 seconds interval.
The 5-second interval can be changed using the --interval option.
.PP
Some information is not available on older processors.
@@ -28,9 +28,10 @@ name as necessary to disambiguate it from others is necessary. Note that option
.PP
\fB--add attributes\fP add column with counter having specified 'attributes'. The 'location' attribute is required, all others are optional.
.nf
- location: {\fBmsrDDD\fP | \fBmsr0xXXX\fP}
+ location: {\fBmsrDDD\fP | \fBmsr0xXXX\fP | \fB/sys/path...\fP}
msrDDD is a decimal offset, eg. msr16
msr0xXXX is a hex offset, eg. msr0x10
+ /sys/path... is an absolute path to a sysfs attribute
scope: {\fBcpu\fP | \fBcore\fP | \fBpackage\fP}
sample and print the counter for every cpu, core, or package.
@@ -45,6 +46,10 @@ name as necessary to disambiguate it from others is necessary. Note that option
'delta' shows the difference in values during the measurement interval.
'percent' shows the delta as a percentage of the cycles elapsed.
default: delta
+
+ name: "name_string"
+ Any string that does not match a key-word above is used
+ as the column header.
.fi
.PP
\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. cpu-set is a comma delimited list of cpu ranges. cpu ranges can be individual cpu numbers or start and end numbers, separated by ".." or '-'. eg. 1,2,8,14..17,21-44
@@ -68,6 +73,8 @@ The file is truncated if it already exists, and it is created if it does not exi
.PP
\fB--Package\fP limits output to the system summary plus the 1st thread in each Package.
.PP
+\fB--list\fP display column header names available for use by --show and --hide, then exit.
+.PP
\fB--processor\fP limits output to the system summary plus the 1st thread in each processor of each package. Ie. it skips hyper-threaded siblings.
.PP
\fB--Summary\fP limits output to a 1-line System Summary for each interval.
@@ -79,24 +86,25 @@ The file is truncated if it already exists, and it is created if it does not exi
The \fBcommand\fP parameter forks \fBcommand\fP, and upon its exit,
displays the statistics gathered since it was forked.
.PP
-.SH DEFAULT FIELD DESCRIPTIONS
+.SH ROW DESCRIPTIONS
+The system configuration dump (if --quiet is not used) is followed by statistics. The first row of the statistics labels the content of each column (below). The second row of statistics is the system summary line. The system summary line has a '-' in the columns for the Package, Core, and CPU. The contents of the system summary line depends on the type of column. Columns that count items (eg. IRQ) show the sum across all CPUs in the system. Columns that show a percentage show the average across all CPUs in the system. Columns that dump raw MSR values simply show 0 in the summary. After the system summary row, each row describes a specific Package/Core/CPU. Note that if the --cpu parameter is used to limit which specific CPUs are displayed, turbostat will still collect statistics for all CPUs in the system and will still show the system summary for all CPUs in the system.
+.SH COLUMN DESCRIPTIONS
.nf
+\fBCore\fP processor core number. Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology (HT).
\fBCPU\fP Linux CPU (logical processor) number. Yes, it is okay that on many systems the CPUs are not listed in numerical order -- for efficiency reasons, turbostat runs in topology order, so HT siblings appear together.
-\fBAVG_MHz\fP number of cycles executed divided by time elapsed.
-\fBBusy%\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state.
-\fBBzy_MHz\fP average clock rate while the CPU was busy (in "c0" state).
+\fBPackage\fP processor package number -- not present on systems with a single processor package.
+\fBAvg_MHz\fP number of cycles executed divided by time elapsed. Note that this includes idle-time when 0 instructions are executed.
+\fBBusy%\fP percent of the measurement interval that the CPU executes instructions, aka. % of time in "C0" state.
+\fBBzy_MHz\fP average clock rate while the CPU was not idle (ie. in "c0" state).
\fBTSC_MHz\fP average MHz that the TSC ran during the entire interval.
-.fi
-.PP
-.SH DEBUG FIELD DESCRIPTIONS
-.nf
-\fBPackage\fP processor package number.
-\fBCore\fP processor core number.
-Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology (HT).
-\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states.
+\fBIRQ\fP The number of interrupts serviced by that CPU during the measurement interval. The system total line is the sum of interrupts serviced across all CPUs. turbostat parses /proc/interrupts to generate this summary.
+\fBSMI\fP The number of System Management Interrupts serviced CPU during the measurement interval. While this counter is actually per-CPU, SMI are triggered on all processors, so the number should be the same for all CPUs.
+\fBC1, C2, C3...\fP The number times Linux requested the C1, C2, C3 idle state during the measurement interval. The system summary line shows the sum for all CPUs. These are C-state names as exported in /sys/devices/system/cpu/cpu*/cpuidle/state*/name. While their names are generic, their attributes are processor specific. They the system description section of output shows what MWAIT sub-states they are mapped to on each system.
+\fBC1%, C2%, C3%\fP The residency percentage that Linux requested C1, C2, C3.... The system summary is the average of all CPUs in the system. Note that these are software, reflecting what was requested. The hardware counters reflect what was actually achieved.
+\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states. These numbers are from hardware residency counters.
\fBCoreTmp\fP Degrees Celsius reported by the per-core Digital Thermal Sensor.
\fBPkgTtmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor.
-\fBPkg%pc2, Pkg%pc3, Pkg%pc6, Pkg%pc7\fP percentage residency in hardware package idle states.
+\fBPkg%pc2, Pkg%pc3, Pkg%pc6, Pkg%pc7\fP percentage residency in hardware package idle states. These numbers are from hardware residency counters.
\fBPkgWatt\fP Watts consumed by the whole package.
\fBCorWatt\fP Watts consumed by the core part of the package.
\fBGFXWatt\fP Watts consumed by the Graphics part of the package -- available only on client processors.
@@ -104,50 +112,110 @@ Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading T
\fBPKG_%\fP percent of the interval that RAPL throttling was active on the Package.
\fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM.
.fi
+.SH TOO MUCH INFORMATION EXAMPLE
+By default, turbostat dumps all possible information -- a system configuration header, followed by columns for all counters.
+This is ideal for remote debugging, use the "--out" option to save everything to a text file, and get that file to the expert helping you debug.
.PP
-.SH PERIODIC EXAMPLE
-Without any parameters, turbostat displays statistics ever 5 seconds.
-Periodic output goes to stdout, by default, unless --out is used to specify an output file.
-The 5-second interval can be changed with th "-i sec" option.
-Or a command may be specified as in "FORK EXAMPLE" below.
+When you are not interested in all that information, and there are several ways to see only what you want. First the "--quiet" option will skip the configuration information, and turbostat will show only the counter columns. Second, you can reduce the columns with the "--hide" and "--show" options. If you use the "--show" option, then turbostat will show only the columns you list. If you use the "--hide" option, turbostat will show all columns, except the ones you list.
+.PP
+To find out what columns are available for --show and --hide, the "--list" option is available. Note, however, there is an exception. The C-state columns collected from sysfs "C1,C2,C3,C1%,C2%,C3%" are not built-in counters, but are discovered after --show and --hide are processed. You can use the special counter name "sysfs" to refer to all of them at the same time.
+.nf
+sudo ./turbostat --show sysfs --quiet sleep 10
+10.003837 sec
+ C1 C1E C3 C6 C7s C1% C1E% C3% C6% C7s%
+ 4 21 2 2 459 0.14 0.82 0.00 0.00 98.93
+ 1 17 2 2 130 0.00 0.02 0.00 0.00 99.80
+ 0 0 0 0 31 0.00 0.00 0.00 0.00 99.95
+ 2 1 0 0 52 1.14 6.49 0.00 0.00 92.21
+ 1 2 0 0 52 0.00 0.08 0.00 0.00 99.86
+ 0 0 0 0 71 0.00 0.00 0.00 0.00 99.89
+ 0 0 0 0 25 0.00 0.00 0.00 0.00 99.96
+ 0 0 0 0 74 0.00 0.00 0.00 0.00 99.94
+ 0 1 0 0 24 0.00 0.00 0.00 0.00 99.84
+.fi
+.PP
+.SH ONE SHOT COMMAND EXAMPLE
+If turbostat is invoked with a command, it will fork that command
+and output the statistics gathered after the command exits.
+In this case, turbostat output goes to stderr, by default.
+Output can instead be saved to a file using the --out option.
+In this example, the "sleep 10" command is forked, and turbostat waits for it to complete before saving all statistics into "ts.out". Note that "sleep 10" is not part of turbostat, but is simply an example of a command that turbostat can fork. The "ts.out" file is what you want to edit in a very wide window, paste into a spreadsheet, or attach to a bugzilla entry.
+
.nf
-[root@hsw]# ./turbostat
- CPU Avg_MHz Busy% Bzy_MHz TSC_MHz
- - 488 12.51 3898 3498
- 0 0 0.01 3885 3498
- 4 3897 99.99 3898 3498
- 1 0 0.00 3861 3498
- 5 0 0.00 3882 3498
- 2 1 0.02 3894 3498
- 6 2 0.06 3898 3498
- 3 0 0.00 3849 3498
- 7 0 0.00 3877 3498
+[root@hsw]# ./turbostat -o ts.out sleep 10
+[root@hsw]#
+.fi
+.SH PERIODIC INTERVAL EXAMPLE
+Without a command to fork, turbostat displays statistics ever 5 seconds.
+Periodic output goes to stdout, by default, unless --out is used to specify an output file.
+The 5-second interval can be changed with the "-i sec" option.
+.nf
+sudo ./turbostat --quiet --hide sysfs,IRQ,SMI,CoreTmp,PkgTmp,GFX%rc6,GFXMHz,PkgWatt,CorWatt,GFXWatt
+ Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c1 CPU%c3 CPU%c6 CPU%c7
+ - - 488 12.52 3900 3498 12.50 0.00 0.00 74.98
+ 0 0 5 0.13 3900 3498 99.87 0.00 0.00 0.00
+ 0 4 3897 99.99 3900 3498 0.01
+ 1 1 0 0.00 3856 3498 0.01 0.00 0.00 99.98
+ 1 5 0 0.00 3861 3498 0.01
+ 2 2 1 0.02 3889 3498 0.03 0.00 0.00 99.95
+ 2 6 0 0.00 3863 3498 0.05
+ 3 3 0 0.01 3869 3498 0.02 0.00 0.00 99.97
+ 3 7 0 0.00 3878 3498 0.03
+ Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c1 CPU%c3 CPU%c6 CPU%c7
+ - - 491 12.59 3900 3498 12.42 0.00 0.00 74.99
+ 0 0 27 0.69 3900 3498 99.31 0.00 0.00 0.00
+ 0 4 3898 99.99 3900 3498 0.01
+ 1 1 0 0.00 3883 3498 0.01 0.00 0.00 99.99
+ 1 5 0 0.00 3898 3498 0.01
+ 2 2 0 0.01 3889 3498 0.02 0.00 0.00 99.98
+ 2 6 0 0.00 3889 3498 0.02
+ 3 3 0 0.00 3856 3498 0.01 0.00 0.00 99.99
+ 3 7 0 0.00 3897 3498 0.01
.fi
-.SH DEBUG EXAMPLE
+This example also shows the use of the --hide option to skip columns that are not wanted.
+Note that cpu4 in this example is 99.99% busy, while the other CPUs are all under 1% busy.
+Notice that cpu4's HT sibling is cpu0, which is under 1% busy, but can get into CPU%c1 only,
+because its cpu4's activity on shared hardware keeps it from entering a deeper C-state.
+
+.SH SYSTEM CONFIGURATION INFORMATION EXAMPLE
-The first row of statistics is a summary for the entire system.
-For residency % columns, the summary is a weighted average.
-For Temperature columns, the summary is the column maximum.
-For Watts columns, the summary is a system total.
-Subsequent rows show per-CPU statistics.
+By default, turbostat always dumps system configuration information
+before taking measurements. In the example above, "--quiet" is used
+to suppress that output. Here is an example of the configuration information:
.nf
-turbostat version 4.1 10-Feb, 2015 - Len Brown <[email protected]>
+turbostat version 2017.02.15 - Len Brown <[email protected]>
CPUID(0): GenuineIntel 13 CPUID levels; family:model:stepping 0x6:3c:3 (6:60:3)
-CPUID(6): APERF, DTS, PTM, EPB
+CPUID(1): SSE3 MONITOR - EIST TM2 TSC MSR ACPI-TM TM
+CPUID(6): APERF, TURBO, DTS, PTM, No-HWP, No-HWPnotify, No-HWPwindow, No-HWPepp, No-HWPpkg, EPB
+cpu4: MSR_IA32_MISC_ENABLE: 0x00850089 (TCC EIST No-MWAIT PREFETCH TURBO)
+CPUID(7): No-SGX
+cpu4: MSR_MISC_PWR_MGMT: 0x00400000 (ENable-EIST_Coordination DISable-EPB DISable-OOB)
RAPL: 3121 sec. Joule Counter Range, at 84 Watts
-cpu0: MSR_NHM_PLATFORM_INFO: 0x80838f3012300
-8 * 100 = 800 MHz max efficiency
-35 * 100 = 3500 MHz TSC frequency
-cpu0: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
-cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0)
-cpu0: MSR_TURBO_RATIO_LIMIT: 0x25262727
-37 * 100 = 3700 MHz max turbo 4 active cores
-38 * 100 = 3800 MHz max turbo 3 active cores
-39 * 100 = 3900 MHz max turbo 2 active cores
-39 * 100 = 3900 MHz max turbo 1 active cores
+cpu4: MSR_PLATFORM_INFO: 0x80838f3012300
+8 * 100.0 = 800.0 MHz max efficiency frequency
+35 * 100.0 = 3500.0 MHz base frequency
+cpu4: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
+cpu4: MSR_TURBO_RATIO_LIMIT: 0x25262727
+37 * 100.0 = 3700.0 MHz max turbo 4 active cores
+38 * 100.0 = 3800.0 MHz max turbo 3 active cores
+39 * 100.0 = 3900.0 MHz max turbo 2 active cores
+39 * 100.0 = 3900.0 MHz max turbo 1 active cores
+cpu4: MSR_CONFIG_TDP_NOMINAL: 0x00000023 (base_ratio=35)
+cpu4: MSR_CONFIG_TDP_LEVEL_1: 0x00000000 ()
+cpu4: MSR_CONFIG_TDP_LEVEL_2: 0x00000000 ()
+cpu4: MSR_CONFIG_TDP_CONTROL: 0x80000000 ( lock=1)
+cpu4: MSR_TURBO_ACTIVATION_RATIO: 0x00000000 (MAX_NON_TURBO_RATIO=0 lock=0)
+cpu4: MSR_PKG_CST_CONFIG_CONTROL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0)
+cpu4: POLL: CPUIDLE CORE POLL IDLE
+cpu4: C1: MWAIT 0x00
+cpu4: C1E: MWAIT 0x01
+cpu4: C3: MWAIT 0x10
+cpu4: C6: MWAIT 0x20
+cpu4: C7s: MWAIT 0x32
+cpu4: MSR_MISC_FEATURE_CONTROL: 0x00000000 (L2-Prefetch L2-Prefetch-pair L1-Prefetch L1-IP-Prefetch)
cpu0: MSR_IA32_ENERGY_PERF_BIAS: 0x00000006 (balanced)
-cpu0: MSR_CORE_PERF_LIMIT_REASONS, 0x31200000 (Active: ) (Logged: Auto-HWP, Amps, MultiCoreTurbo, Transitions, )
+cpu0: MSR_CORE_PERF_LIMIT_REASONS, 0x31200000 (Active: ) (Logged: Transitions, MultiCoreTurbo, Amps, Auto-HWP, )
cpu0: MSR_GFX_PERF_LIMIT_REASONS, 0x00000000 (Active: ) (Logged: )
cpu0: MSR_RING_PERF_LIMIT_REASONS, 0x0d000000 (Active: ) (Logged: Amps, PkgPwrL1, PkgPwrL2, )
cpu0: MSR_RAPL_POWER_UNIT: 0x000a0e03 (0.125000 Watts, 0.000061 Joules, 0.000977 sec.)
@@ -162,23 +230,14 @@ cpu0: MSR_PP1_POLICY: 0
cpu0: MSR_PP1_POWER_LIMIT: 0x00000000 (UNlocked)
cpu0: GFX Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled)
cpu0: MSR_IA32_TEMPERATURE_TARGET: 0x00641400 (100 C)
-cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x88340800 (48 C)
-cpu0: MSR_IA32_THERM_STATUS: 0x88340000 (48 C +/- 1)
-cpu1: MSR_IA32_THERM_STATUS: 0x88440000 (32 C +/- 1)
-cpu2: MSR_IA32_THERM_STATUS: 0x88450000 (31 C +/- 1)
-cpu3: MSR_IA32_THERM_STATUS: 0x88490000 (27 C +/- 1)
- Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp PkgWatt CorWatt GFXWatt
- - - 493 12.64 3898 3498 0 12.64 0.00 0.00 74.72 47 47 21.62 13.74 0.00
- 0 0 4 0.11 3894 3498 0 99.89 0.00 0.00 0.00 47 47 21.62 13.74 0.00
- 0 4 3897 99.98 3898 3498 0 0.02
- 1 1 7 0.17 3887 3498 0 0.04 0.00 0.00 99.79 32
- 1 5 0 0.00 3885 3498 0 0.21
- 2 2 29 0.76 3895 3498 0 0.10 0.01 0.01 99.13 32
- 2 6 2 0.06 3896 3498 0 0.80
- 3 3 1 0.02 3832 3498 0 0.03 0.00 0.00 99.95 28
- 3 7 0 0.00 3879 3498 0 0.04
-^C
-
+cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x884c0800 (24 C)
+cpu0: MSR_IA32_THERM_STATUS: 0x884c0000 (24 C +/- 1)
+cpu1: MSR_IA32_THERM_STATUS: 0x88510000 (19 C +/- 1)
+cpu2: MSR_IA32_THERM_STATUS: 0x884e0000 (22 C +/- 1)
+cpu3: MSR_IA32_THERM_STATUS: 0x88510000 (19 C +/- 1)
+cpu4: MSR_PKGC3_IRTL: 0x00008842 (valid, 67584 ns)
+cpu4: MSR_PKGC6_IRTL: 0x00008873 (valid, 117760 ns)
+cpu4: MSR_PKGC7_IRTL: 0x00008891 (valid, 148480 ns)
.fi
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 base
@@ -188,39 +247,22 @@ should be sustainable on all CPUs indefinitely, given nominal power and cooling.
The remaining rows show what maximum turbo frequency is possible
depending on the number of idle cores. Note that not all information is
available on all processors.
-.SH FORK EXAMPLE
-If turbostat is invoked with a command, it will fork that command
-and output the statistics gathered after the command exits.
-In this case, turbostat output goes to stderr, by default.
-Output can instead be saved to a file using the --out option.
-eg. Here a cycle soaker is run on 1 CPU (see %c0) for a few seconds
-until ^C while the other CPUs are mostly idle:
-
+.SH ADD COUNTER EXAMPLE
+Here we limit turbostat to showing just the CPU number for cpu0 - cpu3.
+We add a counter showing the 32-bit raw value of MSR 0x199 (MSR_IA32_PERF_CTL),
+labeling it with the column header, "PRF_CTRL", and display it only once,
+afte the conclusion of a 0.1 second sleep.
.nf
-root@hsw: turbostat cat /dev/zero > /dev/null
-^C
- CPU Avg_MHz Busy% Bzy_MHz TSC_MHz
- - 482 12.51 3854 3498
- 0 0 0.01 1960 3498
- 4 0 0.00 2128 3498
- 1 0 0.00 3003 3498
- 5 3854 99.98 3855 3498
- 2 0 0.01 3504 3498
- 6 3 0.08 3884 3498
- 3 0 0.00 2553 3498
- 7 0 0.00 2126 3498
-10.783983 sec
+sudo ./turbostat --quiet --cpu 0-3 --show CPU --add msr0x199,u32,raw,PRF_CTRL sleep .1
+0.101604 sec
+CPU PRF_CTRL
+- 0x00000000
+0 0x00000c00
+1 0x00000800
+2 0x00000a00
+3 0x00000800
.fi
-Above the cycle soaker drives cpu5 up its 3.9 GHz turbo limit.
-The first row shows the average MHz and Busy% across all the processors in the system.
-
-Note that the Avg_MHz column reflects the total number of cycles executed
-divided by the measurement interval. If the Busy% column is 100%,
-then the processor was running at that speed the entire interval.
-The Avg_MHz multiplied by the Busy% results in the Bzy_MHz --
-which is the average frequency while the processor was executing --
-not including any non-busy idle time.
.SH NOTES
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Some users want turbostat to tell them everything, by default.
Some users want turbostat to be quiet, by default.
I find that I'm in the 1st camp, and so I've never liked
needing to type the --debug parameter to decode the system
configuration.
So here we change the default and print the system configuration,
by default. (The --debug option is now un-documented, though
it does still exist for debugging turbostat internals)
When you do not want to see the system configuration
header, use the new "--quiet" option.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.8 | 7 +--
tools/power/x86/turbostat/turbostat.c | 105 +++++++++++++++++-----------------
2 files changed, 52 insertions(+), 60 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index e8fb1e02d121..a08de27713e0 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -53,8 +53,7 @@ name as necessary to disambiguate it from others is necessary. Note that option
.PP
\fB--Dump\fP displays the raw counter values.
.PP
-\fB--debug\fP displays additional system configuration information. Invoking this parameter
-more than once may also enable internal turbostat debug information.
+\fB--quiet\fP Do not decode and print the system configuration header information.
.PP
\fB--interval seconds\fP overrides the default 5.0 second measurement interval.
.PP
@@ -124,7 +123,6 @@ Or a command may be specified as in "FORK EXAMPLE" below.
.fi
.SH DEBUG EXAMPLE
-The "--debug" option prints additional system information before measurements:
The first row of statistics is a summary for the entire system.
For residency % columns, the summary is a weighted average.
@@ -188,9 +186,6 @@ should be sustainable on all CPUs indefinitely, given nominal power and cooling.
The remaining rows show what maximum turbo frequency is possible
depending on the number of idle cores. Note that not all information is
available on all processors.
-.PP
-The --debug option adds additional columns to the measurement ouput, including CPU idle power-state residency processor temperature sensor readinds.
-See the field definitions above.
.SH FORK EXAMPLE
If turbostat is invoked with a command, it will fork that command
and output the statistics gathered after the command exits.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index c50b452a404e..6867557596af 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -49,6 +49,7 @@ FILE *outf;
int *fd_percpu;
struct timespec interval_ts = {5, 0};
unsigned int debug;
+unsigned int quiet;
unsigned int rapl_joules;
unsigned int summary_only;
unsigned int dump_only;
@@ -3114,7 +3115,7 @@ void rapl_probe(unsigned int family, unsigned int model)
tdp = get_tdp(model);
rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
- if (debug)
+ if (!quiet)
fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
return;
@@ -3239,11 +3240,9 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr))
return -1;
- if (debug) {
- fprintf(outf, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx "
- "(%f Watts, %f Joules, %f sec.)\n", cpu, msr,
- rapl_power_units, rapl_energy_units, rapl_time_units);
- }
+ fprintf(outf, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr,
+ rapl_power_units, rapl_energy_units, rapl_time_units);
+
if (do_rapl & RAPL_PKG_POWER_INFO) {
if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))
@@ -3264,7 +3263,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return -9;
fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n",
- cpu, msr, (msr >> 63) & 1 ? "": "UN");
+ cpu, msr, (msr >> 63) & 1 ? "" : "UN");
print_power_limit_msr(cpu, msr, "PKG Limit #1");
fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n",
@@ -3290,40 +3289,34 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))
return -9;
fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",
- cpu, msr, (msr >> 31) & 1 ? "": "UN");
+ cpu, msr, (msr >> 31) & 1 ? "" : "UN");
print_power_limit_msr(cpu, msr, "DRAM Limit");
}
if (do_rapl & RAPL_CORE_POLICY) {
- if (debug) {
- if (get_msr(cpu, MSR_PP0_POLICY, &msr))
- return -7;
+ if (get_msr(cpu, MSR_PP0_POLICY, &msr))
+ return -7;
- fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
- }
+ fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
}
if (do_rapl & RAPL_CORES_POWER_LIMIT) {
- if (debug) {
- if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
- return -9;
- fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
- cpu, msr, (msr >> 31) & 1 ? "": "UN");
- print_power_limit_msr(cpu, msr, "Cores Limit");
- }
+ if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
+ return -9;
+ fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
+ cpu, msr, (msr >> 31) & 1 ? "" : "UN");
+ print_power_limit_msr(cpu, msr, "Cores Limit");
}
if (do_rapl & RAPL_GFX) {
- if (debug) {
- if (get_msr(cpu, MSR_PP1_POLICY, &msr))
- return -8;
+ if (get_msr(cpu, MSR_PP1_POLICY, &msr))
+ return -8;
- fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);
+ fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);
- if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))
- return -9;
- fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
- cpu, msr, (msr >> 31) & 1 ? "": "UN");
- print_power_limit_msr(cpu, msr, "GFX Limit");
- }
+ if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))
+ return -9;
+ fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
+ cpu, msr, (msr >> 31) & 1 ? "" : "UN");
+ print_power_limit_msr(cpu, msr, "GFX Limit");
}
return 0;
}
@@ -3469,7 +3462,7 @@ double slm_bclk(void)
}
freq = slm_freq_table[i];
- if (debug)
+ if (!quiet)
fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);
return freq;
@@ -3533,7 +3526,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
target_c_local = (msr >> 16) & 0xFF;
- if (debug)
+ if (!quiet)
fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
cpu, msr, target_c_local);
@@ -3648,7 +3641,7 @@ void process_cpuid()
if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
genuine_intel = 1;
- if (debug)
+ if (!quiet)
fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
(char *)&ebx, (char *)&edx, (char *)&ecx);
@@ -3659,7 +3652,7 @@ void process_cpuid()
if (family == 6 || family == 0xf)
model += ((fms >> 16) & 0xf) << 4;
- if (debug) {
+ if (!quiet) {
fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
max_level, family, model, stepping, family, model, stepping);
fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s\n",
@@ -3721,7 +3714,7 @@ void process_cpuid()
has_hwp_pkg = eax & (1 << 11);
has_epb = ecx & (1 << 3);
- if (debug)
+ if (!quiet)
fprintf(outf, "CPUID(6): %sAPERF, %sTURBO, %sDTS, %sPTM, %sHWP, "
"%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
has_aperf ? "" : "No-",
@@ -3735,11 +3728,11 @@ void process_cpuid()
has_hwp_pkg ? "" : "No-",
has_epb ? "" : "No-");
- if (debug)
+ if (!quiet)
decode_misc_enable_msr();
- if (max_level >= 0x7 && debug) {
+ if (max_level >= 0x7 && !quiet) {
int has_sgx;
ecx = 0;
@@ -3765,7 +3758,7 @@ void process_cpuid()
if (ebx_tsc != 0) {
- if (debug && (ebx != 0))
+ if (!quiet && (ebx != 0))
fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",
eax_crystal, ebx_tsc, crystal_hz);
@@ -3790,7 +3783,7 @@ void process_cpuid()
if (crystal_hz) {
tsc_hz = (unsigned long long) crystal_hz * ebx_tsc / eax_crystal;
- if (debug)
+ if (!quiet)
fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal);
}
@@ -3805,7 +3798,7 @@ void process_cpuid()
base_mhz = max_mhz = bus_mhz = edx = 0;
__cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx);
- if (debug)
+ if (!quiet)
fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n",
base_mhz, max_mhz, bus_mhz);
}
@@ -3845,16 +3838,16 @@ void process_cpuid()
do_slm_cstates = is_slm(family, model);
do_knl_cstates = is_knl(family, model);
- if (debug)
+ if (!quiet)
decode_misc_pwr_mgmt_msr();
- if (debug && has_slv_msrs(family, model))
+ if (!quiet && has_slv_msrs(family, model))
decode_c6_demotion_policy_msr();
rapl_probe(family, model);
perf_limit_reasons_probe(family, model);
- if (debug)
+ if (!quiet)
dump_cstate_pstate_config_info(family, model);
if (has_skl_msrs(family, model))
@@ -3866,7 +3859,7 @@ void process_cpuid()
if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
BIC_PRESENT(BIC_GFXMHz);
- if (debug)
+ if (!quiet)
decode_misc_feature_control();
return;
@@ -3883,7 +3876,7 @@ void help()
"to print statistics, until interrupted.\n"
"--add add a counter\n"
" eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
- "--debug run in \"debug\" mode\n"
+ "--quiet skip decoding system configuration header\n"
"--interval sec Override default 5-second measurement interval\n"
"--help print this help message\n"
"--out file create or truncate \"file\" for all output\n"
@@ -4136,24 +4129,24 @@ void turbostat_init()
process_cpuid();
- if (debug)
+ if (!quiet)
for_all_cpus(print_hwp, ODD_COUNTERS);
- if (debug)
+ if (!quiet)
for_all_cpus(print_epb, ODD_COUNTERS);
- if (debug)
+ if (!quiet)
for_all_cpus(print_perf_limit, ODD_COUNTERS);
- if (debug)
+ if (!quiet)
for_all_cpus(print_rapl, ODD_COUNTERS);
for_all_cpus(set_temperature_target, ODD_COUNTERS);
- if (debug)
+ if (!quiet)
for_all_cpus(print_thermal, ODD_COUNTERS);
- if (debug && do_irtl_snb)
+ if (!quiet && do_irtl_snb)
print_irtl();
}
@@ -4429,7 +4422,7 @@ void cmdline(int argc, char **argv)
static struct option long_options[] = {
{"add", required_argument, 0, 'a'},
{"Dump", no_argument, 0, 'D'},
- {"debug", no_argument, 0, 'd'},
+ {"debug", no_argument, 0, 'd'}, /* internal, not documented */
{"interval", required_argument, 0, 'i'},
{"help", no_argument, 0, 'h'},
{"hide", required_argument, 0, 'H'}, // meh, -h taken by --help
@@ -4437,6 +4430,7 @@ void cmdline(int argc, char **argv)
{"out", required_argument, 0, 'o'},
{"Package", no_argument, 0, 'p'},
{"processor", no_argument, 0, 'p'},
+ {"quiet", no_argument, 0, 'q'},
{"show", required_argument, 0, 's'},
{"Summary", no_argument, 0, 'S'},
{"TCC", required_argument, 0, 'T'},
@@ -4446,7 +4440,7 @@ void cmdline(int argc, char **argv)
progname = argv[0];
- while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:PpST:v",
+ while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:PpqST:v",
long_options, &option_index)) != -1) {
switch (opt) {
case 'a':
@@ -4491,6 +4485,9 @@ void cmdline(int argc, char **argv)
case 'p':
show_core_only++;
break;
+ case 'q':
+ quiet = 1;
+ break;
case 's':
parse_show_hide(optarg, SHOW_LIST);
break;
@@ -4514,7 +4511,7 @@ int main(int argc, char **argv)
cmdline(argc, argv);
- if (debug)
+ if (!quiet)
print_version();
turbostat_init();
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Originally, the only way to hide the sysfs C-state statistics columns
was with "--hide sysfs". This was because we process "--hide" before
we probe for those columns.
hack --hide to remember deferred hide requests, and apply
them when sysfs is probed.
"--hide sysfs" is still available as short-hand to refer to
the entire group of counters.
The down-side of this change is that we no longer error check for
bogus --hide column names. But the user will quickly figure that
out if a column they mean to hide is still there...
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.8 | 2 +-
tools/power/x86/turbostat/turbostat.c | 115 +++++++++++++++++++++-------------
2 files changed, 73 insertions(+), 44 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 5189d9d982fe..fedca3285326 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -114,7 +114,7 @@ This is ideal for remote debugging, use the "--out" option to save everything to
.PP
When you are not interested in all that information, and there are several ways to see only what you want. First the "--quiet" option will skip the configuration information, and turbostat will show only the counter columns. Second, you can reduce the columns with the "--hide" and "--show" options. If you use the "--show" option, then turbostat will show only the columns you list. If you use the "--hide" option, turbostat will show all columns, except the ones you list.
.PP
-To find out what columns are available for --show and --hide, the "--list" option is available. Note, however, there is an exception. The C-state columns collected from sysfs "C1,C2,C3,C1%,C2%,C3%" are not built-in counters, but are discovered after --show and --hide are processed. You can use the special counter name "sysfs" to refer to all of them at the same time.
+To find out what columns are available for --show and --hide, the "--list" option is available. For convenience, the special strings "sysfs" can be used to refer to all of the sysfs C-state counters at once:
.nf
sudo ./turbostat --show sysfs --quiet sleep 10
10.003837 sec
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index c005d9052679..596259f48f50 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -434,12 +434,45 @@ unsigned long long bic_present = BIC_sysfs;
#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
#define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
+#define MAX_DEFERRED 16
+char *deferred_skip_names[MAX_DEFERRED];
+int deferred_skip_index;
+
+/*
+ * HIDE_LIST - hide this list of counters, show the rest [default]
+ * SHOW_LIST - show this list of counters, hide the rest
+ */
+enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;
+
+void help(void)
+{
+ fprintf(outf,
+ "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
+ "\n"
+ "Turbostat forks the specified COMMAND and prints statistics\n"
+ "when COMMAND completes.\n"
+ "If no COMMAND is specified, turbostat wakes every 5-seconds\n"
+ "to print statistics, until interrupted.\n"
+ "--add add a counter\n"
+ " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
+ "--cpu cpu-set limit output to summary plus cpu-set:\n"
+ " {core | package | j,k,l..m,n-p }\n"
+ "--quiet skip decoding system configuration header\n"
+ "--interval sec Override default 5-second measurement interval\n"
+ "--help print this help message\n"
+ "--list list column headers only\n"
+ "--out file create or truncate \"file\" for all output\n"
+ "--version print version information\n"
+ "\n"
+ "For more help, run \"man turbostat\"\n");
+}
+
/*
* bic_lookup
* for all the strings in comma separate name_list,
* set the approprate bit in return value.
*/
-unsigned long long bic_lookup(char *name_list)
+unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode)
{
int i;
unsigned long long retval = 0;
@@ -459,8 +492,19 @@ unsigned long long bic_lookup(char *name_list)
}
}
if (i == MAX_BIC) {
- fprintf(stderr, "Invalid counter name: %s\n", name_list);
- exit(-1);
+ if (mode == SHOW_LIST) {
+ fprintf(stderr, "Invalid counter name: %s\n", name_list);
+ exit(-1);
+ }
+ deferred_skip_names[deferred_skip_index++] = name_list;
+ if (debug)
+ fprintf(stderr, "deferred \"%s\"\n", name_list);
+ if (deferred_skip_index >= MAX_DEFERRED) {
+ fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n",
+ MAX_DEFERRED, name_list);
+ help();
+ exit(1);
+ }
}
name_list = comma;
@@ -471,6 +515,7 @@ unsigned long long bic_lookup(char *name_list)
return retval;
}
+
void print_header(char *delim)
{
struct msr_counter *mp;
@@ -502,20 +547,17 @@ void print_header(char *delim)
outp += sprintf(outp, "%sSMI", (printed++ ? delim : ""));
for (mp = sys.tp; mp; mp = mp->next) {
- if (*delim == ',') {
- outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), "sysfs");
- break;
- }
+
if (mp->format == FORMAT_RAW) {
if (mp->width == 64)
- outp += sprintf(outp, "%s%18.18s", delim, mp->name);
+ outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), mp->name);
else
- outp += sprintf(outp, "%s%10.10s", delim, mp->name);
+ outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), mp->name);
} else {
if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
- outp += sprintf(outp, "%s%8s", delim, mp->name);
+ outp += sprintf(outp, "%s%8s", (printed++ ? delim : ""), mp->name);
else
- outp += sprintf(outp, "%s%s", delim, mp->name);
+ outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), mp->name);
}
}
@@ -4142,29 +4184,6 @@ void process_cpuid()
return;
}
-void help()
-{
- fprintf(outf,
- "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
- "\n"
- "Turbostat forks the specified COMMAND and prints statistics\n"
- "when COMMAND completes.\n"
- "If no COMMAND is specified, turbostat wakes every 5-seconds\n"
- "to print statistics, until interrupted.\n"
- "--add add a counter\n"
- " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
- "--cpu cpu-set limit output to summary plus cpu-set:\n"
- " {core | package | j,k,l..m,n-p }\n"
- "--quiet skip decoding system configuration header\n"
- "--interval sec Override default 5-second measurement interval\n"
- "--help print this help message\n"
- "--list list column headers only\n"
- "--out file create or truncate \"file\" for all output\n"
- "--version print version information\n"
- "\n"
- "For more help, run \"man turbostat\"\n");
-}
-
/*
* in /dev/cpu/ return success for names that are numbers
@@ -4689,6 +4708,16 @@ void parse_add_command(char *add_command)
}
}
+int is_deferred_skip(char *name)
+{
+ int i;
+
+ for (i = 0; i < deferred_skip_index; ++i)
+ if (!strcmp(name, deferred_skip_names[i]))
+ return 1;
+ return 0;
+}
+
void probe_sysfs(void)
{
char path[64];
@@ -4720,6 +4749,9 @@ void probe_sysfs(void)
sprintf(path, "cpuidle/state%d/time", state);
+ if (is_deferred_skip(name_buf))
+ continue;
+
add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC,
FORMAT_PERCENT, SYSFS_PERCPU);
}
@@ -4741,6 +4773,9 @@ void probe_sysfs(void)
sprintf(path, "cpuidle/state%d/usage", state);
+ if (is_deferred_skip(name_buf))
+ continue;
+
add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS,
FORMAT_DELTA, SYSFS_PERCPU);
}
@@ -4834,12 +4869,6 @@ void parse_cpu_command(char *optarg)
exit(-1);
}
-/*
- * HIDE_LIST - hide this list of counters, show the rest [default]
- * SHOW_LIST - show this list of counters, hide the rest
- */
-enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;
-
int shown;
/*
* parse_show_hide() - process cmdline to set default counter action
@@ -4853,9 +4882,9 @@ void parse_show_hide(char *optarg, enum show_hide_mode new_mode)
*/
if (new_mode == SHOW_LIST) {
if (shown == 0)
- bic_enabled = bic_lookup(optarg);
+ bic_enabled = bic_lookup(optarg, new_mode);
else
- bic_enabled |= bic_lookup(optarg);
+ bic_enabled |= bic_lookup(optarg, new_mode);
shown = 1;
return;
@@ -4865,7 +4894,7 @@ void parse_show_hide(char *optarg, enum show_hide_mode new_mode)
* --hide: do not show those specified
* multiple invocations simply clear more bits in enabled mask
*/
- bic_enabled &= ~bic_lookup(optarg);
+ bic_enabled &= ~bic_lookup(optarg, new_mode);
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
show the CPUID feature for turbo to clarify the case
when it may not be shown in MISC_ENABLE
CPUID(6): APERF, TURBO, DTS, PTM, No-HWP, No-HWPnotify, No-HWPwindow, No-HWPepp, No-HWPpkg, EPB
cpu4: MSR_IA32_MISC_ENABLE: 0x00850089 (TCC EIST MWAIT TURBO)
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index da6ec640caf7..1011b5f7f21f 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -3626,6 +3626,7 @@ void process_cpuid()
{
unsigned int eax, ebx, ecx, edx, max_level, max_extended_level;
unsigned int fms, family, model, stepping;
+ unsigned int has_turbo;
eax = ebx = ecx = edx = 0;
@@ -3696,6 +3697,7 @@ void process_cpuid()
do_dts = eax & (1 << 0);
if (do_dts)
BIC_PRESENT(BIC_CoreTmp);
+ has_turbo = eax & (1 << 1);
do_ptm = eax & (1 << 6);
if (do_ptm)
BIC_PRESENT(BIC_PkgTmp);
@@ -3707,9 +3709,10 @@ void process_cpuid()
has_epb = ecx & (1 << 3);
if (debug)
- fprintf(outf, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sHWP, "
+ fprintf(outf, "CPUID(6): %sAPERF, %sTURBO, %sDTS, %sPTM, %sHWP, "
"%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
has_aperf ? "" : "No-",
+ has_turbo ? "" : "No-",
do_dts ? "" : "No-",
do_ptm ? "" : "No-",
has_hwp ? "" : "No-",
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Gemini Lake is similar to Apollo Lake (Broxton/Goldmont)
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 4b04ba86e44f..819d67fbb6ca 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -2535,6 +2535,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
pkg_cstate_limits = phi_pkg_cstate_limits;
break;
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
+ case INTEL_FAM6_ATOM_GEMINI_LAKE:
case INTEL_FAM6_ATOM_DENVERTON: /* DNV */
pkg_cstate_limits = bxt_pkg_cstate_limits;
break;
@@ -3018,6 +3019,7 @@ void rapl_probe(unsigned int family, unsigned int model)
}
break;
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
+ case INTEL_FAM6_ATOM_GEMINI_LAKE:
do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO;
if (rapl_joules)
BIC_PRESENT(BIC_Pkg_J);
@@ -3361,6 +3363,7 @@ int has_snb_msrs(unsigned int family, unsigned int model)
case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */
case INTEL_FAM6_SKYLAKE_X: /* SKX */
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
+ case INTEL_FAM6_ATOM_GEMINI_LAKE:
case INTEL_FAM6_ATOM_DENVERTON: /* DNV */
return 1;
}
@@ -3392,6 +3395,7 @@ int has_hsw_msrs(unsigned int family, unsigned int model)
case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */
case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
+ case INTEL_FAM6_ATOM_GEMINI_LAKE:
return 1;
}
return 0;
@@ -3783,6 +3787,7 @@ void process_cpuid()
crystal_hz = 25000000; /* 25.0 MHz */
break;
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
+ case INTEL_FAM6_ATOM_GEMINI_LAKE:
crystal_hz = 19200000; /* 19.2 MHz */
break;
default:
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Skip these two counters on BDX, as they are always zero:
cc7, pc7
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 67a275882a8d..334c4c29d4b5 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -2612,6 +2612,19 @@ int is_dnv(unsigned int family, unsigned int model)
}
return 0;
}
+int is_bdx(unsigned int family, unsigned int model)
+{
+
+ if (!genuine_intel)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_BROADWELL_X:
+ case INTEL_FAM6_BROADWELL_XEON_D:
+ return 1;
+ }
+ return 0;
+}
int is_skx(unsigned int family, unsigned int model)
{
@@ -3933,6 +3946,10 @@ void process_cpuid()
BIC_NOT_PRESENT(BIC_CPU_c7);
BIC_NOT_PRESENT(BIC_Pkgpc7);
}
+ if (is_bdx(family, model)) {
+ BIC_NOT_PRESENT(BIC_CPU_c7);
+ BIC_NOT_PRESENT(BIC_Pkgpc7);
+ }
if (has_hsw_msrs(family, model)) {
BIC_PRESENT(BIC_Pkgpc8);
BIC_PRESENT(BIC_Pkgpc9);
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
The CC1 column in tubostat can be computed by subtracting
the core c-state residency countes from the total Cx residency.
CC1 = (Idle_time_as_measured by MPERF) - (all core C-states with
residency counters)
However, as the underlying counter reads are not atomic,
error can be noticed in this calculations, especially
when the numbers are small.
Denverton has a hardware CC1 residency counter
to improve the accuracy of the cc1 statistic -- use it.
At the same time, Denverton has no concept of CC3, PC3, CC7, PC7,
so skip collecting and printing those columns.
Finally, a note of clarification.
Turbostat prints the standard PC2 residency counter,
but on Denverton hardware, that actually means PC1E.
Turbostat prints the standard PC6 residency counter,
but on Denverton hardware, that actually means PC2.
At this point, we document that differnce in this commit message,
rather than adding a quirk to the software.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 819d67fbb6ca..1010135ee973 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -2572,6 +2572,18 @@ int has_slv_msrs(unsigned int family, unsigned int model)
}
return 0;
}
+int is_dnv(unsigned int family, unsigned int model)
+{
+
+ if (!genuine_intel)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_ATOM_DENVERTON:
+ return 1;
+ }
+ return 0;
+}
int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
{
@@ -3851,6 +3863,14 @@ void process_cpuid()
BIC_PRESENT(BIC_Mod_c6);
use_c1_residency_msr = 1;
}
+ if (is_dnv(family, model)) {
+ BIC_PRESENT(BIC_CPU_c1);
+ BIC_NOT_PRESENT(BIC_CPU_c3);
+ BIC_NOT_PRESENT(BIC_Pkgpc3);
+ BIC_NOT_PRESENT(BIC_CPU_c7);
+ BIC_NOT_PRESENT(BIC_Pkgpc7);
+ use_c1_residency_msr = 1;
+ }
if (has_hsw_msrs(family, model)) {
BIC_PRESENT(BIC_Pkgpc8);
BIC_PRESENT(BIC_Pkgpc9);
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
When turbostat is run in one-shot command mode,
the parent takes the 'before' counter snapshot,
fork/exec/wait for the child to exit,
takes the 'after' counter snapshot,
and prints the results.
however, if the child fails to exec the command,
it immediately returns, without indicating that
anythign was wrong.
Add an error message showing that exec failed:
sudo turbostat sleeeep 4
...
turbostat: exec sleeeep: No such file or directory
...
Note that the parent will still print out the statistics,
because it can't tell the difference between the failed
exec and a command that is purposefully returning
the same status. Unfortunately, this may obscure the
error message. However, if the --out parameter is used,
the error message is evident on stderr.
Reported-by: Wendy Wang <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 7af5f42a9792..2d758abecd56 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -4525,6 +4525,7 @@ int fork_it(char **argv)
if (!child_pid) {
/* child */
execvp(argv[0], argv);
+ err(errno, "exec %s", argv[0]);
} else {
/* parent */
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
The turbostat before this last set of changes is obsolete.
This new version can do a lot more, but it also has
some different defaults, that might catch some off-guard.
So it seems a good time to give a new version number.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 5216549957f4..828dccd3f01e 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -4578,7 +4578,7 @@ int get_and_dump_counters(void)
}
void print_version() {
- fprintf(outf, "turbostat version 4.17 10 Jan 2017"
+ fprintf(outf, "turbostat version 17.02.24"
" - Len Brown <[email protected]>\n");
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Fix a bug with --add, where the title of the column
is un-initialized if not specified by the user.
The initial implementation of --show and --hide
neglected to handle the pc8/pc9/pc10 counters.
Fix a bug where "--show Core" only worked with --debug
Reported-by: Wendy Wang <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 138 +++++++++++++++++++---------------
1 file changed, 77 insertions(+), 61 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index bbdf9ba9d41b..4b04ba86e44f 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -55,11 +55,6 @@ unsigned int summary_only;
unsigned int dump_only;
unsigned int do_snb_cstates;
unsigned int do_knl_cstates;
-unsigned int do_pc2;
-unsigned int do_pc3;
-unsigned int do_pc6;
-unsigned int do_pc7;
-unsigned int do_c8_c9_c10;
unsigned int do_skl_residency;
unsigned int do_slm_cstates;
unsigned int use_c1_residency_msr;
@@ -365,6 +360,9 @@ struct msr_counter bic[] = {
{ 0x0, "Pkg%pc3" },
{ 0x0, "Pkg%pc6" },
{ 0x0, "Pkg%pc7" },
+ { 0x0, "Pkg%pc8" },
+ { 0x0, "Pkg%pc9" },
+ { 0x0, "Pkg%pc10" },
{ 0x0, "PkgWatt" },
{ 0x0, "CorWatt" },
{ 0x0, "GFXWatt" },
@@ -403,26 +401,30 @@ struct msr_counter bic[] = {
#define BIC_Pkgpc3 (1ULL << 18)
#define BIC_Pkgpc6 (1ULL << 19)
#define BIC_Pkgpc7 (1ULL << 20)
-#define BIC_PkgWatt (1ULL << 21)
-#define BIC_CorWatt (1ULL << 22)
-#define BIC_GFXWatt (1ULL << 23)
-#define BIC_PkgCnt (1ULL << 24)
-#define BIC_RAMWatt (1ULL << 27)
-#define BIC_PKG__ (1ULL << 28)
-#define BIC_RAM__ (1ULL << 29)
-#define BIC_Pkg_J (1ULL << 30)
-#define BIC_Cor_J (1ULL << 31)
-#define BIC_GFX_J (1ULL << 30)
-#define BIC_RAM_J (1ULL << 31)
-#define BIC_Core (1ULL << 32)
-#define BIC_CPU (1ULL << 33)
-#define BIC_Mod_c6 (1ULL << 34)
+#define BIC_Pkgpc8 (1ULL << 21)
+#define BIC_Pkgpc9 (1ULL << 22)
+#define BIC_Pkgpc10 (1ULL << 23)
+#define BIC_PkgWatt (1ULL << 24)
+#define BIC_CorWatt (1ULL << 25)
+#define BIC_GFXWatt (1ULL << 26)
+#define BIC_PkgCnt (1ULL << 27)
+#define BIC_RAMWatt (1ULL << 28)
+#define BIC_PKG__ (1ULL << 29)
+#define BIC_RAM__ (1ULL << 30)
+#define BIC_Pkg_J (1ULL << 31)
+#define BIC_Cor_J (1ULL << 32)
+#define BIC_GFX_J (1ULL << 33)
+#define BIC_RAM_J (1ULL << 34)
+#define BIC_Core (1ULL << 35)
+#define BIC_CPU (1ULL << 36)
+#define BIC_Mod_c6 (1ULL << 37)
unsigned long long bic_enabled = 0xFFFFFFFFFFFFFFFFULL;
unsigned long long bic_present;
#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
+#define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
/*
* bic_lookup
@@ -539,19 +541,20 @@ void print_header(void)
outp += sprintf(outp, "\tCPUGFX%%");
}
- if (do_pc2)
+ if (DO_BIC(BIC_Pkgpc2))
outp += sprintf(outp, "\tPkg%%pc2");
- if (do_pc3)
+ if (DO_BIC(BIC_Pkgpc3))
outp += sprintf(outp, "\tPkg%%pc3");
- if (do_pc6)
+ if (DO_BIC(BIC_Pkgpc6))
outp += sprintf(outp, "\tPkg%%pc6");
- if (do_pc7)
+ if (DO_BIC(BIC_Pkgpc7))
outp += sprintf(outp, "\tPkg%%pc7");
- if (do_c8_c9_c10) {
+ if (DO_BIC(BIC_Pkgpc8))
outp += sprintf(outp, "\tPkg%%pc8");
+ if (DO_BIC(BIC_Pkgpc9))
outp += sprintf(outp, "\tPkg%%pc9");
+ if (DO_BIC(BIC_Pkgpc10))
outp += sprintf(outp, "\tPk%%pc10");
- }
if (do_rapl && !rapl_joules) {
if (DO_BIC(BIC_PkgWatt))
@@ -644,11 +647,11 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0);
outp += sprintf(outp, "pc2: %016llX\n", p->pc2);
- if (do_pc3)
+ if (DO_BIC(BIC_Pkgpc3))
outp += sprintf(outp, "pc3: %016llX\n", p->pc3);
- if (do_pc6)
+ if (DO_BIC(BIC_Pkgpc6))
outp += sprintf(outp, "pc6: %016llX\n", p->pc6);
- if (do_pc7)
+ if (DO_BIC(BIC_Pkgpc7))
outp += sprintf(outp, "pc7: %016llX\n", p->pc7);
outp += sprintf(outp, "pc8: %016llX\n", p->pc8);
outp += sprintf(outp, "pc9: %016llX\n", p->pc9);
@@ -827,19 +830,20 @@ int format_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_both_core_gfxe_c0/tsc);
}
- if (do_pc2)
+ if (DO_BIC(BIC_Pkgpc2))
outp += sprintf(outp, "\t%.2f", 100.0 * p->pc2/tsc);
- if (do_pc3)
+ if (DO_BIC(BIC_Pkgpc3))
outp += sprintf(outp, "\t%.2f", 100.0 * p->pc3/tsc);
- if (do_pc6)
+ if (DO_BIC(BIC_Pkgpc6))
outp += sprintf(outp, "\t%.2f", 100.0 * p->pc6/tsc);
- if (do_pc7)
+ if (DO_BIC(BIC_Pkgpc7))
outp += sprintf(outp, "\t%.2f", 100.0 * p->pc7/tsc);
- if (do_c8_c9_c10) {
+ if (DO_BIC(BIC_Pkgpc8))
outp += sprintf(outp, "\t%.2f", 100.0 * p->pc8/tsc);
+ if (DO_BIC(BIC_Pkgpc9))
outp += sprintf(outp, "\t%.2f", 100.0 * p->pc9/tsc);
+ if (DO_BIC(BIC_Pkgpc10))
outp += sprintf(outp, "\t%.2f", 100.0 * p->pc10/tsc);
- }
/*
* If measurement interval exceeds minimum RAPL Joule Counter range,
@@ -949,11 +953,11 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0;
}
old->pc2 = new->pc2 - old->pc2;
- if (do_pc3)
+ if (DO_BIC(BIC_Pkgpc3))
old->pc3 = new->pc3 - old->pc3;
- if (do_pc6)
+ if (DO_BIC(BIC_Pkgpc6))
old->pc6 = new->pc6 - old->pc6;
- if (do_pc7)
+ if (DO_BIC(BIC_Pkgpc7))
old->pc7 = new->pc7 - old->pc7;
old->pc8 = new->pc8 - old->pc8;
old->pc9 = new->pc9 - old->pc9;
@@ -1126,11 +1130,11 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
p->pkg_both_core_gfxe_c0 = 0;
p->pc2 = 0;
- if (do_pc3)
+ if (DO_BIC(BIC_Pkgpc3))
p->pc3 = 0;
- if (do_pc6)
+ if (DO_BIC(BIC_Pkgpc6))
p->pc6 = 0;
- if (do_pc7)
+ if (DO_BIC(BIC_Pkgpc7))
p->pc7 = 0;
p->pc8 = 0;
p->pc9 = 0;
@@ -1204,11 +1208,11 @@ int sum_counters(struct thread_data *t, struct core_data *c,
}
average.packages.pc2 += p->pc2;
- if (do_pc3)
+ if (DO_BIC(BIC_Pkgpc3))
average.packages.pc3 += p->pc3;
- if (do_pc6)
+ if (DO_BIC(BIC_Pkgpc6))
average.packages.pc6 += p->pc6;
- if (do_pc7)
+ if (DO_BIC(BIC_Pkgpc7))
average.packages.pc7 += p->pc7;
average.packages.pc8 += p->pc8;
average.packages.pc9 += p->pc9;
@@ -1266,11 +1270,11 @@ void compute_average(struct thread_data *t, struct core_data *c,
}
average.packages.pc2 /= topo.num_packages;
- if (do_pc3)
+ if (DO_BIC(BIC_Pkgpc3))
average.packages.pc3 /= topo.num_packages;
- if (do_pc6)
+ if (DO_BIC(BIC_Pkgpc6))
average.packages.pc6 /= topo.num_packages;
- if (do_pc7)
+ if (DO_BIC(BIC_Pkgpc7))
average.packages.pc7 /= topo.num_packages;
average.packages.pc8 /= topo.num_packages;
@@ -1448,10 +1452,10 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0))
return -13;
}
- if (do_pc3)
+ if (DO_BIC(BIC_Pkgpc3))
if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
return -9;
- if (do_pc6) {
+ if (DO_BIC(BIC_Pkgpc6)) {
if (do_slm_cstates) {
if (get_msr(cpu, MSR_ATOM_PKG_C6_RESIDENCY, &p->pc6))
return -10;
@@ -1461,20 +1465,22 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
}
}
- if (do_pc2)
+ if (DO_BIC(BIC_Pkgpc2))
if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2))
return -11;
- if (do_pc7)
+ if (DO_BIC(BIC_Pkgpc7))
if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7))
return -12;
- if (do_c8_c9_c10) {
+ if (DO_BIC(BIC_Pkgpc8))
if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8))
return -13;
+ if (DO_BIC(BIC_Pkgpc9))
if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9))
return -13;
+ if (DO_BIC(BIC_Pkgpc10))
if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10))
return -13;
- }
+
if (do_rapl & RAPL_PKG) {
if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr))
return -13;
@@ -3824,17 +3830,27 @@ void process_cpuid()
BIC_PRESENT(BIC_CPU_c7);
do_irtl_snb = has_snb_msrs(family, model);
- do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2);
- do_pc3 = (pkg_cstate_limit >= PCL__3);
- do_pc6 = (pkg_cstate_limit >= PCL__6);
- do_pc7 = do_snb_cstates && (pkg_cstate_limit >= PCL__7);
+ if (do_snb_cstates && (pkg_cstate_limit >= PCL__2))
+ BIC_PRESENT(BIC_Pkgpc2);
+ if (pkg_cstate_limit >= PCL__3)
+ BIC_PRESENT(BIC_Pkgpc3);
+ if (pkg_cstate_limit >= PCL__6)
+ BIC_PRESENT(BIC_Pkgpc6);
+ if (do_snb_cstates && (pkg_cstate_limit >= PCL__7))
+ BIC_PRESENT(BIC_Pkgpc7);
if (has_slv_msrs(family, model)) {
- do_pc2 = do_pc3 = do_pc7 = 0;
- do_pc6 = 1;
+ BIC_NOT_PRESENT(BIC_Pkgpc2);
+ BIC_NOT_PRESENT(BIC_Pkgpc3);
+ BIC_PRESENT(BIC_Pkgpc6);
+ BIC_NOT_PRESENT(BIC_Pkgpc7);
BIC_PRESENT(BIC_Mod_c6);
use_c1_residency_msr = 1;
}
- do_c8_c9_c10 = has_hsw_msrs(family, model);
+ if (has_hsw_msrs(family, model)) {
+ BIC_PRESENT(BIC_Pkgpc8);
+ BIC_PRESENT(BIC_Pkgpc9);
+ BIC_PRESENT(BIC_Pkgpc10);
+ }
do_irtl_hsw = has_hsw_msrs(family, model);
do_skl_residency = has_skl_msrs(family, model);
do_slm_cstates = is_slm(family, model);
@@ -3981,7 +3997,7 @@ void topology_probe()
if (debug > 1)
fprintf(outf, "max_core_id %d, sizing for %d cores per package\n",
max_core_id, topo.num_cores_per_pkg);
- if (debug && !summary_only && topo.num_cores_per_pkg > 1)
+ if (!summary_only && topo.num_cores_per_pkg > 1)
BIC_PRESENT(BIC_Core);
topo.num_packages = max_package_id + 1;
@@ -4282,7 +4298,7 @@ int add_counter(unsigned int msr_num, char *name, unsigned int width,
void parse_add_command(char *add_command)
{
int msr_num = 0;
- char name_buffer[NAME_BYTES];
+ char name_buffer[NAME_BYTES] = "";
int width = 64;
int fail = 0;
enum counter_scope scope = SCOPE_CPU;
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
When the "u32" keyword is used with --add, it means that
the output should be truncated to 32-bits. This was not
happening and all 64-bits were printed.
Also, when no column name was used for an added MSR,
The default column name was in deximal, eg. MSR16.
Users report that they tend to use hex MSR numbers,
so print them in hex. To always fit into the columns,
use the syntax M0x10. Note that the user can always
supply any column header that they want.
eg --add msr0x10,MY_TSC
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 26 +++++++-------------------
1 file changed, 7 insertions(+), 19 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 2d758abecd56..5216549957f4 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -834,7 +834,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
- outp += sprintf(outp, "%s0x%08lx", (printed++ ? delim : ""), (unsigned long) t->counter[i]);
+ outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) t->counter[i]);
else
outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
@@ -876,7 +876,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
- outp += sprintf(outp, "%s0x%08lx", (printed++ ? delim : ""), (unsigned long) c->counter[i]);
+ outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) c->counter[i]);
else
outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
@@ -967,7 +967,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
- outp += sprintf(outp, "%s0x%08lx", (printed++ ? delim : ""), (unsigned long) p->counter[i]);
+ outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) p->counter[i]);
else
outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
@@ -4732,22 +4732,10 @@ void parse_add_command(char *add_command)
/* generate default column header */
if (*name_buffer == '\0') {
- if (format == FORMAT_RAW) {
- if (width == 32)
- sprintf(name_buffer, "msr%d", msr_num);
- else
- sprintf(name_buffer, "MSR%d", msr_num);
- } else if (format == FORMAT_DELTA) {
- if (width == 32)
- sprintf(name_buffer, "cnt%d", msr_num);
- else
- sprintf(name_buffer, "CNT%d", msr_num);
- } else if (format == FORMAT_PERCENT) {
- if (width == 32)
- sprintf(name_buffer, "msr%d%%", msr_num);
- else
- sprintf(name_buffer, "MSR%d%%", msr_num);
- }
+ if (width == 32)
+ sprintf(name_buffer, "M0x%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
+ else
+ sprintf(name_buffer, "M0X%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
}
if (add_counter(msr_num, path, name_buffer, width, scope, type, format, 0))
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
With the --cpu parameter, turbostat prints only lines
for the specified set of CPUs:
sudo ./turbostat --quiet --show Core,CPU --cpu 0,1,3..5,6-7
Core CPU
- -
0 0
0 4
1 1
1 5
2 6
3 3
3 7
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.8 | 2 +
tools/power/x86/turbostat/turbostat.c | 95 ++++++++++++++++++++++++++++++++++-
2 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index e31b7213fd45..efe6a7147ff2 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -47,6 +47,8 @@ name as necessary to disambiguate it from others is necessary. Note that option
default: delta
.fi
.PP
+\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. cpu-set is a comma delimited list of cpu ranges. cpu ranges can be individual cpu numbers or start and end numbers, separated by ".." or '-'. eg. 1,2,8,14..17,21-44
+.PP
\fB--hide column\fP do not show the specified columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
.PP
\fB--show column\fP show only the specified columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index eb6cc8ccef06..8c965bb2f461 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -143,8 +143,9 @@ unsigned int has_misc_feature_control;
int backwards_count;
char *progname;
-cpu_set_t *cpu_present_set, *cpu_affinity_set;
-size_t cpu_present_setsize, cpu_affinity_setsize;
+#define CPU_SUBSET_MAXCPUS 1024 /* need to use before probe... */
+cpu_set_t *cpu_present_set, *cpu_affinity_set, *cpu_subset;
+size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
#define MAX_ADDED_COUNTERS 16
struct thread_data {
@@ -700,6 +701,11 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
return 0;
+ /*if not summary line and --cpu is used */
+ if ((t != &average.threads) &&
+ (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))
+ return 0;
+
interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
tsc = t->tsc * tsc_tweak;
@@ -4096,6 +4102,7 @@ void help()
"to print statistics, until interrupted.\n"
"--add add a counter\n"
" eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
+ "--cpu cpu-set limit output to summary plus cpu-set cpu-set\n"
"--quiet skip decoding system configuration header\n"
"--interval sec Override default 5-second measurement interval\n"
"--help print this help message\n"
@@ -4159,6 +4166,15 @@ void topology_probe()
for_all_proc_cpus(mark_cpu_present);
/*
+ * Validate that all cpus in cpu_subset are also in cpu_present_set
+ */
+ for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) {
+ if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset))
+ if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set))
+ err(1, "cpu%d not present", i);
+ }
+
+ /*
* Allocate and initialize cpu_affinity_set
*/
cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1));
@@ -4675,6 +4691,77 @@ void probe_sysfs(void)
}
+
+/*
+ * parse cpuset with following syntax
+ * 1,2,4..6,8-10 and set bits in cpu_subset
+ */
+void parse_cpu_command(char *optarg)
+{
+ unsigned int start, end;
+ char *next;
+
+ cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS);
+ if (cpu_subset == NULL)
+ err(3, "CPU_ALLOC");
+ cpu_subset_size = CPU_ALLOC_SIZE(CPU_SUBSET_MAXCPUS);
+
+ CPU_ZERO_S(cpu_subset_size, cpu_subset);
+
+ next = optarg;
+
+ while (next && *next) {
+
+ if (*next == '-') /* no negative cpu numbers */
+ goto error;
+
+ start = strtoul(next, &next, 10);
+
+ if (start >= CPU_SUBSET_MAXCPUS)
+ goto error;
+ CPU_SET_S(start, cpu_subset_size, cpu_subset);
+
+ if (*next == '\0')
+ break;
+
+ if (*next == ',') {
+ next += 1;
+ continue;
+ }
+
+ if (*next == '-') {
+ next += 1; /* start range */
+ } else if (*next == '.') {
+ next += 1;
+ if (*next == '.')
+ next += 1; /* start range */
+ else
+ goto error;
+ }
+
+ end = strtoul(next, &next, 10);
+ if (end <= start)
+ goto error;
+
+ while (++start <= end) {
+ if (start >= CPU_SUBSET_MAXCPUS)
+ goto error;
+ CPU_SET_S(start, cpu_subset_size, cpu_subset);
+ }
+
+ if (*next == ',')
+ next += 1;
+ else if (*next != '\0')
+ goto error;
+ }
+
+ return;
+
+error:
+ fprintf(stderr, "'--cpu %s' malformed\n", optarg);
+ exit(-1);
+}
+
/*
* HIDE_LIST - hide this list of counters, show the rest [default]
* SHOW_LIST - show this list of counters, hide the rest
@@ -4716,6 +4803,7 @@ void cmdline(int argc, char **argv)
int option_index = 0;
static struct option long_options[] = {
{"add", required_argument, 0, 'a'},
+ {"cpu", required_argument, 0, 'c'},
{"Dump", no_argument, 0, 'D'},
{"debug", no_argument, 0, 'd'}, /* internal, not documented */
{"interval", required_argument, 0, 'i'},
@@ -4741,6 +4829,9 @@ void cmdline(int argc, char **argv)
case 'a':
parse_add_command(optarg);
break;
+ case 'c':
+ parse_cpu_command(optarg);
+ break;
case 'D':
dump_only++;
break;
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Some time ago, turbostat overflowed 80 columns.
So on the assumption that a "casual" user would always
want topology and frequency columns, we hid the rest
of the columns and the system configuration decoding
behind the --debug option.
Not everybody liked that change -- including me.
I use --debug 99% of the time...
Well, now we have "-o file" to put turbostat output into a file,
so unless you are watching real-time in a small window,
column count is less frequently a factor.
And more recently, we got the "--hide columnA,columnB" option
to specify columns to skip.
So now we "un-hide" the rest of the columns from behind --debug,
and show them all, by default.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 2f033f3d2a21..c50b452a404e 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -479,9 +479,6 @@ void print_header(void)
if (DO_BIC(BIC_TSC_MHz))
outp += sprintf(outp, "\tTSC_MHz");
- if (!debug)
- goto done;
-
if (DO_BIC(BIC_IRQ))
outp += sprintf(outp, "\tIRQ");
if (DO_BIC(BIC_SMI))
@@ -593,7 +590,6 @@ void print_header(void)
}
}
-done:
outp += sprintf(outp, "\n");
}
@@ -741,9 +737,6 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_TSC_MHz))
outp += sprintf(outp, "\t%.0f", 1.0 * t->tsc/units/interval_float);
- if (!debug)
- goto done;
-
/* IRQ */
if (DO_BIC(BIC_IRQ))
outp += sprintf(outp, "\t%d", t->irq_count);
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
The CPU ticks at a rate in the "bus clock" domain.
eg. 100 MHz * bus_ratio.
On newer processors, the TSC has been moved out of this BCLK
domain and into a separate crystal-clock domain.
While the TSC ticks "close to" the base frequency, those that look
closely at the numbers will notice small errors in calculations that
mix units of TSC clocks and bus clocks.
"tsc_tweak" was introduced to address the most visible
mixing -- the %Busy and the the Busy_MHz calculations.
(A simplification as since removed TSC from the BusyMHz calculation)
Here we apply the tsc_tweak to everyplace where BCLK
and TSC units are mixed. The results is that
on a system which is 100% idle, the sum of the C-states
are now much more likely to be closer to 100%.
Reported-by: Travis Downs <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 48 ++++++++++++++++++-----------------
1 file changed, 25 insertions(+), 23 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 6867557596af..bbdf9ba9d41b 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -680,7 +680,7 @@ int dump_counters(struct thread_data *t, struct core_data *c,
int format_counters(struct thread_data *t, struct core_data *c,
struct pkg_data *p)
{
- double interval_float;
+ double interval_float, tsc;
char *fmt8;
int i;
struct msr_counter *mp;
@@ -695,6 +695,8 @@ int format_counters(struct thread_data *t, struct core_data *c,
interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
+ tsc = t->tsc * tsc_tweak;
+
/* topo columns, print blanks on 1st (average) line */
if (t == &average.threads) {
if (DO_BIC(BIC_Package))
@@ -725,14 +727,14 @@ int format_counters(struct thread_data *t, struct core_data *c,
1.0 / units * t->aperf / interval_float);
if (DO_BIC(BIC_Busy))
- outp += sprintf(outp, "\t%.2f", 100.0 * t->mperf/t->tsc/tsc_tweak);
+ outp += sprintf(outp, "\t%.2f", 100.0 * t->mperf/tsc);
if (DO_BIC(BIC_Bzy_MHz)) {
if (has_base_hz)
outp += sprintf(outp, "\t%.0f", base_hz / units * t->aperf / t->mperf);
else
outp += sprintf(outp, "\t%.0f",
- 1.0 * t->tsc / units * t->aperf / t->mperf / interval_float);
+ tsc / units * t->aperf / t->mperf / interval_float);
}
if (DO_BIC(BIC_TSC_MHz))
@@ -748,7 +750,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
/* C1 */
if (DO_BIC(BIC_CPU_c1))
- outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/tsc);
/* Added counters */
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
@@ -760,7 +762,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
} else if (mp->format == FORMAT_DELTA) {
outp += sprintf(outp, "\t%lld", t->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
- outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/tsc);
}
}
@@ -769,15 +771,15 @@ int format_counters(struct thread_data *t, struct core_data *c,
goto done;
if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates)
- outp += sprintf(outp, "\t%.2f", 100.0 * c->c3/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * c->c3/tsc);
if (DO_BIC(BIC_CPU_c6))
- outp += sprintf(outp, "\t%.2f", 100.0 * c->c6/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * c->c6/tsc);
if (DO_BIC(BIC_CPU_c7))
- outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/tsc);
/* Mod%c6 */
if (DO_BIC(BIC_Mod_c6))
- outp += sprintf(outp, "\t%.2f", 100.0 * c->mc6_us / t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * c->mc6_us / tsc);
if (DO_BIC(BIC_CoreTmp))
outp += sprintf(outp, "\t%d", c->core_temp_c);
@@ -791,7 +793,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
} else if (mp->format == FORMAT_DELTA) {
outp += sprintf(outp, "\t%lld", c->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
- outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/tsc);
}
}
@@ -819,24 +821,24 @@ int format_counters(struct thread_data *t, struct core_data *c,
/* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
if (do_skl_residency) {
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_wtd_core_c0/t->tsc);
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_core_c0/t->tsc);
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_gfxe_c0/t->tsc);
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_both_core_gfxe_c0/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_wtd_core_c0/tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_core_c0/tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_gfxe_c0/tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_both_core_gfxe_c0/tsc);
}
if (do_pc2)
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc2/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pc2/tsc);
if (do_pc3)
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc3/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pc3/tsc);
if (do_pc6)
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc6/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pc6/tsc);
if (do_pc7)
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc7/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pc7/tsc);
if (do_c8_c9_c10) {
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc8/t->tsc);
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc9/t->tsc);
- outp += sprintf(outp, "\t%.2f", 100.0 * p->pc10/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pc8/tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pc9/tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->pc10/tsc);
}
/*
@@ -878,7 +880,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
} else if (mp->format == FORMAT_DELTA) {
outp += sprintf(outp, "\t%lld", p->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
- outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/t->tsc);
+ outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/tsc);
}
}
@@ -1048,7 +1050,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
old->c1 = 0;
else {
/* normal case, derive c1 */
- old->c1 = old->tsc - old->mperf - core_delta->c3
+ old->c1 = (old->tsc * tsc_tweak) - old->mperf - core_delta->c3
- core_delta->c6 - core_delta->c7;
}
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
When turbostat shows % of time in a CPU idle power state,
it has always been showing information from underlying
hardware residency counters.
While this reflects what the hardware is doing, and is thus
useful for understanding the hardware,
it doesn't directly tell us what Linux requested --
which is useful for tuning Linux itself.
Here we add columns to turbostat to show the
Linux cpuidle sub-system statistics:
/sys/devices/system/cpu/cpu*/cpuidle/state*/*
The first group of columns are the "usage", which is the
number of times software requested that C-state in the
measurement interval. eg C1 below.
The second group of columns are the "time", which is the percentage
of the measurement interval time that software has requested
the specified C-state. eg C1% below.
These software counters can be compared to the underlying
hardware residency counters (eg CPU%c1 CPU%c3 CPU%c6 CPU%c7)
to compare what sofware requested to what the hardware delivered.
These sysfs attributes are discovered when turbostat starts,
rather than being "built in". So the --show and --hide
parameters do not know about these dynamic column names.
However "--show sysfs" and "--hide sysfs" act on the
entire group of columns:
turbostat --show sysfs
...
cpu4: POLL: CPUIDLE CORE POLL IDLE
cpu4: C1: MWAIT 0x00
cpu4: C1E: MWAIT 0x01
cpu4: C3: MWAIT 0x10
cpu4: C6: MWAIT 0x20
cpu4: C7s: MWAIT 0x32
...
C1 C1E C3 C6 C7s C1% C1E% C3% C6% C7s%
3 6 5 1 188 0.00 0.02 0.00 0.00 99.93
0 6 5 0 58 0.00 0.16 0.02 0.00 99.70
0 0 0 0 9 0.00 0.00 0.00 0.00 99.96
0 0 0 1 24 0.00 0.00 0.00 0.02 99.93
0 0 0 0 9 0.00 0.00 0.00 0.00 99.97
0 0 0 0 32 0.00 0.00 0.00 0.00 99.96
0 0 0 0 7 0.00 0.00 0.00 0.00 99.98
2 0 0 0 36 0.00 0.00 0.00 0.00 99.97
1 0 0 0 13 0.00 0.00 0.00 0.00 99.98
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.8 | 4 +-
tools/power/x86/turbostat/turbostat.c | 161 ++++++++++++++++++++++++++++++----
2 files changed, 147 insertions(+), 18 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index a08de27713e0..e31b7213fd45 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -47,9 +47,9 @@ name as necessary to disambiguate it from others is necessary. Note that option
default: delta
.fi
.PP
-\fB--hide column\fP do not show the specified columns. May be invoked multiple times, or with a comma-separated list of column names.
+\fB--hide column\fP do not show the specified columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
.PP
-\fB--show column\fP show only the specified columns. May be invoked multiple times, or with a comma-separated list of column names.
+\fB--show column\fP show only the specified columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
.PP
\fB--Dump\fP displays the raw counter values.
.PP
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 841f837e317f..eb6cc8ccef06 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -208,7 +208,7 @@ struct pkg_data {
#define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no)
enum counter_scope {SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE};
-enum counter_type {COUNTER_CYCLES, COUNTER_SECONDS};
+enum counter_type {COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC};
enum counter_format {FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT};
struct msr_counter {
@@ -222,6 +222,7 @@ struct msr_counter {
unsigned int flags;
#define FLAGS_HIDE (1 << 0)
#define FLAGS_SHOW (1 << 1)
+#define SYSFS_PERCPU (1 << 1)
};
struct sys_counters {
@@ -379,6 +380,7 @@ struct msr_counter bic[] = {
{ 0x0, "Core" },
{ 0x0, "CPU" },
{ 0x0, "Mod%c6" },
+ { 0x0, "sysfs" },
};
#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
@@ -420,9 +422,10 @@ struct msr_counter bic[] = {
#define BIC_Core (1ULL << 35)
#define BIC_CPU (1ULL << 36)
#define BIC_Mod_c6 (1ULL << 37)
+#define BIC_sysfs (1ULL << 38)
unsigned long long bic_enabled = 0xFFFFFFFFFFFFFFFFULL;
-unsigned long long bic_present;
+unsigned long long bic_present = BIC_sysfs;
#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
@@ -489,9 +492,6 @@ void print_header(void)
if (DO_BIC(BIC_SMI))
outp += sprintf(outp, "\tSMI");
- if (DO_BIC(BIC_CPU_c1))
- outp += sprintf(outp, "\tCPU%%c1");
-
for (mp = sys.tp; mp; mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 64)
@@ -499,10 +499,12 @@ void print_header(void)
else
outp += sprintf(outp, "\t%10.10s", mp->name);
} else {
- outp += sprintf(outp, "\t%-7.7s", mp->name);
+ outp += sprintf(outp, "\t%s", mp->name);
}
}
+ if (DO_BIC(BIC_CPU_c1))
+ outp += sprintf(outp, "\tCPU%%c1");
if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates)
outp += sprintf(outp, "\tCPU%%c3");
if (DO_BIC(BIC_CPU_c6))
@@ -523,7 +525,7 @@ void print_header(void)
else
outp += sprintf(outp, "\t%10.10s", mp->name);
} else {
- outp += sprintf(outp, "\t%-7.7s", mp->name);
+ outp += sprintf(outp, "\t%s", mp->name);
}
}
@@ -592,7 +594,7 @@ void print_header(void)
else
outp += sprintf(outp, "\t%10.10s", mp->name);
} else {
- outp += sprintf(outp, "\t%-7.7s", mp->name);
+ outp += sprintf(outp, "\t%s", mp->name);
}
}
@@ -753,10 +755,6 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_SMI))
outp += sprintf(outp, "\t%d", t->smi_count);
- /* C1 */
- if (DO_BIC(BIC_CPU_c1))
- outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/tsc);
-
/* Added counters */
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
@@ -767,10 +765,18 @@ int format_counters(struct thread_data *t, struct core_data *c,
} else if (mp->format == FORMAT_DELTA) {
outp += sprintf(outp, "\t%lld", t->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
- outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/tsc);
+ if (mp->type == COUNTER_USEC)
+ outp += sprintf(outp, "\t%.2f", t->counter[i]/interval_float/10000);
+ else
+ outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/tsc);
}
}
+ /* C1 */
+ if (DO_BIC(BIC_CPU_c1))
+ outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/tsc);
+
+
/* print per-core data only for 1st thread in core */
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
goto done;
@@ -1286,6 +1292,8 @@ void compute_average(struct thread_data *t, struct core_data *c,
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW)
continue;
+ if (mp->flags & SYSFS_PERCPU && mp->type == COUNTER_ITEMS)
+ continue;
average.threads.counter[i] /= topo.num_cpus;
}
for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
@@ -1348,7 +1356,16 @@ int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
if (get_msr(cpu, mp->msr_num, counterp))
return -1;
} else {
- *counterp = snapshot_sysfs_counter(mp->path);
+ char path[128];
+
+ if (mp->flags & SYSFS_PERCPU) {
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/%s",
+ cpu, mp->path);
+
+ *counterp = snapshot_sysfs_counter(path);
+ } else {
+ *counterp = snapshot_sysfs_counter(mp->path);
+ }
}
return 0;
@@ -2822,6 +2839,48 @@ dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
dump_nhm_cst_cfg();
}
+static void
+dump_sysfs_cstate_config(void)
+{
+ char path[64];
+ char name_buf[16];
+ char desc[64];
+ FILE *input;
+ int state;
+ char *sp;
+
+ if (!DO_BIC(BIC_sysfs))
+ return;
+
+ for (state = 0; state < 10; ++state) {
+
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
+ base_cpu, state);
+ input = fopen(path, "r");
+ if (input == NULL)
+ continue;
+ fgets(name_buf, sizeof(name_buf), input);
+
+ /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
+ sp = strchr(name_buf, '-');
+ if (!sp)
+ sp = strchrnul(name_buf, '\n');
+ *sp = '\0';
+
+ fclose(input);
+
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc",
+ base_cpu, state);
+ input = fopen(path, "r");
+ if (input == NULL)
+ continue;
+ fgets(desc, sizeof(desc), input);
+
+ fprintf(outf, "cpu%d: %s: %s", base_cpu, name_buf, desc);
+ fclose(input);
+ }
+}
+
/*
* print_epb()
@@ -4008,6 +4067,9 @@ void process_cpuid()
if (!quiet)
dump_cstate_pstate_config_info(family, model);
+ if (!quiet)
+ dump_sysfs_cstate_config();
+
if (has_skl_msrs(family, model))
calculate_tsc_tweak();
@@ -4380,7 +4442,7 @@ void print_version() {
int add_counter(unsigned int msr_num, char *path, char *name,
unsigned int width, enum counter_scope scope,
- enum counter_type type, enum counter_format format)
+ enum counter_type type, enum counter_format format, int flags)
{
struct msr_counter *msrp;
@@ -4397,6 +4459,7 @@ int add_counter(unsigned int msr_num, char *path, char *name,
msrp->width = width;
msrp->type = type;
msrp->format = format;
+ msrp->flags = flags;
switch (scope) {
@@ -4486,6 +4549,10 @@ void parse_add_command(char *add_command)
type = COUNTER_SECONDS;
goto next;
}
+ if (!strncmp(add_command, "usec", strlen("usec"))) {
+ type = COUNTER_USEC;
+ goto next;
+ }
if (!strncmp(add_command, "raw", strlen("raw"))) {
format = FORMAT_RAW;
goto next;
@@ -4541,7 +4608,7 @@ void parse_add_command(char *add_command)
}
}
- if (add_counter(msr_num, path, name_buffer, width, scope, type, format))
+ if (add_counter(msr_num, path, name_buffer, width, scope, type, format, 0))
fail++;
if (fail) {
@@ -4549,6 +4616,65 @@ void parse_add_command(char *add_command)
exit(1);
}
}
+
+void probe_sysfs(void)
+{
+ char path[64];
+ char name_buf[16];
+ FILE *input;
+ int state;
+ char *sp;
+
+ if (!DO_BIC(BIC_sysfs))
+ return;
+
+ for (state = 10; state > 0; --state) {
+
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
+ base_cpu, state);
+ input = fopen(path, "r");
+ if (input == NULL)
+ continue;
+ fgets(name_buf, sizeof(name_buf), input);
+
+ /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
+ sp = strchr(name_buf, '-');
+ if (!sp)
+ sp = strchrnul(name_buf, '\n');
+ *sp = '%';
+ *(sp + 1) = '\0';
+
+ fclose(input);
+
+ sprintf(path, "cpuidle/state%d/time", state);
+
+ add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC,
+ FORMAT_PERCENT, SYSFS_PERCPU);
+ }
+
+ for (state = 10; state > 0; --state) {
+
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
+ base_cpu, state);
+ input = fopen(path, "r");
+ if (input == NULL)
+ continue;
+ fgets(name_buf, sizeof(name_buf), input);
+ /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
+ sp = strchr(name_buf, '-');
+ if (!sp)
+ sp = strchrnul(name_buf, '\n');
+ *sp = '\0';
+ fclose(input);
+
+ sprintf(path, "cpuidle/state%d/usage", state);
+
+ add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS,
+ FORMAT_DELTA, SYSFS_PERCPU);
+ }
+
+}
+
/*
* HIDE_LIST - hide this list of counters, show the rest [default]
* SHOW_LIST - show this list of counters, hide the rest
@@ -4581,6 +4707,7 @@ void parse_show_hide(char *optarg, enum show_hide_mode new_mode)
* multiple invocations simply clear more bits in enabled mask
*/
bic_enabled &= ~bic_lookup(optarg);
+
}
void cmdline(int argc, char **argv)
@@ -4682,6 +4809,8 @@ int main(int argc, char **argv)
if (!quiet)
print_version();
+ probe_sysfs();
+
turbostat_init();
/* dump counters and exit */
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Skip these four counters on SKX, as they are always zero:
cc3, pc3
cc7, pc7
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 1010135ee973..8c437115d41b 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -2584,6 +2584,18 @@ int is_dnv(unsigned int family, unsigned int model)
}
return 0;
}
+int is_skx(unsigned int family, unsigned int model)
+{
+
+ if (!genuine_intel)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_SKYLAKE_X:
+ return 1;
+ }
+ return 0;
+}
int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
{
@@ -3871,6 +3883,12 @@ void process_cpuid()
BIC_NOT_PRESENT(BIC_Pkgpc7);
use_c1_residency_msr = 1;
}
+ if (is_skx(family, model)) {
+ BIC_NOT_PRESENT(BIC_CPU_c3);
+ BIC_NOT_PRESENT(BIC_Pkgpc3);
+ BIC_NOT_PRESENT(BIC_CPU_c7);
+ BIC_NOT_PRESENT(BIC_Pkgpc7);
+ }
if (has_hsw_msrs(family, model)) {
BIC_PRESENT(BIC_Pkgpc8);
BIC_PRESENT(BIC_Pkgpc9);
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
This non-architectural MSR has disable bits
for various prefetchers on modern processors.
While these bits are generally touched only by the BIOS,
say, via BIOS SETUP, it is useful to dump them
when examining options that can alter performance.
Cc: [email protected]
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/include/asm/msr-index.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 83bc672c225c..312fb7e14cdd 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -467,6 +467,7 @@
#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
+#define MSR_MISC_FEATURE_CONTROL 0x000001a4
#define MSR_MISC_PWR_MGMT 0x000001aa
#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Previously, the --add option could specify only an MSR.
Here is is extended so an arbitrary /sys attribute,
as specified by an absolute file path name.
sudo ./turbostat --add /sys/devices/system/cpu/cpu0/cpuidle/state5/usage
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 92 ++++++++++++++++++++++++++---------
1 file changed, 69 insertions(+), 23 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 334c4c29d4b5..841f837e317f 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -138,6 +138,7 @@ unsigned int has_misc_feature_control;
* Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters
*/
#define NAME_BYTES 20
+#define PATH_BYTES 128
int backwards_count;
char *progname;
@@ -213,6 +214,7 @@ enum counter_format {FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT};
struct msr_counter {
unsigned int msr_num;
char name[NAME_BYTES];
+ char path[PATH_BYTES];
unsigned int width;
enum counter_type type;
enum counter_format format;
@@ -344,7 +346,7 @@ struct msr_counter bic[] = {
{ 0x0, "Bzy_MHz" },
{ 0x0, "TSC_MHz" },
{ 0x0, "IRQ" },
- { 0x0, "SMI", 32, 0, FORMAT_DELTA, NULL},
+ { 0x0, "SMI", "", 32, 0, FORMAT_DELTA, NULL},
{ 0x0, "Busy%" },
{ 0x0, "CPU%c1" },
{ 0x0, "CPU%c3" },
@@ -1308,6 +1310,51 @@ static unsigned long long rdtsc(void)
}
/*
+ * Open a file, and exit on failure
+ */
+FILE *fopen_or_die(const char *path, const char *mode)
+{
+ FILE *filep = fopen(path, mode);
+
+ if (!filep)
+ err(1, "%s: open failed", path);
+ return filep;
+}
+/*
+ * snapshot_sysfs_counter()
+ *
+ * return snapshot of given counter
+ */
+unsigned long long snapshot_sysfs_counter(char *path)
+{
+ FILE *fp;
+ int retval;
+ unsigned long long counter;
+
+ fp = fopen_or_die(path, "r");
+
+ retval = fscanf(fp, "%lld", &counter);
+ if (retval != 1)
+ err(1, "snapshot_sysfs_counter(%s)", path);
+
+ fclose(fp);
+
+ return counter;
+}
+
+int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
+{
+ if (mp->msr_num != 0) {
+ if (get_msr(cpu, mp->msr_num, counterp))
+ return -1;
+ } else {
+ *counterp = snapshot_sysfs_counter(mp->path);
+ }
+
+ return 0;
+}
+
+/*
* get_counters(...)
* migrate to cpu
* acquire and record local counters for that cpu
@@ -1397,11 +1444,10 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
}
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
- if (get_msr(cpu, mp->msr_num, &t->counter[i]))
+ if (get_mp(cpu, mp, &t->counter[i]))
return -10;
}
-
/* collect core counters only for 1st thread in core */
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
return 0;
@@ -1434,7 +1480,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
}
for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
- if (get_msr(cpu, mp->msr_num, &c->counter[i]))
+ if (get_mp(cpu, mp, &c->counter[i]))
return -10;
}
@@ -1524,7 +1570,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
p->gfx_mhz = gfx_cur_mhz;
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
- if (get_msr(cpu, mp->msr_num, &p->counter[i]))
+ if (get_mp(cpu, mp, &p->counter[i]))
return -10;
}
@@ -2013,16 +2059,6 @@ void free_all_buffers(void)
free(irqs_per_cpu);
}
-/*
- * Open a file, and exit on failure
- */
-FILE *fopen_or_die(const char *path, const char *mode)
-{
- FILE *filep = fopen(path, mode);
- if (!filep)
- err(1, "%s: open failed", path);
- return filep;
-}
/*
* Parse a file containing a single int.
@@ -2581,7 +2617,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
return 1;
}
/*
- * SLV client has supporet for unique MSRs:
+ * SLV client has support for unique MSRs:
*
* MSR_CC6_DEMOTION_POLICY_CONFIG
* MSR_MC6_DEMOTION_POLICY_CONFIG
@@ -4342,9 +4378,9 @@ void print_version() {
" - Len Brown <[email protected]>\n");
}
-int add_counter(unsigned int msr_num, char *name, unsigned int width,
- enum counter_scope scope, enum counter_type type,
- enum counter_format format)
+int add_counter(unsigned int msr_num, char *path, char *name,
+ unsigned int width, enum counter_scope scope,
+ enum counter_type type, enum counter_format format)
{
struct msr_counter *msrp;
@@ -4356,6 +4392,8 @@ int add_counter(unsigned int msr_num, char *name, unsigned int width,
msrp->msr_num = msr_num;
strncpy(msrp->name, name, NAME_BYTES);
+ if (path)
+ strncpy(msrp->path, path, PATH_BYTES);
msrp->width = width;
msrp->type = type;
msrp->format = format;
@@ -4402,6 +4440,7 @@ int add_counter(unsigned int msr_num, char *name, unsigned int width,
void parse_add_command(char *add_command)
{
int msr_num = 0;
+ char *path = NULL;
char name_buffer[NAME_BYTES] = "";
int width = 64;
int fail = 0;
@@ -4417,6 +4456,11 @@ void parse_add_command(char *add_command)
if (sscanf(add_command, "msr%d", &msr_num) == 1)
goto next;
+ if (*add_command == '/') {
+ path = add_command;
+ goto next;
+ }
+
if (sscanf(add_command, "u%d", &width) == 1) {
if ((width == 32) || (width == 64))
goto next;
@@ -4466,12 +4510,14 @@ void parse_add_command(char *add_command)
next:
add_command = strchr(add_command, ',');
- if (add_command)
+ if (add_command) {
+ *add_command = '\0';
add_command++;
+ }
}
- if (msr_num == 0) {
- fprintf(stderr, "--add: (msrDDD | msr0xXXX) required\n");
+ if ((msr_num == 0) && (path == NULL)) {
+ fprintf(stderr, "--add: (msrDDD | msr0xXXX | /path_to_counter ) required\n");
fail++;
}
@@ -4495,7 +4541,7 @@ void parse_add_command(char *add_command)
}
}
- if (add_counter(msr_num, name_buffer, width, scope, type, format))
+ if (add_counter(msr_num, path, name_buffer, width, scope, type, format))
fail++;
if (fail) {
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Originally, these MSRs were locally defined in this driver.
Now the definitions are in msr-index.h -- use them.
Signed-off-by: Len Brown <[email protected]>
---
drivers/cpufreq/intel_pstate.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 50bd6d987fc3..6e68b556305a 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -39,11 +39,6 @@
#define INTEL_CPUFREQ_TRANSITION_LATENCY 20000
-#define ATOM_RATIOS 0x66a
-#define ATOM_VIDS 0x66b
-#define ATOM_TURBO_RATIOS 0x66c
-#define ATOM_TURBO_VIDS 0x66d
-
#ifdef CONFIG_ACPI
#include <acpi/processor.h>
#include <acpi/cppc_acpi.h>
@@ -1258,7 +1253,7 @@ static int atom_get_min_pstate(void)
{
u64 value;
- rdmsrl(ATOM_RATIOS, value);
+ rdmsrl(MSR_ATOM_CORE_RATIOS, value);
return (value >> 8) & 0x7F;
}
@@ -1266,7 +1261,7 @@ static int atom_get_max_pstate(void)
{
u64 value;
- rdmsrl(ATOM_RATIOS, value);
+ rdmsrl(MSR_ATOM_CORE_RATIOS, value);
return (value >> 16) & 0x7F;
}
@@ -1274,7 +1269,7 @@ static int atom_get_turbo_pstate(void)
{
u64 value;
- rdmsrl(ATOM_TURBO_RATIOS, value);
+ rdmsrl(MSR_ATOM_CORE_TURBO_RATIOS, value);
return value & 0x7F;
}
@@ -1336,7 +1331,7 @@ static void atom_get_vid(struct cpudata *cpudata)
{
u64 value;
- rdmsrl(ATOM_VIDS, value);
+ rdmsrl(MSR_ATOM_CORE_VIDS, value);
cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
cpudata->vid.ratio = div_fp(
@@ -1344,7 +1339,7 @@ static void atom_get_vid(struct cpudata *cpudata)
int_tofp(cpudata->pstate.max_pstate -
cpudata->pstate.min_pstate));
- rdmsrl(ATOM_TURBO_VIDS, value);
+ rdmsrl(MSR_ATOM_CORE_TURBO_VIDS, value);
cpudata->vid.turbo = value & 0x7f;
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
cpu1: cpufreq driver: acpi-cpufreq
cpu1: cpufreq governor: ondemand
cpufreq boost: 1
or
cpu0: cpufreq driver: intel_pstate
cpu0: cpufreq governor: powersave
cpufreq intel_pstate no_turbo: 0
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 50 +++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 2c674ad5ab80..7af5f42a9792 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -2979,6 +2979,54 @@ dump_sysfs_cstate_config(void)
fclose(input);
}
}
+static void
+dump_sysfs_pstate_config(void)
+{
+ char path[64];
+ char driver_buf[64];
+ char governor_buf[64];
+ FILE *input;
+ int turbo;
+
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver",
+ base_cpu);
+ input = fopen(path, "r");
+ if (input == NULL) {
+ fprintf(stderr, "NSFOD %s\n", path);
+ return;
+ }
+ fgets(driver_buf, sizeof(driver_buf), input);
+ fclose(input);
+
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor",
+ base_cpu);
+ input = fopen(path, "r");
+ if (input == NULL) {
+ fprintf(stderr, "NSFOD %s\n", path);
+ return;
+ }
+ fgets(governor_buf, sizeof(governor_buf), input);
+ fclose(input);
+
+ fprintf(outf, "cpu%d: cpufreq driver: %s", base_cpu, driver_buf);
+ fprintf(outf, "cpu%d: cpufreq governor: %s", base_cpu, governor_buf);
+
+ sprintf(path, "/sys/devices/system/cpu/cpufreq/boost");
+ input = fopen(path, "r");
+ if (input != NULL) {
+ fscanf(input, "%d", &turbo);
+ fprintf(outf, "cpufreq boost: %d\n", turbo);
+ fclose(input);
+ }
+
+ sprintf(path, "/sys/devices/system/cpu/intel_pstate/no_turbo");
+ input = fopen(path, "r");
+ if (input != NULL) {
+ fscanf(input, "%d", &turbo);
+ fprintf(outf, "cpufreq intel_pstate no_turbo: %d\n", turbo);
+ fclose(input);
+ }
+}
/*
@@ -4168,6 +4216,8 @@ void process_cpuid()
if (!quiet)
dump_sysfs_cstate_config();
+ if (!quiet)
+ dump_sysfs_pstate_config();
if (has_skl_msrs(family, model))
calculate_tsc_tweak();
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
AMT value 0 is unlimited, not PC0
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 9b35c9bb0489..aedfaddbad30 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1534,7 +1534,7 @@ int nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV,
int snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
int hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
-int amt_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
+int amt_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
int bxt_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
int skx_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
The Baytrail SOC, with its Silvermont core, has some unique properties:
1. a hardware CC1 residency counter
2. a module-c6 residency counter
3. a package-c6 counter at traditional package-c7 counter address.
The SOC does not support c3, pc3, c7 or pc7 counters.
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/include/asm/msr-index.h | 2 ++
tools/power/x86/turbostat/turbostat.c | 46 ++++++++++++++++++++++++++++-------
2 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 12ecc6c1e7f8..079db99f6560 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -147,6 +147,7 @@
/* C-state Residency Counters */
#define MSR_PKG_C3_RESIDENCY 0x000003f8
#define MSR_PKG_C6_RESIDENCY 0x000003f9
+#define MSR_ATOM_PKG_C6_RESIDENCY 0x000003fa
#define MSR_PKG_C7_RESIDENCY 0x000003fa
#define MSR_CORE_C3_RESIDENCY 0x000003fc
#define MSR_CORE_C6_RESIDENCY 0x000003fd
@@ -203,6 +204,7 @@
#define MSR_PKG_BOTH_CORE_GFXE_C0_RES 0x0000065B
#define MSR_CORE_C1_RES 0x00000660
+#define MSR_MODULE_C6_RES_MS 0x00000664
#define MSR_CC6_DEMOTION_POLICY_CONFIG 0x00000668
#define MSR_MC6_DEMOTION_POLICY_CONFIG 0x00000669
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index d56f2b75dc58..19802be6dc02 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -167,6 +167,7 @@ struct core_data {
unsigned long long c3;
unsigned long long c6;
unsigned long long c7;
+ unsigned long long mc6_us; /* duplicate as per-core for now, even though per module */
unsigned int core_temp_c;
unsigned int core_id;
unsigned long long counter[MAX_ADDED_COUNTERS];
@@ -375,6 +376,7 @@ struct msr_counter bic[] = {
{ 0x0, "RAM_J" },
{ 0x0, "Core" },
{ 0x0, "CPU" },
+ { 0x0, "Mod%c6" },
};
#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
@@ -412,6 +414,7 @@ struct msr_counter bic[] = {
#define BIC_RAM_J (1ULL << 31)
#define BIC_Core (1ULL << 32)
#define BIC_CPU (1ULL << 33)
+#define BIC_Mod_c6 (1ULL << 34)
unsigned long long bic_enabled = 0xFFFFFFFFFFFFFFFFULL;
unsigned long long bic_present;
@@ -504,6 +507,8 @@ void print_header(void)
if (DO_BIC(BIC_CPU_c7))
outp += sprintf(outp, "\tCPU%%c7");
+ if (DO_BIC(BIC_Mod_c6))
+ outp += sprintf(outp, "\tMod%%c6");
if (DO_BIC(BIC_CoreTmp))
outp += sprintf(outp, "\tCoreTmp");
@@ -629,6 +634,7 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n",
i, mp->msr_num, c->counter[i]);
}
+ outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us);
}
if (p) {
@@ -774,6 +780,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_CPU_c7))
outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc);
+ /* Mod%c6 */
+ if (DO_BIC(BIC_Mod_c6))
+ outp += sprintf(outp, "\t%.2f", 100.0 * c->mc6_us / t->tsc);
+
if (DO_BIC(BIC_CoreTmp))
outp += sprintf(outp, "\t%d", c->core_temp_c);
@@ -988,6 +998,7 @@ delta_core(struct core_data *new, struct core_data *old)
old->c6 = new->c6 - old->c6;
old->c7 = new->c7 - old->c7;
old->core_temp_c = new->core_temp_c;
+ old->mc6_us = new->mc6_us - old->mc6_us;
for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW)
@@ -1109,6 +1120,7 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
c->c3 = 0;
c->c6 = 0;
c->c7 = 0;
+ c->mc6_us = 0;
c->core_temp_c = 0;
p->pkg_wtd_core_c0 = 0;
@@ -1173,6 +1185,7 @@ int sum_counters(struct thread_data *t, struct core_data *c,
average.cores.c3 += c->c3;
average.cores.c6 += c->c6;
average.cores.c7 += c->c7;
+ average.cores.mc6_us += c->mc6_us;
average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c);
@@ -1246,6 +1259,7 @@ void compute_average(struct thread_data *t, struct core_data *c,
average.cores.c3 /= topo.num_cores;
average.cores.c6 /= topo.num_cores;
average.cores.c7 /= topo.num_cores;
+ average.cores.mc6_us /= topo.num_cores;
if (do_skl_residency) {
average.packages.pkg_wtd_core_c0 /= topo.num_packages;
@@ -1376,8 +1390,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return -5;
t->smi_count = msr & 0xFFFFFFFF;
}
-
- if (use_c1_residency_msr) {
+ if (DO_BIC(BIC_CPU_c1) && use_c1_residency_msr) {
if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1))
return -6;
}
@@ -1409,6 +1422,10 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
return -8;
+ if (DO_BIC(BIC_Mod_c6))
+ if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us))
+ return -8;
+
if (DO_BIC(BIC_CoreTmp)) {
if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
return -9;
@@ -1437,9 +1454,16 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (do_pc3)
if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
return -9;
- if (do_pc6)
- if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
- return -10;
+ if (do_pc6) {
+ if (do_slm_cstates) {
+ if (get_msr(cpu, MSR_ATOM_PKG_C6_RESIDENCY, &p->pc6))
+ return -10;
+ } else {
+ if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
+ return -10;
+ }
+ }
+
if (do_pc2)
if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2))
return -11;
@@ -1533,7 +1557,7 @@ char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2",
int nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
int snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
int hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
-int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
+int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7};
int amt_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
int bxt_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
@@ -3336,8 +3360,6 @@ int has_skl_msrs(unsigned int family, unsigned int model)
return 0;
}
-
-
int is_slm(unsigned int family, unsigned int model)
{
if (!genuine_intel)
@@ -3731,6 +3753,12 @@ void process_cpuid()
do_pc3 = (pkg_cstate_limit >= PCL__3);
do_pc6 = (pkg_cstate_limit >= PCL__6);
do_pc7 = do_snb_cstates && (pkg_cstate_limit >= PCL__7);
+ if (has_slv_msrs(family, model)) {
+ do_pc2 = do_pc3 = do_pc7 = 0;
+ do_pc6 = 1;
+ BIC_PRESENT(BIC_Mod_c6);
+ use_c1_residency_msr = 1;
+ }
do_c8_c9_c10 = has_hsw_msrs(family, model);
do_irtl_hsw = has_hsw_msrs(family, model);
do_skl_residency = has_skl_msrs(family, model);
@@ -4112,7 +4140,7 @@ int get_and_dump_counters(void)
}
void print_version() {
- fprintf(outf, "turbostat version 4.17 1 Jan 2017"
+ fprintf(outf, "turbostat version 4.17 10 Jan 2017"
" - Len Brown <[email protected]>\n");
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
define MSR_PKG_CST_CONFIG_CONTROL (0xE2),
which is the string used by Intel Documentation.
We use this MSR in intel_idle and turbostat by a previous name,
to be updated in the next patch.
Cc: [email protected]
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/include/asm/msr-index.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 710273c617b8..975f23eefe14 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -47,6 +47,7 @@
#define MSR_PLATFORM_INFO 0x000000ce
#define MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2
+#define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
#define NHM_C3_AUTO_DEMOTE (1UL << 25)
#define NHM_C1_AUTO_DEMOTE (1UL << 26)
#define ATM_LNC_C6_AUTO_DEMOTE (1UL << 25)
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
It is handy to know the list of column header names,
so that they can be used with --add and --skip
The new --list option shows them:
sudo ./turbostat --list --hide sysfs
,Core,CPU,Avg_MHz,Busy%,Bzy_MHz,TSC_MHz,IRQ,SMI,CPU%c1,CPU%c3,CPU%c6,CPU%c7,CoreTmp,PkgTmp,GFX%rc6,GFXMHz,PkgWatt,CorWatt,GFXWatt
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 118 +++++++++++++++++++---------------
1 file changed, 66 insertions(+), 52 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 48b540a2fe81..7b02fbb65893 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -52,6 +52,7 @@ unsigned int debug;
unsigned int quiet;
unsigned int rapl_joules;
unsigned int summary_only;
+unsigned int list_header_only;
unsigned int dump_only;
unsigned int do_snb_cstates;
unsigned int do_knl_cstates;
@@ -469,133 +470,133 @@ unsigned long long bic_lookup(char *name_list)
return retval;
}
-void print_header(void)
+void print_header(char *delim)
{
struct msr_counter *mp;
if (DO_BIC(BIC_Package))
- outp += sprintf(outp, "\tPackage");
+ outp += sprintf(outp, "%sPackage", delim);
if (DO_BIC(BIC_Core))
- outp += sprintf(outp, "\tCore");
+ outp += sprintf(outp, "%sCore", delim);
if (DO_BIC(BIC_CPU))
- outp += sprintf(outp, "\tCPU");
+ outp += sprintf(outp, "%sCPU", delim);
if (DO_BIC(BIC_Avg_MHz))
- outp += sprintf(outp, "\tAvg_MHz");
+ outp += sprintf(outp, "%sAvg_MHz", delim);
if (DO_BIC(BIC_Busy))
- outp += sprintf(outp, "\tBusy%%");
+ outp += sprintf(outp, "%sBusy%%", delim);
if (DO_BIC(BIC_Bzy_MHz))
- outp += sprintf(outp, "\tBzy_MHz");
+ outp += sprintf(outp, "%sBzy_MHz", delim);
if (DO_BIC(BIC_TSC_MHz))
- outp += sprintf(outp, "\tTSC_MHz");
+ outp += sprintf(outp, "%sTSC_MHz", delim);
if (DO_BIC(BIC_IRQ))
- outp += sprintf(outp, "\tIRQ");
+ outp += sprintf(outp, "%sIRQ", delim);
if (DO_BIC(BIC_SMI))
- outp += sprintf(outp, "\tSMI");
+ outp += sprintf(outp, "%sSMI", delim);
for (mp = sys.tp; mp; mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 64)
- outp += sprintf(outp, "\t%18.18s", mp->name);
+ outp += sprintf(outp, "%s%18.18s", delim, mp->name);
else
- outp += sprintf(outp, "\t%10.10s", mp->name);
+ outp += sprintf(outp, "%s%10.10s", delim, mp->name);
} else {
- outp += sprintf(outp, "\t%s", mp->name);
+ outp += sprintf(outp, "%s%s", delim, mp->name);
}
}
if (DO_BIC(BIC_CPU_c1))
- outp += sprintf(outp, "\tCPU%%c1");
+ outp += sprintf(outp, "%sCPU%%c1", delim);
if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates)
- outp += sprintf(outp, "\tCPU%%c3");
+ outp += sprintf(outp, "%sCPU%%c3", delim);
if (DO_BIC(BIC_CPU_c6))
- outp += sprintf(outp, "\tCPU%%c6");
+ outp += sprintf(outp, "%sCPU%%c6", delim);
if (DO_BIC(BIC_CPU_c7))
- outp += sprintf(outp, "\tCPU%%c7");
+ outp += sprintf(outp, "%sCPU%%c7", delim);
if (DO_BIC(BIC_Mod_c6))
- outp += sprintf(outp, "\tMod%%c6");
+ outp += sprintf(outp, "%sMod%%c6", delim);
if (DO_BIC(BIC_CoreTmp))
- outp += sprintf(outp, "\tCoreTmp");
+ outp += sprintf(outp, "%sCoreTmp", delim);
for (mp = sys.cp; mp; mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 64)
- outp += sprintf(outp, "\t%18.18s", mp->name);
+ outp += sprintf(outp, "%s%18.18s", delim, mp->name);
else
- outp += sprintf(outp, "\t%10.10s", mp->name);
+ outp += sprintf(outp, "%s%10.10s", delim, mp->name);
} else {
- outp += sprintf(outp, "\t%s", mp->name);
+ outp += sprintf(outp, "%s%s", delim, mp->name);
}
}
if (DO_BIC(BIC_PkgTmp))
- outp += sprintf(outp, "\tPkgTmp");
+ outp += sprintf(outp, "%sPkgTmp", delim);
if (DO_BIC(BIC_GFX_rc6))
- outp += sprintf(outp, "\tGFX%%rc6");
+ outp += sprintf(outp, "%sGFX%%rc6", delim);
if (DO_BIC(BIC_GFXMHz))
- outp += sprintf(outp, "\tGFXMHz");
+ outp += sprintf(outp, "%sGFXMHz", delim);
if (do_skl_residency) {
- outp += sprintf(outp, "\tTotl%%C0");
- outp += sprintf(outp, "\tAny%%C0");
- outp += sprintf(outp, "\tGFX%%C0");
- outp += sprintf(outp, "\tCPUGFX%%");
+ outp += sprintf(outp, "%sTotl%%C0", delim);
+ outp += sprintf(outp, "%sAny%%C0", delim);
+ outp += sprintf(outp, "%sGFX%%C0", delim);
+ outp += sprintf(outp, "%sCPUGFX%%", delim);
}
if (DO_BIC(BIC_Pkgpc2))
- outp += sprintf(outp, "\tPkg%%pc2");
+ outp += sprintf(outp, "%sPkg%%pc2", delim);
if (DO_BIC(BIC_Pkgpc3))
- outp += sprintf(outp, "\tPkg%%pc3");
+ outp += sprintf(outp, "%sPkg%%pc3", delim);
if (DO_BIC(BIC_Pkgpc6))
- outp += sprintf(outp, "\tPkg%%pc6");
+ outp += sprintf(outp, "%sPkg%%pc6", delim);
if (DO_BIC(BIC_Pkgpc7))
- outp += sprintf(outp, "\tPkg%%pc7");
+ outp += sprintf(outp, "%sPkg%%pc7", delim);
if (DO_BIC(BIC_Pkgpc8))
- outp += sprintf(outp, "\tPkg%%pc8");
+ outp += sprintf(outp, "%sPkg%%pc8", delim);
if (DO_BIC(BIC_Pkgpc9))
- outp += sprintf(outp, "\tPkg%%pc9");
+ outp += sprintf(outp, "%sPkg%%pc9", delim);
if (DO_BIC(BIC_Pkgpc10))
- outp += sprintf(outp, "\tPk%%pc10");
+ outp += sprintf(outp, "%sPk%%pc10", delim);
if (do_rapl && !rapl_joules) {
if (DO_BIC(BIC_PkgWatt))
- outp += sprintf(outp, "\tPkgWatt");
+ outp += sprintf(outp, "%sPkgWatt", delim);
if (DO_BIC(BIC_CorWatt))
- outp += sprintf(outp, "\tCorWatt");
+ outp += sprintf(outp, "%sCorWatt", delim);
if (DO_BIC(BIC_GFXWatt))
- outp += sprintf(outp, "\tGFXWatt");
+ outp += sprintf(outp, "%sGFXWatt", delim);
if (DO_BIC(BIC_RAMWatt))
- outp += sprintf(outp, "\tRAMWatt");
+ outp += sprintf(outp, "%sRAMWatt", delim);
if (DO_BIC(BIC_PKG__))
- outp += sprintf(outp, "\tPKG_%%");
+ outp += sprintf(outp, "%sPKG_%%", delim);
if (DO_BIC(BIC_RAM__))
- outp += sprintf(outp, "\tRAM_%%");
+ outp += sprintf(outp, "%sRAM_%%", delim);
} else if (do_rapl && rapl_joules) {
if (DO_BIC(BIC_Pkg_J))
- outp += sprintf(outp, "\tPkg_J");
+ outp += sprintf(outp, "%sPkg_J", delim);
if (DO_BIC(BIC_Cor_J))
- outp += sprintf(outp, "\tCor_J");
+ outp += sprintf(outp, "%sCor_J", delim);
if (DO_BIC(BIC_GFX_J))
- outp += sprintf(outp, "\tGFX_J");
+ outp += sprintf(outp, "%sGFX_J", delim);
if (DO_BIC(BIC_RAM_J))
- outp += sprintf(outp, "\tRAM_J");
+ outp += sprintf(outp, "%sRAM_J", delim);
if (DO_BIC(BIC_PKG__))
- outp += sprintf(outp, "\tPKG_%%");
+ outp += sprintf(outp, "%sPKG_%%", delim);
if (DO_BIC(BIC_RAM__))
- outp += sprintf(outp, "\tRAM_%%");
+ outp += sprintf(outp, "%sRAM_%%", delim);
}
for (mp = sys.pp; mp; mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 64)
- outp += sprintf(outp, "\t%18.18s", mp->name);
+ outp += sprintf(outp, "%s%18.18s", delim, mp->name);
else
- outp += sprintf(outp, "\t%10.10s", mp->name);
+ outp += sprintf(outp, "%s%10.10s", delim, mp->name);
} else {
- outp += sprintf(outp, "\t%s", mp->name);
+ outp += sprintf(outp, "%s%s", delim, mp->name);
}
}
@@ -933,7 +934,7 @@ void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_
static int printed;
if (!printed || !summary_only)
- print_header();
+ print_header("\t");
if (topo.num_cpus > 1)
format_counters(&average.threads, &average.cores,
@@ -4107,6 +4108,7 @@ void help()
"--quiet skip decoding system configuration header\n"
"--interval sec Override default 5-second measurement interval\n"
"--help print this help message\n"
+ "--list list column headers only\n"
"--out file create or truncate \"file\" for all output\n"
"--version print version information\n"
"\n"
@@ -4814,6 +4816,7 @@ void cmdline(int argc, char **argv)
{"help", no_argument, 0, 'h'},
{"hide", required_argument, 0, 'H'}, // meh, -h taken by --help
{"Joules", no_argument, 0, 'J'},
+ {"list", no_argument, 0, 'l'},
{"out", required_argument, 0, 'o'},
{"Package", no_argument, 0, 'p'},
{"processor", no_argument, 0, 'p'},
@@ -4866,6 +4869,10 @@ void cmdline(int argc, char **argv)
case 'J':
rapl_joules++;
break;
+ case 'l':
+ list_header_only++;
+ quiet++;
+ break;
case 'o':
outf = fopen_or_die(optarg, "w");
break;
@@ -4912,6 +4919,13 @@ int main(int argc, char **argv)
if (dump_only)
return get_and_dump_counters();
+ /* list header and exit */
+ if (list_header_only) {
+ print_header(",");
+ flush_output_stdout();
+ return 0;
+ }
+
/*
* if any params left, it must be a command to fork
*/
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Add the "--show" and "--hide" cmdline parameters.
By default, turbostat shows all columns.
turbostat --hide counter_list
will continue showing all columns, except for those listed.
turbostat --show counter_list
will show _only_ the listed columns
These features work for built-in counters, and have no effect
on columns added with the --add parameter.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.8 | 4 +
tools/power/x86/turbostat/turbostat.c | 463 +++++++++++++++++++++++++---------
2 files changed, 347 insertions(+), 120 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 03cb639b292e..e8fb1e02d121 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -47,6 +47,10 @@ name as necessary to disambiguate it from others is necessary. Note that option
default: delta
.fi
.PP
+\fB--hide column\fP do not show the specified columns. May be invoked multiple times, or with a comma-separated list of column names.
+.PP
+\fB--show column\fP show only the specified columns. May be invoked multiple times, or with a comma-separated list of column names.
+.PP
\fB--Dump\fP displays the raw counter values.
.PP
\fB--debug\fP displays additional system configuration information. Invoking this parameter
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index c7fadf0faa4b..fff280b50af0 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -52,7 +52,6 @@ unsigned int debug;
unsigned int rapl_joules;
unsigned int summary_only;
unsigned int dump_only;
-unsigned int do_nhm_cstates;
unsigned int do_snb_cstates;
unsigned int do_knl_cstates;
unsigned int do_pc2;
@@ -72,24 +71,17 @@ unsigned int genuine_intel;
unsigned int has_invariant_tsc;
unsigned int do_nhm_platform_info;
unsigned int aperf_mperf_multiplier = 1;
-int do_irq = 1;
-int do_smi;
double bclk;
double base_hz;
unsigned int has_base_hz;
double tsc_tweak = 1.0;
-unsigned int show_pkg;
-unsigned int show_core;
-unsigned int show_cpu;
unsigned int show_pkg_only;
unsigned int show_core_only;
char *output_buffer, *outp;
unsigned int do_rapl;
unsigned int do_dts;
unsigned int do_ptm;
-unsigned int do_gfx_rc6_ms;
unsigned long long gfx_cur_rc6_ms;
-unsigned int do_gfx_mhz;
unsigned int gfx_cur_mhz;
unsigned int tcc_activation_temp;
unsigned int tcc_activation_temp_override;
@@ -226,6 +218,9 @@ struct msr_counter {
enum counter_type type;
enum counter_format format;
struct msr_counter *next;
+ unsigned int flags;
+#define FLAGS_HIDE (1 << 0)
+#define FLAGS_SHOW (1 << 1)
};
struct sys_counters {
@@ -341,39 +336,153 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
}
/*
- * Example Format w/ field column widths:
- *
- * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz IRQ SMI Busy% CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 ThreadC CoreTmp CoreCnt PkgTmp GFXMHz Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt PkgCnt
- * 12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678
+ * Each string in this array is compared in --show and --hide cmdline.
+ * Thus, strings that are proper sub-sets must follow their more specific peers.
*/
+struct msr_counter bic[] = {
+ { 0x0, "Package" },
+ { 0x0, "Avg_MHz" },
+ { 0x0, "Bzy_MHz" },
+ { 0x0, "TSC_MHz" },
+ { 0x0, "IRQ" },
+ { 0x0, "SMI", 32, 0, FORMAT_DELTA, NULL},
+ { 0x0, "Busy%" },
+ { 0x0, "CPU%c1" },
+ { 0x0, "CPU%c3" },
+ { 0x0, "CPU%c6" },
+ { 0x0, "CPU%c7" },
+ { 0x0, "ThreadC" },
+ { 0x0, "CoreTmp" },
+ { 0x0, "CoreCnt" },
+ { 0x0, "PkgTmp" },
+ { 0x0, "GFX%rc6" },
+ { 0x0, "GFXMHz" },
+ { 0x0, "Pkg%pc2" },
+ { 0x0, "Pkg%pc3" },
+ { 0x0, "Pkg%pc6" },
+ { 0x0, "Pkg%pc7" },
+ { 0x0, "PkgWatt" },
+ { 0x0, "CorWatt" },
+ { 0x0, "GFXWatt" },
+ { 0x0, "PkgCnt" },
+ { 0x0, "RAMWatt" },
+ { 0x0, "PKG_%" },
+ { 0x0, "RAM_%" },
+ { 0x0, "Pkg_J" },
+ { 0x0, "Cor_J" },
+ { 0x0, "GFX_J" },
+ { 0x0, "RAM_J" },
+ { 0x0, "Core" },
+ { 0x0, "CPU" },
+};
+
+#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
+#define BIC_Package (1ULL << 0)
+#define BIC_Avg_MHz (1ULL << 1)
+#define BIC_Bzy_MHz (1ULL << 2)
+#define BIC_TSC_MHz (1ULL << 3)
+#define BIC_IRQ (1ULL << 4)
+#define BIC_SMI (1ULL << 5)
+#define BIC_Busy (1ULL << 6)
+#define BIC_CPU_c1 (1ULL << 7)
+#define BIC_CPU_c3 (1ULL << 8)
+#define BIC_CPU_c6 (1ULL << 9)
+#define BIC_CPU_c7 (1ULL << 10)
+#define BIC_ThreadC (1ULL << 11)
+#define BIC_CoreTmp (1ULL << 12)
+#define BIC_CoreCnt (1ULL << 13)
+#define BIC_PkgTmp (1ULL << 14)
+#define BIC_GFX_rc6 (1ULL << 15)
+#define BIC_GFXMHz (1ULL << 16)
+#define BIC_Pkgpc2 (1ULL << 17)
+#define BIC_Pkgpc3 (1ULL << 18)
+#define BIC_Pkgpc6 (1ULL << 19)
+#define BIC_Pkgpc7 (1ULL << 20)
+#define BIC_PkgWatt (1ULL << 21)
+#define BIC_CorWatt (1ULL << 22)
+#define BIC_GFXWatt (1ULL << 23)
+#define BIC_PkgCnt (1ULL << 24)
+#define BIC_RAMWatt (1ULL << 27)
+#define BIC_PKG__ (1ULL << 28)
+#define BIC_RAM__ (1ULL << 29)
+#define BIC_Pkg_J (1ULL << 30)
+#define BIC_Cor_J (1ULL << 31)
+#define BIC_GFX_J (1ULL << 30)
+#define BIC_RAM_J (1ULL << 31)
+#define BIC_Core (1ULL << 32)
+#define BIC_CPU (1ULL << 33)
+
+unsigned long long bic_enabled = 0xFFFFFFFFFFFFFFFFULL;
+unsigned long long bic_present;
+
+#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
+#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
+
+/*
+ * bic_lookup
+ * for all the strings in comma separate name_list,
+ * set the approprate bit in return value.
+ */
+unsigned long long bic_lookup(char *name_list)
+{
+ int i;
+ unsigned long long retval = 0;
+
+ while (name_list) {
+ char *comma;
+
+ comma = strchr(name_list, ',');
+
+ if (comma)
+ *comma = '\0';
+
+ for (i = 0; i < MAX_BIC; ++i) {
+ if (!strcmp(name_list, bic[i].name)) {
+ retval |= (1ULL << i);
+ break;
+ }
+ }
+ if (i == MAX_BIC) {
+ fprintf(stderr, "Invalid counter name: %s\n", name_list);
+ exit(-1);
+ }
+
+ name_list = comma;
+ if (name_list)
+ name_list++;
+
+ }
+ return retval;
+}
void print_header(void)
{
struct msr_counter *mp;
- if (show_pkg)
+ if (DO_BIC(BIC_Package))
outp += sprintf(outp, "\tPackage");
- if (show_core)
+ if (DO_BIC(BIC_Core))
outp += sprintf(outp, "\tCore");
- if (show_cpu)
+ if (DO_BIC(BIC_CPU))
outp += sprintf(outp, "\tCPU");
- if (has_aperf)
+ if (DO_BIC(BIC_Avg_MHz))
outp += sprintf(outp, "\tAvg_MHz");
- if (has_aperf)
+ if (DO_BIC(BIC_Busy))
outp += sprintf(outp, "\tBusy%%");
- if (has_aperf)
+ if (DO_BIC(BIC_Bzy_MHz))
outp += sprintf(outp, "\tBzy_MHz");
- outp += sprintf(outp, "\tTSC_MHz");
+ if (DO_BIC(BIC_TSC_MHz))
+ outp += sprintf(outp, "\tTSC_MHz");
if (!debug)
goto done;
- if (do_irq)
+ if (DO_BIC(BIC_IRQ))
outp += sprintf(outp, "\tIRQ");
- if (do_smi)
+ if (DO_BIC(BIC_SMI))
outp += sprintf(outp, "\tSMI");
- if (do_nhm_cstates)
+ if (DO_BIC(BIC_CPU_c1))
outp += sprintf(outp, "\tCPU%%c1");
for (mp = sys.tp; mp; mp = mp->next) {
@@ -387,15 +496,15 @@ void print_header(void)
}
}
- if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates)
+ if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates)
outp += sprintf(outp, "\tCPU%%c3");
- if (do_nhm_cstates)
+ if (DO_BIC(BIC_CPU_c6))
outp += sprintf(outp, "\tCPU%%c6");
- if (do_snb_cstates)
+ if (DO_BIC(BIC_CPU_c7))
outp += sprintf(outp, "\tCPU%%c7");
- if (do_dts)
+ if (DO_BIC(BIC_CoreTmp))
outp += sprintf(outp, "\tCoreTmp");
for (mp = sys.cp; mp; mp = mp->next) {
@@ -409,13 +518,13 @@ void print_header(void)
}
}
- if (do_ptm)
+ if (DO_BIC(BIC_PkgTmp))
outp += sprintf(outp, "\tPkgTmp");
- if (do_gfx_rc6_ms)
+ if (DO_BIC(BIC_GFX_rc6))
outp += sprintf(outp, "\tGFX%%rc6");
- if (do_gfx_mhz)
+ if (DO_BIC(BIC_GFXMHz))
outp += sprintf(outp, "\tGFXMHz");
if (do_skl_residency) {
@@ -440,30 +549,30 @@ void print_header(void)
}
if (do_rapl && !rapl_joules) {
- if (do_rapl & RAPL_PKG)
+ if (DO_BIC(BIC_PkgWatt))
outp += sprintf(outp, "\tPkgWatt");
- if (do_rapl & RAPL_CORES_ENERGY_STATUS)
+ if (DO_BIC(BIC_CorWatt))
outp += sprintf(outp, "\tCorWatt");
- if (do_rapl & RAPL_GFX)
+ if (DO_BIC(BIC_GFXWatt))
outp += sprintf(outp, "\tGFXWatt");
- if (do_rapl & RAPL_DRAM)
+ if (DO_BIC(BIC_RAMWatt))
outp += sprintf(outp, "\tRAMWatt");
- if (do_rapl & RAPL_PKG_PERF_STATUS)
+ if (DO_BIC(BIC_PKG__))
outp += sprintf(outp, "\tPKG_%%");
- if (do_rapl & RAPL_DRAM_PERF_STATUS)
+ if (DO_BIC(BIC_RAM__))
outp += sprintf(outp, "\tRAM_%%");
} else if (do_rapl && rapl_joules) {
- if (do_rapl & RAPL_PKG)
+ if (DO_BIC(BIC_Pkg_J))
outp += sprintf(outp, "\tPkg_J");
- if (do_rapl & RAPL_CORES_ENERGY_STATUS)
+ if (DO_BIC(BIC_Cor_J))
outp += sprintf(outp, "\tCor_J");
- if (do_rapl & RAPL_GFX)
+ if (DO_BIC(BIC_GFX_J))
outp += sprintf(outp, "\tGFX_J");
- if (do_rapl & RAPL_DRAM)
+ if (DO_BIC(BIC_RAM_J))
outp += sprintf(outp, "\tRAM_J");
- if (do_rapl & RAPL_PKG_PERF_STATUS)
+ if (DO_BIC(BIC_PKG__))
outp += sprintf(outp, "\tPKG_%%");
- if (do_rapl & RAPL_DRAM_PERF_STATUS)
+ if (DO_BIC(BIC_RAM__))
outp += sprintf(outp, "\tRAM_%%");
}
for (mp = sys.pp; mp; mp = mp->next) {
@@ -497,9 +606,9 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "mperf: %016llX\n", t->mperf);
outp += sprintf(outp, "c1: %016llX\n", t->c1);
- if (do_irq)
+ if (DO_BIC(BIC_IRQ))
outp += sprintf(outp, "IRQ: %08X\n", t->irq_count);
- if (do_smi)
+ if (DO_BIC(BIC_SMI))
outp += sprintf(outp, "SMI: %08X\n", t->smi_count);
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
@@ -583,40 +692,37 @@ int format_counters(struct thread_data *t, struct core_data *c,
/* topo columns, print blanks on 1st (average) line */
if (t == &average.threads) {
- if (show_pkg)
+ if (DO_BIC(BIC_Package))
outp += sprintf(outp, "\t-");
- if (show_core)
+ if (DO_BIC(BIC_Core))
outp += sprintf(outp, "\t-");
- if (show_cpu)
+ if (DO_BIC(BIC_CPU))
outp += sprintf(outp, "\t-");
} else {
- if (show_pkg) {
+ if (DO_BIC(BIC_Package)) {
if (p)
outp += sprintf(outp, "\t%d", p->package_id);
else
outp += sprintf(outp, "\t-");
}
- if (show_core) {
+ if (DO_BIC(BIC_Core)) {
if (c)
outp += sprintf(outp, "\t%d", c->core_id);
else
outp += sprintf(outp, "\t-");
}
- if (show_cpu)
+ if (DO_BIC(BIC_CPU))
outp += sprintf(outp, "\t%d", t->cpu_id);
}
- /* Avg_MHz */
- if (has_aperf)
+ if (DO_BIC(BIC_Avg_MHz))
outp += sprintf(outp, "\t%.0f",
1.0 / units * t->aperf / interval_float);
- /* Busy% */
- if (has_aperf)
+ if (DO_BIC(BIC_Busy))
outp += sprintf(outp, "\t%.2f", 100.0 * t->mperf/t->tsc/tsc_tweak);
- /* Bzy_MHz */
- if (has_aperf) {
+ if (DO_BIC(BIC_Bzy_MHz)) {
if (has_base_hz)
outp += sprintf(outp, "\t%.0f", base_hz / units * t->aperf / t->mperf);
else
@@ -624,22 +730,22 @@ int format_counters(struct thread_data *t, struct core_data *c,
1.0 * t->tsc / units * t->aperf / t->mperf / interval_float);
}
- /* TSC_MHz */
- outp += sprintf(outp, "\t%.0f", 1.0 * t->tsc/units/interval_float);
+ if (DO_BIC(BIC_TSC_MHz))
+ outp += sprintf(outp, "\t%.0f", 1.0 * t->tsc/units/interval_float);
if (!debug)
goto done;
/* IRQ */
- if (do_irq)
+ if (DO_BIC(BIC_IRQ))
outp += sprintf(outp, "\t%d", t->irq_count);
/* SMI */
- if (do_smi)
+ if (DO_BIC(BIC_SMI))
outp += sprintf(outp, "\t%d", t->smi_count);
/* C1 */
- if (do_nhm_cstates)
+ if (DO_BIC(BIC_CPU_c1))
outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/t->tsc);
/* Added counters */
@@ -660,15 +766,14 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
goto done;
- if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates)
+ if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates)
outp += sprintf(outp, "\t%.2f", 100.0 * c->c3/t->tsc);
- if (do_nhm_cstates)
+ if (DO_BIC(BIC_CPU_c6))
outp += sprintf(outp, "\t%.2f", 100.0 * c->c6/t->tsc);
- if (do_snb_cstates)
+ if (DO_BIC(BIC_CPU_c7))
outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc);
-
- if (do_dts)
+ if (DO_BIC(BIC_CoreTmp))
outp += sprintf(outp, "\t%d", c->core_temp_c);
for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
@@ -689,11 +794,11 @@ int format_counters(struct thread_data *t, struct core_data *c,
goto done;
/* PkgTmp */
- if (do_ptm)
+ if (DO_BIC(BIC_PkgTmp))
outp += sprintf(outp, "\t%d", p->pkg_temp_c);
/* GFXrc6 */
- if (do_gfx_rc6_ms) {
+ if (DO_BIC(BIC_GFX_rc6)) {
if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */
outp += sprintf(outp, "\t**.**");
} else {
@@ -703,7 +808,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
}
/* GFXMHz */
- if (do_gfx_mhz)
+ if (DO_BIC(BIC_GFXMHz))
outp += sprintf(outp, "\t%d", p->gfx_mhz);
/* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
@@ -737,37 +842,27 @@ int format_counters(struct thread_data *t, struct core_data *c,
else
fmt8 = "%6.0f**";
- if (do_rapl && !rapl_joules) {
- if (do_rapl & RAPL_PKG)
- outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units / interval_float);
- if (do_rapl & RAPL_CORES_ENERGY_STATUS)
- outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units / interval_float);
- if (do_rapl & RAPL_GFX)
- outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float);
- if (do_rapl & RAPL_DRAM)
- outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units / interval_float);
- if (do_rapl & RAPL_PKG_PERF_STATUS)
- outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
- if (do_rapl & RAPL_DRAM_PERF_STATUS)
- outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
- } else if (do_rapl && rapl_joules) {
- if (do_rapl & RAPL_PKG)
- outp += sprintf(outp, fmt8,
- p->energy_pkg * rapl_energy_units);
- if (do_rapl & RAPL_CORES)
- outp += sprintf(outp, fmt8,
- p->energy_cores * rapl_energy_units);
- if (do_rapl & RAPL_GFX)
- outp += sprintf(outp, fmt8,
- p->energy_gfx * rapl_energy_units);
- if (do_rapl & RAPL_DRAM)
- outp += sprintf(outp, fmt8,
- p->energy_dram * rapl_dram_energy_units);
- if (do_rapl & RAPL_PKG_PERF_STATUS)
- outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
- if (do_rapl & RAPL_DRAM_PERF_STATUS)
- outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
- }
+ if (DO_BIC(BIC_PkgWatt))
+ outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units / interval_float);
+ if (DO_BIC(BIC_CorWatt))
+ outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units / interval_float);
+ if (DO_BIC(BIC_GFXWatt))
+ outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float);
+ if (DO_BIC(BIC_RAMWatt))
+ outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units / interval_float);
+ if (DO_BIC(BIC_Pkg_J))
+ outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units);
+ if (DO_BIC(BIC_Cor_J))
+ outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units);
+ if (DO_BIC(BIC_GFX_J))
+ outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units);
+ if (DO_BIC(BIC_RAM_J))
+ outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units);
+ if (DO_BIC(BIC_PKG__))
+ outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
+ if (DO_BIC(BIC_RAM__))
+ outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
+
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
@@ -921,7 +1016,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
old->c1 = new->c1 - old->c1;
- if (has_aperf) {
+ if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) {
if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
old->aperf = new->aperf - old->aperf;
old->mperf = new->mperf - old->mperf;
@@ -957,10 +1052,10 @@ delta_thread(struct thread_data *new, struct thread_data *old,
old->mperf = 1; /* divide by 0 protection */
}
- if (do_irq)
+ if (DO_BIC(BIC_IRQ))
old->irq_count = new->irq_count - old->irq_count;
- if (do_smi)
+ if (DO_BIC(BIC_SMI))
old->smi_count = new->smi_count - old->smi_count;
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
@@ -1217,7 +1312,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
retry:
t->tsc = rdtsc(); /* we are running on local CPU of interest */
- if (has_aperf) {
+ if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) {
unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
/*
@@ -1273,9 +1368,9 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
t->mperf = t->mperf * aperf_mperf_multiplier;
}
- if (do_irq)
+ if (DO_BIC(BIC_IRQ))
t->irq_count = irqs_per_cpu[cpu];
- if (do_smi) {
+ if (DO_BIC(BIC_SMI)) {
if (get_msr(cpu, MSR_SMI_COUNT, &msr))
return -5;
t->smi_count = msr & 0xFFFFFFFF;
@@ -1296,12 +1391,12 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
return 0;
- if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates) {
+ if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates) {
if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
return -6;
}
- if (do_nhm_cstates && !do_knl_cstates) {
+ if (DO_BIC(BIC_CPU_c6) && !do_knl_cstates) {
if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
return -7;
} else if (do_knl_cstates) {
@@ -1309,11 +1404,11 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return -7;
}
- if (do_snb_cstates)
+ if (DO_BIC(BIC_CPU_c7))
if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
return -8;
- if (do_dts) {
+ if (DO_BIC(BIC_CoreTmp)) {
if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
return -9;
c->core_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
@@ -1388,16 +1483,16 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return -16;
p->rapl_dram_perf_status = msr & 0xFFFFFFFF;
}
- if (do_ptm) {
+ if (DO_BIC(BIC_PkgTmp)) {
if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
return -17;
p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
}
- if (do_gfx_rc6_ms)
+ if (DO_BIC(BIC_GFX_rc6))
p->gfx_rc6_ms = gfx_cur_rc6_ms;
- if (do_gfx_mhz)
+ if (DO_BIC(BIC_GFXMHz))
p->gfx_mhz = gfx_cur_mhz;
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
@@ -2155,10 +2250,10 @@ int snapshot_proc_sysfs_files(void)
if (snapshot_proc_interrupts())
return 1;
- if (do_gfx_rc6_ms)
+ if (DO_BIC(BIC_GFX_rc6))
snapshot_gfx_rc6_ms();
- if (do_gfx_mhz)
+ if (DO_BIC(BIC_GFXMHz))
snapshot_gfx_mhz();
return 0;
@@ -2794,15 +2889,39 @@ void rapl_probe(unsigned int family, unsigned int model)
case INTEL_FAM6_BROADWELL_CORE: /* BDW */
case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
+ if (rapl_joules) {
+ BIC_PRESENT(BIC_Pkg_J);
+ BIC_PRESENT(BIC_Cor_J);
+ BIC_PRESENT(BIC_GFX_J);
+ } else {
+ BIC_PRESENT(BIC_PkgWatt);
+ BIC_PRESENT(BIC_CorWatt);
+ BIC_PRESENT(BIC_GFXWatt);
+ }
break;
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO;
+ if (rapl_joules)
+ BIC_PRESENT(BIC_Pkg_J);
+ else
+ BIC_PRESENT(BIC_PkgWatt);
break;
case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */
case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */
case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */
do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
+ BIC_PRESENT(BIC_PKG__);
+ BIC_PRESENT(BIC_RAM__);
+ if (rapl_joules) {
+ BIC_PRESENT(BIC_Pkg_J);
+ BIC_PRESENT(BIC_Cor_J);
+ BIC_PRESENT(BIC_RAM_J);
+ } else {
+ BIC_PRESENT(BIC_PkgWatt);
+ BIC_PRESENT(BIC_CorWatt);
+ BIC_PRESENT(BIC_RAMWatt);
+ }
break;
case INTEL_FAM6_HASWELL_X: /* HSX */
case INTEL_FAM6_BROADWELL_X: /* BDX */
@@ -2811,17 +2930,55 @@ void rapl_probe(unsigned int family, unsigned int model)
case INTEL_FAM6_XEON_PHI_KNL: /* KNL */
case INTEL_FAM6_XEON_PHI_KNM:
do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
+ BIC_PRESENT(BIC_PKG__);
+ BIC_PRESENT(BIC_RAM__);
+ if (rapl_joules) {
+ BIC_PRESENT(BIC_Pkg_J);
+ BIC_PRESENT(BIC_RAM_J);
+ } else {
+ BIC_PRESENT(BIC_PkgWatt);
+ BIC_PRESENT(BIC_RAMWatt);
+ }
break;
case INTEL_FAM6_SANDYBRIDGE_X:
case INTEL_FAM6_IVYBRIDGE_X:
do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
+ BIC_PRESENT(BIC_PKG__);
+ BIC_PRESENT(BIC_RAM__);
+ if (rapl_joules) {
+ BIC_PRESENT(BIC_Pkg_J);
+ BIC_PRESENT(BIC_Cor_J);
+ BIC_PRESENT(BIC_RAM_J);
+ } else {
+ BIC_PRESENT(BIC_PkgWatt);
+ BIC_PRESENT(BIC_CorWatt);
+ BIC_PRESENT(BIC_RAMWatt);
+ }
break;
case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */
case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */
do_rapl = RAPL_PKG | RAPL_CORES;
+ if (rapl_joules) {
+ BIC_PRESENT(BIC_Pkg_J);
+ BIC_PRESENT(BIC_Cor_J);
+ } else {
+ BIC_PRESENT(BIC_PkgWatt);
+ BIC_PRESENT(BIC_CorWatt);
+ }
break;
case INTEL_FAM6_ATOM_DENVERTON: /* DNV */
do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS;
+ BIC_PRESENT(BIC_PKG__);
+ BIC_PRESENT(BIC_RAM__);
+ if (rapl_joules) {
+ BIC_PRESENT(BIC_Pkg_J);
+ BIC_PRESENT(BIC_Cor_J);
+ BIC_PRESENT(BIC_RAM_J);
+ } else {
+ BIC_PRESENT(BIC_PkgWatt);
+ BIC_PRESENT(BIC_CorWatt);
+ BIC_PRESENT(BIC_RAMWatt);
+ }
break;
default:
return;
@@ -3398,8 +3555,17 @@ void process_cpuid()
__cpuid(0x6, eax, ebx, ecx, edx);
has_aperf = ecx & (1 << 0);
+ if (has_aperf) {
+ BIC_PRESENT(BIC_Avg_MHz);
+ BIC_PRESENT(BIC_Busy);
+ BIC_PRESENT(BIC_Bzy_MHz);
+ }
do_dts = eax & (1 << 0);
+ if (do_dts)
+ BIC_PRESENT(BIC_CoreTmp);
do_ptm = eax & (1 << 6);
+ if (do_ptm)
+ BIC_PRESENT(BIC_PkgTmp);
has_hwp = eax & (1 << 7);
has_hwp_notify = eax & (1 << 8);
has_hwp_activity_window = eax & (1 << 9);
@@ -3497,8 +3663,21 @@ void process_cpuid()
if (has_aperf)
aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model);
- do_nhm_platform_info = do_nhm_cstates = do_smi = probe_nhm_msrs(family, model);
+ BIC_PRESENT(BIC_IRQ);
+ BIC_PRESENT(BIC_TSC_MHz);
+
+ if (probe_nhm_msrs(family, model)) {
+ do_nhm_platform_info = 1;
+ BIC_PRESENT(BIC_CPU_c1);
+ BIC_PRESENT(BIC_CPU_c3);
+ BIC_PRESENT(BIC_CPU_c6);
+ BIC_PRESENT(BIC_SMI);
+ }
do_snb_cstates = has_snb_msrs(family, model);
+
+ if (do_snb_cstates)
+ BIC_PRESENT(BIC_CPU_c7);
+
do_irtl_snb = has_snb_msrs(family, model);
do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2);
do_pc3 = (pkg_cstate_limit >= PCL__3);
@@ -3522,9 +3701,11 @@ void process_cpuid()
if (has_skl_msrs(family, model))
calculate_tsc_tweak();
- do_gfx_rc6_ms = !access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK);
+ if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK))
+ BIC_PRESENT(BIC_GFX_rc6);
- do_gfx_mhz = !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK);
+ if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
+ BIC_PRESENT(BIC_GFXMHz);
return;
}
@@ -3583,7 +3764,7 @@ void topology_probe()
topo.max_cpu_num = 0;
for_all_proc_cpus(count_cpus);
if (!summary_only && topo.num_cpus > 1)
- show_cpu = 1;
+ BIC_PRESENT(BIC_CPU);
if (debug > 1)
fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
@@ -3644,14 +3825,14 @@ void topology_probe()
fprintf(outf, "max_core_id %d, sizing for %d cores per package\n",
max_core_id, topo.num_cores_per_pkg);
if (debug && !summary_only && topo.num_cores_per_pkg > 1)
- show_core = 1;
+ BIC_PRESENT(BIC_Core);
topo.num_packages = max_package_id + 1;
if (debug > 1)
fprintf(outf, "max_package_id %d, sizing for %d packages\n",
max_package_id, topo.num_packages);
if (debug && !summary_only && topo.num_packages > 1)
- show_pkg = 1;
+ BIC_PRESENT(BIC_Package);
topo.num_threads_per_core = max_siblings;
if (debug > 1)
@@ -4045,6 +4226,40 @@ void parse_add_command(char *add_command)
exit(1);
}
}
+/*
+ * HIDE_LIST - hide this list of counters, show the rest [default]
+ * SHOW_LIST - show this list of counters, hide the rest
+ */
+enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;
+
+int shown;
+/*
+ * parse_show_hide() - process cmdline to set default counter action
+ */
+void parse_show_hide(char *optarg, enum show_hide_mode new_mode)
+{
+ /*
+ * --show: show only those specified
+ * The 1st invocation will clear and replace the enabled mask
+ * subsequent invocations can add to it.
+ */
+ if (new_mode == SHOW_LIST) {
+ if (shown == 0)
+ bic_enabled = bic_lookup(optarg);
+ else
+ bic_enabled |= bic_lookup(optarg);
+ shown = 1;
+
+ return;
+ }
+
+ /*
+ * --hide: do not show those specified
+ * multiple invocations simply clear more bits in enabled mask
+ */
+ bic_enabled &= ~bic_lookup(optarg);
+}
+
void cmdline(int argc, char **argv)
{
int opt;
@@ -4055,10 +4270,12 @@ void cmdline(int argc, char **argv)
{"debug", no_argument, 0, 'd'},
{"interval", required_argument, 0, 'i'},
{"help", no_argument, 0, 'h'},
+ {"hide", required_argument, 0, 'H'}, // meh, -h taken by --help
{"Joules", no_argument, 0, 'J'},
{"out", required_argument, 0, 'o'},
{"Package", no_argument, 0, 'p'},
{"processor", no_argument, 0, 'p'},
+ {"show", required_argument, 0, 's'},
{"Summary", no_argument, 0, 'S'},
{"TCC", required_argument, 0, 'T'},
{"version", no_argument, 0, 'v' },
@@ -4079,6 +4296,9 @@ void cmdline(int argc, char **argv)
case 'd':
debug++;
break;
+ case 'H':
+ parse_show_hide(optarg, HIDE_LIST);
+ break;
case 'h':
default:
help();
@@ -4109,6 +4329,9 @@ void cmdline(int argc, char **argv)
case 'p':
show_core_only++;
break;
+ case 's':
+ parse_show_hide(optarg, SHOW_LIST);
+ break;
case 'S':
summary_only++;
break;
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Cc: [email protected]
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/include/asm/intel-family.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h
index 8167fdb67ae8..9814db42b790 100644
--- a/arch/x86/include/asm/intel-family.h
+++ b/arch/x86/include/asm/intel-family.h
@@ -59,6 +59,7 @@
#define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */
#define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Anniedale */
#define INTEL_FAM6_ATOM_GOLDMONT 0x5C
+#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A
#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */
/* Xeon Phi */
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
previously known as MSR_NHM_SNB_PKG_CST_CFG_CTL
Signed-off-by: Len Brown <[email protected]>
---
drivers/idle/intel_idle.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 7d8ea3d5fda6..930537da76d4 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -961,9 +961,9 @@ static void auto_demotion_disable(void)
{
unsigned long long msr_bits;
- rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+ rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
msr_bits &= ~(icpu->auto_demotion_disable_flags);
- wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+ wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
}
static void c1e_promotion_disable(void)
{
@@ -1273,7 +1273,7 @@ static void sklh_idle_state_table_update(void)
if ((mwait_substates & (0xF << 28)) == 0)
return;
- rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr);
+ rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
/* PC10 is not enabled in PKG C-state limit */
if ((msr & 0xF) != 8)
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
On multi-package systems, the "Package" column was being displayed
only if --debug was used. Show it always.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 596259f48f50..2c674ad5ab80 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -4294,7 +4294,7 @@ void topology_probe()
if (debug > 1)
fprintf(outf, "max_package_id %d, sizing for %d packages\n",
max_package_id, topo.num_packages);
- if (debug && !summary_only && topo.num_packages > 1)
+ if (!summary_only && topo.num_packages > 1)
BIC_PRESENT(BIC_Package);
topo.num_threads_per_core = max_siblings;
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Add a digit of precision to the --debug output for frequency range.
This is useful when BCLK is not an integer.
old:
6 * 83 = 500 MHz max efficiency frequency
26 * 83 = 2166 MHz base frequency
new:
6 * 83.3 = 499.8 MHz max efficiency frequency
26 * 83.3 = 2165.8 MHz base frequency
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 42 +++++++++++++++++------------------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 19802be6dc02..762b81497c3b 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1581,11 +1581,11 @@ dump_nhm_platform_info(void)
fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
ratio = (msr >> 40) & 0xFF;
- fprintf(outf, "%d * %.0f = %.0f MHz max efficiency frequency\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0xFF;
- fprintf(outf, "%d * %.0f = %.0f MHz base frequency\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
ratio, bclk, ratio * bclk);
get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr);
@@ -1607,12 +1607,12 @@ dump_hsw_turbo_ratio_limits(void)
ratio = (msr >> 8) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 18 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 0) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 17 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n",
ratio, bclk, ratio * bclk);
return;
}
@@ -1629,42 +1629,42 @@ dump_ivt_turbo_ratio_limits(void)
ratio = (msr >> 56) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 16 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 48) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 15 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 40) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 14 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 32) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 13 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 24) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 12 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 16) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 11 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 10 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 0) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n",
ratio, bclk, ratio * bclk);
return;
}
@@ -1681,42 +1681,42 @@ dump_nhm_turbo_ratio_limits(void)
ratio = (msr >> 56) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 8 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 8 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 48) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 7 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 7 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 40) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 6 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 6 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 32) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 5 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 5 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 24) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 16) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 3 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 2 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n",
ratio, bclk, ratio * bclk);
ratio = (msr >> 0) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active cores\n",
ratio, bclk, ratio * bclk);
return;
}
@@ -1776,7 +1776,7 @@ dump_knl_turbo_ratio_limits(void)
for (i = buckets_no - 1; i >= 0; i--)
if (i > 0 ? ratio[i] != ratio[i - 1] : 1)
fprintf(outf,
- "%d * %.0f = %.0f MHz max turbo %d active cores\n",
+ "%d * %.1f = %.1f MHz max turbo %d active cores\n",
ratio[i], bclk, ratio[i] * bclk, cores[i]);
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
and so --debug fails with:
turbostat: msr 1 offset 0x1aa read failed: Input/output error
It seems that baytrail, and airmont do not have this MSR.
It is included in subsequent Goldmont Atom.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index fff280b50af0..fdf0273465fa 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -70,6 +70,7 @@ unsigned int units = 1000000; /* MHz etc */
unsigned int genuine_intel;
unsigned int has_invariant_tsc;
unsigned int do_nhm_platform_info;
+unsigned int no_MSR_MISC_PWR_MGMT;
unsigned int aperf_mperf_multiplier = 1;
double bclk;
double base_hz;
@@ -330,7 +331,7 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
if (retval != sizeof *msr)
- err(-1, "msr %d offset 0x%llx read failed", cpu, (unsigned long long)offset);
+ err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);
return 0;
}
@@ -2384,6 +2385,8 @@ void check_permissions()
* MSR_PLATFORM_INFO 0x000000ce
* MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2
*
+ * MSR_MISC_PWR_MGMT 0x000001aa
+ *
* MSR_PKG_C3_RESIDENCY 0x000003f8
* MSR_PKG_C6_RESIDENCY 0x000003f9
* MSR_CORE_C3_RESIDENCY 0x000003fc
@@ -2440,11 +2443,13 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
pkg_cstate_limits = skx_pkg_cstate_limits;
break;
case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */
+ no_MSR_MISC_PWR_MGMT = 1;
case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */
pkg_cstate_limits = slv_pkg_cstate_limits;
break;
case INTEL_FAM6_ATOM_AIRMONT: /* AMT */
pkg_cstate_limits = amt_pkg_cstate_limits;
+ no_MSR_MISC_PWR_MGMT = 1;
break;
case INTEL_FAM6_XEON_PHI_KNL: /* PHI */
case INTEL_FAM6_XEON_PHI_KNM:
@@ -3481,6 +3486,9 @@ void decode_misc_pwr_mgmt_msr(void)
if (!do_nhm_platform_info)
return;
+ if (no_MSR_MISC_PWR_MGMT)
+ return;
+
if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr))
fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n",
base_cpu, msr,
@@ -4061,7 +4069,7 @@ int get_and_dump_counters(void)
}
void print_version() {
- fprintf(outf, "turbostat version 4.16 24 Dec 2016"
+ fprintf(outf, "turbostat version 4.17 1 Jan 2017"
" - Len Brown <[email protected]>\n");
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Without --debug, a debug line was printed on Baytrail:
SLM BCLK: 83.3 Mhz
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 1b762f67e3e2..9b35c9bb0489 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -3388,7 +3388,8 @@ double slm_bclk(void)
}
freq = slm_freq_table[i];
- fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);
+ if (debug)
+ fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);
return freq;
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
These MSRs are currently used by the intel_pstate driver,
using a local definition.
Cc: [email protected]
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/include/asm/msr-index.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 079db99f6560..83bc672c225c 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -209,6 +209,12 @@
#define MSR_CC6_DEMOTION_POLICY_CONFIG 0x00000668
#define MSR_MC6_DEMOTION_POLICY_CONFIG 0x00000669
+#define MSR_ATOM_CORE_RATIOS 0x0000066a
+#define MSR_ATOM_CORE_VIDS 0x0000066b
+#define MSR_ATOM_CORE_TURBO_RATIOS 0x0000066c
+#define MSR_ATOM_CORE_TURBO_VIDS 0x0000066d
+
+
#define MSR_CORE_PERF_LIMIT_REASONS 0x00000690
#define MSR_GFX_PERF_LIMIT_REASONS 0x000006B0
#define MSR_RING_PERF_LIMIT_REASONS 0x000006B1
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
The two users, intel_idle driver and turbostat utility
are using the new name, MSR_PKG_CST_CONFIG_CONTROL
Cc: [email protected]
Signed-off-by: Len Brown <[email protected]>
---
arch/x86/include/asm/msr-index.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 975f23eefe14..12ecc6c1e7f8 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -46,7 +46,6 @@
#define MSR_FSB_FREQ 0x000000cd
#define MSR_PLATFORM_INFO 0x000000ce
-#define MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2
#define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
#define NHM_C3_AUTO_DEMOTE (1UL << 25)
#define NHM_C1_AUTO_DEMOTE (1UL << 26)
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
When --add was used more than once, overflowed buffers
caused some counters to be stored on top of others,
corrupting the results. Simplify the code by simply
reserving space for up to 16 added counters per each
cpu, core, package.
Per-cpu added counters were being printed only per-core.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 88 +++++++++++++++++++++--------------
1 file changed, 52 insertions(+), 36 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index f13f61b065c6..c7fadf0faa4b 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -154,6 +154,7 @@ char *progname;
cpu_set_t *cpu_present_set, *cpu_affinity_set;
size_t cpu_present_setsize, cpu_affinity_setsize;
+#define MAX_ADDED_COUNTERS 16
struct thread_data {
unsigned long long tsc;
@@ -166,7 +167,7 @@ struct thread_data {
unsigned int flags;
#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4
- unsigned long long counter[1];
+ unsigned long long counter[MAX_ADDED_COUNTERS];
} *thread_even, *thread_odd;
struct core_data {
@@ -175,7 +176,7 @@ struct core_data {
unsigned long long c7;
unsigned int core_temp_c;
unsigned int core_id;
- unsigned long long counter[1];
+ unsigned long long counter[MAX_ADDED_COUNTERS];
} *core_even, *core_odd;
struct pkg_data {
@@ -200,7 +201,7 @@ struct pkg_data {
unsigned int rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */
unsigned int rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */
unsigned int pkg_temp_c;
- unsigned long long counter[1];
+ unsigned long long counter[MAX_ADDED_COUNTERS];
} *package_even, *package_odd;
#define ODD_COUNTERS thread_odd, core_odd, package_odd
@@ -228,9 +229,9 @@ struct msr_counter {
};
struct sys_counters {
- unsigned int thread_counter_bytes;
- unsigned int core_counter_bytes;
- unsigned int package_counter_bytes;
+ unsigned int added_thread_counters;
+ unsigned int added_core_counters;
+ unsigned int added_package_counters;
struct msr_counter *tp;
struct msr_counter *cp;
struct msr_counter *pp;
@@ -374,12 +375,6 @@ void print_header(void)
if (do_nhm_cstates)
outp += sprintf(outp, "\tCPU%%c1");
- if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates)
- outp += sprintf(outp, "\tCPU%%c3");
- if (do_nhm_cstates)
- outp += sprintf(outp, "\tCPU%%c6");
- if (do_snb_cstates)
- outp += sprintf(outp, "\tCPU%%c7");
for (mp = sys.tp; mp; mp = mp->next) {
if (mp->format == FORMAT_RAW) {
@@ -392,6 +387,14 @@ void print_header(void)
}
}
+ if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates)
+ outp += sprintf(outp, "\tCPU%%c3");
+ if (do_nhm_cstates)
+ outp += sprintf(outp, "\tCPU%%c6");
+ if (do_snb_cstates)
+ outp += sprintf(outp, "\tCPU%%c7");
+
+
if (do_dts)
outp += sprintf(outp, "\tCoreTmp");
@@ -635,20 +638,11 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (do_smi)
outp += sprintf(outp, "\t%d", t->smi_count);
+ /* C1 */
if (do_nhm_cstates)
outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/t->tsc);
- /* print per-core data only for 1st thread in core */
- if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
- goto done;
-
- if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates)
- outp += sprintf(outp, "\t%.2f", 100.0 * c->c3/t->tsc);
- if (do_nhm_cstates)
- outp += sprintf(outp, "\t%.2f", 100.0 * c->c6/t->tsc);
- if (do_snb_cstates)
- outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc);
-
+ /* Added counters */
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
@@ -656,12 +650,23 @@ int format_counters(struct thread_data *t, struct core_data *c,
else
outp += sprintf(outp, "\t0x%016llx", t->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
- outp += sprintf(outp, "\t%8lld", t->counter[i]);
+ outp += sprintf(outp, "\t%lld", t->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/t->tsc);
}
}
+ /* print per-core data only for 1st thread in core */
+ if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
+ goto done;
+
+ if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates)
+ outp += sprintf(outp, "\t%.2f", 100.0 * c->c3/t->tsc);
+ if (do_nhm_cstates)
+ outp += sprintf(outp, "\t%.2f", 100.0 * c->c6/t->tsc);
+ if (do_snb_cstates)
+ outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc);
+
if (do_dts)
outp += sprintf(outp, "\t%d", c->core_temp_c);
@@ -673,7 +678,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
else
outp += sprintf(outp, "\t0x%016llx", c->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
- outp += sprintf(outp, "\t%8lld", c->counter[i]);
+ outp += sprintf(outp, "\t%lld", c->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/t->tsc);
}
@@ -770,7 +775,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
else
outp += sprintf(outp, "\t0x%016llx", p->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
- outp += sprintf(outp, "\t%8lld", p->counter[i]);
+ outp += sprintf(outp, "\t%lld", p->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/t->tsc);
}
@@ -1036,7 +1041,6 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
p->gfx_rc6_ms = 0;
p->gfx_mhz = 0;
-
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)
t->counter[i] = 0;
@@ -3662,7 +3666,7 @@ allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data
int i;
*t = calloc(topo.num_threads_per_core * topo.num_cores_per_pkg *
- topo.num_packages, sizeof(struct thread_data) + sys.thread_counter_bytes);
+ topo.num_packages, sizeof(struct thread_data));
if (*t == NULL)
goto error;
@@ -3671,14 +3675,14 @@ allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data
(*t)[i].cpu_id = -1;
*c = calloc(topo.num_cores_per_pkg * topo.num_packages,
- sizeof(struct core_data) + sys.core_counter_bytes);
+ sizeof(struct core_data));
if (*c == NULL)
goto error;
for (i = 0; i < topo.num_cores_per_pkg * topo.num_packages; i++)
(*c)[i].core_id = -1;
- *p = calloc(topo.num_packages, sizeof(struct pkg_data) + sys.package_counter_bytes);
+ *p = calloc(topo.num_packages, sizeof(struct pkg_data));
if (*p == NULL)
goto error;
@@ -3901,24 +3905,36 @@ int add_counter(unsigned int msr_num, char *name, unsigned int width,
switch (scope) {
case SCOPE_CPU:
- sys.thread_counter_bytes += 64;
msrp->next = sys.tp;
sys.tp = msrp;
- sys.thread_counter_bytes += sizeof(unsigned long long);
+ sys.added_thread_counters++;
+ if (sys.added_thread_counters > MAX_ADDED_COUNTERS) {
+ fprintf(stderr, "exceeded max %d added thread counters\n",
+ MAX_ADDED_COUNTERS);
+ exit(-1);
+ }
break;
case SCOPE_CORE:
- sys.core_counter_bytes += 64;
msrp->next = sys.cp;
sys.cp = msrp;
- sys.core_counter_bytes += sizeof(unsigned long long);
+ sys.added_core_counters++;
+ if (sys.added_core_counters > MAX_ADDED_COUNTERS) {
+ fprintf(stderr, "exceeded max %d added core counters\n",
+ MAX_ADDED_COUNTERS);
+ exit(-1);
+ }
break;
case SCOPE_PACKAGE:
- sys.package_counter_bytes += 64;
msrp->next = sys.pp;
sys.pp = msrp;
- sys.package_counter_bytes += sizeof(unsigned long long);
+ sys.added_package_counters++;
+ if (sys.added_package_counters > MAX_ADDED_COUNTERS) {
+ fprintf(stderr, "exceeded max %d added package counters\n",
+ MAX_ADDED_COUNTERS);
+ exit(-1);
+ }
break;
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Decode MISC_ENABLE.NO_TURBO,
also use the #defines in msr-index.h for decoding this register
cpu0: MSR_IA32_MISC_ENABLE: 0x00850089 (TCC EIST MWAIT TURBO)
Although it is not architectural, decode also
MSR_IA32_MISC_ENABLE.prefetch-disable (bit-9).
documented to be present on: Core, P4, Intel-Xeon
reserved on: Atom, Silvermont, Nehalem, SNB, PHI ec.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 762b81497c3b..a1ec9d816dfa 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -3509,11 +3509,13 @@ void decode_misc_enable_msr(void)
unsigned long long msr;
if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr))
- fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%s %s %s)\n",
+ fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n",
base_cpu, msr,
- msr & (1 << 3) ? "TCC" : "",
- msr & (1 << 16) ? "EIST" : "",
- msr & (1 << 18) ? "MONITOR" : "");
+ msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-",
+ msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-",
+ msr & MSR_IA32_MISC_ENABLE_MWAIT ? "No-" : "",
+ msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "",
+ msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : "");
}
/*
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
The IRQ column has been working for periodic mode,
but not in one-shot command mode, it shows only 0.
until now.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 8c965bb2f461..48b540a2fe81 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -619,9 +619,9 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "c1: %016llX\n", t->c1);
if (DO_BIC(BIC_IRQ))
- outp += sprintf(outp, "IRQ: %08X\n", t->irq_count);
+ outp += sprintf(outp, "IRQ: %d\n", t->irq_count);
if (DO_BIC(BIC_SMI))
- outp += sprintf(outp, "SMI: %08X\n", t->smi_count);
+ outp += sprintf(outp, "SMI: %d\n", t->smi_count);
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n",
@@ -2410,8 +2410,9 @@ int snapshot_gfx_mhz(void)
*/
int snapshot_proc_sysfs_files(void)
{
- if (snapshot_proc_interrupts())
- return 1;
+ if (DO_BIC(BIC_IRQ))
+ if (snapshot_proc_interrupts())
+ return 1;
if (DO_BIC(BIC_GFX_rc6))
snapshot_gfx_rc6_ms();
@@ -4391,6 +4392,7 @@ int fork_it(char **argv)
pid_t child_pid;
int status;
+ snapshot_proc_sysfs_files();
status = for_all_cpus(get_counters, EVEN_COUNTERS);
if (status)
exit(status);
@@ -4417,6 +4419,7 @@ int fork_it(char **argv)
* n.b. fork_it() does not check for errors from for_all_cpus()
* because re-starting is problematic when forking
*/
+ snapshot_proc_sysfs_files();
for_all_cpus(get_counters, ODD_COUNTERS);
gettimeofday(&tv_odd, (struct timezone *)NULL);
timersub(&tv_odd, &tv_even, &tv_delta);
@@ -4438,6 +4441,7 @@ int get_and_dump_counters(void)
{
int status;
+ snapshot_proc_sysfs_files();
status = for_all_cpus(get_counters, ODD_COUNTERS);
if (status)
return status;
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Turbostat dumps MSR_TURBO_RATIO_LIMIT on Core Architecture.
But Atom Architecture uses MSR_ATOM_CORE_RATIOS and
MSR_ATOM_CORE_TURBO_RATIOS.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 103 +++++++++++++++++++++++++++-------
1 file changed, 82 insertions(+), 21 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index a1ec9d816dfa..da6ec640caf7 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1722,6 +1722,54 @@ dump_nhm_turbo_ratio_limits(void)
}
static void
+dump_atom_turbo_ratio_limits(void)
+{
+ unsigned long long msr;
+ unsigned int ratio;
+
+ get_msr(base_cpu, MSR_ATOM_CORE_RATIOS, &msr);
+ fprintf(outf, "cpu%d: MSR_ATOM_CORE_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
+
+ ratio = (msr >> 0) & 0x3F;
+ if (ratio)
+ fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 8) & 0x3F;
+ if (ratio)
+ fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 16) & 0x3F;
+ if (ratio)
+ fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
+ ratio, bclk, ratio * bclk);
+
+ get_msr(base_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr);
+ fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
+
+ ratio = (msr >> 24) & 0x3F;
+ if (ratio)
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 16) & 0x3F;
+ if (ratio)
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 8) & 0x3F;
+ if (ratio)
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 0) & 0x3F;
+ if (ratio)
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n",
+ ratio, bclk, ratio * bclk);
+}
+
+static void
dump_knl_turbo_ratio_limits(void)
{
const unsigned int buckets_no = 7;
@@ -2496,8 +2544,32 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
has_base_hz = 1;
return 1;
}
+/*
+ * SLV client has supporet for unique MSRs:
+ *
+ * MSR_CC6_DEMOTION_POLICY_CONFIG
+ * MSR_MC6_DEMOTION_POLICY_CONFIG
+ */
+
+int has_slv_msrs(unsigned int family, unsigned int model)
+{
+ if (!genuine_intel)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_ATOM_SILVERMONT1:
+ case INTEL_FAM6_ATOM_MERRIFIELD:
+ case INTEL_FAM6_ATOM_MOOREFIELD:
+ return 1;
+ }
+ return 0;
+}
+
int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
{
+ if (has_slv_msrs(family, model))
+ return 0;
+
switch (model) {
/* Nehalem compatible, but do not include turbo-ratio limit support */
case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */
@@ -2509,6 +2581,13 @@ int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
return 1;
}
}
+int has_atom_turbo_ratio_limit(unsigned int family, unsigned int model)
+{
+ if (has_slv_msrs(family, model))
+ return 1;
+
+ return 0;
+}
int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
{
if (!genuine_intel)
@@ -2606,6 +2685,9 @@ dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
if (has_nhm_turbo_ratio_limit(family, model))
dump_nhm_turbo_ratio_limits();
+ if (has_atom_turbo_ratio_limit(family, model))
+ dump_atom_turbo_ratio_limits();
+
if (has_knl_turbo_ratio_limit(family, model))
dump_knl_turbo_ratio_limits();
@@ -3287,27 +3369,6 @@ int has_snb_msrs(unsigned int family, unsigned int model)
}
/*
- * SLV client has supporet for unique MSRs:
- *
- * MSR_CC6_DEMOTION_POLICY_CONFIG
- * MSR_MC6_DEMOTION_POLICY_CONFIG
- */
-
-int has_slv_msrs(unsigned int family, unsigned int model)
-{
- if (!genuine_intel)
- return 0;
-
- switch (model) {
- case INTEL_FAM6_ATOM_SILVERMONT1:
- case INTEL_FAM6_ATOM_MERRIFIELD:
- case INTEL_FAM6_ATOM_MOOREFIELD:
- return 1;
- }
- return 0;
-}
-
-/*
* HSW adds support for additional MSRs:
*
* MSR_PKG_C8_RESIDENCY 0x00000630
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
with --debug, see:
cpu0: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x00000000 (DISable-CC6-Demotion)
cpu0: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x00000000 (DISable-MC6-Demotion)
Note that the hardware default is to enable demotion,
and Linux started clearing these registers in 3.17.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 42 +++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index fdf0273465fa..1b762f67e3e2 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -3263,6 +3263,27 @@ int has_snb_msrs(unsigned int family, unsigned int model)
}
/*
+ * SLV client has supporet for unique MSRs:
+ *
+ * MSR_CC6_DEMOTION_POLICY_CONFIG
+ * MSR_MC6_DEMOTION_POLICY_CONFIG
+ */
+
+int has_slv_msrs(unsigned int family, unsigned int model)
+{
+ if (!genuine_intel)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_ATOM_SILVERMONT1:
+ case INTEL_FAM6_ATOM_MERRIFIELD:
+ case INTEL_FAM6_ATOM_MOOREFIELD:
+ return 1;
+ }
+ return 0;
+}
+
+/*
* HSW adds support for additional MSRs:
*
* MSR_PKG_C8_RESIDENCY 0x00000630
@@ -3496,6 +3517,24 @@ void decode_misc_pwr_mgmt_msr(void)
msr & (1 << 1) ? "EN" : "DIS",
msr & (1 << 8) ? "EN" : "DIS");
}
+/*
+ * Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG
+ *
+ * This MSRs are present on Silvermont processors,
+ * Intel Atom processor E3000 series (Baytrail), and friends.
+ */
+void decode_c6_demotion_policy_msr(void)
+{
+ unsigned long long msr;
+
+ if (!get_msr(base_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr))
+ fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n",
+ base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
+
+ if (!get_msr(base_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr))
+ fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n",
+ base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
+}
void process_cpuid()
{
@@ -3700,6 +3739,9 @@ void process_cpuid()
if (debug)
decode_misc_pwr_mgmt_msr();
+ if (debug && has_slv_msrs(family, model))
+ decode_c6_demotion_policy_msr();
+
rapl_probe(family, model);
perf_limit_reasons_probe(family, model);
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Previously called MSR_NHM_SNB_PKG_CST_CFG_CTL
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index aedfaddbad30..d56f2b75dc58 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1761,12 +1761,12 @@ dump_nhm_cst_cfg(void)
{
unsigned long long msr;
- get_msr(base_cpu, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr);
+ get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
#define SNB_C1_AUTO_UNDEMOTE (1UL << 27)
#define SNB_C3_AUTO_UNDEMOTE (1UL << 28)
- fprintf(outf, "cpu%d: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", base_cpu, msr);
+ fprintf(outf, "cpu%d: MSR_PKG_CST_CONFIG_CONTROL: 0x%08llx", base_cpu, msr);
fprintf(outf, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n",
(msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
@@ -2383,7 +2383,7 @@ void check_permissions()
* MSR_SMI_COUNT 0x00000034
*
* MSR_PLATFORM_INFO 0x000000ce
- * MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2
+ * MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
*
* MSR_MISC_PWR_MGMT 0x000001aa
*
@@ -2393,7 +2393,7 @@ void check_permissions()
* MSR_CORE_C6_RESIDENCY 0x000003fd
*
* Side effect:
- * sets global pkg_cstate_limit to decode MSR_NHM_SNB_PKG_CST_CFG_CTL
+ * sets global pkg_cstate_limit to decode MSR_PKG_CST_CONFIG_CONTROL
*/
int probe_nhm_msrs(unsigned int family, unsigned int model)
{
@@ -2462,7 +2462,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
default:
return 0;
}
- get_msr(base_cpu, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr);
+ get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
pkg_cstate_limit = pkg_cstate_limits[msr & 0xF];
get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
When a counter overlfows 7 columns, it shifts the remaining
columns to the right, so they no longer line up under
their column header.
Update turbostat to dectect when it is handling large
numbers, and switch to wider columns where, necessary.
Reported-by: Artem Bityutskiy <[email protected]>
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 68 ++++++++++++++++++++++++++++-------
1 file changed, 55 insertions(+), 13 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 7b02fbb65893..cafc6bba6539 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -50,6 +50,7 @@ int *fd_percpu;
struct timespec interval_ts = {5, 0};
unsigned int debug;
unsigned int quiet;
+unsigned int sums_need_wide_columns;
unsigned int rapl_joules;
unsigned int summary_only;
unsigned int list_header_only;
@@ -154,7 +155,7 @@ struct thread_data {
unsigned long long aperf;
unsigned long long mperf;
unsigned long long c1;
- unsigned int irq_count;
+ unsigned long long irq_count;
unsigned int smi_count;
unsigned int cpu_id;
unsigned int flags;
@@ -489,8 +490,13 @@ void print_header(char *delim)
if (DO_BIC(BIC_TSC_MHz))
outp += sprintf(outp, "%sTSC_MHz", delim);
- if (DO_BIC(BIC_IRQ))
- outp += sprintf(outp, "%sIRQ", delim);
+ if (DO_BIC(BIC_IRQ)) {
+ if (sums_need_wide_columns)
+ outp += sprintf(outp, "%s IRQ", delim);
+ else
+ outp += sprintf(outp, "%sIRQ", delim);
+ }
+
if (DO_BIC(BIC_SMI))
outp += sprintf(outp, "%sSMI", delim);
@@ -501,7 +507,10 @@ void print_header(char *delim)
else
outp += sprintf(outp, "%s%10.10s", delim, mp->name);
} else {
- outp += sprintf(outp, "%s%s", delim, mp->name);
+ if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
+ outp += sprintf(outp, "%s%8s", delim, mp->name);
+ else
+ outp += sprintf(outp, "%s%s", delim, mp->name);
}
}
@@ -527,7 +536,10 @@ void print_header(char *delim)
else
outp += sprintf(outp, "%s%10.10s", delim, mp->name);
} else {
- outp += sprintf(outp, "%s%s", delim, mp->name);
+ if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
+ outp += sprintf(outp, "%s%8s", delim, mp->name);
+ else
+ outp += sprintf(outp, "%s%s", delim, mp->name);
}
}
@@ -596,7 +608,10 @@ void print_header(char *delim)
else
outp += sprintf(outp, "%s%10.10s", delim, mp->name);
} else {
- outp += sprintf(outp, "%s%s", delim, mp->name);
+ if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
+ outp += sprintf(outp, "%s%8s", delim, mp->name);
+ else
+ outp += sprintf(outp, "%s%s", delim, mp->name);
}
}
@@ -620,7 +635,7 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "c1: %016llX\n", t->c1);
if (DO_BIC(BIC_IRQ))
- outp += sprintf(outp, "IRQ: %d\n", t->irq_count);
+ outp += sprintf(outp, "IRQ: %lld\n", t->irq_count);
if (DO_BIC(BIC_SMI))
outp += sprintf(outp, "SMI: %d\n", t->smi_count);
@@ -755,8 +770,12 @@ int format_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "\t%.0f", 1.0 * t->tsc/units/interval_float);
/* IRQ */
- if (DO_BIC(BIC_IRQ))
- outp += sprintf(outp, "\t%d", t->irq_count);
+ if (DO_BIC(BIC_IRQ)) {
+ if (sums_need_wide_columns)
+ outp += sprintf(outp, "\t%8lld", t->irq_count);
+ else
+ outp += sprintf(outp, "\t%lld", t->irq_count);
+ }
/* SMI */
if (DO_BIC(BIC_SMI))
@@ -770,7 +789,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
else
outp += sprintf(outp, "\t0x%016llx", t->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
- outp += sprintf(outp, "\t%lld", t->counter[i]);
+ if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
+ outp += sprintf(outp, "\t%8lld", t->counter[i]);
+ else
+ outp += sprintf(outp, "\t%lld", t->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
if (mp->type == COUNTER_USEC)
outp += sprintf(outp, "\t%.2f", t->counter[i]/interval_float/10000);
@@ -809,7 +831,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
else
outp += sprintf(outp, "\t0x%016llx", c->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
- outp += sprintf(outp, "\t%lld", c->counter[i]);
+ if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
+ outp += sprintf(outp, "\t%8lld", c->counter[i]);
+ else
+ outp += sprintf(outp, "\t%lld", c->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/tsc);
}
@@ -897,7 +922,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
else
outp += sprintf(outp, "\t0x%016llx", p->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
- outp += sprintf(outp, "\t%lld", p->counter[i]);
+ if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
+ outp += sprintf(outp, "\t%8lld", p->counter[i]);
+ else
+ outp += sprintf(outp, "\t%lld", p->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/tsc);
}
@@ -1272,6 +1300,9 @@ void compute_average(struct thread_data *t, struct core_data *c,
average.threads.mperf /= topo.num_cpus;
average.threads.c1 /= topo.num_cpus;
+ if (average.threads.irq_count > 9999999)
+ sums_need_wide_columns = 1;
+
average.cores.c3 /= topo.num_cores;
average.cores.c6 /= topo.num_cores;
average.cores.c7 /= topo.num_cores;
@@ -1299,18 +1330,29 @@ void compute_average(struct thread_data *t, struct core_data *c,
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW)
continue;
- if (mp->flags & SYSFS_PERCPU && mp->type == COUNTER_ITEMS)
+ if (mp->type == COUNTER_ITEMS) {
+ if (average.threads.counter[i] > 9999999)
+ sums_need_wide_columns = 1;
continue;
+ }
average.threads.counter[i] /= topo.num_cpus;
}
for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW)
continue;
+ if (mp->type == COUNTER_ITEMS) {
+ if (average.cores.counter[i] > 9999999)
+ sums_need_wide_columns = 1;
+ }
average.cores.counter[i] /= topo.num_cores;
}
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW)
continue;
+ if (mp->type == COUNTER_ITEMS) {
+ if (average.packages.counter[i] > 9999999)
+ sums_need_wide_columns = 1;
+ }
average.packages.counter[i] /= topo.num_packages;
}
}
--
2.11.0.161.g6610af872
From: Len Brown <[email protected]>
Newer processors do not hard-code the the number of cpus in each bin
to {1, 2, 3, 4, 5, 6, 7, 8} Rather, they can specify any number
of CPUS in each of the 8 bins:
eg.
...
37 * 100.0 = 3600.0 MHz max turbo 4 active cores
38 * 100.0 = 3700.0 MHz max turbo 3 active cores
39 * 100.0 = 3800.0 MHz max turbo 2 active cores
39 * 100.0 = 3900.0 MHz max turbo 1 active cores
could now look something like this:
...
37 * 100.0 = 3600.0 MHz max turbo 16 active cores
38 * 100.0 = 3700.0 MHz max turbo 8 active cores
39 * 100.0 = 3800.0 MHz max turbo 4 active cores
39 * 100.0 = 3900.0 MHz max turbo 2 active cores
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 90 ++++++++++++++++++++++++++---------
1 file changed, 67 insertions(+), 23 deletions(-)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 8c437115d41b..67a275882a8d 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1671,56 +1671,84 @@ dump_ivt_turbo_ratio_limits(void)
ratio, bclk, ratio * bclk);
return;
}
+int has_turbo_ratio_group_limits(int family, int model)
+{
+
+ if (!genuine_intel)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_ATOM_GOLDMONT:
+ case INTEL_FAM6_SKYLAKE_X:
+ case INTEL_FAM6_ATOM_DENVERTON:
+ return 1;
+ }
+ return 0;
+}
static void
-dump_nhm_turbo_ratio_limits(void)
+dump_turbo_ratio_limits(int family, int model)
{
- unsigned long long msr;
- unsigned int ratio;
+ unsigned long long msr, core_counts;
+ unsigned int ratio, group_size;
get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
-
fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
+ if (has_turbo_ratio_group_limits(family, model)) {
+ get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts);
+ fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, core_counts);
+ } else {
+ core_counts = 0x0807060504030201;
+ }
+
ratio = (msr >> 56) & 0xFF;
+ group_size = (core_counts >> 56) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 8 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
+ ratio, bclk, ratio * bclk, group_size);
ratio = (msr >> 48) & 0xFF;
+ group_size = (core_counts >> 48) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 7 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
+ ratio, bclk, ratio * bclk, group_size);
ratio = (msr >> 40) & 0xFF;
+ group_size = (core_counts >> 40) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 6 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
+ ratio, bclk, ratio * bclk, group_size);
ratio = (msr >> 32) & 0xFF;
+ group_size = (core_counts >> 32) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 5 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
+ ratio, bclk, ratio * bclk, group_size);
ratio = (msr >> 24) & 0xFF;
+ group_size = (core_counts >> 24) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
+ ratio, bclk, ratio * bclk, group_size);
ratio = (msr >> 16) & 0xFF;
+ group_size = (core_counts >> 16) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
+ ratio, bclk, ratio * bclk, group_size);
ratio = (msr >> 8) & 0xFF;
+ group_size = (core_counts >> 8) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
+ ratio, bclk, ratio * bclk, group_size);
ratio = (msr >> 0) & 0xFF;
+ group_size = (core_counts >> 0) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
+ ratio, bclk, ratio * bclk, group_size);
return;
}
@@ -2597,7 +2625,7 @@ int is_skx(unsigned int family, unsigned int model)
return 0;
}
-int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
+int has_turbo_ratio_limit(unsigned int family, unsigned int model)
{
if (has_slv_msrs(family, model))
return 0;
@@ -2668,6 +2696,22 @@ int has_knl_turbo_ratio_limit(unsigned int family, unsigned int model)
return 0;
}
}
+int has_glm_turbo_ratio_limit(unsigned int family, unsigned int model)
+{
+ if (!genuine_intel)
+ return 0;
+
+ if (family != 6)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_ATOM_GOLDMONT:
+ case INTEL_FAM6_SKYLAKE_X:
+ return 1;
+ default:
+ return 0;
+ }
+}
int has_config_tdp(unsigned int family, unsigned int model)
{
if (!genuine_intel)
@@ -2714,8 +2758,8 @@ dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
if (has_ivt_turbo_ratio_limit(family, model))
dump_ivt_turbo_ratio_limits();
- if (has_nhm_turbo_ratio_limit(family, model))
- dump_nhm_turbo_ratio_limits();
+ if (has_turbo_ratio_limit(family, model))
+ dump_turbo_ratio_limits(family, model);
if (has_atom_turbo_ratio_limit(family, model))
dump_atom_turbo_ratio_limits();
--
2.11.0.161.g6610af872
On Wed, Mar 1, 2017 at 7:27 AM, Len Brown <[email protected]> wrote:
> From: Len Brown <[email protected]>
> --- a/arch/x86/include/asm/intel-family.h
> +++ b/arch/x86/include/asm/intel-family.h
> @@ -59,6 +59,7 @@
> #define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */
> #define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Anniedale */
> #define INTEL_FAM6_ATOM_GOLDMONT 0x5C
> +#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A
> #define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */
One nit: can we keep it in order by model ID?
--
With Best Regards,
Andy Shevchenko
From: Len Brown <[email protected]>
useful for observing if the BIOS disabled prefetch
Not architectural, but docuemented as present on NHM, SNB
and is present on others.
Signed-off-by: Len Brown <[email protected]>
---
tools/power/x86/turbostat/turbostat.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 1011b5f7f21f..2f033f3d2a21 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -102,6 +102,7 @@ unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */
unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */
unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
+unsigned int has_misc_feature_control;
#define RAPL_PKG (1 << 0)
/* 0x610 MSR_PKG_POWER_LIMIT */
@@ -2466,6 +2467,7 @@ void check_permissions()
*
* Side effect:
* sets global pkg_cstate_limit to decode MSR_PKG_CST_CONFIG_CONTROL
+ * sets has_misc_feature_control
*/
int probe_nhm_msrs(unsigned int family, unsigned int model)
{
@@ -2496,6 +2498,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
case INTEL_FAM6_IVYBRIDGE: /* IVB */
case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */
pkg_cstate_limits = snb_pkg_cstate_limits;
+ has_misc_feature_control = 1;
break;
case INTEL_FAM6_HASWELL_CORE: /* HSW */
case INTEL_FAM6_HASWELL_X: /* HSX */
@@ -2510,9 +2513,11 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */
case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */
pkg_cstate_limits = hsw_pkg_cstate_limits;
+ has_misc_feature_control = 1;
break;
case INTEL_FAM6_SKYLAKE_X: /* SKX */
pkg_cstate_limits = skx_pkg_cstate_limits;
+ has_misc_feature_control = 1;
break;
case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */
no_MSR_MISC_PWR_MGMT = 1;
@@ -3579,6 +3584,21 @@ void decode_misc_enable_msr(void)
msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : "");
}
+void decode_misc_feature_control(void)
+{
+ unsigned long long msr;
+
+ if (!has_misc_feature_control)
+ return;
+
+ if (!get_msr(base_cpu, MSR_MISC_FEATURE_CONTROL, &msr))
+ fprintf(outf, "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n",
+ base_cpu, msr,
+ msr & (0 << 0) ? "No-" : "",
+ msr & (1 << 0) ? "No-" : "",
+ msr & (2 << 0) ? "No-" : "",
+ msr & (3 << 0) ? "No-" : "");
+}
/*
* Decode MSR_MISC_PWR_MGMT
*
@@ -3725,6 +3745,7 @@ void process_cpuid()
if (debug)
decode_misc_enable_msr();
+
if (max_level >= 0x7 && debug) {
int has_sgx;
@@ -3852,6 +3873,9 @@ void process_cpuid()
if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
BIC_PRESENT(BIC_GFXMHz);
+ if (debug)
+ decode_misc_feature_control();
+
return;
}
--
2.11.0.161.g6610af872