Commit b7d8c148 authored by Len Brown's avatar Len Brown

tools/power turbostat: add --out option for saving output in a file

By default...

Turbostat --debug gconfiguration info goes to stderr.

In FORK mode, turbostat statistics go to stderr.

In PERIODIC mode, turbostat statistics go to stdout.

These defaults do not change, but an option "--out file"
will send all output above only to the specified file.
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 75d2e44e
...@@ -36,6 +36,9 @@ more than once may also enable internal turbostat debug information. ...@@ -36,6 +36,9 @@ more than once may also enable internal turbostat debug information.
.PP .PP
\fB--interval seconds\fP overrides the default 5.0 second measurement interval. \fB--interval seconds\fP overrides the default 5.0 second measurement interval.
.PP .PP
\fB--out output_file\fP turbostat output is written to the specified output_file.
The file is truncated if it already exists, and it is created if it does not exist.
.PP
\fB--help\fP displays usage for the most common parameters. \fB--help\fP displays usage for the most common parameters.
.PP .PP
\fB--Joules\fP displays energy in Joules, rather than dividing Joules by time to print power in Watts. \fB--Joules\fP displays energy in Joules, rather than dividing Joules by time to print power in Watts.
...@@ -83,10 +86,11 @@ Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading T ...@@ -83,10 +86,11 @@ Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading T
\fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM. \fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM.
.fi .fi
.PP .PP
.SH EXAMPLE .SH PERIODIC EXAMPLE
Without any parameters, turbostat displays statistics ever 5 seconds. Without any parameters, turbostat displays statistics ever 5 seconds.
(override interval with "-i sec" option, or specify a command Periodic output goes to stdout, by default, unless --out is used to specify an output file.
for turbostat to fork). The 5-second interval can be changed with th "-i sec" option.
Or a command may be specified as in "FORK EXAMPLE" below.
.nf .nf
[root@hsw]# ./turbostat [root@hsw]# ./turbostat
CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU Avg_MHz Busy% Bzy_MHz TSC_MHz
...@@ -171,7 +175,9 @@ The --debug option adds additional columns to the measurement ouput, including C ...@@ -171,7 +175,9 @@ The --debug option adds additional columns to the measurement ouput, including C
See the field definitions above. See the field definitions above.
.SH FORK EXAMPLE .SH FORK EXAMPLE
If turbostat is invoked with a command, it will fork that command If turbostat is invoked with a command, it will fork that command
and output the statistics gathered when the command exits. and output the statistics gathered 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 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: until ^C while the other CPUs are mostly idle:
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <errno.h> #include <errno.h>
char *proc_stat = "/proc/stat"; char *proc_stat = "/proc/stat";
FILE *outf;
struct timespec interval_ts = {5, 0}; struct timespec interval_ts = {5, 0};
unsigned int debug; unsigned int debug;
unsigned int rapl_joules; unsigned int rapl_joules;
...@@ -652,15 +653,24 @@ int format_counters(struct thread_data *t, struct core_data *c, ...@@ -652,15 +653,24 @@ int format_counters(struct thread_data *t, struct core_data *c,
return 0; return 0;
} }
void flush_stdout() void flush_output_stdout(void)
{ {
fputs(output_buffer, stdout); FILE *filep;
fflush(stdout);
if (outf == stderr)
filep = stdout;
else
filep = outf;
fputs(output_buffer, filep);
fflush(filep);
outp = output_buffer; outp = output_buffer;
} }
void flush_stderr() void flush_output_stderr(void)
{ {
fputs(output_buffer, stderr); fputs(output_buffer, outf);
fflush(outf);
outp = output_buffer; outp = output_buffer;
} }
void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
...@@ -752,9 +762,9 @@ delta_thread(struct thread_data *new, struct thread_data *old, ...@@ -752,9 +762,9 @@ delta_thread(struct thread_data *new, struct thread_data *old,
} else { } else {
if (!aperf_mperf_unstable) { if (!aperf_mperf_unstable) {
fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname); fprintf(outf, "%s: APERF or MPERF went backwards *\n", progname);
fprintf(stderr, "* Frequency results do not cover entire interval *\n"); fprintf(outf, "* Frequency results do not cover entire interval *\n");
fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n"); fprintf(outf, "* fix this by running Linux-2.6.30 or later *\n");
aperf_mperf_unstable = 1; aperf_mperf_unstable = 1;
} }
...@@ -789,7 +799,8 @@ delta_thread(struct thread_data *new, struct thread_data *old, ...@@ -789,7 +799,8 @@ delta_thread(struct thread_data *new, struct thread_data *old,
} }
if (old->mperf == 0) { if (old->mperf == 0) {
if (debug > 1) fprintf(stderr, "cpu%d MPERF 0!\n", old->cpu_id); if (debug > 1)
fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id);
old->mperf = 1; /* divide by 0 protection */ old->mperf = 1; /* divide by 0 protection */
} }
...@@ -989,7 +1000,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -989,7 +1000,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
unsigned long long msr; unsigned long long msr;
if (cpu_migrate(cpu)) { if (cpu_migrate(cpu)) {
fprintf(stderr, "Could not migrate to CPU %d\n", cpu); fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1; return -1;
} }
...@@ -1182,18 +1193,18 @@ dump_nhm_platform_info(void) ...@@ -1182,18 +1193,18 @@ dump_nhm_platform_info(void)
get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
fprintf(stderr, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr); fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
ratio = (msr >> 40) & 0xFF; ratio = (msr >> 40) & 0xFF;
fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency frequency\n", fprintf(outf, "%d * %.0f = %.0f MHz max efficiency frequency\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0xFF; ratio = (msr >> 8) & 0xFF;
fprintf(stderr, "%d * %.0f = %.0f MHz base frequency\n", fprintf(outf, "%d * %.0f = %.0f MHz base frequency\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr); get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr);
fprintf(stderr, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n", fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",
base_cpu, msr, msr & 0x2 ? "EN" : "DIS"); base_cpu, msr, msr & 0x2 ? "EN" : "DIS");
return; return;
...@@ -1207,16 +1218,16 @@ dump_hsw_turbo_ratio_limits(void) ...@@ -1207,16 +1218,16 @@ dump_hsw_turbo_ratio_limits(void)
get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr); get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr);
fprintf(stderr, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr); fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr);
ratio = (msr >> 8) & 0xFF; ratio = (msr >> 8) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 18 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 18 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 0) & 0xFF; ratio = (msr >> 0) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 17 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 17 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
return; return;
} }
...@@ -1229,46 +1240,46 @@ dump_ivt_turbo_ratio_limits(void) ...@@ -1229,46 +1240,46 @@ dump_ivt_turbo_ratio_limits(void)
get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr); get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr);
fprintf(stderr, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr); fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr);
ratio = (msr >> 56) & 0xFF; ratio = (msr >> 56) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 16 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 16 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 48) & 0xFF; ratio = (msr >> 48) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 15 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 15 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 40) & 0xFF; ratio = (msr >> 40) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 14 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 14 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 32) & 0xFF; ratio = (msr >> 32) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 13 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 13 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 24) & 0xFF; ratio = (msr >> 24) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 12 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 12 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 16) & 0xFF; ratio = (msr >> 16) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 11 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 11 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0xFF; ratio = (msr >> 8) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 10 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 10 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 0) & 0xFF; ratio = (msr >> 0) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
return; return;
} }
...@@ -1281,46 +1292,46 @@ dump_nhm_turbo_ratio_limits(void) ...@@ -1281,46 +1292,46 @@ dump_nhm_turbo_ratio_limits(void)
get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr); get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
fprintf(stderr, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr); fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
ratio = (msr >> 56) & 0xFF; ratio = (msr >> 56) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 8 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 8 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 48) & 0xFF; ratio = (msr >> 48) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 7 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 7 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 40) & 0xFF; ratio = (msr >> 40) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 6 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 6 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 32) & 0xFF; ratio = (msr >> 32) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 5 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 5 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 24) & 0xFF; ratio = (msr >> 24) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 16) & 0xFF; ratio = (msr >> 16) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 3 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 3 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0xFF; ratio = (msr >> 8) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 2 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 2 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
ratio = (msr >> 0) & 0xFF; ratio = (msr >> 0) & 0xFF;
if (ratio) if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", fprintf(outf, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
ratio, bclk, ratio * bclk); ratio, bclk, ratio * bclk);
return; return;
} }
...@@ -1338,7 +1349,7 @@ dump_knl_turbo_ratio_limits(void) ...@@ -1338,7 +1349,7 @@ dump_knl_turbo_ratio_limits(void)
get_msr(base_cpu, MSR_NHM_TURBO_RATIO_LIMIT, &msr); get_msr(base_cpu, MSR_NHM_TURBO_RATIO_LIMIT, &msr);
fprintf(stderr, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n",
base_cpu, msr); base_cpu, msr);
/** /**
...@@ -1379,7 +1390,7 @@ dump_knl_turbo_ratio_limits(void) ...@@ -1379,7 +1390,7 @@ dump_knl_turbo_ratio_limits(void)
for (i = buckets_no - 1; i >= 0; i--) for (i = buckets_no - 1; i >= 0; i--)
if (i > 0 ? ratio[i] != ratio[i - 1] : 1) if (i > 0 ? ratio[i] != ratio[i - 1] : 1)
fprintf(stderr, fprintf(outf,
"%d * %.0f = %.0f MHz max turbo %d active cores\n", "%d * %.0f = %.0f MHz max turbo %d active cores\n",
ratio[i], bclk, ratio[i] * bclk, cores[i]); ratio[i], bclk, ratio[i] * bclk, cores[i]);
} }
...@@ -1394,9 +1405,9 @@ dump_nhm_cst_cfg(void) ...@@ -1394,9 +1405,9 @@ dump_nhm_cst_cfg(void)
#define SNB_C1_AUTO_UNDEMOTE (1UL << 27) #define SNB_C1_AUTO_UNDEMOTE (1UL << 27)
#define SNB_C3_AUTO_UNDEMOTE (1UL << 28) #define SNB_C3_AUTO_UNDEMOTE (1UL << 28)
fprintf(stderr, "cpu%d: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", base_cpu, msr); fprintf(outf, "cpu%d: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", base_cpu, msr);
fprintf(stderr, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n", fprintf(outf, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n",
(msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "", (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
(msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "", (msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",
(msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "", (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
...@@ -1413,41 +1424,41 @@ dump_config_tdp(void) ...@@ -1413,41 +1424,41 @@ dump_config_tdp(void)
unsigned long long msr; unsigned long long msr;
get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr); get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr);
fprintf(stderr, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr); fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr);
fprintf(stderr, " (base_ratio=%d)\n", (unsigned int)msr & 0xEF); fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xEF);
get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr); get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr);
fprintf(stderr, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr); fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr);
if (msr) { if (msr) {
fprintf(stderr, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0xEFFF); fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0xEFFF);
fprintf(stderr, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0xEFFF); fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0xEFFF);
fprintf(stderr, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xEF); fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xEF);
fprintf(stderr, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0xEFFF); fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0xEFFF);
} }
fprintf(stderr, ")\n"); fprintf(outf, ")\n");
get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr); get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr);
fprintf(stderr, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr); fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr);
if (msr) { if (msr) {
fprintf(stderr, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0xEFFF); fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0xEFFF);
fprintf(stderr, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0xEFFF); fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0xEFFF);
fprintf(stderr, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xEF); fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xEF);
fprintf(stderr, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0xEFFF); fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0xEFFF);
} }
fprintf(stderr, ")\n"); fprintf(outf, ")\n");
get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr); get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr);
fprintf(stderr, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr); fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr);
if ((msr) & 0x3) if ((msr) & 0x3)
fprintf(stderr, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3); fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3);
fprintf(stderr, " lock=%d", (unsigned int)(msr >> 31) & 1); fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
fprintf(stderr, ")\n"); fprintf(outf, ")\n");
get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr); get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr);
fprintf(stderr, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr); fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr);
fprintf(stderr, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0x7F); fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0x7F);
fprintf(stderr, " lock=%d", (unsigned int)(msr >> 31) & 1); fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
fprintf(stderr, ")\n"); fprintf(outf, ")\n");
} }
void free_all_buffers(void) void free_all_buffers(void)
...@@ -1486,7 +1497,7 @@ void free_all_buffers(void) ...@@ -1486,7 +1497,7 @@ void free_all_buffers(void)
*/ */
FILE *fopen_or_die(const char *path, const char *mode) FILE *fopen_or_die(const char *path, const char *mode)
{ {
FILE *filep = fopen(path, "r"); FILE *filep = fopen(path, mode);
if (!filep) if (!filep)
err(1, "%s: open failed", path); err(1, "%s: open failed", path);
return filep; return filep;
...@@ -1740,7 +1751,7 @@ void turbostat_loop() ...@@ -1740,7 +1751,7 @@ void turbostat_loop()
for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS); for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS);
compute_average(EVEN_COUNTERS); compute_average(EVEN_COUNTERS);
format_all_counters(EVEN_COUNTERS); format_all_counters(EVEN_COUNTERS);
flush_stdout(); flush_output_stdout();
nanosleep(&interval_ts, NULL); nanosleep(&interval_ts, NULL);
retval = for_all_cpus(get_counters, EVEN_COUNTERS); retval = for_all_cpus(get_counters, EVEN_COUNTERS);
if (retval < -1) { if (retval < -1) {
...@@ -1754,7 +1765,7 @@ void turbostat_loop() ...@@ -1754,7 +1765,7 @@ void turbostat_loop()
for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS); for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS);
compute_average(ODD_COUNTERS); compute_average(ODD_COUNTERS);
format_all_counters(ODD_COUNTERS); format_all_counters(ODD_COUNTERS);
flush_stdout(); flush_output_stdout();
} }
} }
...@@ -2022,7 +2033,7 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2022,7 +2033,7 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return 0; return 0;
if (cpu_migrate(cpu)) { if (cpu_migrate(cpu)) {
fprintf(stderr, "Could not migrate to CPU %d\n", cpu); fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1; return -1;
} }
...@@ -2043,7 +2054,7 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2043,7 +2054,7 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
epb_string = "custom"; epb_string = "custom";
break; break;
} }
fprintf(stderr, "cpu%d: MSR_IA32_ENERGY_PERF_BIAS: 0x%08llx (%s)\n", cpu, msr, epb_string); fprintf(outf, "cpu%d: MSR_IA32_ENERGY_PERF_BIAS: 0x%08llx (%s)\n", cpu, msr, epb_string);
return 0; return 0;
} }
...@@ -2066,14 +2077,14 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2066,14 +2077,14 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return 0; return 0;
if (cpu_migrate(cpu)) { if (cpu_migrate(cpu)) {
fprintf(stderr, "Could not migrate to CPU %d\n", cpu); fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1; return -1;
} }
if (get_msr(cpu, MSR_PM_ENABLE, &msr)) if (get_msr(cpu, MSR_PM_ENABLE, &msr))
return 0; return 0;
fprintf(stderr, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n", fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n",
cpu, msr, (msr & (1 << 0)) ? "" : "No-"); cpu, msr, (msr & (1 << 0)) ? "" : "No-");
/* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */ /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
...@@ -2083,7 +2094,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2083,7 +2094,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr)) if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr))
return 0; return 0;
fprintf(stderr, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx " fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx "
"(high 0x%x guar 0x%x eff 0x%x low 0x%x)\n", "(high 0x%x guar 0x%x eff 0x%x low 0x%x)\n",
cpu, msr, cpu, msr,
(unsigned int)HWP_HIGHEST_PERF(msr), (unsigned int)HWP_HIGHEST_PERF(msr),
...@@ -2094,7 +2105,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2094,7 +2105,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_HWP_REQUEST, &msr)) if (get_msr(cpu, MSR_HWP_REQUEST, &msr))
return 0; return 0;
fprintf(stderr, "cpu%d: MSR_HWP_REQUEST: 0x%08llx " fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx "
"(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x pkg 0x%x)\n", "(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x pkg 0x%x)\n",
cpu, msr, cpu, msr,
(unsigned int)(((msr) >> 0) & 0xff), (unsigned int)(((msr) >> 0) & 0xff),
...@@ -2108,7 +2119,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2108,7 +2119,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr)) if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr))
return 0; return 0;
fprintf(stderr, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx " fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx "
"(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x)\n", "(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x)\n",
cpu, msr, cpu, msr,
(unsigned int)(((msr) >> 0) & 0xff), (unsigned int)(((msr) >> 0) & 0xff),
...@@ -2121,7 +2132,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2121,7 +2132,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr)) if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr))
return 0; return 0;
fprintf(stderr, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx " fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx "
"(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n", "(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n",
cpu, msr, cpu, msr,
((msr) & 0x1) ? "EN" : "Dis", ((msr) & 0x1) ? "EN" : "Dis",
...@@ -2130,7 +2141,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2130,7 +2141,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_HWP_STATUS, &msr)) if (get_msr(cpu, MSR_HWP_STATUS, &msr))
return 0; return 0;
fprintf(stderr, "cpu%d: MSR_HWP_STATUS: 0x%08llx " fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx "
"(%sGuaranteed_Perf_Change, %sExcursion_Min)\n", "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n",
cpu, msr, cpu, msr,
((msr) & 0x1) ? "" : "No-", ((msr) & 0x1) ? "" : "No-",
...@@ -2154,14 +2165,14 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data ...@@ -2154,14 +2165,14 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
return 0; return 0;
if (cpu_migrate(cpu)) { if (cpu_migrate(cpu)) {
fprintf(stderr, "Could not migrate to CPU %d\n", cpu); fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1; return -1;
} }
if (do_core_perf_limit_reasons) { if (do_core_perf_limit_reasons) {
get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr); get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr);
fprintf(stderr, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
fprintf(stderr, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)", fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",
(msr & 1 << 15) ? "bit15, " : "", (msr & 1 << 15) ? "bit15, " : "",
(msr & 1 << 14) ? "bit14, " : "", (msr & 1 << 14) ? "bit14, " : "",
(msr & 1 << 13) ? "Transitions, " : "", (msr & 1 << 13) ? "Transitions, " : "",
...@@ -2176,7 +2187,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data ...@@ -2176,7 +2187,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
(msr & 1 << 2) ? "bit2, " : "", (msr & 1 << 2) ? "bit2, " : "",
(msr & 1 << 1) ? "ThermStatus, " : "", (msr & 1 << 1) ? "ThermStatus, " : "",
(msr & 1 << 0) ? "PROCHOT, " : ""); (msr & 1 << 0) ? "PROCHOT, " : "");
fprintf(stderr, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n", fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
(msr & 1 << 31) ? "bit31, " : "", (msr & 1 << 31) ? "bit31, " : "",
(msr & 1 << 30) ? "bit30, " : "", (msr & 1 << 30) ? "bit30, " : "",
(msr & 1 << 29) ? "Transitions, " : "", (msr & 1 << 29) ? "Transitions, " : "",
...@@ -2195,8 +2206,8 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data ...@@ -2195,8 +2206,8 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
} }
if (do_gfx_perf_limit_reasons) { if (do_gfx_perf_limit_reasons) {
get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr); get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr);
fprintf(stderr, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
fprintf(stderr, " (Active: %s%s%s%s%s%s%s%s)", fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)",
(msr & 1 << 0) ? "PROCHOT, " : "", (msr & 1 << 0) ? "PROCHOT, " : "",
(msr & 1 << 1) ? "ThermStatus, " : "", (msr & 1 << 1) ? "ThermStatus, " : "",
(msr & 1 << 4) ? "Graphics, " : "", (msr & 1 << 4) ? "Graphics, " : "",
...@@ -2205,7 +2216,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data ...@@ -2205,7 +2216,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
(msr & 1 << 9) ? "GFXPwr, " : "", (msr & 1 << 9) ? "GFXPwr, " : "",
(msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 10) ? "PkgPwrL1, " : "",
(msr & 1 << 11) ? "PkgPwrL2, " : ""); (msr & 1 << 11) ? "PkgPwrL2, " : "");
fprintf(stderr, " (Logged: %s%s%s%s%s%s%s%s)\n", fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n",
(msr & 1 << 16) ? "PROCHOT, " : "", (msr & 1 << 16) ? "PROCHOT, " : "",
(msr & 1 << 17) ? "ThermStatus, " : "", (msr & 1 << 17) ? "ThermStatus, " : "",
(msr & 1 << 20) ? "Graphics, " : "", (msr & 1 << 20) ? "Graphics, " : "",
...@@ -2217,15 +2228,15 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data ...@@ -2217,15 +2228,15 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
} }
if (do_ring_perf_limit_reasons) { if (do_ring_perf_limit_reasons) {
get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr); get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr);
fprintf(stderr, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
fprintf(stderr, " (Active: %s%s%s%s%s%s)", fprintf(outf, " (Active: %s%s%s%s%s%s)",
(msr & 1 << 0) ? "PROCHOT, " : "", (msr & 1 << 0) ? "PROCHOT, " : "",
(msr & 1 << 1) ? "ThermStatus, " : "", (msr & 1 << 1) ? "ThermStatus, " : "",
(msr & 1 << 6) ? "VR-Therm, " : "", (msr & 1 << 6) ? "VR-Therm, " : "",
(msr & 1 << 8) ? "Amps, " : "", (msr & 1 << 8) ? "Amps, " : "",
(msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 10) ? "PkgPwrL1, " : "",
(msr & 1 << 11) ? "PkgPwrL2, " : ""); (msr & 1 << 11) ? "PkgPwrL2, " : "");
fprintf(stderr, " (Logged: %s%s%s%s%s%s)\n", fprintf(outf, " (Logged: %s%s%s%s%s%s)\n",
(msr & 1 << 16) ? "PROCHOT, " : "", (msr & 1 << 16) ? "PROCHOT, " : "",
(msr & 1 << 17) ? "ThermStatus, " : "", (msr & 1 << 17) ? "ThermStatus, " : "",
(msr & 1 << 22) ? "VR-Therm, " : "", (msr & 1 << 22) ? "VR-Therm, " : "",
...@@ -2348,7 +2359,7 @@ void rapl_probe(unsigned int family, unsigned int model) ...@@ -2348,7 +2359,7 @@ void rapl_probe(unsigned int family, unsigned int model)
rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
if (debug) if (debug)
fprintf(stderr, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp); fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
return; return;
} }
...@@ -2390,7 +2401,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p ...@@ -2390,7 +2401,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
return 0; return 0;
if (cpu_migrate(cpu)) { if (cpu_migrate(cpu)) {
fprintf(stderr, "Could not migrate to CPU %d\n", cpu); fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1; return -1;
} }
...@@ -2399,7 +2410,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p ...@@ -2399,7 +2410,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
return 0; return 0;
dts = (msr >> 16) & 0x7F; dts = (msr >> 16) & 0x7F;
fprintf(stderr, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n",
cpu, msr, tcc_activation_temp - dts); cpu, msr, tcc_activation_temp - dts);
#ifdef THERM_DEBUG #ifdef THERM_DEBUG
...@@ -2408,7 +2419,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p ...@@ -2408,7 +2419,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
dts = (msr >> 16) & 0x7F; dts = (msr >> 16) & 0x7F;
dts2 = (msr >> 8) & 0x7F; dts2 = (msr >> 8) & 0x7F;
fprintf(stderr, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2); cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
#endif #endif
} }
...@@ -2422,7 +2433,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p ...@@ -2422,7 +2433,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
dts = (msr >> 16) & 0x7F; dts = (msr >> 16) & 0x7F;
resolution = (msr >> 27) & 0xF; resolution = (msr >> 27) & 0xF;
fprintf(stderr, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n", fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n",
cpu, msr, tcc_activation_temp - dts, resolution); cpu, msr, tcc_activation_temp - dts, resolution);
#ifdef THERM_DEBUG #ifdef THERM_DEBUG
...@@ -2431,7 +2442,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p ...@@ -2431,7 +2442,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
dts = (msr >> 16) & 0x7F; dts = (msr >> 16) & 0x7F;
dts2 = (msr >> 8) & 0x7F; dts2 = (msr >> 8) & 0x7F;
fprintf(stderr, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2); cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
#endif #endif
} }
...@@ -2441,7 +2452,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p ...@@ -2441,7 +2452,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
void print_power_limit_msr(int cpu, unsigned long long msr, char *label) void print_power_limit_msr(int cpu, unsigned long long msr, char *label)
{ {
fprintf(stderr, "cpu%d: %s: %sabled (%f Watts, %f sec, clamp %sabled)\n", fprintf(outf, "cpu%d: %s: %sabled (%f Watts, %f sec, clamp %sabled)\n",
cpu, label, cpu, label,
((msr >> 15) & 1) ? "EN" : "DIS", ((msr >> 15) & 1) ? "EN" : "DIS",
((msr >> 0) & 0x7FFF) * rapl_power_units, ((msr >> 0) & 0x7FFF) * rapl_power_units,
...@@ -2465,7 +2476,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2465,7 +2476,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
cpu = t->cpu_id; cpu = t->cpu_id;
if (cpu_migrate(cpu)) { if (cpu_migrate(cpu)) {
fprintf(stderr, "Could not migrate to CPU %d\n", cpu); fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1; return -1;
} }
...@@ -2473,7 +2484,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2473,7 +2484,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return -1; return -1;
if (debug) { if (debug) {
fprintf(stderr, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx " fprintf(outf, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx "
"(%f Watts, %f Joules, %f sec.)\n", cpu, msr, "(%f Watts, %f Joules, %f sec.)\n", cpu, msr,
rapl_power_units, rapl_energy_units, rapl_time_units); rapl_power_units, rapl_energy_units, rapl_time_units);
} }
...@@ -2483,7 +2494,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2483,7 +2494,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return -5; return -5;
fprintf(stderr, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
cpu, msr, cpu, msr,
((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
...@@ -2496,11 +2507,11 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2496,11 +2507,11 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr)) if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr))
return -9; return -9;
fprintf(stderr, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n", 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"); print_power_limit_msr(cpu, msr, "PKG Limit #1");
fprintf(stderr, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n", fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n",
cpu, cpu,
((msr >> 47) & 1) ? "EN" : "DIS", ((msr >> 47) & 1) ? "EN" : "DIS",
((msr >> 32) & 0x7FFF) * rapl_power_units, ((msr >> 32) & 0x7FFF) * rapl_power_units,
...@@ -2512,7 +2523,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2512,7 +2523,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr)) if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr))
return -6; return -6;
fprintf(stderr, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
cpu, msr, cpu, msr,
((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
...@@ -2522,7 +2533,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2522,7 +2533,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (do_rapl & RAPL_DRAM) { if (do_rapl & RAPL_DRAM) {
if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr)) if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))
return -9; return -9;
fprintf(stderr, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n", 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"); print_power_limit_msr(cpu, msr, "DRAM Limit");
...@@ -2532,7 +2543,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2532,7 +2543,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_PP0_POLICY, &msr)) if (get_msr(cpu, MSR_PP0_POLICY, &msr))
return -7; return -7;
fprintf(stderr, "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) { if (do_rapl & RAPL_CORES) {
...@@ -2540,7 +2551,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2540,7 +2551,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
return -9; return -9;
fprintf(stderr, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n", fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
cpu, msr, (msr >> 31) & 1 ? "": "UN"); cpu, msr, (msr >> 31) & 1 ? "": "UN");
print_power_limit_msr(cpu, msr, "Cores Limit"); print_power_limit_msr(cpu, msr, "Cores Limit");
} }
...@@ -2550,11 +2561,11 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -2550,11 +2561,11 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_PP1_POLICY, &msr)) if (get_msr(cpu, MSR_PP1_POLICY, &msr))
return -8; return -8;
fprintf(stderr, "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)) if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))
return -9; return -9;
fprintf(stderr, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n", fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
cpu, msr, (msr >> 31) & 1 ? "": "UN"); cpu, msr, (msr >> 31) & 1 ? "": "UN");
print_power_limit_msr(cpu, msr, "GFX Limit"); print_power_limit_msr(cpu, msr, "GFX Limit");
} }
...@@ -2680,16 +2691,16 @@ double slm_bclk(void) ...@@ -2680,16 +2691,16 @@ double slm_bclk(void)
double freq; double freq;
if (get_msr(base_cpu, MSR_FSB_FREQ, &msr)) if (get_msr(base_cpu, MSR_FSB_FREQ, &msr))
fprintf(stderr, "SLM BCLK: unknown\n"); fprintf(outf, "SLM BCLK: unknown\n");
i = msr & 0xf; i = msr & 0xf;
if (i >= SLM_BCLK_FREQS) { if (i >= SLM_BCLK_FREQS) {
fprintf(stderr, "SLM BCLK[%d] invalid\n", i); fprintf(outf, "SLM BCLK[%d] invalid\n", i);
msr = 3; msr = 3;
} }
freq = slm_freq_table[i]; freq = slm_freq_table[i];
fprintf(stderr, "SLM BCLK: %.1f Mhz\n", freq); fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);
return freq; return freq;
} }
...@@ -2732,13 +2743,13 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk ...@@ -2732,13 +2743,13 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
cpu = t->cpu_id; cpu = t->cpu_id;
if (cpu_migrate(cpu)) { if (cpu_migrate(cpu)) {
fprintf(stderr, "Could not migrate to CPU %d\n", cpu); fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1; return -1;
} }
if (tcc_activation_temp_override != 0) { if (tcc_activation_temp_override != 0) {
tcc_activation_temp = tcc_activation_temp_override; tcc_activation_temp = tcc_activation_temp_override;
fprintf(stderr, "cpu%d: Using cmdline TCC Target (%d C)\n", fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n",
cpu, tcc_activation_temp); cpu, tcc_activation_temp);
return 0; return 0;
} }
...@@ -2753,7 +2764,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk ...@@ -2753,7 +2764,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
target_c_local = (msr >> 16) & 0xFF; target_c_local = (msr >> 16) & 0xFF;
if (debug) if (debug)
fprintf(stderr, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
cpu, msr, target_c_local); cpu, msr, target_c_local);
if (!target_c_local) if (!target_c_local)
...@@ -2765,7 +2776,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk ...@@ -2765,7 +2776,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
guess: guess:
tcc_activation_temp = TJMAX_DEFAULT; tcc_activation_temp = TJMAX_DEFAULT;
fprintf(stderr, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n", fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n",
cpu, tcc_activation_temp); cpu, tcc_activation_temp);
return 0; return 0;
...@@ -2776,7 +2787,7 @@ void decode_misc_enable_msr(void) ...@@ -2776,7 +2787,7 @@ void decode_misc_enable_msr(void)
unsigned long long msr; unsigned long long msr;
if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr)) if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr))
fprintf(stderr, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%s %s %s)\n", fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%s %s %s)\n",
base_cpu, msr, base_cpu, msr,
msr & (1 << 3) ? "TCC" : "", msr & (1 << 3) ? "TCC" : "",
msr & (1 << 16) ? "EIST" : "", msr & (1 << 16) ? "EIST" : "",
...@@ -2798,7 +2809,7 @@ void decode_misc_pwr_mgmt_msr(void) ...@@ -2798,7 +2809,7 @@ void decode_misc_pwr_mgmt_msr(void)
return; return;
if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr)) if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr))
fprintf(stderr, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB)\n", fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB)\n",
base_cpu, msr, base_cpu, msr,
msr & (1 << 0) ? "DIS" : "EN", msr & (1 << 0) ? "DIS" : "EN",
msr & (1 << 1) ? "EN" : "DIS"); msr & (1 << 1) ? "EN" : "DIS");
...@@ -2817,7 +2828,7 @@ void process_cpuid() ...@@ -2817,7 +2828,7 @@ void process_cpuid()
genuine_intel = 1; genuine_intel = 1;
if (debug) if (debug)
fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
(char *)&ebx, (char *)&edx, (char *)&ecx); (char *)&ebx, (char *)&edx, (char *)&ecx);
__get_cpuid(1, &fms, &ebx, &ecx, &edx); __get_cpuid(1, &fms, &ebx, &ecx, &edx);
...@@ -2828,9 +2839,9 @@ void process_cpuid() ...@@ -2828,9 +2839,9 @@ void process_cpuid()
model += ((fms >> 16) & 0xf) << 4; model += ((fms >> 16) & 0xf) << 4;
if (debug) { if (debug) {
fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
max_level, family, model, stepping, family, model, stepping); max_level, family, model, stepping, family, model, stepping);
fprintf(stderr, "CPUID(1): %s %s %s %s %s %s %s %s\n", fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s\n",
ecx & (1 << 0) ? "SSE3" : "-", ecx & (1 << 0) ? "SSE3" : "-",
ecx & (1 << 3) ? "MONITOR" : "-", ecx & (1 << 3) ? "MONITOR" : "-",
ecx & (1 << 7) ? "EIST" : "-", ecx & (1 << 7) ? "EIST" : "-",
...@@ -2879,7 +2890,7 @@ void process_cpuid() ...@@ -2879,7 +2890,7 @@ void process_cpuid()
has_epb = ecx & (1 << 3); has_epb = ecx & (1 << 3);
if (debug) if (debug)
fprintf(stderr, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sHWP, " fprintf(outf, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sHWP, "
"%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n", "%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
has_aperf ? "" : "No-", has_aperf ? "" : "No-",
do_dts ? "" : "No-", do_dts ? "" : "No-",
...@@ -2907,7 +2918,7 @@ void process_cpuid() ...@@ -2907,7 +2918,7 @@ void process_cpuid()
if (ebx_tsc != 0) { if (ebx_tsc != 0) {
if (debug && (ebx != 0)) if (debug && (ebx != 0))
fprintf(stderr, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n", fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",
eax_crystal, ebx_tsc, crystal_hz); eax_crystal, ebx_tsc, crystal_hz);
if (crystal_hz == 0) if (crystal_hz == 0)
...@@ -2923,7 +2934,7 @@ void process_cpuid() ...@@ -2923,7 +2934,7 @@ void process_cpuid()
if (crystal_hz) { if (crystal_hz) {
tsc_hz = (unsigned long long) crystal_hz * ebx_tsc / eax_crystal; tsc_hz = (unsigned long long) crystal_hz * ebx_tsc / eax_crystal;
if (debug) if (debug)
fprintf(stderr, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n", fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal); tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal);
} }
} }
...@@ -2938,7 +2949,7 @@ void process_cpuid() ...@@ -2938,7 +2949,7 @@ void process_cpuid()
__get_cpuid(0x16, &base_mhz, &max_mhz, &bus_mhz, &edx); __get_cpuid(0x16, &base_mhz, &max_mhz, &bus_mhz, &edx);
if (debug) if (debug)
fprintf(stderr, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n", fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n",
base_mhz, max_mhz, bus_mhz); base_mhz, max_mhz, bus_mhz);
} }
...@@ -2973,7 +2984,7 @@ void process_cpuid() ...@@ -2973,7 +2984,7 @@ void process_cpuid()
void help() void help()
{ {
fprintf(stderr, fprintf(outf,
"Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n" "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
"\n" "\n"
"Turbostat forks the specified COMMAND and prints statistics\n" "Turbostat forks the specified COMMAND and prints statistics\n"
...@@ -2985,6 +2996,7 @@ void help() ...@@ -2985,6 +2996,7 @@ void help()
"--help print this help message\n" "--help print this help message\n"
"--counter msr print 32-bit counter at address \"msr\"\n" "--counter msr print 32-bit counter at address \"msr\"\n"
"--Counter msr print 64-bit Counter at address \"msr\"\n" "--Counter msr print 64-bit Counter at address \"msr\"\n"
"--out file create or truncate \"file\" for all output\n"
"--msr msr print 32-bit value at address \"msr\"\n" "--msr msr print 32-bit value at address \"msr\"\n"
"--MSR msr print 64-bit Value at address \"msr\"\n" "--MSR msr print 64-bit Value at address \"msr\"\n"
"--version print version information\n" "--version print version information\n"
...@@ -3029,7 +3041,7 @@ void topology_probe() ...@@ -3029,7 +3041,7 @@ void topology_probe()
show_cpu = 1; show_cpu = 1;
if (debug > 1) if (debug > 1)
fprintf(stderr, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num); fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology)); cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology));
if (cpus == NULL) if (cpus == NULL)
...@@ -3064,7 +3076,7 @@ void topology_probe() ...@@ -3064,7 +3076,7 @@ void topology_probe()
if (cpu_is_not_present(i)) { if (cpu_is_not_present(i)) {
if (debug > 1) if (debug > 1)
fprintf(stderr, "cpu%d NOT PRESENT\n", i); fprintf(outf, "cpu%d NOT PRESENT\n", i);
continue; continue;
} }
cpus[i].core_id = get_core_id(i); cpus[i].core_id = get_core_id(i);
...@@ -3079,26 +3091,26 @@ void topology_probe() ...@@ -3079,26 +3091,26 @@ void topology_probe()
if (siblings > max_siblings) if (siblings > max_siblings)
max_siblings = siblings; max_siblings = siblings;
if (debug > 1) if (debug > 1)
fprintf(stderr, "cpu %d pkg %d core %d\n", fprintf(outf, "cpu %d pkg %d core %d\n",
i, cpus[i].physical_package_id, cpus[i].core_id); i, cpus[i].physical_package_id, cpus[i].core_id);
} }
topo.num_cores_per_pkg = max_core_id + 1; topo.num_cores_per_pkg = max_core_id + 1;
if (debug > 1) if (debug > 1)
fprintf(stderr, "max_core_id %d, sizing for %d cores per package\n", fprintf(outf, "max_core_id %d, sizing for %d cores per package\n",
max_core_id, topo.num_cores_per_pkg); max_core_id, topo.num_cores_per_pkg);
if (debug && !summary_only && topo.num_cores_per_pkg > 1) if (debug && !summary_only && topo.num_cores_per_pkg > 1)
show_core = 1; show_core = 1;
topo.num_packages = max_package_id + 1; topo.num_packages = max_package_id + 1;
if (debug > 1) if (debug > 1)
fprintf(stderr, "max_package_id %d, sizing for %d packages\n", fprintf(outf, "max_package_id %d, sizing for %d packages\n",
max_package_id, topo.num_packages); max_package_id, topo.num_packages);
if (debug && !summary_only && topo.num_packages > 1) if (debug && !summary_only && topo.num_packages > 1)
show_pkg = 1; show_pkg = 1;
topo.num_threads_per_core = max_siblings; topo.num_threads_per_core = max_siblings;
if (debug > 1) if (debug > 1)
fprintf(stderr, "max_siblings %d\n", max_siblings); fprintf(outf, "max_siblings %d\n", max_siblings);
free(cpus); free(cpus);
} }
...@@ -3207,7 +3219,7 @@ void set_base_cpu(void) ...@@ -3207,7 +3219,7 @@ void set_base_cpu(void)
err(-ENODEV, "No valid cpus found"); err(-ENODEV, "No valid cpus found");
if (debug > 1) if (debug > 1)
fprintf(stderr, "base_cpu = %d\n", base_cpu); fprintf(outf, "base_cpu = %d\n", base_cpu);
} }
void turbostat_init() void turbostat_init()
...@@ -3274,9 +3286,10 @@ int fork_it(char **argv) ...@@ -3274,9 +3286,10 @@ int fork_it(char **argv)
for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS); for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS);
compute_average(EVEN_COUNTERS); compute_average(EVEN_COUNTERS);
format_all_counters(EVEN_COUNTERS); format_all_counters(EVEN_COUNTERS);
flush_stderr();
fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0); fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
flush_output_stderr();
return status; return status;
} }
...@@ -3293,13 +3306,13 @@ int get_and_dump_counters(void) ...@@ -3293,13 +3306,13 @@ int get_and_dump_counters(void)
if (status) if (status)
return status; return status;
flush_stdout(); flush_output_stdout();
return status; return status;
} }
void print_version() { void print_version() {
fprintf(stderr, "turbostat version 4.10 10 Dec, 2015" fprintf(outf, "turbostat version 4.10 10 Dec, 2015"
" - Len Brown <lenb@kernel.org>\n"); " - Len Brown <lenb@kernel.org>\n");
} }
...@@ -3317,6 +3330,7 @@ void cmdline(int argc, char **argv) ...@@ -3317,6 +3330,7 @@ void cmdline(int argc, char **argv)
{"Joules", no_argument, 0, 'J'}, {"Joules", no_argument, 0, 'J'},
{"MSR", required_argument, 0, 'M'}, {"MSR", required_argument, 0, 'M'},
{"msr", required_argument, 0, 'm'}, {"msr", required_argument, 0, 'm'},
{"out", required_argument, 0, 'o'},
{"Package", no_argument, 0, 'p'}, {"Package", no_argument, 0, 'p'},
{"processor", no_argument, 0, 'p'}, {"processor", no_argument, 0, 'p'},
{"Summary", no_argument, 0, 'S'}, {"Summary", no_argument, 0, 'S'},
...@@ -3327,7 +3341,7 @@ void cmdline(int argc, char **argv) ...@@ -3327,7 +3341,7 @@ void cmdline(int argc, char **argv)
progname = argv[0]; progname = argv[0];
while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:PpST:v", while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:PpST:v",
long_options, &option_index)) != -1) { long_options, &option_index)) != -1) {
switch (opt) { switch (opt) {
case 'C': case 'C':
...@@ -3351,7 +3365,7 @@ void cmdline(int argc, char **argv) ...@@ -3351,7 +3365,7 @@ void cmdline(int argc, char **argv)
double interval = strtod(optarg, NULL); double interval = strtod(optarg, NULL);
if (interval < 0.001) { if (interval < 0.001) {
fprintf(stderr, "interval %f seconds is too small\n", fprintf(outf, "interval %f seconds is too small\n",
interval); interval);
exit(2); exit(2);
} }
...@@ -3369,6 +3383,9 @@ void cmdline(int argc, char **argv) ...@@ -3369,6 +3383,9 @@ void cmdline(int argc, char **argv)
case 'm': case 'm':
sscanf(optarg, "%x", &extra_msr_offset32); sscanf(optarg, "%x", &extra_msr_offset32);
break; break;
case 'o':
outf = fopen_or_die(optarg, "w");
break;
case 'P': case 'P':
show_pkg_only++; show_pkg_only++;
break; break;
...@@ -3391,6 +3408,8 @@ void cmdline(int argc, char **argv) ...@@ -3391,6 +3408,8 @@ void cmdline(int argc, char **argv)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
outf = stderr;
cmdline(argc, argv); cmdline(argc, argv);
if (debug) if (debug)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment