diff options
Diffstat (limited to 'tools/power/x86/turbostat/turbostat.c')
-rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 68 |
1 files changed, 53 insertions, 15 deletions
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(); |