aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power/x86/turbostat
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2012-09-22 01:25:08 -0400
committerLen Brown <len.brown@intel.com>2012-09-27 22:04:56 -0400
commit8e180f3cb6b7510a3bdf14e16ce87c9f5d86f102 (patch)
tree2a7b3ac9789a47d1bfb9ccbb7a9a4fa31f91b61d /tools/power/x86/turbostat
parent2f32edf12c1eafc8e5b1b0337360993fde1b3565 (diff)
tools/power turbostat: add [-d MSR#][-D MSR#] options to print counter deltas
# turbostat -d 0x34 is useful for printing the number of SMI's within an interval on Nehalem and newer processors. where # turbostat -m 0x34 will simply print out the total SMI count since reset. Suggested-by: Andi Kleen Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'tools/power/x86/turbostat')
-rw-r--r--tools/power/x86/turbostat/turbostat.843
-rw-r--r--tools/power/x86/turbostat/turbostat.c95
2 files changed, 94 insertions, 44 deletions
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 8e7b29af78f6..0fc7a11f300e 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -4,17 +4,11 @@ turbostat \- Report processor frequency and idle statistics
4.SH SYNOPSIS 4.SH SYNOPSIS
5.ft B 5.ft B
6.B turbostat 6.B turbostat
7.RB [ "\-s" ] 7.RB [ Options ]
8.RB [ "\-v" ]
9.RB [ "\-m MSR#" ]
10.RB [ "\-M MSR#" ]
11.RB command 8.RB command
12.br 9.br
13.B turbostat 10.B turbostat
14.RB [ "\-s" ] 11.RB [ Options ]
15.RB [ "\-v" ]
16.RB [ "\-m MSR#" ]
17.RB [ "\-M MSR#" ]
18.RB [ "\-i interval_sec" ] 12.RB [ "\-i interval_sec" ]
19.SH DESCRIPTION 13.SH DESCRIPTION
20\fBturbostat \fP reports processor topology, frequency 14\fBturbostat \fP reports processor topology, frequency
@@ -37,11 +31,13 @@ The \fB-p\fP option limits output to the 1st thread in each package.
37.PP 31.PP
38The \fB-v\fP option increases verbosity. 32The \fB-v\fP option increases verbosity.
39.PP 33.PP
40The \fB-m MSR#\fP option dumps the specified 32-bit MSR, 34The \fB-d MSR#\fP option includes the delta of the specified 32-bit MSR counter.
41in addition to the usual frequency and idle statistics.
42.PP 35.PP
43The \fB-M MSR#\fP option dumps the specified 64-bit MSR, 36The \fB-D MSR#\fP option includes the delta of the specified 64-bit MSR counter.
44in addition to the usual frequency and idle statistics. 37.PP
38The \fB-m MSR#\fP option includes the the specified 32-bit MSR value.
39.PP
40The \fB-M MSR#\fP option includes the the specified 64-bit MSR value.
45.PP 41.PP
46The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. 42The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds.
47The default is 5 seconds. 43The default is 5 seconds.
@@ -155,6 +151,29 @@ Note that turbostat reports average GHz of 3.63, while
155the arithmetic average of the GHz column above is lower. 151the arithmetic average of the GHz column above is lower.
156This is a weighted average, where the weight is %c0. ie. it is the total number of 152This is a weighted average, where the weight is %c0. ie. it is the total number of
157un-halted cycles elapsed per time divided by the number of CPUs. 153un-halted cycles elapsed per time divided by the number of CPUs.
154.SH SMI COUNTING EXAMPLE
155On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter.
156Using the -m option, you can display how many SMIs have fired since reset, or if there
157are SMIs during the measurement interval, you can display the delta using the -d option.
158.nf
159[root@x980 ~]# turbostat -m 0x34
160cor CPU %c0 GHz TSC MSR 0x034 %c1 %c3 %c6 %pc3 %pc6
161 1.41 1.82 3.38 0x00000000 8.92 37.82 51.85 17.37 0.55
162 0 0 3.73 2.03 3.38 0x00000055 1.72 48.25 46.31 17.38 0.55
163 0 6 0.14 1.63 3.38 0x00000056 5.30
164 1 2 2.51 1.80 3.38 0x00000056 15.65 29.33 52.52
165 1 8 0.10 1.65 3.38 0x00000056 18.05
166 2 4 1.16 1.68 3.38 0x00000056 5.87 24.47 68.50
167 2 10 0.10 1.63 3.38 0x00000056 6.93
168 8 1 3.84 1.91 3.38 0x00000056 1.36 50.65 44.16
169 8 7 0.08 1.64 3.38 0x00000056 5.12
170 9 3 1.82 1.73 3.38 0x00000056 7.59 24.21 66.38
171 9 9 0.09 1.68 3.38 0x00000056 9.32
172 10 5 1.66 1.65 3.38 0x00000056 15.10 50.00 33.23
173 10 11 1.72 1.65 3.38 0x00000056 15.05
174^C
175[root@x980 ~]#
176.fi
158.SH NOTES 177.SH NOTES
159 178
160.B "turbostat " 179.B "turbostat "
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 946e9ab48edb..e38976c0b0a2 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -65,6 +65,8 @@ unsigned int do_nehalem_turbo_ratio_limit;
65unsigned int do_ivt_turbo_ratio_limit; 65unsigned int do_ivt_turbo_ratio_limit;
66unsigned int extra_msr_offset32; 66unsigned int extra_msr_offset32;
67unsigned int extra_msr_offset64; 67unsigned int extra_msr_offset64;
68unsigned int extra_delta_offset32;
69unsigned int extra_delta_offset64;
68double bclk; 70double bclk;
69unsigned int show_pkg; 71unsigned int show_pkg;
70unsigned int show_core; 72unsigned int show_core;
@@ -86,7 +88,9 @@ struct thread_data {
86 unsigned long long mperf; 88 unsigned long long mperf;
87 unsigned long long c1; /* derived */ 89 unsigned long long c1; /* derived */
88 unsigned long long extra_msr64; 90 unsigned long long extra_msr64;
89 unsigned int extra_msr32; 91 unsigned long long extra_delta64;
92 unsigned long long extra_msr32;
93 unsigned long long extra_delta32;
90 unsigned int cpu_id; 94 unsigned int cpu_id;
91 unsigned int flags; 95 unsigned int flags;
92#define CPU_IS_FIRST_THREAD_IN_CORE 0x2 96#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
@@ -208,24 +212,6 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
208 return 0; 212 return 0;
209} 213}
210 214
211/*
212 * Truncate the 8 bytes we read from /dev/cpu/.../msr
213 * to the 4 bytes requested
214 */
215
216int 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
229void print_header(void) 215void print_header(void)
230{ 216{
231 if (show_pkg) 217 if (show_pkg)
@@ -243,10 +229,14 @@ void print_header(void)
243 if (has_aperf) 229 if (has_aperf)
244 outp += sprintf(outp, " GHz"); 230 outp += sprintf(outp, " GHz");
245 outp += sprintf(outp, " TSC"); 231 outp += sprintf(outp, " TSC");
232 if (extra_delta_offset32)
233 outp += sprintf(outp, " delta 0x%03X", extra_delta_offset32);
234 if (extra_delta_offset64)
235 outp += sprintf(outp, " DELTA 0x%03X", extra_delta_offset64);
246 if (extra_msr_offset32) 236 if (extra_msr_offset32)
247 outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset32); 237 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32);
248 if (extra_msr_offset64) 238 if (extra_msr_offset64)
249 outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset64); 239 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
250 if (do_nhm_cstates) 240 if (do_nhm_cstates)
251 outp += sprintf(outp, " %%c1"); 241 outp += sprintf(outp, " %%c1");
252 if (do_nhm_cstates) 242 if (do_nhm_cstates)
@@ -278,7 +268,11 @@ int dump_counters(struct thread_data *t, struct core_data *c,
278 fprintf(stderr, "aperf: %016llX\n", t->aperf); 268 fprintf(stderr, "aperf: %016llX\n", t->aperf);
279 fprintf(stderr, "mperf: %016llX\n", t->mperf); 269 fprintf(stderr, "mperf: %016llX\n", t->mperf);
280 fprintf(stderr, "c1: %016llX\n", t->c1); 270 fprintf(stderr, "c1: %016llX\n", t->c1);
281 fprintf(stderr, "msr0x%x: %08X\n", 271 fprintf(stderr, "msr0x%x: %08llX\n",
272 extra_delta_offset32, t->extra_delta32);
273 fprintf(stderr, "msr0x%x: %016llX\n",
274 extra_delta_offset64, t->extra_delta64);
275 fprintf(stderr, "msr0x%x: %08llX\n",
282 extra_msr_offset32, t->extra_msr32); 276 extra_msr_offset32, t->extra_msr32);
283 fprintf(stderr, "msr0x%x: %016llX\n", 277 fprintf(stderr, "msr0x%x: %016llX\n",
284 extra_msr_offset64, t->extra_msr64); 278 extra_msr_offset64, t->extra_msr64);
@@ -385,9 +379,16 @@ int format_counters(struct thread_data *t, struct core_data *c,
385 /* TSC */ 379 /* TSC */
386 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); 380 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float);
387 381
382 /* delta */
383 if (extra_delta_offset32)
384 outp += sprintf(outp, " %11llu", t->extra_delta32);
385
386 /* DELTA */
387 if (extra_delta_offset64)
388 outp += sprintf(outp, " %11llu", t->extra_delta64);
388 /* msr */ 389 /* msr */
389 if (extra_msr_offset32) 390 if (extra_msr_offset32)
390 outp += sprintf(outp, " 0x%08x", t->extra_msr32); 391 outp += sprintf(outp, " 0x%08llx", t->extra_msr32);
391 392
392 /* MSR */ 393 /* MSR */
393 if (extra_msr_offset64) 394 if (extra_msr_offset64)
@@ -533,8 +534,13 @@ delta_thread(struct thread_data *new, struct thread_data *old,
533 old->mperf = 1; /* divide by 0 protection */ 534 old->mperf = 1; /* divide by 0 protection */
534 } 535 }
535 536
537 old->extra_delta32 = new->extra_delta32 - old->extra_delta32;
538 old->extra_delta32 &= 0xFFFFFFFF;
539
540 old->extra_delta64 = new->extra_delta64 - old->extra_delta64;
541
536 /* 542 /*
537 * Extra MSR is a snapshot, simply copy latest w/o subtracting 543 * Extra MSR is just a snapshot, simply copy latest w/o subtracting
538 */ 544 */
539 old->extra_msr32 = new->extra_msr32; 545 old->extra_msr32 = new->extra_msr32;
540 old->extra_msr64 = new->extra_msr64; 546 old->extra_msr64 = new->extra_msr64;
@@ -565,6 +571,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
565 t->mperf = 0; 571 t->mperf = 0;
566 t->c1 = 0; 572 t->c1 = 0;
567 573
574 t->extra_delta32 = 0;
575 t->extra_delta64 = 0;
576
568 /* tells format_counters to dump all fields from this set */ 577 /* tells format_counters to dump all fields from this set */
569 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; 578 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
570 579
@@ -585,6 +594,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
585 average.threads.mperf += t->mperf; 594 average.threads.mperf += t->mperf;
586 average.threads.c1 += t->c1; 595 average.threads.c1 += t->c1;
587 596
597 average.threads.extra_delta32 += t->extra_delta32;
598 average.threads.extra_delta64 += t->extra_delta64;
599
588 /* sum per-core values only for 1st thread in core */ 600 /* sum per-core values only for 1st thread in core */
589 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 601 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
590 return 0; 602 return 0;
@@ -620,6 +632,11 @@ void compute_average(struct thread_data *t, struct core_data *c,
620 average.threads.mperf /= topo.num_cpus; 632 average.threads.mperf /= topo.num_cpus;
621 average.threads.c1 /= topo.num_cpus; 633 average.threads.c1 /= topo.num_cpus;
622 634
635 average.threads.extra_delta32 /= topo.num_cpus;
636 average.threads.extra_delta32 &= 0xFFFFFFFF;
637
638 average.threads.extra_delta64 /= topo.num_cpus;
639
623 average.cores.c3 /= topo.num_cores; 640 average.cores.c3 /= topo.num_cores;
624 average.cores.c6 /= topo.num_cores; 641 average.cores.c6 /= topo.num_cores;
625 average.cores.c7 /= topo.num_cores; 642 average.cores.c7 /= topo.num_cores;
@@ -661,10 +678,22 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
661 return -4; 678 return -4;
662 } 679 }
663 680
664 if (extra_msr_offset32) 681 if (extra_delta_offset32) {
665 if (get_msr32(cpu, extra_msr_offset32, &t->extra_msr32)) 682 if (get_msr(cpu, extra_delta_offset32, &t->extra_delta32))
683 return -5;
684 t->extra_delta32 &= 0xFFFFFFFF;
685 }
686
687 if (extra_delta_offset64)
688 if (get_msr(cpu, extra_delta_offset64, &t->extra_delta64))
666 return -5; 689 return -5;
667 690
691 if (extra_msr_offset32) {
692 if (get_msr(cpu, extra_msr_offset32, &t->extra_msr32))
693 return -5;
694 t->extra_msr32 &= 0xFFFFFFFF;
695 }
696
668 if (extra_msr_offset64) 697 if (extra_msr_offset64)
669 if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64)) 698 if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64))
670 return -5; 699 return -5;
@@ -1275,7 +1304,7 @@ void check_cpuid()
1275 1304
1276void usage() 1305void usage()
1277{ 1306{
1278 fprintf(stderr, "%s: [-v] [-m msr#] [-M MSR#] [-i interval_sec | command ...]\n", 1307 fprintf(stderr, "%s: [-v][-d MSR#][-D MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n",
1279 progname); 1308 progname);
1280 exit(1); 1309 exit(1);
1281} 1310}
@@ -1565,7 +1594,7 @@ void cmdline(int argc, char **argv)
1565 1594
1566 progname = argv[0]; 1595 progname = argv[0];
1567 1596
1568 while ((opt = getopt(argc, argv, "+cpsvi:m:M:")) != -1) { 1597 while ((opt = getopt(argc, argv, "+cpsvid:D:m:M:")) != -1) {
1569 switch (opt) { 1598 switch (opt) {
1570 case 'c': 1599 case 'c':
1571 show_core_only++; 1600 show_core_only++;
@@ -1582,15 +1611,17 @@ void cmdline(int argc, char **argv)
1582 case 'i': 1611 case 'i':
1583 interval_sec = atoi(optarg); 1612 interval_sec = atoi(optarg);
1584 break; 1613 break;
1614 case 'd':
1615 sscanf(optarg, "%x", &extra_delta_offset32);
1616 break;
1617 case 'D':
1618 sscanf(optarg, "%x", &extra_delta_offset64);
1619 break;
1585 case 'm': 1620 case 'm':
1586 sscanf(optarg, "%x", &extra_msr_offset32); 1621 sscanf(optarg, "%x", &extra_msr_offset32);
1587 if (verbose > 1)
1588 fprintf(stderr, "msr 0x%X\n", extra_msr_offset32);
1589 break; 1622 break;
1590 case 'M': 1623 case 'M':
1591 sscanf(optarg, "%x", &extra_msr_offset64); 1624 sscanf(optarg, "%x", &extra_msr_offset64);
1592 if (verbose > 1)
1593 fprintf(stderr, "MSR 0x%X\n", extra_msr_offset64);
1594 break; 1625 break;
1595 default: 1626 default:
1596 usage(); 1627 usage();