diff options
-rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 188 |
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(); |