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