|
@@ -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();
|