aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2015-01-23 00:12:33 -0500
committerLen Brown <len.brown@intel.com>2015-02-09 18:28:08 -0500
commitd7899447535929b3672442b7b42a09ae4e48fa91 (patch)
tree884d0376a050c9118a6cd4ce33693061727e7791 /tools/power
parent3a9a941d0b9361eac81fb763a89fb465f70b1c28 (diff)
tools/power turbostat: relax dependency on invariant TSC
Turbostat can be useful on systems that do not support invariant TSC, so allow it to run on those systgems. All arithmetic in turbostat using the TSC value is per-processsor, so it does not depend on the TSC values being in sync acrosss processors. Turbostat uses gettimeofday() for the measurement interval rather than using the TSC directly, so that key metric is also immune from variable TSC. Turbostat prints a TSC sanity check column: TSC_MHz = TSC_delta/interval If this column is constant and is close to the processor base frequency, then the TSC is behaving properly. The other key turbostat columns are calculated this way: Avg_Mhz = APERF_delta/interval %Busy = MPERF_delta/TSC_delta Bzy_MHz = TSC_delta/APERF_delta/MPERF_delta/interval Tested on Core2 and Core2-Xeon, and so this patch includes a few other changes to remove the assumption that target systems are Nehalem and newer. Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'tools/power')
-rw-r--r--tools/power/x86/turbostat/turbostat.c114
1 files changed, 75 insertions, 39 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 58913096d7b2..b654b641d4c3 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -61,8 +61,8 @@ unsigned int has_epb;
61unsigned int units = 1000000; /* MHz etc */ 61unsigned int units = 1000000; /* MHz etc */
62unsigned int genuine_intel; 62unsigned int genuine_intel;
63unsigned int has_invariant_tsc; 63unsigned int has_invariant_tsc;
64unsigned int do_nehalem_platform_info; 64unsigned int do_nhm_platform_info;
65unsigned int do_nehalem_turbo_ratio_limit; 65unsigned int do_nhm_turbo_ratio_limit;
66unsigned int do_ivt_turbo_ratio_limit; 66unsigned int do_ivt_turbo_ratio_limit;
67unsigned int extra_msr_offset32; 67unsigned int extra_msr_offset32;
68unsigned int extra_msr_offset64; 68unsigned int extra_msr_offset64;
@@ -284,7 +284,7 @@ void print_header(void)
284 outp += sprintf(outp, " CPU"); 284 outp += sprintf(outp, " CPU");
285 if (has_aperf) 285 if (has_aperf)
286 outp += sprintf(outp, " Avg_MHz"); 286 outp += sprintf(outp, " Avg_MHz");
287 if (do_nhm_cstates) 287 if (has_aperf)
288 outp += sprintf(outp, " %%Busy"); 288 outp += sprintf(outp, " %%Busy");
289 if (has_aperf) 289 if (has_aperf)
290 outp += sprintf(outp, " Bzy_MHz"); 290 outp += sprintf(outp, " Bzy_MHz");
@@ -340,7 +340,7 @@ void print_header(void)
340 outp += sprintf(outp, " PKG_%%"); 340 outp += sprintf(outp, " PKG_%%");
341 if (do_rapl & RAPL_DRAM_PERF_STATUS) 341 if (do_rapl & RAPL_DRAM_PERF_STATUS)
342 outp += sprintf(outp, " RAM_%%"); 342 outp += sprintf(outp, " RAM_%%");
343 } else { 343 } else if (do_rapl && rapl_joules) {
344 if (do_rapl & RAPL_PKG) 344 if (do_rapl & RAPL_PKG)
345 outp += sprintf(outp, " Pkg_J"); 345 outp += sprintf(outp, " Pkg_J");
346 if (do_rapl & RAPL_CORES) 346 if (do_rapl & RAPL_CORES)
@@ -460,25 +460,25 @@ int format_counters(struct thread_data *t, struct core_data *c,
460 outp += sprintf(outp, "%8d", t->cpu_id); 460 outp += sprintf(outp, "%8d", t->cpu_id);
461 } 461 }
462 462
463 /* AvgMHz */ 463 /* Avg_MHz */
464 if (has_aperf) 464 if (has_aperf)
465 outp += sprintf(outp, "%8.0f", 465 outp += sprintf(outp, "%8.0f",
466 1.0 / units * t->aperf / interval_float); 466 1.0 / units * t->aperf / interval_float);
467 467
468 /* %c0 */ 468 /* %Busy */
469 if (do_nhm_cstates) { 469 if (has_aperf) {
470 if (!skip_c0) 470 if (!skip_c0)
471 outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc); 471 outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc);
472 else 472 else
473 outp += sprintf(outp, "********"); 473 outp += sprintf(outp, "********");
474 } 474 }
475 475
476 /* BzyMHz */ 476 /* Bzy_MHz */
477 if (has_aperf) 477 if (has_aperf)
478 outp += sprintf(outp, "%8.0f", 478 outp += sprintf(outp, "%8.0f",
479 1.0 * t->tsc / units * t->aperf / t->mperf / interval_float); 479 1.0 * t->tsc / units * t->aperf / t->mperf / interval_float);
480 480
481 /* TSC */ 481 /* TSC_MHz */
482 outp += sprintf(outp, "%8.0f", 1.0 * t->tsc/units/interval_float); 482 outp += sprintf(outp, "%8.0f", 1.0 * t->tsc/units/interval_float);
483 483
484 /* SMI */ 484 /* SMI */
@@ -564,7 +564,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
564 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 564 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
565 if (do_rapl & RAPL_DRAM_PERF_STATUS) 565 if (do_rapl & RAPL_DRAM_PERF_STATUS)
566 outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); 566 outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
567 } else { 567 } else if (do_rapl && rapl_joules) {
568 if (do_rapl & RAPL_PKG) 568 if (do_rapl & RAPL_PKG)
569 outp += sprintf(outp, fmt8, 569 outp += sprintf(outp, fmt8,
570 p->energy_pkg * rapl_energy_units); 570 p->energy_pkg * rapl_energy_units);
@@ -581,8 +581,8 @@ int format_counters(struct thread_data *t, struct core_data *c,
581 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 581 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
582 if (do_rapl & RAPL_DRAM_PERF_STATUS) 582 if (do_rapl & RAPL_DRAM_PERF_STATUS)
583 outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); 583 outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
584 outp += sprintf(outp, fmt8, interval_float);
585 584
585 outp += sprintf(outp, fmt8, interval_float);
586 } 586 }
587done: 587done:
588 outp += sprintf(outp, "\n"); 588 outp += sprintf(outp, "\n");
@@ -1022,7 +1022,7 @@ void print_verbose_header(void)
1022 unsigned long long msr; 1022 unsigned long long msr;
1023 unsigned int ratio; 1023 unsigned int ratio;
1024 1024
1025 if (!do_nehalem_platform_info) 1025 if (!do_nhm_platform_info)
1026 return; 1026 return;
1027 1027
1028 get_msr(0, MSR_NHM_PLATFORM_INFO, &msr); 1028 get_msr(0, MSR_NHM_PLATFORM_INFO, &msr);
@@ -1135,7 +1135,7 @@ print_nhm_turbo_ratio_limits:
1135 } 1135 }
1136 fprintf(stderr, ")\n"); 1136 fprintf(stderr, ")\n");
1137 1137
1138 if (!do_nehalem_turbo_ratio_limit) 1138 if (!do_nhm_turbo_ratio_limit)
1139 return; 1139 return;
1140 1140
1141 get_msr(0, MSR_NHM_TURBO_RATIO_LIMIT, &msr); 1141 get_msr(0, MSR_NHM_TURBO_RATIO_LIMIT, &msr);
@@ -1462,8 +1462,7 @@ void check_dev_msr()
1462 struct stat sb; 1462 struct stat sb;
1463 1463
1464 if (stat("/dev/cpu/0/msr", &sb)) 1464 if (stat("/dev/cpu/0/msr", &sb))
1465 err(-5, "no /dev/cpu/0/msr\n" 1465 err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
1466 "Try \"# modprobe msr\"");
1467} 1466}
1468 1467
1469void check_permissions() 1468void check_permissions()
@@ -1496,13 +1495,27 @@ void check_permissions()
1496 /* if all else fails, thell them to be root */ 1495 /* if all else fails, thell them to be root */
1497 if (do_exit) 1496 if (do_exit)
1498 if (getuid() != 0) 1497 if (getuid() != 0)
1499 warnx("Or simply run as root"); 1498 warnx("... or simply run as root");
1500 1499
1501 if (do_exit) 1500 if (do_exit)
1502 exit(-6); 1501 exit(-6);
1503} 1502}
1504 1503
1505int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) 1504/*
1505 * NHM adds support for additional MSRs:
1506 *
1507 * MSR_SMI_COUNT 0x00000034
1508 *
1509 * MSR_NHM_PLATFORM_INFO 0x000000ce
1510 * MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2
1511 *
1512 * MSR_PKG_C3_RESIDENCY 0x000003f8
1513 * MSR_PKG_C6_RESIDENCY 0x000003f9
1514 * MSR_CORE_C3_RESIDENCY 0x000003fc
1515 * MSR_CORE_C6_RESIDENCY 0x000003fd
1516 *
1517 */
1518int has_nhm_msrs(unsigned int family, unsigned int model)
1506{ 1519{
1507 if (!genuine_intel) 1520 if (!genuine_intel)
1508 return 0; 1521 return 0;
@@ -1529,13 +1542,27 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1529 case 0x3D: /* BDW */ 1542 case 0x3D: /* BDW */
1530 case 0x4F: /* BDX */ 1543 case 0x4F: /* BDX */
1531 case 0x56: /* BDX-DE */ 1544 case 0x56: /* BDX-DE */
1532 return 1;
1533 case 0x2E: /* Nehalem-EX Xeon - Beckton */ 1545 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1534 case 0x2F: /* Westmere-EX Xeon - Eagleton */ 1546 case 0x2F: /* Westmere-EX Xeon - Eagleton */
1547 return 1;
1535 default: 1548 default:
1536 return 0; 1549 return 0;
1537 } 1550 }
1538} 1551}
1552int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
1553{
1554 if (!has_nhm_msrs(family, model))
1555 return 0;
1556
1557 switch (model) {
1558 /* Nehalem compatible, but do not include turbo-ratio limit support */
1559 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1560 case 0x2F: /* Westmere-EX Xeon - Eagleton */
1561 return 0;
1562 default:
1563 return 1;
1564 }
1565}
1539int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model) 1566int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
1540{ 1567{
1541 if (!genuine_intel) 1568 if (!genuine_intel)
@@ -1994,8 +2021,15 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1994 return 0; 2021 return 0;
1995} 2022}
1996 2023
2024/*
2025 * SNB adds support for additional MSRs:
2026 *
2027 * MSR_PKG_C7_RESIDENCY 0x000003fa
2028 * MSR_CORE_C7_RESIDENCY 0x000003fe
2029 * MSR_PKG_C2_RESIDENCY 0x0000060d
2030 */
1997 2031
1998int is_snb(unsigned int family, unsigned int model) 2032int has_snb_msrs(unsigned int family, unsigned int model)
1999{ 2033{
2000 if (!genuine_intel) 2034 if (!genuine_intel)
2001 return 0; 2035 return 0;
@@ -2017,7 +2051,14 @@ int is_snb(unsigned int family, unsigned int model)
2017 return 0; 2051 return 0;
2018} 2052}
2019 2053
2020int has_c8_c9_c10(unsigned int family, unsigned int model) 2054/*
2055 * HSW adds support for additional MSRs:
2056 *
2057 * MSR_PKG_C8_RESIDENCY 0x00000630
2058 * MSR_PKG_C9_RESIDENCY 0x00000631
2059 * MSR_PKG_C10_RESIDENCY 0x00000632
2060 */
2061int has_hsw_msrs(unsigned int family, unsigned int model)
2021{ 2062{
2022 if (!genuine_intel) 2063 if (!genuine_intel)
2023 return 0; 2064 return 0;
@@ -2069,7 +2110,7 @@ double slm_bclk(void)
2069 2110
2070double discover_bclk(unsigned int family, unsigned int model) 2111double discover_bclk(unsigned int family, unsigned int model)
2071{ 2112{
2072 if (is_snb(family, model)) 2113 if (has_snb_msrs(family, model))
2073 return 100.00; 2114 return 100.00;
2074 else if (is_slm(family, model)) 2115 else if (is_slm(family, model))
2075 return slm_bclk(); 2116 return slm_bclk();
@@ -2117,7 +2158,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
2117 } 2158 }
2118 2159
2119 /* Temperature Target MSR is Nehalem and newer only */ 2160 /* Temperature Target MSR is Nehalem and newer only */
2120 if (!do_nehalem_platform_info) 2161 if (!do_nhm_platform_info)
2121 goto guess; 2162 goto guess;
2122 2163
2123 if (get_msr(0, MSR_IA32_TEMPERATURE_TARGET, &msr)) 2164 if (get_msr(0, MSR_IA32_TEMPERATURE_TARGET, &msr))
@@ -2181,18 +2222,15 @@ void check_cpuid()
2181 ebx = ecx = edx = 0; 2222 ebx = ecx = edx = 0;
2182 __get_cpuid(0x80000000, &max_level, &ebx, &ecx, &edx); 2223 __get_cpuid(0x80000000, &max_level, &ebx, &ecx, &edx);
2183 2224
2184 if (max_level < 0x80000007) 2225 if (max_level >= 0x80000007) {
2185 errx(1, "CPUID: no invariant TSC (max_level 0x%x)", max_level);
2186 2226
2187 /* 2227 /*
2188 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8 2228 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
2189 * this check is valid for both Intel and AMD 2229 * this check is valid for both Intel and AMD
2190 */ 2230 */
2191 __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx); 2231 __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
2192 has_invariant_tsc = edx & (1 << 8); 2232 has_invariant_tsc = edx & (1 << 8);
2193 2233 }
2194 if (!has_invariant_tsc)
2195 errx(1, "No invariant TSC");
2196 2234
2197 /* 2235 /*
2198 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0 2236 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0
@@ -2215,15 +2253,13 @@ void check_cpuid()
2215 if (!has_aperf) 2253 if (!has_aperf)
2216 errx(-1, "No APERF"); 2254 errx(-1, "No APERF");
2217 2255
2218 do_nehalem_platform_info = genuine_intel && has_invariant_tsc; 2256 do_nhm_platform_info = do_nhm_cstates = do_smi = has_nhm_msrs(family, model);
2219 do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */ 2257 do_snb_cstates = has_snb_msrs(family, model);
2220 do_smi = do_nhm_cstates; 2258 do_c8_c9_c10 = has_hsw_msrs(family, model);
2221 do_snb_cstates = is_snb(family, model);
2222 do_c8_c9_c10 = has_c8_c9_c10(family, model);
2223 do_slm_cstates = is_slm(family, model); 2259 do_slm_cstates = is_slm(family, model);
2224 bclk = discover_bclk(family, model); 2260 bclk = discover_bclk(family, model);
2225 2261
2226 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); 2262 do_nhm_turbo_ratio_limit = has_nhm_turbo_ratio_limit(family, model);
2227 do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model); 2263 do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model);
2228 rapl_probe(family, model); 2264 rapl_probe(family, model);
2229 perf_limit_reasons_probe(family, model); 2265 perf_limit_reasons_probe(family, model);