aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2013-11-09 00:30:16 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-12 17:16:02 -0500
commit144b44b1355df48eac7fee4c7519f4be0aafa4a3 (patch)
tree8d2d1d0c18acb9bc328898b4f3b1c61fede8be7e /tools
parent5e01dc7b26d9f24f39abace5da98ccbd6a5ceb52 (diff)
tools / power turbostat: Support Silvermont
Support the next generation Intel Atom processor mirco-architecture, formerly called Silvermont. The server version, formerly called "Avoton", is named the "Intel(R) Atom(TM) Processor C2000 Product Family". The client version, formerly called "Bay Trail", is named the "Intel Atom Processor Z3000 Series", as well as various "Intel Pentium Processor" and "Intel Celeron Processor" brands, depending on form-factor. Silvermont has a set of MSRs not far off from NHM, but the RAPL register set is a sub-set of those previously supported. Signed-off-by: Len Brown <len.brown@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/power/x86/turbostat/turbostat.c197
1 files changed, 141 insertions, 56 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index fe702076ca46..9d77f13c2d25 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -2,7 +2,7 @@
2 * turbostat -- show CPU frequency and C-state residency 2 * turbostat -- show CPU frequency and C-state residency
3 * on modern Intel turbo-capable processors. 3 * on modern Intel turbo-capable processors.
4 * 4 *
5 * Copyright (c) 2012 Intel Corporation. 5 * Copyright (c) 2013 Intel Corporation.
6 * Len Brown <len.brown@intel.com> 6 * Len Brown <len.brown@intel.com>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
@@ -47,6 +47,8 @@ unsigned int skip_c1;
47unsigned int do_nhm_cstates; 47unsigned int do_nhm_cstates;
48unsigned int do_snb_cstates; 48unsigned int do_snb_cstates;
49unsigned int do_c8_c9_c10; 49unsigned int do_c8_c9_c10;
50unsigned int do_slm_cstates;
51unsigned int use_c1_residency_msr;
50unsigned int has_aperf; 52unsigned int has_aperf;
51unsigned int has_epb; 53unsigned int has_epb;
52unsigned int units = 1000000000; /* Ghz etc */ 54unsigned int units = 1000000000; /* Ghz etc */
@@ -81,6 +83,8 @@ double rapl_joule_counter_range;
81#define RAPL_DRAM (1 << 3) 83#define RAPL_DRAM (1 << 3)
82#define RAPL_PKG_PERF_STATUS (1 << 4) 84#define RAPL_PKG_PERF_STATUS (1 << 4)
83#define RAPL_DRAM_PERF_STATUS (1 << 5) 85#define RAPL_DRAM_PERF_STATUS (1 << 5)
86#define RAPL_PKG_POWER_INFO (1 << 6)
87#define RAPL_CORE_POLICY (1 << 7)
84#define TJMAX_DEFAULT 100 88#define TJMAX_DEFAULT 100
85 89
86#define MAX(a, b) ((a) > (b) ? (a) : (b)) 90#define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -96,7 +100,7 @@ struct thread_data {
96 unsigned long long tsc; 100 unsigned long long tsc;
97 unsigned long long aperf; 101 unsigned long long aperf;
98 unsigned long long mperf; 102 unsigned long long mperf;
99 unsigned long long c1; /* derived */ 103 unsigned long long c1;
100 unsigned long long extra_msr64; 104 unsigned long long extra_msr64;
101 unsigned long long extra_delta64; 105 unsigned long long extra_delta64;
102 unsigned long long extra_msr32; 106 unsigned long long extra_msr32;
@@ -266,7 +270,7 @@ void print_header(void)
266 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64); 270 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
267 if (do_nhm_cstates) 271 if (do_nhm_cstates)
268 outp += sprintf(outp, " %%c1"); 272 outp += sprintf(outp, " %%c1");
269 if (do_nhm_cstates) 273 if (do_nhm_cstates && !do_slm_cstates)
270 outp += sprintf(outp, " %%c3"); 274 outp += sprintf(outp, " %%c3");
271 if (do_nhm_cstates) 275 if (do_nhm_cstates)
272 outp += sprintf(outp, " %%c6"); 276 outp += sprintf(outp, " %%c6");
@@ -280,9 +284,9 @@ void print_header(void)
280 284
281 if (do_snb_cstates) 285 if (do_snb_cstates)
282 outp += sprintf(outp, " %%pc2"); 286 outp += sprintf(outp, " %%pc2");
283 if (do_nhm_cstates) 287 if (do_nhm_cstates && !do_slm_cstates)
284 outp += sprintf(outp, " %%pc3"); 288 outp += sprintf(outp, " %%pc3");
285 if (do_nhm_cstates) 289 if (do_nhm_cstates && !do_slm_cstates)
286 outp += sprintf(outp, " %%pc6"); 290 outp += sprintf(outp, " %%pc6");
287 if (do_snb_cstates) 291 if (do_snb_cstates)
288 outp += sprintf(outp, " %%pc7"); 292 outp += sprintf(outp, " %%pc7");
@@ -480,7 +484,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
480 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 484 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
481 goto done; 485 goto done;
482 486
483 if (do_nhm_cstates) 487 if (do_nhm_cstates && !do_slm_cstates)
484 outp += sprintf(outp, " %6.2f", 100.0 * c->c3/t->tsc); 488 outp += sprintf(outp, " %6.2f", 100.0 * c->c3/t->tsc);
485 if (do_nhm_cstates) 489 if (do_nhm_cstates)
486 outp += sprintf(outp, " %6.2f", 100.0 * c->c6/t->tsc); 490 outp += sprintf(outp, " %6.2f", 100.0 * c->c6/t->tsc);
@@ -499,9 +503,9 @@ int format_counters(struct thread_data *t, struct core_data *c,
499 503
500 if (do_snb_cstates) 504 if (do_snb_cstates)
501 outp += sprintf(outp, " %6.2f", 100.0 * p->pc2/t->tsc); 505 outp += sprintf(outp, " %6.2f", 100.0 * p->pc2/t->tsc);
502 if (do_nhm_cstates) 506 if (do_nhm_cstates && !do_slm_cstates)
503 outp += sprintf(outp, " %6.2f", 100.0 * p->pc3/t->tsc); 507 outp += sprintf(outp, " %6.2f", 100.0 * p->pc3/t->tsc);
504 if (do_nhm_cstates) 508 if (do_nhm_cstates && !do_slm_cstates)
505 outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc); 509 outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc);
506 if (do_snb_cstates) 510 if (do_snb_cstates)
507 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); 511 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc);
@@ -648,17 +652,24 @@ delta_thread(struct thread_data *new, struct thread_data *old,
648 } 652 }
649 653
650 654
651 /* 655 if (use_c1_residency_msr) {
652 * As counter collection is not atomic, 656 /*
653 * it is possible for mperf's non-halted cycles + idle states 657 * Some models have a dedicated C1 residency MSR,
654 * to exceed TSC's all cycles: show c1 = 0% in that case. 658 * which should be more accurate than the derivation below.
655 */ 659 */
656 if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > old->tsc) 660 } else {
657 old->c1 = 0; 661 /*
658 else { 662 * As counter collection is not atomic,
659 /* normal case, derive c1 */ 663 * it is possible for mperf's non-halted cycles + idle states
660 old->c1 = old->tsc - old->mperf - core_delta->c3 664 * to exceed TSC's all cycles: show c1 = 0% in that case.
665 */
666 if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > old->tsc)
667 old->c1 = 0;
668 else {
669 /* normal case, derive c1 */
670 old->c1 = old->tsc - old->mperf - core_delta->c3
661 - core_delta->c6 - core_delta->c7; 671 - core_delta->c6 - core_delta->c7;
672 }
662 } 673 }
663 674
664 if (old->mperf == 0) { 675 if (old->mperf == 0) {
@@ -872,13 +883,21 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
872 if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64)) 883 if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64))
873 return -5; 884 return -5;
874 885
886 if (use_c1_residency_msr) {
887 if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1))
888 return -6;
889 }
890
875 /* collect core counters only for 1st thread in core */ 891 /* collect core counters only for 1st thread in core */
876 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 892 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
877 return 0; 893 return 0;
878 894
879 if (do_nhm_cstates) { 895 if (do_nhm_cstates && !do_slm_cstates) {
880 if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3)) 896 if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
881 return -6; 897 return -6;
898 }
899
900 if (do_nhm_cstates) {
882 if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6)) 901 if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
883 return -7; 902 return -7;
884 } 903 }
@@ -898,7 +917,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
898 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 917 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
899 return 0; 918 return 0;
900 919
901 if (do_nhm_cstates) { 920 if (do_nhm_cstates && !do_slm_cstates) {
902 if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3)) 921 if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
903 return -9; 922 return -9;
904 if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6)) 923 if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
@@ -977,7 +996,7 @@ void print_verbose_header(void)
977 ratio, bclk, ratio * bclk); 996 ratio, bclk, ratio * bclk);
978 997
979 get_msr(0, MSR_IA32_POWER_CTL, &msr); 998 get_msr(0, MSR_IA32_POWER_CTL, &msr);
980 fprintf(stderr, "cpu0: MSR_IA32_POWER_CTL: 0x%08llx (C1E: %sabled)\n", 999 fprintf(stderr, "cpu0: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",
981 msr, msr & 0x2 ? "EN" : "DIS"); 1000 msr, msr & 0x2 ? "EN" : "DIS");
982 1001
983 if (!do_ivt_turbo_ratio_limit) 1002 if (!do_ivt_turbo_ratio_limit)
@@ -1046,25 +1065,28 @@ print_nhm_turbo_ratio_limits:
1046 1065
1047 switch(msr & 0x7) { 1066 switch(msr & 0x7) {
1048 case 0: 1067 case 0:
1049 fprintf(stderr, "pc0"); 1068 fprintf(stderr, do_slm_cstates ? "no pkg states" : "pc0");
1050 break; 1069 break;
1051 case 1: 1070 case 1:
1052 fprintf(stderr, do_snb_cstates ? "pc2" : "pc0"); 1071 fprintf(stderr, do_slm_cstates ? "no pkg states" : do_snb_cstates ? "pc2" : "pc0");
1053 break; 1072 break;
1054 case 2: 1073 case 2:
1055 fprintf(stderr, do_snb_cstates ? "pc6-noret" : "pc3"); 1074 fprintf(stderr, do_slm_cstates ? "invalid" : do_snb_cstates ? "pc6-noret" : "pc3");
1056 break; 1075 break;
1057 case 3: 1076 case 3:
1058 fprintf(stderr, "pc6"); 1077 fprintf(stderr, do_slm_cstates ? "invalid" : "pc6");
1059 break; 1078 break;
1060 case 4: 1079 case 4:
1061 fprintf(stderr, "pc7"); 1080 fprintf(stderr, do_slm_cstates ? "pc4" : "pc7");
1062 break; 1081 break;
1063 case 5: 1082 case 5:
1064 fprintf(stderr, do_snb_cstates ? "pc7s" : "invalid"); 1083 fprintf(stderr, do_slm_cstates ? "invalid" : do_snb_cstates ? "pc7s" : "invalid");
1084 break;
1085 case 6:
1086 fprintf(stderr, do_slm_cstates ? "pc6" : "invalid");
1065 break; 1087 break;
1066 case 7: 1088 case 7:
1067 fprintf(stderr, "unlimited"); 1089 fprintf(stderr, do_slm_cstates ? "pc7" : "unlimited");
1068 break; 1090 break;
1069 default: 1091 default:
1070 fprintf(stderr, "invalid"); 1092 fprintf(stderr, "invalid");
@@ -1460,6 +1482,8 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1460 case 0x3F: /* HSW */ 1482 case 0x3F: /* HSW */
1461 case 0x45: /* HSW */ 1483 case 0x45: /* HSW */
1462 case 0x46: /* HSW */ 1484 case 0x46: /* HSW */
1485 case 0x37: /* BYT */
1486 case 0x4D: /* AVN */
1463 return 1; 1487 return 1;
1464 case 0x2E: /* Nehalem-EX Xeon - Beckton */ 1488 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1465 case 0x2F: /* Westmere-EX Xeon - Eagleton */ 1489 case 0x2F: /* Westmere-EX Xeon - Eagleton */
@@ -1532,14 +1556,33 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1532#define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */ 1556#define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */
1533#define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */ 1557#define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */
1534 1558
1559double get_tdp(model)
1560{
1561 unsigned long long msr;
1562
1563 if (do_rapl & RAPL_PKG_POWER_INFO)
1564 if (!get_msr(0, MSR_PKG_POWER_INFO, &msr))
1565 return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units;
1566
1567 switch (model) {
1568 case 0x37:
1569 case 0x4D:
1570 return 30.0;
1571 default:
1572 return 135.0;
1573 }
1574}
1575
1576
1535/* 1577/*
1536 * rapl_probe() 1578 * rapl_probe()
1537 * 1579 *
1538 * sets do_rapl 1580 * sets do_rapl, rapl_power_units, rapl_energy_units, rapl_time_units
1539 */ 1581 */
1540void rapl_probe(unsigned int family, unsigned int model) 1582void rapl_probe(unsigned int family, unsigned int model)
1541{ 1583{
1542 unsigned long long msr; 1584 unsigned long long msr;
1585 unsigned int time_unit;
1543 double tdp; 1586 double tdp;
1544 1587
1545 if (!genuine_intel) 1588 if (!genuine_intel)
@@ -1555,11 +1598,15 @@ void rapl_probe(unsigned int family, unsigned int model)
1555 case 0x3F: /* HSW */ 1598 case 0x3F: /* HSW */
1556 case 0x45: /* HSW */ 1599 case 0x45: /* HSW */
1557 case 0x46: /* HSW */ 1600 case 0x46: /* HSW */
1558 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX; 1601 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
1559 break; 1602 break;
1560 case 0x2D: 1603 case 0x2D:
1561 case 0x3E: 1604 case 0x3E:
1562 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_DRAM | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS; 1605 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
1606 break;
1607 case 0x37: /* BYT */
1608 case 0x4D: /* AVN */
1609 do_rapl = RAPL_PKG | RAPL_CORES ;
1563 break; 1610 break;
1564 default: 1611 default:
1565 return; 1612 return;
@@ -1570,19 +1617,22 @@ void rapl_probe(unsigned int family, unsigned int model)
1570 return; 1617 return;
1571 1618
1572 rapl_power_units = 1.0 / (1 << (msr & 0xF)); 1619 rapl_power_units = 1.0 / (1 << (msr & 0xF));
1573 rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F)); 1620 if (model == 0x37)
1574 rapl_time_units = 1.0 / (1 << (msr >> 16 & 0xF)); 1621 rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000;
1622 else
1623 rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));
1575 1624
1576 /* get TDP to determine energy counter range */ 1625 time_unit = msr >> 16 & 0xF;
1577 if (get_msr(0, MSR_PKG_POWER_INFO, &msr)) 1626 if (time_unit == 0)
1578 return; 1627 time_unit = 0xA;
1579 1628
1580 tdp = ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; 1629 rapl_time_units = 1.0 / (1 << (time_unit));
1581 1630
1582 rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; 1631 tdp = get_tdp(model);
1583 1632
1633 rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
1584 if (verbose) 1634 if (verbose)
1585 fprintf(stderr, "RAPL: %.0f sec. Joule Counter Range\n", rapl_joule_counter_range); 1635 fprintf(stderr, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
1586 1636
1587 return; 1637 return;
1588} 1638}
@@ -1668,7 +1718,6 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1668{ 1718{
1669 unsigned long long msr; 1719 unsigned long long msr;
1670 int cpu; 1720 int cpu;
1671 double local_rapl_power_units, local_rapl_energy_units, local_rapl_time_units;
1672 1721
1673 if (!do_rapl) 1722 if (!do_rapl)
1674 return 0; 1723 return 0;
@@ -1686,23 +1735,13 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1686 if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr)) 1735 if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr))
1687 return -1; 1736 return -1;
1688 1737
1689 local_rapl_power_units = 1.0 / (1 << (msr & 0xF));
1690 local_rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));
1691 local_rapl_time_units = 1.0 / (1 << (msr >> 16 & 0xF));
1692
1693 if (local_rapl_power_units != rapl_power_units)
1694 fprintf(stderr, "cpu%d, ERROR: Power units mis-match\n", cpu);
1695 if (local_rapl_energy_units != rapl_energy_units)
1696 fprintf(stderr, "cpu%d, ERROR: Energy units mis-match\n", cpu);
1697 if (local_rapl_time_units != rapl_time_units)
1698 fprintf(stderr, "cpu%d, ERROR: Time units mis-match\n", cpu);
1699
1700 if (verbose) { 1738 if (verbose) {
1701 fprintf(stderr, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx " 1739 fprintf(stderr, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx "
1702 "(%f Watts, %f Joules, %f sec.)\n", cpu, msr, 1740 "(%f Watts, %f Joules, %f sec.)\n", cpu, msr,
1703 local_rapl_power_units, local_rapl_energy_units, local_rapl_time_units); 1741 rapl_power_units, rapl_energy_units, rapl_time_units);
1704 } 1742 }
1705 if (do_rapl & RAPL_PKG) { 1743 if (do_rapl & RAPL_PKG_POWER_INFO) {
1744
1706 if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr)) 1745 if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))
1707 return -5; 1746 return -5;
1708 1747
@@ -1714,6 +1753,9 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1714 ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, 1753 ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
1715 ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); 1754 ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
1716 1755
1756 }
1757 if (do_rapl & RAPL_PKG) {
1758
1717 if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr)) 1759 if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr))
1718 return -9; 1760 return -9;
1719 1761
@@ -1749,12 +1791,16 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1749 1791
1750 print_power_limit_msr(cpu, msr, "DRAM Limit"); 1792 print_power_limit_msr(cpu, msr, "DRAM Limit");
1751 } 1793 }
1752 if (do_rapl & RAPL_CORES) { 1794 if (do_rapl & RAPL_CORE_POLICY) {
1753 if (verbose) { 1795 if (verbose) {
1754 if (get_msr(cpu, MSR_PP0_POLICY, &msr)) 1796 if (get_msr(cpu, MSR_PP0_POLICY, &msr))
1755 return -7; 1797 return -7;
1756 1798
1757 fprintf(stderr, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF); 1799 fprintf(stderr, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
1800 }
1801 }
1802 if (do_rapl & RAPL_CORES) {
1803 if (verbose) {
1758 1804
1759 if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) 1805 if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
1760 return -9; 1806 return -9;
@@ -1813,10 +1859,48 @@ int has_c8_c9_c10(unsigned int family, unsigned int model)
1813} 1859}
1814 1860
1815 1861
1862int is_slm(unsigned int family, unsigned int model)
1863{
1864 if (!genuine_intel)
1865 return 0;
1866 switch (model) {
1867 case 0x37: /* BYT */
1868 case 0x4D: /* AVN */
1869 return 1;
1870 }
1871 return 0;
1872}
1873
1874#define SLM_BCLK_FREQS 5
1875double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0};
1876
1877double slm_bclk(void)
1878{
1879 unsigned long long msr = 3;
1880 unsigned int i;
1881 double freq;
1882
1883 if (get_msr(0, MSR_FSB_FREQ, &msr))
1884 fprintf(stderr, "SLM BCLK: unknown\n");
1885
1886 i = msr & 0xf;
1887 if (i >= SLM_BCLK_FREQS) {
1888 fprintf(stderr, "SLM BCLK[%d] invalid\n", i);
1889 msr = 3;
1890 }
1891 freq = slm_freq_table[i];
1892
1893 fprintf(stderr, "SLM BCLK: %.1f Mhz\n", freq);
1894
1895 return freq;
1896}
1897
1816double discover_bclk(unsigned int family, unsigned int model) 1898double discover_bclk(unsigned int family, unsigned int model)
1817{ 1899{
1818 if (is_snb(family, model)) 1900 if (is_snb(family, model))
1819 return 100.00; 1901 return 100.00;
1902 else if (is_slm(family, model))
1903 return slm_bclk();
1820 else 1904 else
1821 return 133.33; 1905 return 133.33;
1822} 1906}
@@ -1873,7 +1957,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
1873 fprintf(stderr, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", 1957 fprintf(stderr, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
1874 cpu, msr, target_c_local); 1958 cpu, msr, target_c_local);
1875 1959
1876 if (target_c_local < 85 || target_c_local > 120) 1960 if (target_c_local < 85 || target_c_local > 127)
1877 goto guess; 1961 goto guess;
1878 1962
1879 tcc_activation_temp = target_c_local; 1963 tcc_activation_temp = target_c_local;
@@ -1970,6 +2054,7 @@ void check_cpuid()
1970 do_smi = do_nhm_cstates; 2054 do_smi = do_nhm_cstates;
1971 do_snb_cstates = is_snb(family, model); 2055 do_snb_cstates = is_snb(family, model);
1972 do_c8_c9_c10 = has_c8_c9_c10(family, model); 2056 do_c8_c9_c10 = has_c8_c9_c10(family, model);
2057 do_slm_cstates = is_slm(family, model);
1973 bclk = discover_bclk(family, model); 2058 bclk = discover_bclk(family, model);
1974 2059
1975 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); 2060 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
@@ -2331,7 +2416,7 @@ int main(int argc, char **argv)
2331 cmdline(argc, argv); 2416 cmdline(argc, argv);
2332 2417
2333 if (verbose) 2418 if (verbose)
2334 fprintf(stderr, "turbostat v3.4 April 17, 2013" 2419 fprintf(stderr, "turbostat v3.5 April 26, 2013"
2335 " - Len Brown <lenb@kernel.org>\n"); 2420 " - Len Brown <lenb@kernel.org>\n");
2336 2421
2337 turbostat_init(); 2422 turbostat_init();