Skip to content

Commit

Permalink
tools/power turbostat: add [-m MSR#] option
Browse files Browse the repository at this point in the history
-m MSR# prints the specified MSR in 32-bit format
-M MSR# prints the specified MSR in 64-bit format

Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Len Brown committed Sep 26, 2012
1 parent 130ff30 commit 2f32edf
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 16 deletions.
14 changes: 13 additions & 1 deletion tools/power/x86/turbostat/turbostat.8
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ turbostat \- Report processor frequency and idle statistics
.B turbostat
.RB [ "\-s" ]
.RB [ "\-v" ]
.RB [ "\-m MSR#" ]
.RB [ "\-M MSR#" ]
.RB command
.br
.B turbostat
.RB [ "\-s" ]
.RB [ "\-v" ]
.RB [ "\-m MSR#" ]
.RB [ "\-M MSR#" ]
.RB [ "\-i interval_sec" ]
.SH DESCRIPTION
Expand All @@ -35,7 +37,10 @@ The \fB-p\fP option limits output to the 1st thread in each package.
.PP
The \fB-v\fP option increases verbosity.
.PP
The \fB-M MSR#\fP option dumps the specified MSR,
The \fB-m MSR#\fP option dumps the specified 32-bit MSR,
in addition to the usual frequency and idle statistics.
.PP
The \fB-M MSR#\fP option dumps the specified 64-bit MSR,
in addition to the usual frequency and idle statistics.
.PP
The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds.
Expand Down Expand Up @@ -165,6 +170,13 @@ may work poorly on Linux-2.6.20 through 2.6.29,
as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF
in those kernels.

If the TSC column does not make sense, then
the other numbers will also make no sense.
Turbostat is lightweight, and its data collection is not atomic.
These issues are usually caused by an extremely short measurement
interval (much less than 1 second), or system activity that prevents
turbostat from being able to run on all CPUS to quickly collect data.

The APERF, MPERF MSRs are defined to count non-halted cycles.
Although it is not guaranteed by the architecture, turbostat assumes
that they count at TSC rate, which is true on all processors tested to date.
Expand Down
68 changes: 53 additions & 15 deletions tools/power/x86/turbostat/turbostat.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ unsigned int has_invariant_tsc;
unsigned int do_nehalem_platform_info;
unsigned int do_nehalem_turbo_ratio_limit;
unsigned int do_ivt_turbo_ratio_limit;
unsigned int extra_msr_offset;
unsigned int extra_msr_offset32;
unsigned int extra_msr_offset64;
double bclk;
unsigned int show_pkg;
unsigned int show_core;
Expand All @@ -84,7 +85,8 @@ struct thread_data {
unsigned long long aperf;
unsigned long long mperf;
unsigned long long c1; /* derived */
unsigned long long extra_msr;
unsigned long long extra_msr64;
unsigned int extra_msr32;
unsigned int cpu_id;
unsigned int flags;
#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
Expand Down Expand Up @@ -206,6 +208,24 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
return 0;
}

/*
* Truncate the 8 bytes we read from /dev/cpu/.../msr
* to the 4 bytes requested
*/

int get_msr32(int cpu, off_t offset, unsigned int *msr)
{
int retval;

unsigned long long msr64;

retval = get_msr(cpu, offset, &msr64);
*msr = (unsigned int) msr64;

return retval;
}


void print_header(void)
{
if (show_pkg)
Expand All @@ -223,8 +243,10 @@ void print_header(void)
if (has_aperf)
outp += sprintf(outp, " GHz");
outp += sprintf(outp, " TSC");
if (extra_msr_offset)
outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset);
if (extra_msr_offset32)
outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset32);
if (extra_msr_offset64)
outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset64);
if (do_nhm_cstates)
outp += sprintf(outp, " %%c1");
if (do_nhm_cstates)
Expand Down Expand Up @@ -256,8 +278,10 @@ int dump_counters(struct thread_data *t, struct core_data *c,
fprintf(stderr, "aperf: %016llX\n", t->aperf);
fprintf(stderr, "mperf: %016llX\n", t->mperf);
fprintf(stderr, "c1: %016llX\n", t->c1);
fprintf(stderr, "msr0x%x: %08X\n",
extra_msr_offset32, t->extra_msr32);
fprintf(stderr, "msr0x%x: %016llX\n",
extra_msr_offset, t->extra_msr);
extra_msr_offset64, t->extra_msr64);
}

if (c) {
Expand Down Expand Up @@ -361,9 +385,13 @@ int format_counters(struct thread_data *t, struct core_data *c,
/* TSC */
outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float);

/* msr */
if (extra_msr_offset32)
outp += sprintf(outp, " 0x%08x", t->extra_msr32);

/* MSR */
if (extra_msr_offset)
outp += sprintf(outp, " 0x%016llx", t->extra_msr);
if (extra_msr_offset64)
outp += sprintf(outp, " 0x%016llx", t->extra_msr64);

if (do_nhm_cstates) {
if (!skip_c1)
Expand Down Expand Up @@ -506,9 +534,10 @@ delta_thread(struct thread_data *new, struct thread_data *old,
}

/*
* for "extra msr", just copy the latest w/o subtracting
* Extra MSR is a snapshot, simply copy latest w/o subtracting
*/
old->extra_msr = new->extra_msr;
old->extra_msr32 = new->extra_msr32;
old->extra_msr64 = new->extra_msr64;
}

int delta_cpu(struct thread_data *t, struct core_data *c,
Expand Down Expand Up @@ -632,8 +661,12 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return -4;
}

if (extra_msr_offset)
if (get_msr(cpu, extra_msr_offset, &t->extra_msr))
if (extra_msr_offset32)
if (get_msr32(cpu, extra_msr_offset32, &t->extra_msr32))
return -5;

if (extra_msr_offset64)
if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64))
return -5;

/* collect core counters only for 1st thread in core */
Expand Down Expand Up @@ -1242,7 +1275,7 @@ void check_cpuid()

void usage()
{
fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n",
fprintf(stderr, "%s: [-v] [-m msr#] [-M MSR#] [-i interval_sec | command ...]\n",
progname);
exit(1);
}
Expand Down Expand Up @@ -1532,7 +1565,7 @@ void cmdline(int argc, char **argv)

progname = argv[0];

while ((opt = getopt(argc, argv, "+cpsvi:M:")) != -1) {
while ((opt = getopt(argc, argv, "+cpsvi:m:M:")) != -1) {
switch (opt) {
case 'c':
show_core_only++;
Expand All @@ -1549,10 +1582,15 @@ void cmdline(int argc, char **argv)
case 'i':
interval_sec = atoi(optarg);
break;
case 'm':
sscanf(optarg, "%x", &extra_msr_offset32);
if (verbose > 1)
fprintf(stderr, "msr 0x%X\n", extra_msr_offset32);
break;
case 'M':
sscanf(optarg, "%x", &extra_msr_offset);
sscanf(optarg, "%x", &extra_msr_offset64);
if (verbose > 1)
fprintf(stderr, "MSR 0x%X\n", extra_msr_offset);
fprintf(stderr, "MSR 0x%X\n", extra_msr_offset64);
break;
default:
usage();
Expand Down

0 comments on commit 2f32edf

Please sign in to comment.