diff options
| -rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 114 |
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; | |||
| 61 | unsigned int units = 1000000; /* MHz etc */ | 61 | unsigned int units = 1000000; /* MHz etc */ |
| 62 | unsigned int genuine_intel; | 62 | unsigned int genuine_intel; |
| 63 | unsigned int has_invariant_tsc; | 63 | unsigned int has_invariant_tsc; |
| 64 | unsigned int do_nehalem_platform_info; | 64 | unsigned int do_nhm_platform_info; |
| 65 | unsigned int do_nehalem_turbo_ratio_limit; | 65 | unsigned int do_nhm_turbo_ratio_limit; |
| 66 | unsigned int do_ivt_turbo_ratio_limit; | 66 | unsigned int do_ivt_turbo_ratio_limit; |
| 67 | unsigned int extra_msr_offset32; | 67 | unsigned int extra_msr_offset32; |
| 68 | unsigned int extra_msr_offset64; | 68 | unsigned 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 | } |
| 587 | done: | 587 | done: |
| 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 | ||
| 1469 | void check_permissions() | 1468 | void 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 | ||
| 1505 | int 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 | */ | ||
| 1518 | int 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 | } |
| 1552 | int 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 | } | ||
| 1539 | int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model) | 1566 | int 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 | ||
| 1998 | int is_snb(unsigned int family, unsigned int model) | 2032 | int 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 | ||
| 2020 | int 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 | */ | ||
| 2061 | int 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 | ||
| 2070 | double discover_bclk(unsigned int family, unsigned int model) | 2111 | double 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); |
