19338Srafael.vanoni@sun.com /*
29338Srafael.vanoni@sun.com * Copyright 2009, Intel Corporation
39338Srafael.vanoni@sun.com * Copyright 2009, Sun Microsystems, Inc
49338Srafael.vanoni@sun.com *
59338Srafael.vanoni@sun.com * This file is part of PowerTOP
69338Srafael.vanoni@sun.com *
79338Srafael.vanoni@sun.com * This program file is free software; you can redistribute it and/or modify it
89338Srafael.vanoni@sun.com * under the terms of the GNU General Public License as published by the
99338Srafael.vanoni@sun.com * Free Software Foundation; version 2 of the License.
109338Srafael.vanoni@sun.com *
119338Srafael.vanoni@sun.com * This program is distributed in the hope that it will be useful, but WITHOUT
129338Srafael.vanoni@sun.com * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
139338Srafael.vanoni@sun.com * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
149338Srafael.vanoni@sun.com * for more details.
159338Srafael.vanoni@sun.com *
169338Srafael.vanoni@sun.com * You should have received a copy of the GNU General Public License
179338Srafael.vanoni@sun.com * along with this program in a file named COPYING; if not, write to the
189338Srafael.vanoni@sun.com * Free Software Foundation, Inc.,
199338Srafael.vanoni@sun.com * 51 Franklin Street, Fifth Floor,
209338Srafael.vanoni@sun.com * Boston, MA 02110-1301 USA
219338Srafael.vanoni@sun.com *
229338Srafael.vanoni@sun.com * Authors:
239338Srafael.vanoni@sun.com * Arjan van de Ven <arjan@linux.intel.com>
249338Srafael.vanoni@sun.com * Eric C Saxe <eric.saxe@sun.com>
259338Srafael.vanoni@sun.com * Aubrey Li <aubrey.li@intel.com>
269338Srafael.vanoni@sun.com */
279338Srafael.vanoni@sun.com
289338Srafael.vanoni@sun.com /*
299338Srafael.vanoni@sun.com * GPL Disclaimer
309338Srafael.vanoni@sun.com *
319338Srafael.vanoni@sun.com * For the avoidance of doubt, except that if any license choice other
329338Srafael.vanoni@sun.com * than GPL or LGPL is available it will apply instead, Sun elects to
339338Srafael.vanoni@sun.com * use only the General Public License version 2 (GPLv2) at this time
349338Srafael.vanoni@sun.com * for any software where a choice of GPL license versions is made
359338Srafael.vanoni@sun.com * available with the language indicating that GPLv2 or any later
369338Srafael.vanoni@sun.com * version may be used, or where a choice of which version of the GPL
379338Srafael.vanoni@sun.com * is applied is otherwise unspecified.
389338Srafael.vanoni@sun.com */
399338Srafael.vanoni@sun.com
409338Srafael.vanoni@sun.com #include <stdlib.h>
419338Srafael.vanoni@sun.com #include <string.h>
429338Srafael.vanoni@sun.com #include <dtrace.h>
439338Srafael.vanoni@sun.com #include <kstat.h>
449338Srafael.vanoni@sun.com #include <errno.h>
459338Srafael.vanoni@sun.com #include "powertop.h"
469338Srafael.vanoni@sun.com
479338Srafael.vanoni@sun.com /*
489338Srafael.vanoni@sun.com * Global turbo related variables definitions
499338Srafael.vanoni@sun.com */
509338Srafael.vanoni@sun.com boolean_t g_turbo_supported;
519338Srafael.vanoni@sun.com double g_turbo_ratio;
529338Srafael.vanoni@sun.com
539338Srafael.vanoni@sun.com /*
549338Srafael.vanoni@sun.com * The variables to store kstat snapshot
559338Srafael.vanoni@sun.com */
569338Srafael.vanoni@sun.com static turbo_info_t *cpu_turbo_info = NULL;
579338Srafael.vanoni@sun.com static turbo_info_t *t_new = NULL;
589338Srafael.vanoni@sun.com
599338Srafael.vanoni@sun.com /*
609338Srafael.vanoni@sun.com * Perform setup necessary to enumerate and track CPU turbo information
619338Srafael.vanoni@sun.com */
629338Srafael.vanoni@sun.com static int
pt_turbo_init(void)639338Srafael.vanoni@sun.com pt_turbo_init(void)
649338Srafael.vanoni@sun.com {
659338Srafael.vanoni@sun.com kstat_ctl_t *kc;
669338Srafael.vanoni@sun.com kstat_t *ksp;
679338Srafael.vanoni@sun.com kstat_named_t *knp;
689338Srafael.vanoni@sun.com
699338Srafael.vanoni@sun.com /*
709338Srafael.vanoni@sun.com * check if the CPU turbo is supported
719338Srafael.vanoni@sun.com */
729338Srafael.vanoni@sun.com if ((kc = kstat_open()) == NULL) {
739338Srafael.vanoni@sun.com g_turbo_supported = B_FALSE;
749338Srafael.vanoni@sun.com return (errno);
759338Srafael.vanoni@sun.com }
769338Srafael.vanoni@sun.com
779338Srafael.vanoni@sun.com ksp = kstat_lookup(kc, "turbo", 0, NULL);
789338Srafael.vanoni@sun.com if (ksp == NULL) {
799338Srafael.vanoni@sun.com g_turbo_supported = B_FALSE;
809338Srafael.vanoni@sun.com (void) kstat_close(kc);
819338Srafael.vanoni@sun.com return (-1);
829338Srafael.vanoni@sun.com }
839338Srafael.vanoni@sun.com
849338Srafael.vanoni@sun.com (void) kstat_read(kc, ksp, NULL);
859338Srafael.vanoni@sun.com
869338Srafael.vanoni@sun.com knp = kstat_data_lookup(ksp, "turbo_supported");
879338Srafael.vanoni@sun.com if (knp == NULL) {
88*11122Srafael.vanoni@sun.com pt_error("couldn't find 'turbo_supported' kstat\n");
899338Srafael.vanoni@sun.com g_turbo_supported = B_FALSE;
909338Srafael.vanoni@sun.com (void) kstat_close(kc);
919338Srafael.vanoni@sun.com return (-2);
929338Srafael.vanoni@sun.com }
939338Srafael.vanoni@sun.com
949338Srafael.vanoni@sun.com /*
959338Srafael.vanoni@sun.com * Initialize turbo information structure if turbo mode is supported
969338Srafael.vanoni@sun.com */
979338Srafael.vanoni@sun.com if (knp->value.ui32) {
989338Srafael.vanoni@sun.com g_turbo_supported = B_TRUE;
999338Srafael.vanoni@sun.com cpu_turbo_info = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
1009338Srafael.vanoni@sun.com t_new = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
1019338Srafael.vanoni@sun.com }
1029338Srafael.vanoni@sun.com
1039338Srafael.vanoni@sun.com (void) kstat_close(kc);
1049338Srafael.vanoni@sun.com return (0);
1059338Srafael.vanoni@sun.com }
1069338Srafael.vanoni@sun.com
1079338Srafael.vanoni@sun.com /*
1089338Srafael.vanoni@sun.com * Take a snapshot of each CPU's turbo information
1099338Srafael.vanoni@sun.com * by looking through the turbo kstats.
1109338Srafael.vanoni@sun.com */
1119338Srafael.vanoni@sun.com static int
pt_turbo_snapshot(turbo_info_t * turbo_snapshot)1129338Srafael.vanoni@sun.com pt_turbo_snapshot(turbo_info_t *turbo_snapshot)
1139338Srafael.vanoni@sun.com {
1149338Srafael.vanoni@sun.com kstat_ctl_t *kc;
1159338Srafael.vanoni@sun.com kstat_t *ksp;
1169338Srafael.vanoni@sun.com kstat_named_t *knp;
1179338Srafael.vanoni@sun.com int cpu;
1189338Srafael.vanoni@sun.com turbo_info_t *turbo_info;
1199338Srafael.vanoni@sun.com
1209338Srafael.vanoni@sun.com if ((kc = kstat_open()) == NULL)
1219338Srafael.vanoni@sun.com return (errno);
1229338Srafael.vanoni@sun.com
1239338Srafael.vanoni@sun.com for (cpu = 0; cpu < g_ncpus; cpu++) {
1249338Srafael.vanoni@sun.com turbo_info = &turbo_snapshot[cpu];
1259338Srafael.vanoni@sun.com ksp = kstat_lookup(kc, "turbo", g_cpu_table[cpu], NULL);
1269338Srafael.vanoni@sun.com if (ksp == NULL) {
127*11122Srafael.vanoni@sun.com pt_error("couldn't find 'turbo' kstat for CPU %d\n",
128*11122Srafael.vanoni@sun.com cpu);
1299338Srafael.vanoni@sun.com (void) kstat_close(kc);
1309338Srafael.vanoni@sun.com return (-1);
1319338Srafael.vanoni@sun.com }
1329338Srafael.vanoni@sun.com
1339338Srafael.vanoni@sun.com if (kstat_read(kc, ksp, NULL) == -1) {
134*11122Srafael.vanoni@sun.com pt_error("couldn't read 'turbo' kstat for CPU %d\n",
135*11122Srafael.vanoni@sun.com cpu);
1369338Srafael.vanoni@sun.com (void) kstat_close(kc);
1379338Srafael.vanoni@sun.com return (-2);
1389338Srafael.vanoni@sun.com }
1399338Srafael.vanoni@sun.com
1409338Srafael.vanoni@sun.com knp = kstat_data_lookup(ksp, "turbo_mcnt");
1419338Srafael.vanoni@sun.com if (knp == NULL) {
142*11122Srafael.vanoni@sun.com pt_error("couldn't find 'turbo_mcnt' kstat for CPU "
143*11122Srafael.vanoni@sun.com "%d\n", cpu);
1449338Srafael.vanoni@sun.com (void) kstat_close(kc);
1459338Srafael.vanoni@sun.com return (-3);
1469338Srafael.vanoni@sun.com }
1479338Srafael.vanoni@sun.com
1489338Srafael.vanoni@sun.com /*
1499338Srafael.vanoni@sun.com * snapshot IA32_MPERF_MSR
1509338Srafael.vanoni@sun.com */
1519338Srafael.vanoni@sun.com turbo_info->t_mcnt = knp->value.ui64;
1529338Srafael.vanoni@sun.com
1539338Srafael.vanoni@sun.com knp = kstat_data_lookup(ksp, "turbo_acnt");
1549338Srafael.vanoni@sun.com if (knp == NULL) {
155*11122Srafael.vanoni@sun.com pt_error("couldn't find 'turbo_acnt' kstat for CPU "
156*11122Srafael.vanoni@sun.com "%d\n", cpu);
1579338Srafael.vanoni@sun.com (void) kstat_close(kc);
1589338Srafael.vanoni@sun.com return (-4);
1599338Srafael.vanoni@sun.com }
1609338Srafael.vanoni@sun.com
1619338Srafael.vanoni@sun.com /*
1629338Srafael.vanoni@sun.com * snapshot IA32_APERF_MSR
1639338Srafael.vanoni@sun.com */
1649338Srafael.vanoni@sun.com turbo_info->t_acnt = knp->value.ui64;
1659338Srafael.vanoni@sun.com }
1669338Srafael.vanoni@sun.com
1679338Srafael.vanoni@sun.com if (kstat_close(kc) != 0)
168*11122Srafael.vanoni@sun.com pt_error("couldn't close 'turbo' kstat\n");
1699338Srafael.vanoni@sun.com
1709338Srafael.vanoni@sun.com return (0);
1719338Srafael.vanoni@sun.com }
1729338Srafael.vanoni@sun.com
1739338Srafael.vanoni@sun.com /*
1749338Srafael.vanoni@sun.com * Turbo support checking and information initialization
1759338Srafael.vanoni@sun.com */
1769338Srafael.vanoni@sun.com int
pt_turbo_stat_prepare(void)1779338Srafael.vanoni@sun.com pt_turbo_stat_prepare(void)
1789338Srafael.vanoni@sun.com {
179*11122Srafael.vanoni@sun.com int ret = 0;
1809338Srafael.vanoni@sun.com
181*11122Srafael.vanoni@sun.com if ((ret = pt_turbo_init()) != 0)
1829338Srafael.vanoni@sun.com return (ret);
1839338Srafael.vanoni@sun.com
184*11122Srafael.vanoni@sun.com if ((ret = pt_turbo_snapshot(cpu_turbo_info)) != 0)
185*11122Srafael.vanoni@sun.com pt_error("failed to snapshot 'turbo' kstat\n");
1869338Srafael.vanoni@sun.com
1879338Srafael.vanoni@sun.com return (ret);
1889338Srafael.vanoni@sun.com }
1899338Srafael.vanoni@sun.com
1909338Srafael.vanoni@sun.com /*
1919338Srafael.vanoni@sun.com * When doing the statistics collection, we compare two kstat snapshot
1929338Srafael.vanoni@sun.com * and get a delta. the final ratio of performance boost will be worked
1939338Srafael.vanoni@sun.com * out according to the kstat delta
1949338Srafael.vanoni@sun.com */
1959338Srafael.vanoni@sun.com int
pt_turbo_stat_collect(void)1969338Srafael.vanoni@sun.com pt_turbo_stat_collect(void)
1979338Srafael.vanoni@sun.com {
1989338Srafael.vanoni@sun.com int cpu;
1999338Srafael.vanoni@sun.com uint64_t delta_mcnt, delta_acnt;
2009338Srafael.vanoni@sun.com double ratio;
2019338Srafael.vanoni@sun.com int ret;
2029338Srafael.vanoni@sun.com
2039338Srafael.vanoni@sun.com /*
2049338Srafael.vanoni@sun.com * Take a snapshot of turbo information to setup turbo_info_t
2059338Srafael.vanoni@sun.com * structure
2069338Srafael.vanoni@sun.com */
207*11122Srafael.vanoni@sun.com if ((ret = pt_turbo_snapshot(t_new)) != 0) {
208*11122Srafael.vanoni@sun.com pt_error("failed to snapshot 'turbo' kstat\n");
2099338Srafael.vanoni@sun.com return (ret);
2109338Srafael.vanoni@sun.com }
2119338Srafael.vanoni@sun.com
2129338Srafael.vanoni@sun.com /*
2139338Srafael.vanoni@sun.com * Calculate the kstat delta and work out the performance boost ratio
2149338Srafael.vanoni@sun.com */
2159338Srafael.vanoni@sun.com for (cpu = 0; cpu < g_ncpus; cpu++) {
2169338Srafael.vanoni@sun.com delta_mcnt = t_new[cpu].t_mcnt - cpu_turbo_info[cpu].t_mcnt;
2179338Srafael.vanoni@sun.com delta_acnt = t_new[cpu].t_acnt - cpu_turbo_info[cpu].t_acnt;
2189338Srafael.vanoni@sun.com
2199338Srafael.vanoni@sun.com if ((delta_mcnt > delta_acnt) || (delta_mcnt == 0))
2209338Srafael.vanoni@sun.com ratio = 1.0;
2219338Srafael.vanoni@sun.com else
2229338Srafael.vanoni@sun.com ratio = (double)delta_acnt / (double)delta_mcnt;
2239338Srafael.vanoni@sun.com g_turbo_ratio += ratio;
2249338Srafael.vanoni@sun.com }
2259338Srafael.vanoni@sun.com
2269338Srafael.vanoni@sun.com g_turbo_ratio = g_turbo_ratio / (double)g_ncpus;
2279338Srafael.vanoni@sun.com
2289338Srafael.vanoni@sun.com /*
2299338Srafael.vanoni@sun.com * Update the structure of the kstat for the next time calculation
2309338Srafael.vanoni@sun.com */
2319338Srafael.vanoni@sun.com (void) memcpy(cpu_turbo_info, t_new, g_ncpus * (sizeof (turbo_info_t)));
2329338Srafael.vanoni@sun.com
2339338Srafael.vanoni@sun.com return (0);
2349338Srafael.vanoni@sun.com }
235