diff options
author | Len Brown <len.brown@intel.com> | 2012-09-21 23:45:46 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-09-26 18:17:21 -0400 |
commit | 2f32edf12c1eafc8e5b1b0337360993fde1b3565 (patch) | |
tree | 4064b83fc867a2fb1d745590fddfc323f66c19d1 /tools | |
parent | 130ff304f6d31484fc73bb337bc635cba1ffe04c (diff) |
tools/power turbostat: add [-m MSR#] option
-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>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/power/x86/turbostat/turbostat.8 | 14 | ||||
-rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 68 |
2 files changed, 66 insertions, 16 deletions
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 74e44507dfe9..8e7b29af78f6 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 | |||
@@ -6,12 +6,14 @@ turbostat \- Report processor frequency and idle statistics | |||
6 | .B turbostat | 6 | .B turbostat |
7 | .RB [ "\-s" ] | 7 | .RB [ "\-s" ] |
8 | .RB [ "\-v" ] | 8 | .RB [ "\-v" ] |
9 | .RB [ "\-m MSR#" ] | ||
9 | .RB [ "\-M MSR#" ] | 10 | .RB [ "\-M MSR#" ] |
10 | .RB command | 11 | .RB command |
11 | .br | 12 | .br |
12 | .B turbostat | 13 | .B turbostat |
13 | .RB [ "\-s" ] | 14 | .RB [ "\-s" ] |
14 | .RB [ "\-v" ] | 15 | .RB [ "\-v" ] |
16 | .RB [ "\-m MSR#" ] | ||
15 | .RB [ "\-M MSR#" ] | 17 | .RB [ "\-M MSR#" ] |
16 | .RB [ "\-i interval_sec" ] | 18 | .RB [ "\-i interval_sec" ] |
17 | .SH DESCRIPTION | 19 | .SH DESCRIPTION |
@@ -35,7 +37,10 @@ The \fB-p\fP option limits output to the 1st thread in each package. | |||
35 | .PP | 37 | .PP |
36 | The \fB-v\fP option increases verbosity. | 38 | The \fB-v\fP option increases verbosity. |
37 | .PP | 39 | .PP |
38 | The \fB-M MSR#\fP option dumps the specified MSR, | 40 | The \fB-m MSR#\fP option dumps the specified 32-bit MSR, |
41 | in addition to the usual frequency and idle statistics. | ||
42 | .PP | ||
43 | The \fB-M MSR#\fP option dumps the specified 64-bit MSR, | ||
39 | in addition to the usual frequency and idle statistics. | 44 | in addition to the usual frequency and idle statistics. |
40 | .PP | 45 | .PP |
41 | The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. | 46 | The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. |
@@ -165,6 +170,13 @@ may work poorly on Linux-2.6.20 through 2.6.29, | |||
165 | as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF | 170 | as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF |
166 | in those kernels. | 171 | in those kernels. |
167 | 172 | ||
173 | If the TSC column does not make sense, then | ||
174 | the other numbers will also make no sense. | ||
175 | Turbostat is lightweight, and its data collection is not atomic. | ||
176 | These issues are usually caused by an extremely short measurement | ||
177 | interval (much less than 1 second), or system activity that prevents | ||
178 | turbostat from being able to run on all CPUS to quickly collect data. | ||
179 | |||
168 | The APERF, MPERF MSRs are defined to count non-halted cycles. | 180 | The APERF, MPERF MSRs are defined to count non-halted cycles. |
169 | Although it is not guaranteed by the architecture, turbostat assumes | 181 | Although it is not guaranteed by the architecture, turbostat assumes |
170 | that they count at TSC rate, which is true on all processors tested to date. | 182 | that they count at TSC rate, which is true on all processors tested to date. |
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 5ce88dd8c95a..946e9ab48edb 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
@@ -63,7 +63,8 @@ unsigned int has_invariant_tsc; | |||
63 | unsigned int do_nehalem_platform_info; | 63 | unsigned int do_nehalem_platform_info; |
64 | unsigned int do_nehalem_turbo_ratio_limit; | 64 | unsigned int do_nehalem_turbo_ratio_limit; |
65 | unsigned int do_ivt_turbo_ratio_limit; | 65 | unsigned int do_ivt_turbo_ratio_limit; |
66 | unsigned int extra_msr_offset; | 66 | unsigned int extra_msr_offset32; |
67 | unsigned int extra_msr_offset64; | ||
67 | double bclk; | 68 | double bclk; |
68 | unsigned int show_pkg; | 69 | unsigned int show_pkg; |
69 | unsigned int show_core; | 70 | unsigned int show_core; |
@@ -84,7 +85,8 @@ struct thread_data { | |||
84 | unsigned long long aperf; | 85 | unsigned long long aperf; |
85 | unsigned long long mperf; | 86 | unsigned long long mperf; |
86 | unsigned long long c1; /* derived */ | 87 | unsigned long long c1; /* derived */ |
87 | unsigned long long extra_msr; | 88 | unsigned long long extra_msr64; |
89 | unsigned int extra_msr32; | ||
88 | unsigned int cpu_id; | 90 | unsigned int cpu_id; |
89 | unsigned int flags; | 91 | unsigned int flags; |
90 | #define CPU_IS_FIRST_THREAD_IN_CORE 0x2 | 92 | #define CPU_IS_FIRST_THREAD_IN_CORE 0x2 |
@@ -206,6 +208,24 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) | |||
206 | return 0; | 208 | return 0; |
207 | } | 209 | } |
208 | 210 | ||
211 | /* | ||
212 | * Truncate the 8 bytes we read from /dev/cpu/.../msr | ||
213 | * to the 4 bytes requested | ||
214 | */ | ||
215 | |||
216 | int get_msr32(int cpu, off_t offset, unsigned int *msr) | ||
217 | { | ||
218 | int retval; | ||
219 | |||
220 | unsigned long long msr64; | ||
221 | |||
222 | retval = get_msr(cpu, offset, &msr64); | ||
223 | *msr = (unsigned int) msr64; | ||
224 | |||
225 | return retval; | ||
226 | } | ||
227 | |||
228 | |||
209 | void print_header(void) | 229 | void print_header(void) |
210 | { | 230 | { |
211 | if (show_pkg) | 231 | if (show_pkg) |
@@ -223,8 +243,10 @@ void print_header(void) | |||
223 | if (has_aperf) | 243 | if (has_aperf) |
224 | outp += sprintf(outp, " GHz"); | 244 | outp += sprintf(outp, " GHz"); |
225 | outp += sprintf(outp, " TSC"); | 245 | outp += sprintf(outp, " TSC"); |
226 | if (extra_msr_offset) | 246 | if (extra_msr_offset32) |
227 | outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset); | 247 | outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset32); |
248 | if (extra_msr_offset64) | ||
249 | outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset64); | ||
228 | if (do_nhm_cstates) | 250 | if (do_nhm_cstates) |
229 | outp += sprintf(outp, " %%c1"); | 251 | outp += sprintf(outp, " %%c1"); |
230 | if (do_nhm_cstates) | 252 | if (do_nhm_cstates) |
@@ -256,8 +278,10 @@ int dump_counters(struct thread_data *t, struct core_data *c, | |||
256 | fprintf(stderr, "aperf: %016llX\n", t->aperf); | 278 | fprintf(stderr, "aperf: %016llX\n", t->aperf); |
257 | fprintf(stderr, "mperf: %016llX\n", t->mperf); | 279 | fprintf(stderr, "mperf: %016llX\n", t->mperf); |
258 | fprintf(stderr, "c1: %016llX\n", t->c1); | 280 | fprintf(stderr, "c1: %016llX\n", t->c1); |
281 | fprintf(stderr, "msr0x%x: %08X\n", | ||
282 | extra_msr_offset32, t->extra_msr32); | ||
259 | fprintf(stderr, "msr0x%x: %016llX\n", | 283 | fprintf(stderr, "msr0x%x: %016llX\n", |
260 | extra_msr_offset, t->extra_msr); | 284 | extra_msr_offset64, t->extra_msr64); |
261 | } | 285 | } |
262 | 286 | ||
263 | if (c) { | 287 | if (c) { |
@@ -361,9 +385,13 @@ int format_counters(struct thread_data *t, struct core_data *c, | |||
361 | /* TSC */ | 385 | /* TSC */ |
362 | outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); | 386 | outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); |
363 | 387 | ||
388 | /* msr */ | ||
389 | if (extra_msr_offset32) | ||
390 | outp += sprintf(outp, " 0x%08x", t->extra_msr32); | ||
391 | |||
364 | /* MSR */ | 392 | /* MSR */ |
365 | if (extra_msr_offset) | 393 | if (extra_msr_offset64) |
366 | outp += sprintf(outp, " 0x%016llx", t->extra_msr); | 394 | outp += sprintf(outp, " 0x%016llx", t->extra_msr64); |
367 | 395 | ||
368 | if (do_nhm_cstates) { | 396 | if (do_nhm_cstates) { |
369 | if (!skip_c1) | 397 | if (!skip_c1) |
@@ -506,9 +534,10 @@ delta_thread(struct thread_data *new, struct thread_data *old, | |||
506 | } | 534 | } |
507 | 535 | ||
508 | /* | 536 | /* |
509 | * for "extra msr", just copy the latest w/o subtracting | 537 | * Extra MSR is a snapshot, simply copy latest w/o subtracting |
510 | */ | 538 | */ |
511 | old->extra_msr = new->extra_msr; | 539 | old->extra_msr32 = new->extra_msr32; |
540 | old->extra_msr64 = new->extra_msr64; | ||
512 | } | 541 | } |
513 | 542 | ||
514 | int delta_cpu(struct thread_data *t, struct core_data *c, | 543 | int delta_cpu(struct thread_data *t, struct core_data *c, |
@@ -632,8 +661,12 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) | |||
632 | return -4; | 661 | return -4; |
633 | } | 662 | } |
634 | 663 | ||
635 | if (extra_msr_offset) | 664 | if (extra_msr_offset32) |
636 | if (get_msr(cpu, extra_msr_offset, &t->extra_msr)) | 665 | if (get_msr32(cpu, extra_msr_offset32, &t->extra_msr32)) |
666 | return -5; | ||
667 | |||
668 | if (extra_msr_offset64) | ||
669 | if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64)) | ||
637 | return -5; | 670 | return -5; |
638 | 671 | ||
639 | /* collect core counters only for 1st thread in core */ | 672 | /* collect core counters only for 1st thread in core */ |
@@ -1242,7 +1275,7 @@ void check_cpuid() | |||
1242 | 1275 | ||
1243 | void usage() | 1276 | void usage() |
1244 | { | 1277 | { |
1245 | fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n", | 1278 | fprintf(stderr, "%s: [-v] [-m msr#] [-M MSR#] [-i interval_sec | command ...]\n", |
1246 | progname); | 1279 | progname); |
1247 | exit(1); | 1280 | exit(1); |
1248 | } | 1281 | } |
@@ -1532,7 +1565,7 @@ void cmdline(int argc, char **argv) | |||
1532 | 1565 | ||
1533 | progname = argv[0]; | 1566 | progname = argv[0]; |
1534 | 1567 | ||
1535 | while ((opt = getopt(argc, argv, "+cpsvi:M:")) != -1) { | 1568 | while ((opt = getopt(argc, argv, "+cpsvi:m:M:")) != -1) { |
1536 | switch (opt) { | 1569 | switch (opt) { |
1537 | case 'c': | 1570 | case 'c': |
1538 | show_core_only++; | 1571 | show_core_only++; |
@@ -1549,10 +1582,15 @@ void cmdline(int argc, char **argv) | |||
1549 | case 'i': | 1582 | case 'i': |
1550 | interval_sec = atoi(optarg); | 1583 | interval_sec = atoi(optarg); |
1551 | break; | 1584 | break; |
1585 | case 'm': | ||
1586 | sscanf(optarg, "%x", &extra_msr_offset32); | ||
1587 | if (verbose > 1) | ||
1588 | fprintf(stderr, "msr 0x%X\n", extra_msr_offset32); | ||
1589 | break; | ||
1552 | case 'M': | 1590 | case 'M': |
1553 | sscanf(optarg, "%x", &extra_msr_offset); | 1591 | sscanf(optarg, "%x", &extra_msr_offset64); |
1554 | if (verbose > 1) | 1592 | if (verbose > 1) |
1555 | fprintf(stderr, "MSR 0x%X\n", extra_msr_offset); | 1593 | fprintf(stderr, "MSR 0x%X\n", extra_msr_offset64); |
1556 | break; | 1594 | break; |
1557 | default: | 1595 | default: |
1558 | usage(); | 1596 | usage(); |