summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/power/x86/turbostat/turbostat.c188
1 files changed, 116 insertions, 72 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index a02c02f25e88..ba8846b309f7 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -53,6 +53,10 @@ unsigned int skip_c0;
unsigned int skip_c1;
unsigned int do_nhm_cstates;
unsigned int do_snb_cstates;
+unsigned int do_pc2;
+unsigned int do_pc3;
+unsigned int do_pc6;
+unsigned int do_pc7;
unsigned int do_c8_c9_c10;
unsigned int do_slm_cstates;
unsigned int use_c1_residency_msr;
@@ -313,13 +317,13 @@ void print_header(void)
if (do_ptm)
outp += sprintf(outp, " PkgTmp");
- if (do_snb_cstates)
+ if (do_pc2)
outp += sprintf(outp, " Pkg%%pc2");
- if (do_nhm_cstates && !do_slm_cstates)
+ if (do_pc3)
outp += sprintf(outp, " Pkg%%pc3");
- if (do_nhm_cstates && !do_slm_cstates)
+ if (do_pc6)
outp += sprintf(outp, " Pkg%%pc6");
- if (do_snb_cstates)
+ if (do_pc7)
outp += sprintf(outp, " Pkg%%pc7");
if (do_c8_c9_c10) {
outp += sprintf(outp, " Pkg%%pc8");
@@ -394,9 +398,12 @@ int dump_counters(struct thread_data *t, struct core_data *c,
if (p) {
outp += sprintf(outp, "package: %d\n", p->package_id);
outp += sprintf(outp, "pc2: %016llX\n", p->pc2);
- outp += sprintf(outp, "pc3: %016llX\n", p->pc3);
- outp += sprintf(outp, "pc6: %016llX\n", p->pc6);
- outp += sprintf(outp, "pc7: %016llX\n", p->pc7);
+ if (do_pc3)
+ outp += sprintf(outp, "pc3: %016llX\n", p->pc3);
+ if (do_pc6)
+ outp += sprintf(outp, "pc6: %016llX\n", p->pc6);
+ if (do_pc7)
+ outp += sprintf(outp, "pc7: %016llX\n", p->pc7);
outp += sprintf(outp, "pc8: %016llX\n", p->pc8);
outp += sprintf(outp, "pc9: %016llX\n", p->pc9);
outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
@@ -528,13 +535,13 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (do_ptm)
outp += sprintf(outp, "%8d", p->pkg_temp_c);
- if (do_snb_cstates)
+ if (do_pc2)
outp += sprintf(outp, "%8.2f", 100.0 * p->pc2/t->tsc);
- if (do_nhm_cstates && !do_slm_cstates)
+ if (do_pc3)
outp += sprintf(outp, "%8.2f", 100.0 * p->pc3/t->tsc);
- if (do_nhm_cstates && !do_slm_cstates)
+ if (do_pc6)
outp += sprintf(outp, "%8.2f", 100.0 * p->pc6/t->tsc);
- if (do_snb_cstates)
+ if (do_pc7)
outp += sprintf(outp, "%8.2f", 100.0 * p->pc7/t->tsc);
if (do_c8_c9_c10) {
outp += sprintf(outp, "%8.2f", 100.0 * p->pc8/t->tsc);
@@ -631,9 +638,12 @@ void
delta_package(struct pkg_data *new, struct pkg_data *old)
{
old->pc2 = new->pc2 - old->pc2;
- old->pc3 = new->pc3 - old->pc3;
- old->pc6 = new->pc6 - old->pc6;
- old->pc7 = new->pc7 - old->pc7;
+ if (do_pc3)
+ old->pc3 = new->pc3 - old->pc3;
+ if (do_pc6)
+ old->pc6 = new->pc6 - old->pc6;
+ if (do_pc7)
+ old->pc7 = new->pc7 - old->pc7;
old->pc8 = new->pc8 - old->pc8;
old->pc9 = new->pc9 - old->pc9;
old->pc10 = new->pc10 - old->pc10;
@@ -774,9 +784,12 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
c->core_temp_c = 0;
p->pc2 = 0;
- p->pc3 = 0;
- p->pc6 = 0;
- p->pc7 = 0;
+ if (do_pc3)
+ p->pc3 = 0;
+ if (do_pc6)
+ p->pc6 = 0;
+ if (do_pc7)
+ p->pc7 = 0;
p->pc8 = 0;
p->pc9 = 0;
p->pc10 = 0;
@@ -815,9 +828,12 @@ int sum_counters(struct thread_data *t, struct core_data *c,
return 0;
average.packages.pc2 += p->pc2;
- average.packages.pc3 += p->pc3;
- average.packages.pc6 += p->pc6;
- average.packages.pc7 += p->pc7;
+ if (do_pc3)
+ average.packages.pc3 += p->pc3;
+ if (do_pc6)
+ average.packages.pc6 += p->pc6;
+ if (do_pc7)
+ average.packages.pc7 += p->pc7;
average.packages.pc8 += p->pc8;
average.packages.pc9 += p->pc9;
average.packages.pc10 += p->pc10;
@@ -859,9 +875,12 @@ void compute_average(struct thread_data *t, struct core_data *c,
average.cores.c7 /= topo.num_cores;
average.packages.pc2 /= topo.num_packages;
- average.packages.pc3 /= topo.num_packages;
- average.packages.pc6 /= topo.num_packages;
- average.packages.pc7 /= topo.num_packages;
+ if (do_pc3)
+ average.packages.pc3 /= topo.num_packages;
+ if (do_pc6)
+ average.packages.pc6 /= topo.num_packages;
+ if (do_pc7)
+ average.packages.pc7 /= topo.num_packages;
average.packages.pc8 /= topo.num_packages;
average.packages.pc9 /= topo.num_packages;
@@ -961,18 +980,18 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
return 0;
- if (do_nhm_cstates && !do_slm_cstates) {
+ if (do_pc3)
if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
return -9;
+ if (do_pc6)
if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
return -10;
- }
- if (do_snb_cstates) {
+ if (do_pc2)
if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2))
return -11;
+ if (do_pc7)
if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7))
return -12;
- }
if (do_c8_c9_c10) {
if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8))
return -13;
@@ -1019,6 +1038,37 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return 0;
}
+/*
+ * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit:
+ * If you change the values, note they are used both in comparisons
+ * (>= PCL__7) and to index pkg_cstate_limit_strings[].
+ */
+
+#define PCLUKN 0 /* Unknown */
+#define PCLRSV 1 /* Reserved */
+#define PCL__0 2 /* PC0 */
+#define PCL__1 3 /* PC1 */
+#define PCL__2 4 /* PC2 */
+#define PCL__3 5 /* PC3 */
+#define PCL__4 6 /* PC4 */
+#define PCL__6 7 /* PC6 */
+#define PCL_6N 8 /* PC6 No Retention */
+#define PCL_6R 9 /* PC6 Retention */
+#define PCL__7 10 /* PC7 */
+#define PCL_7S 11 /* PC7 Shrink */
+#define PCLUNL 12 /* Unlimited */
+
+int pkg_cstate_limit = PCLUKN;
+char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2",
+ "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "unlimited"};
+
+int nhm_pkg_cstate_limits[8] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL};
+int snb_pkg_cstate_limits[8] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL};
+int hsw_pkg_cstate_limits[8] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCLRSV, PCLUNL};
+int slv_pkg_cstate_limits[8] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7};
+int amt_pkg_cstate_limits[8] = {PCL__0, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7};
+int phi_pkg_cstate_limits[8] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL};
+
void print_verbose_header(void)
{
unsigned long long msr;
@@ -1098,44 +1148,14 @@ print_nhm_turbo_ratio_limits:
fprintf(stderr, "cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", msr);
- fprintf(stderr, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: ",
+ fprintf(stderr, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n",
(msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
(msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",
(msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
(msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",
(msr & (1 << 15)) ? "" : "UN",
- (unsigned int)msr & 7);
-
-
- switch(msr & 0x7) {
- case 0:
- fprintf(stderr, do_slm_cstates ? "no pkg states" : "pc0");
- break;
- case 1:
- fprintf(stderr, do_slm_cstates ? "no pkg states" : do_snb_cstates ? "pc2" : "pc0");
- break;
- case 2:
- fprintf(stderr, do_slm_cstates ? "invalid" : do_snb_cstates ? "pc6-noret" : "pc3");
- break;
- case 3:
- fprintf(stderr, do_slm_cstates ? "invalid" : "pc6");
- break;
- case 4:
- fprintf(stderr, do_slm_cstates ? "pc4" : "pc7");
- break;
- case 5:
- fprintf(stderr, do_slm_cstates ? "invalid" : do_snb_cstates ? "pc7s" : "invalid");
- break;
- case 6:
- fprintf(stderr, do_slm_cstates ? "pc6" : "invalid");
- break;
- case 7:
- fprintf(stderr, do_slm_cstates ? "pc7" : "unlimited");
- break;
- default:
- fprintf(stderr, "invalid");
- }
- fprintf(stderr, ")\n");
+ (unsigned int)msr & 7,
+ pkg_cstate_limit_strings[pkg_cstate_limit]);
if (!do_nhm_turbo_ratio_limit)
return;
@@ -1516,9 +1536,14 @@ void check_permissions()
* MSR_CORE_C3_RESIDENCY 0x000003fc
* MSR_CORE_C6_RESIDENCY 0x000003fd
*
+ * Side effect:
+ * sets global pkg_cstate_limit to decode MSR_NHM_SNB_PKG_CST_CFG_CTL
*/
-int has_nhm_msrs(unsigned int family, unsigned int model)
+int probe_nhm_msrs(unsigned int family, unsigned int model)
{
+ unsigned long long msr;
+ int *pkg_cstate_limits;
+
if (!genuine_intel)
return 0;
@@ -1531,31 +1556,46 @@ int has_nhm_msrs(unsigned int family, unsigned int model)
case 0x1F: /* Core i7 and i5 Processor - Nehalem */
case 0x25: /* Westmere Client - Clarkdale, Arrandale */
case 0x2C: /* Westmere EP - Gulftown */
+ case 0x2E: /* Nehalem-EX Xeon - Beckton */
+ case 0x2F: /* Westmere-EX Xeon - Eagleton */
+ pkg_cstate_limits = nhm_pkg_cstate_limits;
+ break;
case 0x2A: /* SNB */
case 0x2D: /* SNB Xeon */
case 0x3A: /* IVB */
case 0x3E: /* IVB Xeon */
+ pkg_cstate_limits = snb_pkg_cstate_limits;
+ break;
case 0x3C: /* HSW */
case 0x3F: /* HSX */
case 0x45: /* HSW */
case 0x46: /* HSW */
- case 0x37: /* BYT */
- case 0x4D: /* AVN */
case 0x3D: /* BDW */
case 0x4F: /* BDX */
case 0x56: /* BDX-DE */
- case 0x2E: /* Nehalem-EX Xeon - Beckton */
- case 0x2F: /* Westmere-EX Xeon - Eagleton */
- return 1;
+ pkg_cstate_limits = hsw_pkg_cstate_limits;
+ break;
+ case 0x37: /* BYT */
+ case 0x4D: /* AVN */
+ pkg_cstate_limits = slv_pkg_cstate_limits;
+ break;
+ case 0x4C: /* AMT */
+ pkg_cstate_limits = amt_pkg_cstate_limits;
+ break;
+ case 0x57: /* PHI */
+ pkg_cstate_limits = phi_pkg_cstate_limits;
+ break;
default:
return 0;
}
+ get_msr(0, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr);
+
+ pkg_cstate_limit = pkg_cstate_limits[msr & 0x7];
+
+ return 1;
}
int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
{
- if (!has_nhm_msrs(family, model))
- return 0;
-
switch (model) {
/* Nehalem compatible, but do not include turbo-ratio limit support */
case 0x2E: /* Nehalem-EX Xeon - Beckton */
@@ -2252,13 +2292,17 @@ void check_cpuid()
do_ptm ? "" : "No ",
has_epb ? "" : "No ");
- do_nhm_platform_info = do_nhm_cstates = do_smi = has_nhm_msrs(family, model);
+ do_nhm_platform_info = do_nhm_cstates = do_smi = probe_nhm_msrs(family, model);
do_snb_cstates = has_snb_msrs(family, model);
+ do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2);
+ do_pc3 = (pkg_cstate_limit >= PCL__3);
+ do_pc6 = (pkg_cstate_limit >= PCL__6);
+ do_pc7 = do_snb_cstates && (pkg_cstate_limit >= PCL__7);
do_c8_c9_c10 = has_hsw_msrs(family, model);
do_slm_cstates = is_slm(family, model);
bclk = discover_bclk(family, model);
- do_nhm_turbo_ratio_limit = has_nhm_turbo_ratio_limit(family, model);
+ do_nhm_turbo_ratio_limit = do_nhm_platform_info && has_nhm_turbo_ratio_limit(family, model);
do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model);
rapl_probe(family, model);
perf_limit_reasons_probe(family, model);
@@ -2631,7 +2675,7 @@ int main(int argc, char **argv)
cmdline(argc, argv);
if (verbose)
- fprintf(stderr, "turbostat v3.9 23-Jan, 2015"
+ fprintf(stderr, "turbostat v3.10 9-Feb, 2015"
" - Len Brown <lenb@kernel.org>\n");
turbostat_init();