aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2016-04-22 20:31:46 -0400
committerLen Brown <len.brown@intel.com>2016-12-01 01:33:15 -0500
commitba3dec99fc99fbe5a08d6c37f06feeb4d4bcb921 (patch)
treea0fe95381e5e073f7a5dec38f20bedea07a649a8
parente975db5d528abf5c42adfc50a6b0384993b6280b (diff)
tools/power turbostat: Gracefully handle ACPI S3
turbostat gives valid results across suspend to idle, aka freeze, whether invoked in interval mode, or in command mode. Indeed, this can be used to measure suspend to idle: turbostat echo freeze > /sys/power/state But this does not work across suspend to ACPI S3, because the processor counters, including the TSC, are reset on resume. Further, when turbostat detects a problem, it does't forgive the hardware, and interval mode will print *'s from there on out. Instead, upon detecting counters going backwards, simply reset and start over. Interval mode across ACPI S3: (observe TSC going backwards) root@sharkbay:/home/lenb/turbostat-src# ./turbostat -M 0x10 CPU Avg_MHz Busy% Bzy_MHz TSC_MHz MSR 0x010 - 1 0.06 858 2294 0x0000000000000000 0 0 0.06 847 2294 0x0000002a254b98ac 1 1 0.06 878 2294 0x0000002a254efa3a 2 1 0.07 843 2294 0x0000002a2551df65 3 0 0.05 863 2294 0x0000002a2553fea2 turbostat: re-initialized with num_cpus 4 CPU Avg_MHz Busy% Bzy_MHz TSC_MHz MSR 0x010 - 2 0.20 849 2294 0x0000000000000000 0 2 0.26 856 2294 0x0000000449abb60d 1 2 0.20 844 2294 0x0000000449b087ec 2 2 0.21 850 2294 0x0000000449b35d5d 3 1 0.12 839 2294 0x0000000449b5fd5a ^C Command mode across ACPI S3: root@sharkbay:/home/lenb/turbostat-src# ./turbostat -M 0x10 sleep 10 ./turbostat: Counter reset detected 14.196299 sec Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--tools/power/x86/turbostat/turbostat.c77
1 files changed, 35 insertions, 42 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index a302a333c084..c0dade0c1921 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -51,8 +51,6 @@ unsigned int debug;
51unsigned int rapl_joules; 51unsigned int rapl_joules;
52unsigned int summary_only; 52unsigned int summary_only;
53unsigned int dump_only; 53unsigned int dump_only;
54unsigned int skip_c0;
55unsigned int skip_c1;
56unsigned int do_nhm_cstates; 54unsigned int do_nhm_cstates;
57unsigned int do_snb_cstates; 55unsigned int do_snb_cstates;
58unsigned int do_knl_cstates; 56unsigned int do_knl_cstates;
@@ -145,7 +143,6 @@ unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
145 143
146#define MAX(a, b) ((a) > (b) ? (a) : (b)) 144#define MAX(a, b) ((a) > (b) ? (a) : (b))
147 145
148int aperf_mperf_unstable;
149int backwards_count; 146int backwards_count;
150char *progname; 147char *progname;
151 148
@@ -546,12 +543,8 @@ int format_counters(struct thread_data *t, struct core_data *c,
546 1.0 / units * t->aperf / interval_float); 543 1.0 / units * t->aperf / interval_float);
547 544
548 /* Busy% */ 545 /* Busy% */
549 if (has_aperf) { 546 if (has_aperf)
550 if (!skip_c0) 547 outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc/tsc_tweak);
551 outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc/tsc_tweak);
552 else
553 outp += sprintf(outp, "********");
554 }
555 548
556 /* Bzy_MHz */ 549 /* Bzy_MHz */
557 if (has_aperf) { 550 if (has_aperf) {
@@ -591,12 +584,8 @@ int format_counters(struct thread_data *t, struct core_data *c,
591 if (do_smi) 584 if (do_smi)
592 outp += sprintf(outp, "%8d", t->smi_count); 585 outp += sprintf(outp, "%8d", t->smi_count);
593 586
594 if (do_nhm_cstates) { 587 if (do_nhm_cstates)
595 if (!skip_c1) 588 outp += sprintf(outp, "%8.2f", 100.0 * t->c1/t->tsc);
596 outp += sprintf(outp, "%8.2f", 100.0 * t->c1/t->tsc);
597 else
598 outp += sprintf(outp, "********");
599 }
600 589
601 /* print per-core data only for 1st thread in core */ 590 /* print per-core data only for 1st thread in core */
602 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 591 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
@@ -622,8 +611,8 @@ int format_counters(struct thread_data *t, struct core_data *c,
622 611
623 /* GFXrc6 */ 612 /* GFXrc6 */
624 if (do_gfx_rc6_ms) { 613 if (do_gfx_rc6_ms) {
625 if (p->gfx_rc6_ms == -1) { /* detect counter reset */ 614 if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */
626 outp += sprintf(outp, " ***.**"); 615 outp += sprintf(outp, " **.**");
627 } else { 616 } else {
628 outp += sprintf(outp, "%8.2f", 617 outp += sprintf(outp, "%8.2f",
629 p->gfx_rc6_ms / 10.0 / interval_float); 618 p->gfx_rc6_ms / 10.0 / interval_float);
@@ -748,7 +737,7 @@ void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_
748 old = 0x100000000 + new - old; \ 737 old = 0x100000000 + new - old; \
749 } 738 }
750 739
751void 740int
752delta_package(struct pkg_data *new, struct pkg_data *old) 741delta_package(struct pkg_data *new, struct pkg_data *old)
753{ 742{
754 743
@@ -784,6 +773,8 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
784 DELTA_WRAP32(new->energy_dram, old->energy_dram); 773 DELTA_WRAP32(new->energy_dram, old->energy_dram);
785 DELTA_WRAP32(new->rapl_pkg_perf_status, old->rapl_pkg_perf_status); 774 DELTA_WRAP32(new->rapl_pkg_perf_status, old->rapl_pkg_perf_status);
786 DELTA_WRAP32(new->rapl_dram_perf_status, old->rapl_dram_perf_status); 775 DELTA_WRAP32(new->rapl_dram_perf_status, old->rapl_dram_perf_status);
776
777 return 0;
787} 778}
788 779
789void 780void
@@ -798,7 +789,7 @@ delta_core(struct core_data *new, struct core_data *old)
798/* 789/*
799 * old = new - old 790 * old = new - old
800 */ 791 */
801void 792int
802delta_thread(struct thread_data *new, struct thread_data *old, 793delta_thread(struct thread_data *new, struct thread_data *old,
803 struct core_data *core_delta) 794 struct core_data *core_delta)
804{ 795{
@@ -817,20 +808,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
817 old->aperf = new->aperf - old->aperf; 808 old->aperf = new->aperf - old->aperf;
818 old->mperf = new->mperf - old->mperf; 809 old->mperf = new->mperf - old->mperf;
819 } else { 810 } else {
820 811 return -1;
821 if (!aperf_mperf_unstable) {
822 fprintf(outf, "%s: APERF or MPERF went backwards *\n", progname);
823 fprintf(outf, "* Frequency results do not cover entire interval *\n");
824 fprintf(outf, "* fix this by running Linux-2.6.30 or later *\n");
825
826 aperf_mperf_unstable = 1;
827 }
828 /*
829 * mperf delta is likely a huge "positive" number
830 * can not use it for calculating c0 time
831 */
832 skip_c0 = 1;
833 skip_c1 = 1;
834 } 812 }
835 } 813 }
836 814
@@ -877,24 +855,30 @@ delta_thread(struct thread_data *new, struct thread_data *old,
877 855
878 if (do_smi) 856 if (do_smi)
879 old->smi_count = new->smi_count - old->smi_count; 857 old->smi_count = new->smi_count - old->smi_count;
858
859 return 0;
880} 860}
881 861
882int delta_cpu(struct thread_data *t, struct core_data *c, 862int delta_cpu(struct thread_data *t, struct core_data *c,
883 struct pkg_data *p, struct thread_data *t2, 863 struct pkg_data *p, struct thread_data *t2,
884 struct core_data *c2, struct pkg_data *p2) 864 struct core_data *c2, struct pkg_data *p2)
885{ 865{
866 int retval = 0;
867
886 /* calculate core delta only for 1st thread in core */ 868 /* calculate core delta only for 1st thread in core */
887 if (t->flags & CPU_IS_FIRST_THREAD_IN_CORE) 869 if (t->flags & CPU_IS_FIRST_THREAD_IN_CORE)
888 delta_core(c, c2); 870 delta_core(c, c2);
889 871
890 /* always calculate thread delta */ 872 /* always calculate thread delta */
891 delta_thread(t, t2, c2); /* c2 is core delta */ 873 retval = delta_thread(t, t2, c2); /* c2 is core delta */
874 if (retval)
875 return retval;
892 876
893 /* calculate package delta only for 1st core in package */ 877 /* calculate package delta only for 1st core in package */
894 if (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE) 878 if (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)
895 delta_package(p, p2); 879 retval = delta_package(p, p2);
896 880
897 return 0; 881 return retval;
898} 882}
899 883
900void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) 884void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
@@ -2067,7 +2051,10 @@ restart:
2067 } 2051 }
2068 gettimeofday(&tv_odd, (struct timezone *)NULL); 2052 gettimeofday(&tv_odd, (struct timezone *)NULL);
2069 timersub(&tv_odd, &tv_even, &tv_delta); 2053 timersub(&tv_odd, &tv_even, &tv_delta);
2070 for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS); 2054 if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) {
2055 re_initialize();
2056 goto restart;
2057 }
2071 compute_average(EVEN_COUNTERS); 2058 compute_average(EVEN_COUNTERS);
2072 format_all_counters(EVEN_COUNTERS); 2059 format_all_counters(EVEN_COUNTERS);
2073 flush_output_stdout(); 2060 flush_output_stdout();
@@ -2083,7 +2070,10 @@ restart:
2083 } 2070 }
2084 gettimeofday(&tv_even, (struct timezone *)NULL); 2071 gettimeofday(&tv_even, (struct timezone *)NULL);
2085 timersub(&tv_even, &tv_odd, &tv_delta); 2072 timersub(&tv_even, &tv_odd, &tv_delta);
2086 for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS); 2073 if (for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS)) {
2074 re_initialize();
2075 goto restart;
2076 }
2087 compute_average(ODD_COUNTERS); 2077 compute_average(ODD_COUNTERS);
2088 format_all_counters(ODD_COUNTERS); 2078 format_all_counters(ODD_COUNTERS);
2089 flush_output_stdout(); 2079 flush_output_stdout();
@@ -3693,9 +3683,12 @@ int fork_it(char **argv)
3693 for_all_cpus(get_counters, ODD_COUNTERS); 3683 for_all_cpus(get_counters, ODD_COUNTERS);
3694 gettimeofday(&tv_odd, (struct timezone *)NULL); 3684 gettimeofday(&tv_odd, (struct timezone *)NULL);
3695 timersub(&tv_odd, &tv_even, &tv_delta); 3685 timersub(&tv_odd, &tv_even, &tv_delta);
3696 for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS); 3686 if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS))
3697 compute_average(EVEN_COUNTERS); 3687 fprintf(outf, "%s: Counter reset detected\n", progname);
3698 format_all_counters(EVEN_COUNTERS); 3688 else {
3689 compute_average(EVEN_COUNTERS);
3690 format_all_counters(EVEN_COUNTERS);
3691 }
3699 3692
3700 fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0); 3693 fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
3701 3694
@@ -3722,7 +3715,7 @@ int get_and_dump_counters(void)
3722} 3715}
3723 3716
3724void print_version() { 3717void print_version() {
3725 fprintf(outf, "turbostat version 4.12 5 Apr 2016" 3718 fprintf(outf, "turbostat version 4.13 22 Apr 2016"
3726 " - Len Brown <lenb@kernel.org>\n"); 3719 " - Len Brown <lenb@kernel.org>\n");
3727} 3720}
3728 3721