aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power/x86/turbostat/turbostat.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-02-09 18:35:39 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-02-09 18:35:39 -0500
commit994b7f10b0ea3b70a19043f8adb3326707bdc2a9 (patch)
tree5c853734205bc94c7028e626d6993f7bdbdd66b6 /tools/power/x86/turbostat/turbostat.c
parente840b41031acdbb7cd60fce7c67f46f9025d8df1 (diff)
parenta729617c58529be0be8faa22c5d45748bb0f12e5 (diff)
Merge branch 'turbostat' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux into pm-tools
Pull turbostate changes for v3.20 from Len Brown. * 'turbostat' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux: tools/power turbostat: relax dependency on APERF_MSR tools/power turbostat: relax dependency on invariant TSC tools/power turbostat: decode MSR_*_PERF_LIMIT_REASONS tools/power turbostat: relax dependency on root permission
Diffstat (limited to 'tools/power/x86/turbostat/turbostat.c')
-rw-r--r--tools/power/x86/turbostat/turbostat.c338
1 files changed, 264 insertions, 74 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 5b1b807265a1..a02c02f25e88 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -38,6 +38,8 @@
38#include <ctype.h> 38#include <ctype.h>
39#include <sched.h> 39#include <sched.h>
40#include <cpuid.h> 40#include <cpuid.h>
41#include <linux/capability.h>
42#include <errno.h>
41 43
42char *proc_stat = "/proc/stat"; 44char *proc_stat = "/proc/stat";
43unsigned int interval_sec = 5; /* set with -i interval_sec */ 45unsigned int interval_sec = 5; /* set with -i interval_sec */
@@ -59,8 +61,8 @@ unsigned int has_epb;
59unsigned int units = 1000000; /* MHz etc */ 61unsigned int units = 1000000; /* MHz etc */
60unsigned int genuine_intel; 62unsigned int genuine_intel;
61unsigned int has_invariant_tsc; 63unsigned int has_invariant_tsc;
62unsigned int do_nehalem_platform_info; 64unsigned int do_nhm_platform_info;
63unsigned int do_nehalem_turbo_ratio_limit; 65unsigned int do_nhm_turbo_ratio_limit;
64unsigned int do_ivt_turbo_ratio_limit; 66unsigned int do_ivt_turbo_ratio_limit;
65unsigned int extra_msr_offset32; 67unsigned int extra_msr_offset32;
66unsigned int extra_msr_offset64; 68unsigned int extra_msr_offset64;
@@ -81,6 +83,9 @@ unsigned int tcc_activation_temp;
81unsigned int tcc_activation_temp_override; 83unsigned int tcc_activation_temp_override;
82double rapl_power_units, rapl_energy_units, rapl_time_units; 84double rapl_power_units, rapl_energy_units, rapl_time_units;
83double rapl_joule_counter_range; 85double rapl_joule_counter_range;
86unsigned int do_core_perf_limit_reasons;
87unsigned int do_gfx_perf_limit_reasons;
88unsigned int do_ring_perf_limit_reasons;
84 89
85#define RAPL_PKG (1 << 0) 90#define RAPL_PKG (1 << 0)
86 /* 0x610 MSR_PKG_POWER_LIMIT */ 91 /* 0x610 MSR_PKG_POWER_LIMIT */
@@ -251,15 +256,13 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
251 sprintf(pathname, "/dev/cpu/%d/msr", cpu); 256 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
252 fd = open(pathname, O_RDONLY); 257 fd = open(pathname, O_RDONLY);
253 if (fd < 0) 258 if (fd < 0)
254 return -1; 259 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
255 260
256 retval = pread(fd, msr, sizeof *msr, offset); 261 retval = pread(fd, msr, sizeof *msr, offset);
257 close(fd); 262 close(fd);
258 263
259 if (retval != sizeof *msr) { 264 if (retval != sizeof *msr)
260 fprintf(stderr, "%s offset 0x%llx read failed\n", pathname, (unsigned long long)offset); 265 err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
261 return -1;
262 }
263 266
264 return 0; 267 return 0;
265} 268}
@@ -281,7 +284,7 @@ void print_header(void)
281 outp += sprintf(outp, " CPU"); 284 outp += sprintf(outp, " CPU");
282 if (has_aperf) 285 if (has_aperf)
283 outp += sprintf(outp, " Avg_MHz"); 286 outp += sprintf(outp, " Avg_MHz");
284 if (do_nhm_cstates) 287 if (has_aperf)
285 outp += sprintf(outp, " %%Busy"); 288 outp += sprintf(outp, " %%Busy");
286 if (has_aperf) 289 if (has_aperf)
287 outp += sprintf(outp, " Bzy_MHz"); 290 outp += sprintf(outp, " Bzy_MHz");
@@ -337,7 +340,7 @@ void print_header(void)
337 outp += sprintf(outp, " PKG_%%"); 340 outp += sprintf(outp, " PKG_%%");
338 if (do_rapl & RAPL_DRAM_PERF_STATUS) 341 if (do_rapl & RAPL_DRAM_PERF_STATUS)
339 outp += sprintf(outp, " RAM_%%"); 342 outp += sprintf(outp, " RAM_%%");
340 } else { 343 } else if (do_rapl && rapl_joules) {
341 if (do_rapl & RAPL_PKG) 344 if (do_rapl & RAPL_PKG)
342 outp += sprintf(outp, " Pkg_J"); 345 outp += sprintf(outp, " Pkg_J");
343 if (do_rapl & RAPL_CORES) 346 if (do_rapl & RAPL_CORES)
@@ -457,25 +460,25 @@ int format_counters(struct thread_data *t, struct core_data *c,
457 outp += sprintf(outp, "%8d", t->cpu_id); 460 outp += sprintf(outp, "%8d", t->cpu_id);
458 } 461 }
459 462
460 /* AvgMHz */ 463 /* Avg_MHz */
461 if (has_aperf) 464 if (has_aperf)
462 outp += sprintf(outp, "%8.0f", 465 outp += sprintf(outp, "%8.0f",
463 1.0 / units * t->aperf / interval_float); 466 1.0 / units * t->aperf / interval_float);
464 467
465 /* %c0 */ 468 /* %Busy */
466 if (do_nhm_cstates) { 469 if (has_aperf) {
467 if (!skip_c0) 470 if (!skip_c0)
468 outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc); 471 outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc);
469 else 472 else
470 outp += sprintf(outp, "********"); 473 outp += sprintf(outp, "********");
471 } 474 }
472 475
473 /* BzyMHz */ 476 /* Bzy_MHz */
474 if (has_aperf) 477 if (has_aperf)
475 outp += sprintf(outp, "%8.0f", 478 outp += sprintf(outp, "%8.0f",
476 1.0 * t->tsc / units * t->aperf / t->mperf / interval_float); 479 1.0 * t->tsc / units * t->aperf / t->mperf / interval_float);
477 480
478 /* TSC */ 481 /* TSC_MHz */
479 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);
480 483
481 /* SMI */ 484 /* SMI */
@@ -561,7 +564,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
561 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);
562 if (do_rapl & RAPL_DRAM_PERF_STATUS) 565 if (do_rapl & RAPL_DRAM_PERF_STATUS)
563 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);
564 } else { 567 } else if (do_rapl && rapl_joules) {
565 if (do_rapl & RAPL_PKG) 568 if (do_rapl & RAPL_PKG)
566 outp += sprintf(outp, fmt8, 569 outp += sprintf(outp, fmt8,
567 p->energy_pkg * rapl_energy_units); 570 p->energy_pkg * rapl_energy_units);
@@ -578,8 +581,8 @@ int format_counters(struct thread_data *t, struct core_data *c,
578 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);
579 if (do_rapl & RAPL_DRAM_PERF_STATUS) 582 if (do_rapl & RAPL_DRAM_PERF_STATUS)
580 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);
581 outp += sprintf(outp, fmt8, interval_float);
582 584
585 outp += sprintf(outp, fmt8, interval_float);
583 } 586 }
584done: 587done:
585 outp += sprintf(outp, "\n"); 588 outp += sprintf(outp, "\n");
@@ -670,24 +673,26 @@ delta_thread(struct thread_data *new, struct thread_data *old,
670 673
671 old->c1 = new->c1 - old->c1; 674 old->c1 = new->c1 - old->c1;
672 675
673 if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) { 676 if (has_aperf) {
674 old->aperf = new->aperf - old->aperf; 677 if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
675 old->mperf = new->mperf - old->mperf; 678 old->aperf = new->aperf - old->aperf;
676 } else { 679 old->mperf = new->mperf - old->mperf;
680 } else {
677 681
678 if (!aperf_mperf_unstable) { 682 if (!aperf_mperf_unstable) {
679 fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname); 683 fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname);
680 fprintf(stderr, "* Frequency results do not cover entire interval *\n"); 684 fprintf(stderr, "* Frequency results do not cover entire interval *\n");
681 fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n"); 685 fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n");
682 686
683 aperf_mperf_unstable = 1; 687 aperf_mperf_unstable = 1;
688 }
689 /*
690 * mperf delta is likely a huge "positive" number
691 * can not use it for calculating c0 time
692 */
693 skip_c0 = 1;
694 skip_c1 = 1;
684 } 695 }
685 /*
686 * mperf delta is likely a huge "positive" number
687 * can not use it for calculating c0 time
688 */
689 skip_c0 = 1;
690 skip_c1 = 1;
691 } 696 }
692 697
693 698
@@ -1019,7 +1024,7 @@ void print_verbose_header(void)
1019 unsigned long long msr; 1024 unsigned long long msr;
1020 unsigned int ratio; 1025 unsigned int ratio;
1021 1026
1022 if (!do_nehalem_platform_info) 1027 if (!do_nhm_platform_info)
1023 return; 1028 return;
1024 1029
1025 get_msr(0, MSR_NHM_PLATFORM_INFO, &msr); 1030 get_msr(0, MSR_NHM_PLATFORM_INFO, &msr);
@@ -1132,7 +1137,7 @@ print_nhm_turbo_ratio_limits:
1132 } 1137 }
1133 fprintf(stderr, ")\n"); 1138 fprintf(stderr, ")\n");
1134 1139
1135 if (!do_nehalem_turbo_ratio_limit) 1140 if (!do_nhm_turbo_ratio_limit)
1136 return; 1141 return;
1137 1142
1138 get_msr(0, MSR_NHM_TURBO_RATIO_LIMIT, &msr); 1143 get_msr(0, MSR_NHM_TURBO_RATIO_LIMIT, &msr);
@@ -1178,6 +1183,7 @@ print_nhm_turbo_ratio_limits:
1178 if (ratio) 1183 if (ratio)
1179 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", 1184 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
1180 ratio, bclk, ratio * bclk); 1185 ratio, bclk, ratio * bclk);
1186
1181} 1187}
1182 1188
1183void free_all_buffers(void) 1189void free_all_buffers(void)
@@ -1458,17 +1464,60 @@ void check_dev_msr()
1458 struct stat sb; 1464 struct stat sb;
1459 1465
1460 if (stat("/dev/cpu/0/msr", &sb)) 1466 if (stat("/dev/cpu/0/msr", &sb))
1461 err(-5, "no /dev/cpu/0/msr\n" 1467 err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
1462 "Try \"# modprobe msr\"");
1463} 1468}
1464 1469
1465void check_super_user() 1470void check_permissions()
1466{ 1471{
1467 if (getuid() != 0) 1472 struct __user_cap_header_struct cap_header_data;
1468 errx(-6, "must be root"); 1473 cap_user_header_t cap_header = &cap_header_data;
1474 struct __user_cap_data_struct cap_data_data;
1475 cap_user_data_t cap_data = &cap_data_data;
1476 extern int capget(cap_user_header_t hdrp, cap_user_data_t datap);
1477 int do_exit = 0;
1478
1479 /* check for CAP_SYS_RAWIO */
1480 cap_header->pid = getpid();
1481 cap_header->version = _LINUX_CAPABILITY_VERSION;
1482 if (capget(cap_header, cap_data) < 0)
1483 err(-6, "capget(2) failed");
1484
1485 if ((cap_data->effective & (1 << CAP_SYS_RAWIO)) == 0) {
1486 do_exit++;
1487 warnx("capget(CAP_SYS_RAWIO) failed,"
1488 " try \"# setcap cap_sys_rawio=ep %s\"", progname);
1489 }
1490
1491 /* test file permissions */
1492 if (euidaccess("/dev/cpu/0/msr", R_OK)) {
1493 do_exit++;
1494 warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr");
1495 }
1496
1497 /* if all else fails, thell them to be root */
1498 if (do_exit)
1499 if (getuid() != 0)
1500 warnx("... or simply run as root");
1501
1502 if (do_exit)
1503 exit(-6);
1469} 1504}
1470 1505
1471int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) 1506/*
1507 * NHM adds support for additional MSRs:
1508 *
1509 * MSR_SMI_COUNT 0x00000034
1510 *
1511 * MSR_NHM_PLATFORM_INFO 0x000000ce
1512 * MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2
1513 *
1514 * MSR_PKG_C3_RESIDENCY 0x000003f8
1515 * MSR_PKG_C6_RESIDENCY 0x000003f9
1516 * MSR_CORE_C3_RESIDENCY 0x000003fc
1517 * MSR_CORE_C6_RESIDENCY 0x000003fd
1518 *
1519 */
1520int has_nhm_msrs(unsigned int family, unsigned int model)
1472{ 1521{
1473 if (!genuine_intel) 1522 if (!genuine_intel)
1474 return 0; 1523 return 0;
@@ -1495,13 +1544,27 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1495 case 0x3D: /* BDW */ 1544 case 0x3D: /* BDW */
1496 case 0x4F: /* BDX */ 1545 case 0x4F: /* BDX */
1497 case 0x56: /* BDX-DE */ 1546 case 0x56: /* BDX-DE */
1498 return 1;
1499 case 0x2E: /* Nehalem-EX Xeon - Beckton */ 1547 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1500 case 0x2F: /* Westmere-EX Xeon - Eagleton */ 1548 case 0x2F: /* Westmere-EX Xeon - Eagleton */
1549 return 1;
1501 default: 1550 default:
1502 return 0; 1551 return 0;
1503 } 1552 }
1504} 1553}
1554int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
1555{
1556 if (!has_nhm_msrs(family, model))
1557 return 0;
1558
1559 switch (model) {
1560 /* Nehalem compatible, but do not include turbo-ratio limit support */
1561 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1562 case 0x2F: /* Westmere-EX Xeon - Eagleton */
1563 return 0;
1564 default:
1565 return 1;
1566 }
1567}
1505int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model) 1568int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
1506{ 1569{
1507 if (!genuine_intel) 1570 if (!genuine_intel)
@@ -1564,6 +1627,103 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1564 return 0; 1627 return 0;
1565} 1628}
1566 1629
1630/*
1631 * print_perf_limit()
1632 */
1633int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1634{
1635 unsigned long long msr;
1636 int cpu;
1637
1638 cpu = t->cpu_id;
1639
1640 /* per-package */
1641 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
1642 return 0;
1643
1644 if (cpu_migrate(cpu)) {
1645 fprintf(stderr, "Could not migrate to CPU %d\n", cpu);
1646 return -1;
1647 }
1648
1649 if (do_core_perf_limit_reasons) {
1650 get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr);
1651 fprintf(stderr, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
1652 fprintf(stderr, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",
1653 (msr & 1 << 0) ? "PROCHOT, " : "",
1654 (msr & 1 << 1) ? "ThermStatus, " : "",
1655 (msr & 1 << 2) ? "bit2, " : "",
1656 (msr & 1 << 4) ? "Graphics, " : "",
1657 (msr & 1 << 5) ? "Auto-HWP, " : "",
1658 (msr & 1 << 6) ? "VR-Therm, " : "",
1659 (msr & 1 << 8) ? "Amps, " : "",
1660 (msr & 1 << 9) ? "CorePwr, " : "",
1661 (msr & 1 << 10) ? "PkgPwrL1, " : "",
1662 (msr & 1 << 11) ? "PkgPwrL2, " : "",
1663 (msr & 1 << 12) ? "MultiCoreTurbo, " : "",
1664 (msr & 1 << 13) ? "Transitions, " : "",
1665 (msr & 1 << 14) ? "bit14, " : "",
1666 (msr & 1 << 15) ? "bit15, " : "");
1667 fprintf(stderr, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
1668 (msr & 1 << 16) ? "PROCHOT, " : "",
1669 (msr & 1 << 17) ? "ThermStatus, " : "",
1670 (msr & 1 << 18) ? "bit18, " : "",
1671 (msr & 1 << 20) ? "Graphics, " : "",
1672 (msr & 1 << 21) ? "Auto-HWP, " : "",
1673 (msr & 1 << 22) ? "VR-Therm, " : "",
1674 (msr & 1 << 24) ? "Amps, " : "",
1675 (msr & 1 << 25) ? "CorePwr, " : "",
1676 (msr & 1 << 26) ? "PkgPwrL1, " : "",
1677 (msr & 1 << 27) ? "PkgPwrL2, " : "",
1678 (msr & 1 << 28) ? "MultiCoreTurbo, " : "",
1679 (msr & 1 << 29) ? "Transitions, " : "",
1680 (msr & 1 << 30) ? "bit30, " : "",
1681 (msr & 1 << 31) ? "bit31, " : "");
1682
1683 }
1684 if (do_gfx_perf_limit_reasons) {
1685 get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr);
1686 fprintf(stderr, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
1687 fprintf(stderr, " (Active: %s%s%s%s%s%s%s%s)",
1688 (msr & 1 << 0) ? "PROCHOT, " : "",
1689 (msr & 1 << 1) ? "ThermStatus, " : "",
1690 (msr & 1 << 4) ? "Graphics, " : "",
1691 (msr & 1 << 6) ? "VR-Therm, " : "",
1692 (msr & 1 << 8) ? "Amps, " : "",
1693 (msr & 1 << 9) ? "GFXPwr, " : "",
1694 (msr & 1 << 10) ? "PkgPwrL1, " : "",
1695 (msr & 1 << 11) ? "PkgPwrL2, " : "");
1696 fprintf(stderr, " (Logged: %s%s%s%s%s%s%s%s)\n",
1697 (msr & 1 << 16) ? "PROCHOT, " : "",
1698 (msr & 1 << 17) ? "ThermStatus, " : "",
1699 (msr & 1 << 20) ? "Graphics, " : "",
1700 (msr & 1 << 22) ? "VR-Therm, " : "",
1701 (msr & 1 << 24) ? "Amps, " : "",
1702 (msr & 1 << 25) ? "GFXPwr, " : "",
1703 (msr & 1 << 26) ? "PkgPwrL1, " : "",
1704 (msr & 1 << 27) ? "PkgPwrL2, " : "");
1705 }
1706 if (do_ring_perf_limit_reasons) {
1707 get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr);
1708 fprintf(stderr, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
1709 fprintf(stderr, " (Active: %s%s%s%s%s%s)",
1710 (msr & 1 << 0) ? "PROCHOT, " : "",
1711 (msr & 1 << 1) ? "ThermStatus, " : "",
1712 (msr & 1 << 6) ? "VR-Therm, " : "",
1713 (msr & 1 << 8) ? "Amps, " : "",
1714 (msr & 1 << 10) ? "PkgPwrL1, " : "",
1715 (msr & 1 << 11) ? "PkgPwrL2, " : "");
1716 fprintf(stderr, " (Logged: %s%s%s%s%s%s)\n",
1717 (msr & 1 << 16) ? "PROCHOT, " : "",
1718 (msr & 1 << 17) ? "ThermStatus, " : "",
1719 (msr & 1 << 22) ? "VR-Therm, " : "",
1720 (msr & 1 << 24) ? "Amps, " : "",
1721 (msr & 1 << 26) ? "PkgPwrL1, " : "",
1722 (msr & 1 << 27) ? "PkgPwrL2, " : "");
1723 }
1724 return 0;
1725}
1726
1567#define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */ 1727#define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */
1568#define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */ 1728#define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */
1569 1729
@@ -1653,6 +1813,27 @@ void rapl_probe(unsigned int family, unsigned int model)
1653 return; 1813 return;
1654} 1814}
1655 1815
1816void perf_limit_reasons_probe(family, model)
1817{
1818 if (!genuine_intel)
1819 return;
1820
1821 if (family != 6)
1822 return;
1823
1824 switch (model) {
1825 case 0x3C: /* HSW */
1826 case 0x45: /* HSW */
1827 case 0x46: /* HSW */
1828 do_gfx_perf_limit_reasons = 1;
1829 case 0x3F: /* HSX */
1830 do_core_perf_limit_reasons = 1;
1831 do_ring_perf_limit_reasons = 1;
1832 default:
1833 return;
1834 }
1835}
1836
1656int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p) 1837int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1657{ 1838{
1658 unsigned long long msr; 1839 unsigned long long msr;
@@ -1842,8 +2023,15 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1842 return 0; 2023 return 0;
1843} 2024}
1844 2025
2026/*
2027 * SNB adds support for additional MSRs:
2028 *
2029 * MSR_PKG_C7_RESIDENCY 0x000003fa
2030 * MSR_CORE_C7_RESIDENCY 0x000003fe
2031 * MSR_PKG_C2_RESIDENCY 0x0000060d
2032 */
1845 2033
1846int is_snb(unsigned int family, unsigned int model) 2034int has_snb_msrs(unsigned int family, unsigned int model)
1847{ 2035{
1848 if (!genuine_intel) 2036 if (!genuine_intel)
1849 return 0; 2037 return 0;
@@ -1865,7 +2053,14 @@ int is_snb(unsigned int family, unsigned int model)
1865 return 0; 2053 return 0;
1866} 2054}
1867 2055
1868int has_c8_c9_c10(unsigned int family, unsigned int model) 2056/*
2057 * HSW adds support for additional MSRs:
2058 *
2059 * MSR_PKG_C8_RESIDENCY 0x00000630
2060 * MSR_PKG_C9_RESIDENCY 0x00000631
2061 * MSR_PKG_C10_RESIDENCY 0x00000632
2062 */
2063int has_hsw_msrs(unsigned int family, unsigned int model)
1869{ 2064{
1870 if (!genuine_intel) 2065 if (!genuine_intel)
1871 return 0; 2066 return 0;
@@ -1917,7 +2112,7 @@ double slm_bclk(void)
1917 2112
1918double discover_bclk(unsigned int family, unsigned int model) 2113double discover_bclk(unsigned int family, unsigned int model)
1919{ 2114{
1920 if (is_snb(family, model)) 2115 if (has_snb_msrs(family, model))
1921 return 100.00; 2116 return 100.00;
1922 else if (is_slm(family, model)) 2117 else if (is_slm(family, model))
1923 return slm_bclk(); 2118 return slm_bclk();
@@ -1965,7 +2160,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
1965 } 2160 }
1966 2161
1967 /* Temperature Target MSR is Nehalem and newer only */ 2162 /* Temperature Target MSR is Nehalem and newer only */
1968 if (!do_nehalem_platform_info) 2163 if (!do_nhm_platform_info)
1969 goto guess; 2164 goto guess;
1970 2165
1971 if (get_msr(0, MSR_IA32_TEMPERATURE_TARGET, &msr)) 2166 if (get_msr(0, MSR_IA32_TEMPERATURE_TARGET, &msr))
@@ -2029,18 +2224,15 @@ void check_cpuid()
2029 ebx = ecx = edx = 0; 2224 ebx = ecx = edx = 0;
2030 __get_cpuid(0x80000000, &max_level, &ebx, &ecx, &edx); 2225 __get_cpuid(0x80000000, &max_level, &ebx, &ecx, &edx);
2031 2226
2032 if (max_level < 0x80000007) 2227 if (max_level >= 0x80000007) {
2033 errx(1, "CPUID: no invariant TSC (max_level 0x%x)", max_level);
2034 2228
2035 /* 2229 /*
2036 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8 2230 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
2037 * this check is valid for both Intel and AMD 2231 * this check is valid for both Intel and AMD
2038 */ 2232 */
2039 __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx); 2233 __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
2040 has_invariant_tsc = edx & (1 << 8); 2234 has_invariant_tsc = edx & (1 << 8);
2041 2235 }
2042 if (!has_invariant_tsc)
2043 errx(1, "No invariant TSC");
2044 2236
2045 /* 2237 /*
2046 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0 2238 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0
@@ -2054,26 +2246,22 @@ void check_cpuid()
2054 has_epb = ecx & (1 << 3); 2246 has_epb = ecx & (1 << 3);
2055 2247
2056 if (verbose) 2248 if (verbose)
2057 fprintf(stderr, "CPUID(6): %s%s%s%s\n", 2249 fprintf(stderr, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sEPB\n",
2058 has_aperf ? "APERF" : "No APERF!", 2250 has_aperf ? "" : "No ",
2059 do_dts ? ", DTS" : "", 2251 do_dts ? "" : "No ",
2060 do_ptm ? ", PTM": "", 2252 do_ptm ? "" : "No ",
2061 has_epb ? ", EPB": ""); 2253 has_epb ? "" : "No ");
2062 2254
2063 if (!has_aperf) 2255 do_nhm_platform_info = do_nhm_cstates = do_smi = has_nhm_msrs(family, model);
2064 errx(-1, "No APERF"); 2256 do_snb_cstates = has_snb_msrs(family, model);
2065 2257 do_c8_c9_c10 = has_hsw_msrs(family, model);
2066 do_nehalem_platform_info = genuine_intel && has_invariant_tsc;
2067 do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */
2068 do_smi = do_nhm_cstates;
2069 do_snb_cstates = is_snb(family, model);
2070 do_c8_c9_c10 = has_c8_c9_c10(family, model);
2071 do_slm_cstates = is_slm(family, model); 2258 do_slm_cstates = is_slm(family, model);
2072 bclk = discover_bclk(family, model); 2259 bclk = discover_bclk(family, model);
2073 2260
2074 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); 2261 do_nhm_turbo_ratio_limit = has_nhm_turbo_ratio_limit(family, model);
2075 do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model); 2262 do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model);
2076 rapl_probe(family, model); 2263 rapl_probe(family, model);
2264 perf_limit_reasons_probe(family, model);
2077 2265
2078 return; 2266 return;
2079} 2267}
@@ -2299,10 +2487,9 @@ void setup_all_buffers(void)
2299 2487
2300void turbostat_init() 2488void turbostat_init()
2301{ 2489{
2302 check_cpuid();
2303
2304 check_dev_msr(); 2490 check_dev_msr();
2305 check_super_user(); 2491 check_permissions();
2492 check_cpuid();
2306 2493
2307 setup_all_buffers(); 2494 setup_all_buffers();
2308 2495
@@ -2313,6 +2500,9 @@ void turbostat_init()
2313 for_all_cpus(print_epb, ODD_COUNTERS); 2500 for_all_cpus(print_epb, ODD_COUNTERS);
2314 2501
2315 if (verbose) 2502 if (verbose)
2503 for_all_cpus(print_perf_limit, ODD_COUNTERS);
2504
2505 if (verbose)
2316 for_all_cpus(print_rapl, ODD_COUNTERS); 2506 for_all_cpus(print_rapl, ODD_COUNTERS);
2317 2507
2318 for_all_cpus(set_temperature_target, ODD_COUNTERS); 2508 for_all_cpus(set_temperature_target, ODD_COUNTERS);
@@ -2441,7 +2631,7 @@ int main(int argc, char **argv)
2441 cmdline(argc, argv); 2631 cmdline(argc, argv);
2442 2632
2443 if (verbose) 2633 if (verbose)
2444 fprintf(stderr, "turbostat v3.7 Feb 6, 2014" 2634 fprintf(stderr, "turbostat v3.9 23-Jan, 2015"
2445 " - Len Brown <lenb@kernel.org>\n"); 2635 " - Len Brown <lenb@kernel.org>\n");
2446 2636
2447 turbostat_init(); 2637 turbostat_init();