PSARC/2009/086 PowerTOP --cpu option
authorRafael Vanoni <rafael.vanoni@sun.com>
Fri, 10 Apr 2009 11:48:42 -0700
changeset 9338 fd0d0071cbee
parent 9337 1f7afb6a061f
child 9339 7c09601804ed
PSARC/2009/086 PowerTOP --cpu option 6781152 PowerTOP should be able to report statistics for a specific CPU 6781149 PowerTOP should identify function names when reporting xcalls 6776103 typo in powertop/battery.c battery_stat_snapsho() 6790804 PowerTOP needlessly reports past, zero'ed events 6781580 PowerTOP has global variables declared in header file 6804434 PowerTOP displays the wrong name for idle/freq transitions on sparc
usr/src/cmd/powertop/Makefile
usr/src/cmd/powertop/Makefile.com
usr/src/cmd/powertop/amd64/Makefile
usr/src/cmd/powertop/amd64/pt_amd64.c
usr/src/cmd/powertop/battery.c
usr/src/cmd/powertop/common/battery.c
usr/src/cmd/powertop/common/cpufreq.c
usr/src/cmd/powertop/common/cpuidle.c
usr/src/cmd/powertop/common/display.c
usr/src/cmd/powertop/common/events.c
usr/src/cmd/powertop/common/powertop.c
usr/src/cmd/powertop/common/powertop.h
usr/src/cmd/powertop/common/suggestions.c
usr/src/cmd/powertop/common/turbo.c
usr/src/cmd/powertop/common/util.c
usr/src/cmd/powertop/cpufreq.c
usr/src/cmd/powertop/cpuidle.c
usr/src/cmd/powertop/display.c
usr/src/cmd/powertop/events.c
usr/src/cmd/powertop/i386/Makefile
usr/src/cmd/powertop/i386/pt_i386.c
usr/src/cmd/powertop/powertop.c
usr/src/cmd/powertop/powertop.h
usr/src/cmd/powertop/sparcv9/Makefile
usr/src/cmd/powertop/sparcv9/pt_sparcv9.c
usr/src/cmd/powertop/suggestions.c
usr/src/cmd/powertop/turbo.c
usr/src/cmd/powertop/util.c
--- a/usr/src/cmd/powertop/Makefile	Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/Makefile	Fri Apr 10 11:48:42 2009 -0700
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # cmd/powertop/Makefile
@@ -28,8 +28,8 @@
 
 include ../Makefile.cmd
 
-$(64ONLY)SUBDIRS= $(MACH)
-$(BUILD64)SUBDIRS += $(MACH64)
+$(64ONLY)SUBDIRS	= $(MACH)
+$(BUILD64)SUBDIRS	+= $(MACH64)
 
 all	:=	TARGET = all
 install	:=	TARGET = install
@@ -39,9 +39,7 @@
 
 .KEEP_STATE:
 
-all:	$(SUBDIRS)
-
-clean clobber lint:	$(SUBDIRS)
+all clean clobber lint:	$(SUBDIRS)
 
 install:	$(SUBDIRS)
 	-$(RM) $(ROOTPROG)
--- a/usr/src/cmd/powertop/Makefile.com	Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/Makefile.com	Fri Apr 10 11:48:42 2009 -0700
@@ -23,34 +23,36 @@
 #
 
 PROG = powertop
-OBJS = $(PROG).o display.o battery.o cpufreq.o cpuidle.o events.o util.o suggestions.o turbo.o
-SRCS = $(OBJS:%.o=../%.c)
+
+COMMON_OBJS = $(PROG).o \
+	display.o \
+	battery.o \
+	cpufreq.o \
+	cpuidle.o \
+	events.o \
+	util.o \
+	suggestions.o \
+	turbo.o
+
+SRCS		= $(COMMON_OBJS:%.o=../common/%.c)
 
 include ../../Makefile.cmd
-
-CFLAGS += $(CCVERBOSE)
-CFLAGS64 += $(CCVERBOSE)
-
-LDLIBS += -lcurses -ldtrace -lkstat
-
-FILEMODE = 0555
-GROUP = bin
-
-CLEANFILES += $(OBJS)
-
 .KEEP_STATE:
 
-all: $(PROG)
+CFLAGS		+= $(CCVERBOSE)
+CFLAGS64	+= $(CCVERBOSE)
+LDLIBS		+= -lcurses -ldtrace -lkstat
 
-$(PROG): $(OBJS)
-	$(LINK.c) -o $@ $(OBJS) $(LDLIBS)
-	$(POST_PROCESS)
+FILEMODE	= 0555
+GROUP		= bin
+
+CLEANFILES	+= $(COMMON_OBJS)
+
+all:	$(PROG)
+
 clean:
 	$(RM) $(CLEANFILES)
 
 lint:	lint_SRCS
 
-%.o: ../%.c
-	$(COMPILE.c) $<
-
 include ../../Makefile.targ
--- a/usr/src/cmd/powertop/amd64/Makefile	Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/amd64/Makefile	Fri Apr 10 11:48:42 2009 -0700
@@ -18,11 +18,27 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
 include ../Makefile.com
 include ../../Makefile.cmd.64
 
+MACH_OBJS	= pt_amd64.o
+SRCS		+= $(MACH_OBJS:%.o=%.c)
+
+.KEEP_STATE:
+
+CLEANFILES	+= $(MACH_OBJS)
+
+all: $(PROG)
+
+$(PROG): $(MACH_OBJS) $(COMMON_OBJS)
+	$(LINK.c) -o $@ $(MACH_OBJS) $(COMMON_OBJS) $(LDLIBS)
+	$(POST_PROCESS)
+
+%.o: ../common/%.c
+	$(COMPILE.c) -o $@ $<
+
 install: all $(ROOTPROG64)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/amd64/pt_amd64.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+/*
+ * DTrace scripts for observing interrupts, callouts and cyclic events
+ * that cause CPU activity. Such activity prevents the processor from
+ * entering lower power states and reducing power consumption.
+ *
+ * g_dtp_events is the default script
+ */
+const char *g_dtp_events =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+"	this->devi = (struct dev_info *)arg0;"
+"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+"	     this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"{"
+"	self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+"       @events_x[execname, self->xc_func] = sum(arg0);"
+"}"
+""
+"fbt::xc_common:return"
+"/self->xc_func/"
+"{"
+"	self->xc_func = 0;"
+"}";
+
+/*
+ * g_dtp_events_v is enabled through the -v option, it includes cyclic events
+ * in the report, allowing a complete view of system activity
+ */
+const char *g_dtp_events_v =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+"	this->devi = (struct dev_info *)arg0;"
+"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+"	     this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_deadman &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_clean/"
+"{"
+"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"{"
+"	self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+"       @events_x[execname, self->xc_func] = sum(arg0);"
+"}"
+""
+"fbt::xc_common:return"
+"/self->xc_func/"
+"{"
+"	self->xc_func = 0;"
+"}";
+
+/*
+ * This script is selected through the -c option, it takes the CPU id as
+ * argument and observes activity generated by that CPU
+ */
+const char *g_dtp_events_c =
+"interrupt-complete"
+"/cpu == $0 &&"
+" arg0 != NULL && arg3 != 0/"
+"{"
+"	this->devi = (struct dev_info *)arg0;"
+"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+"	     this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/cpu == $0 &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"/cpu == $0/"
+"{"
+"	self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid &&"
+" cpu == $0/"
+"{"
+"       @events_x[execname, self->xc_func] = count();"
+"}"
+""
+"fbt::xc_common:return"
+"/cpu == $0 &&"
+" self->xc_func/"
+"{"
+"	self->xc_func = 0;"
+"}"
+""
+"fbt::xc_common:entry"
+"/cpu != $0/"
+"{"
+"	self->xc_func = arg0;"
+"	self->xc_cpu = cpu;"
+"}"
+""
+"fbt::send_dirint:entry"
+"/pid != $pid &&"
+" self->xc_func &&"
+" arg0 == $0/"
+"{"
+"	@events_xc[execname, self->xc_func, self->xc_cpu] = count();"
+"	self->xc_func = 0;"
+"	self->xc_cpu = 0;"
+"}";
+
+/*
+ * amd64 platform specific display messages
+ */
+const char *g_msg_idle_state = "C-states (idle power states)";
+const char *g_msg_freq_state = "P-states (frequencies)";
--- a/usr/src/cmd/powertop/battery.c	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,223 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *	Arjan van de Ven <[email protected]>
- *	Eric C Saxe <[email protected]>
- *	Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <string.h>
-#include <kstat.h>
-#include <errno.h>
-#include "powertop.h"
-
-typedef struct battery_state {
-	uint32_t exist;
-	uint32_t power_unit;
-	uint32_t bst_state;
-	double present_rate;
-	double remain_cap;
-	double last_cap;
-} battery_state_t;
-
-battery_state_t battery;
-
-static	int	battery_stat_snapshot(void);
-
-#define	mW2W(value)	((value) / 1000)
-
-void
-print_battery(void)
-{
-	int err;
-
-	(void) memset(&battery, 0, sizeof (battery_state_t));
-
-	/*
-	 * The return value of battery_stat_snapsho() can be used for
-	 * debug or to show/hide the acpi power line. We currently don't
-	 * make the distinction of a system that runs only on AC and one
-	 * that runs on battery but has no kstat battery info.
-	 *
-	 * We still display the estimate power usage for systems
-	 * running on AC with a fully charged battery because some
-	 * batteries may still consume power.
-	 *
-	 * If battery_mod_lookup() didn't find a kstat battery module, don't
-	 * bother trying to take the snapshot
-	 */
-	if (kstat_batt_idx > 0) {
-		if ((err = battery_stat_snapshot()) < 0)
-			pt_error("%s : battery kstat not found %d\n", __FILE__,
-			    err);
-	}
-
-	show_acpi_power_line(battery.exist, battery.present_rate,
-	    battery.remain_cap, battery.last_cap, battery.bst_state);
-}
-
-static int
-battery_stat_snapshot(void)
-{
-	kstat_ctl_t	*kc;
-	kstat_t		*ksp;
-	kstat_named_t	*knp;
-
-	kc = kstat_open();
-
-	/*
-	 * power unit:
-	 * 	0 - Capacity information is reported in [mWh] and
-	 *	    charge/discharge rate information in [mW]
-	 *	1 - Capacity information is reported in [mAh] and
-	 *	    charge/discharge rate information in [mA].
-	 */
-	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
-	    "battery BIF0");
-
-	if (ksp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	(void) kstat_read(kc, ksp, NULL);
-	knp = kstat_data_lookup(ksp, "bif_unit");
-
-	if (knp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	battery.power_unit = knp->value.ui32;
-
-	/*
-	 * Present rate:
-	 *	the power or current being supplied or accepted
-	 *	through the battery's terminal
-	 */
-	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
-	    "battery BST0");
-
-	if (ksp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	(void) kstat_read(kc, ksp, NULL);
-	knp = kstat_data_lookup(ksp, "bst_rate");
-
-	if (knp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	if (knp->value.ui32 == 0xFFFFFFFF)
-		battery.present_rate = 0;
-	else {
-		battery.exist = 1;
-		battery.present_rate = mW2W((double)(knp->value.ui32));
-	}
-
-	/*
-	 * Last Full charge capacity:
-	 *	Predicted battery capacity when fully charged.
-	 */
-	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
-	    "battery BIF0");
-
-	if (ksp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	(void) kstat_read(kc, ksp, NULL);
-	knp = kstat_data_lookup(ksp, "bif_last_cap");
-
-	if (knp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	battery.last_cap = mW2W((double)(knp->value.ui32));
-
-	/*
-	 * Remaining capacity:
-	 *	the estimated remaining battery capacity
-	 */
-	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
-	    "battery BST0");
-
-	if (ksp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	(void) kstat_read(kc, ksp, NULL);
-	knp = kstat_data_lookup(ksp, "bst_rem_cap");
-
-	if (knp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	battery.remain_cap = mW2W((double)(knp->value.ui32));
-
-	/*
-	 * Battery State:
-	 *	Bit0 - 1 : discharging
-	 *	Bit1 - 1 : charging
-	 *	Bit2 - 1 : critical energy state
-	 */
-	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
-	    "battery BST0");
-
-	if (ksp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	(void) kstat_read(kc, ksp, NULL);
-	knp = kstat_data_lookup(ksp, "bst_state");
-
-	if (knp == NULL) {
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	battery.bst_state = knp->value.ui32;
-
-	(void) kstat_close(kc);
-
-	return (0);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/battery.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <string.h>
+#include <kstat.h>
+#include <errno.h>
+#include "powertop.h"
+
+#define	mW2W(value)	((value) / 1000)
+
+typedef struct battery_state {
+	uint32_t exist;
+	uint32_t power_unit;
+	uint32_t bst_state;
+	double present_rate;
+	double remain_cap;
+	double last_cap;
+} battery_state_t;
+
+static char		*kstat_batt_mod[3] = {NULL, "battery", "acpi_drv"};
+static uint_t		kstat_batt_idx;
+static battery_state_t	battery_state;
+
+static int		battery_stat_snapshot(void);
+
+/*
+ * Checks if the kstat module for battery information is present and
+ * whether it's called 'battery' or 'acpi_drv'
+ */
+void
+battery_mod_lookup(void)
+{
+	kstat_ctl_t *kc = kstat_open();
+
+	if (kstat_lookup(kc, kstat_batt_mod[1], 0, NULL))
+		kstat_batt_idx = 1;
+	else
+		if (kstat_lookup(kc, kstat_batt_mod[2], 0, NULL))
+			kstat_batt_idx = 2;
+		else
+			kstat_batt_idx = 0;
+
+	(void) kstat_close(kc);
+}
+
+void
+print_battery(void)
+{
+	int err;
+
+	(void) memset(&battery_state, 0, sizeof (battery_state_t));
+
+	/*
+	 * The return value of battery_stat_snapshot() can be used for
+	 * debug or to show/hide the acpi power line. We currently don't
+	 * make the distinction of a system that runs only on AC and one
+	 * that runs on battery but has no kstat battery info.
+	 *
+	 * We still display the estimate power usage for systems
+	 * running on AC with a fully charged battery because some
+	 * batteries may still consume power.
+	 *
+	 * If battery_mod_lookup() didn't find a kstat battery module, don't
+	 * bother trying to take the snapshot
+	 */
+	if (kstat_batt_idx > 0) {
+		if ((err = battery_stat_snapshot()) < 0)
+			pt_error("%s : battery kstat not found %d\n", __FILE__,
+			    err);
+	}
+
+	show_acpi_power_line(battery_state.exist, battery_state.present_rate,
+	    battery_state.remain_cap, battery_state.last_cap,
+	    battery_state.bst_state);
+}
+
+static int
+battery_stat_snapshot(void)
+{
+	kstat_ctl_t	*kc;
+	kstat_t		*ksp;
+	kstat_named_t	*knp;
+
+	kc = kstat_open();
+
+	/*
+	 * power unit:
+	 * 	0 - Capacity information is reported in [mWh] and
+	 *	    charge/discharge rate information in [mW]
+	 *	1 - Capacity information is reported in [mAh] and
+	 *	    charge/discharge rate information in [mA].
+	 */
+	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+	    "battery BIF0");
+
+	if (ksp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	(void) kstat_read(kc, ksp, NULL);
+	knp = kstat_data_lookup(ksp, "bif_unit");
+
+	if (knp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	battery_state.power_unit = knp->value.ui32;
+
+	/*
+	 * Present rate:
+	 *	the power or current being supplied or accepted
+	 *	through the battery's terminal
+	 */
+	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+	    "battery BST0");
+
+	if (ksp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	(void) kstat_read(kc, ksp, NULL);
+	knp = kstat_data_lookup(ksp, "bst_rate");
+
+	if (knp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	if (knp->value.ui32 == 0xFFFFFFFF)
+		battery_state.present_rate = 0;
+	else {
+		battery_state.exist = 1;
+		battery_state.present_rate = mW2W((double)(knp->value.ui32));
+	}
+
+	/*
+	 * Last Full charge capacity:
+	 *	Predicted battery capacity when fully charged.
+	 */
+	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+	    "battery BIF0");
+
+	if (ksp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	(void) kstat_read(kc, ksp, NULL);
+	knp = kstat_data_lookup(ksp, "bif_last_cap");
+
+	if (knp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	battery_state.last_cap = mW2W((double)(knp->value.ui32));
+
+	/*
+	 * Remaining capacity:
+	 *	the estimated remaining battery capacity
+	 */
+	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+	    "battery BST0");
+
+	if (ksp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	(void) kstat_read(kc, ksp, NULL);
+	knp = kstat_data_lookup(ksp, "bst_rem_cap");
+
+	if (knp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	battery_state.remain_cap = mW2W((double)(knp->value.ui32));
+
+	/*
+	 * Battery State:
+	 *	Bit0 - 1 : discharging
+	 *	Bit1 - 1 : charging
+	 *	Bit2 - 1 : critical energy state
+	 */
+	ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+	    "battery BST0");
+
+	if (ksp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	(void) kstat_read(kc, ksp, NULL);
+	knp = kstat_data_lookup(ksp, "bst_state");
+
+	if (knp == NULL) {
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	battery_state.bst_state = knp->value.ui32;
+
+	(void) kstat_close(kc);
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/cpufreq.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,537 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <dtrace.h>
+#include <kstat.h>
+#include <errno.h>
+#include "powertop.h"
+
+#define	HZ2MHZ(speed)	((speed) / 1000000)
+#define	DTP_ARG_COUNT	2
+#define	DTP_ARG_LENGTH	5
+
+static uint64_t		max_cpufreq = 0;
+static dtrace_hdl_t	*dtp;
+static char		**dtp_argv;
+
+/*
+ * Enabling PM through /etc/power.conf
+ * See suggest_p_state()
+ */
+static char default_conf[]	= "/etc/power.conf";
+static char default_pmconf[]	= "/usr/sbin/pmconfig";
+static char cpupm_enable[]	= " echo cpupm enable >> /etc/power.conf";
+static char cpupm_treshold[]	= " echo cpu-threshold 1s >> /etc/power.conf";
+
+/*
+ * Buffer containing DTrace program to track CPU frequency transitions
+ */
+static const char *dtp_cpufreq =
+"hrtime_t last[$0];"
+""
+"BEGIN"
+"{"
+"	begin = timestamp;"
+"}"
+""
+":::cpu-change-speed"
+"/last[(processorid_t)arg0] != 0/"
+"{"
+"	this->cpu = (processorid_t)arg0;"
+"	this->oldspeed = (uint32_t)(arg1/1000000);"
+"	@times[this->cpu, this->oldspeed] = sum(timestamp - last[this->cpu]);"
+"	last[this->cpu] = timestamp;"
+"}"
+":::cpu-change-speed"
+"/last[(processorid_t)arg0] == 0/"
+"{"
+"	this->cpu = (processorid_t)arg0;"
+"	this->oldspeed = (uint32_t)(arg1/1000000);"
+"	@times[this->cpu, this->oldspeed] = sum(timestamp - begin);"
+"	last[this->cpu] = timestamp;"
+"}";
+
+/*
+ * Same as above, but only for a specific CPU
+ */
+static const char *dtp_cpufreq_c =
+"hrtime_t last;"
+""
+"BEGIN"
+"{"
+"	begin = timestamp;"
+"}"
+""
+":::cpu-change-speed"
+"/(processorid_t)arg0 == $1 &&"
+" last != 0/"
+"{"
+"	this->cpu = (processorid_t)arg0;"
+"	this->oldspeed = (uint32_t)(arg1/1000000);"
+"	@times[this->cpu, this->oldspeed] = sum(timestamp - last);"
+"	last = timestamp;"
+"}"
+":::cpu-change-speed"
+"/(processorid_t)arg0 == $1 &&"
+" last == 0/"
+"{"
+"	this->cpu = (processorid_t)arg0;"
+"	this->oldspeed = (uint32_t)(arg1/1000000);"
+"	@times[this->cpu, this->oldspeed] = sum(timestamp - begin);"
+"	last = timestamp;"
+"}";
+
+static int	pt_cpufreq_setup(void);
+static int	pt_cpufreq_snapshot(void);
+static int	pt_cpufreq_dtrace_walk(const dtrace_aggdata_t *, void *);
+static void	pt_cpufreq_stat_account(double, uint_t);
+static int	pt_cpufreq_snapshot_cpu(kstat_ctl_t *,
+    uint_t);
+
+static int
+pt_cpufreq_setup(void)
+{
+	if ((dtp_argv = malloc(sizeof (char *) * DTP_ARG_COUNT)) == NULL)
+		return (EXIT_FAILURE);
+
+	if ((dtp_argv[0] = malloc(sizeof (char) * DTP_ARG_LENGTH)) == NULL) {
+		free(dtp_argv);
+		return (EXIT_FAILURE);
+	}
+
+	(void) snprintf(dtp_argv[0], 5, "%d\0", g_ncpus_observed);
+
+	if (PTOP_ON_CPU) {
+		if ((dtp_argv[1] = malloc(sizeof (char) * DTP_ARG_LENGTH))
+		    == NULL) {
+			free(dtp_argv[0]);
+			free(dtp_argv);
+			return (EXIT_FAILURE);
+		}
+		(void) snprintf(dtp_argv[1], 5, "%d\0", g_observed_cpu);
+	}
+
+	return (0);
+}
+
+/*
+ * Perform setup necessary to enumerate and track CPU speed changes
+ */
+int
+pt_cpufreq_stat_prepare(void)
+{
+	dtrace_prog_t 		*prog;
+	dtrace_proginfo_t 	info;
+	dtrace_optval_t 	statustime;
+	kstat_ctl_t 		*kc;
+	kstat_t 		*ksp;
+	kstat_named_t 		*knp;
+	freq_state_info_t 	*state;
+	char 			*s, *token, *prog_ptr;
+	int 			err;
+
+	if ((err = pt_cpufreq_setup()) != 0) {
+		pt_error("%s : failed to setup", __FILE__);
+		return (errno);
+	}
+
+	state = g_pstate_info;
+	if ((g_cpu_power_states = calloc((size_t)g_ncpus,
+	    sizeof (cpu_power_info_t))) == NULL)
+		return (-1);
+
+	/*
+	 * Enumerate the CPU frequencies
+	 */
+	if ((kc = kstat_open()) == NULL)
+		return (errno);
+
+	ksp = kstat_lookup(kc, "cpu_info", g_cpu_table[g_observed_cpu], NULL);
+
+	if (ksp == NULL) {
+		err = errno;
+		(void) kstat_close(kc);
+		return (err);
+	}
+
+	(void) kstat_read(kc, ksp, NULL);
+
+	knp = kstat_data_lookup(ksp, "supported_frequencies_Hz");
+	s = knp->value.str.addr.ptr;
+
+	g_npstates = 0;
+
+	for (token = strtok(s, ":"), s = NULL;
+	    NULL != token && g_npstates < NSTATES;
+	    token = strtok(NULL, ":")) {
+
+		state->speed = HZ2MHZ(atoll(token));
+
+		if (state->speed > max_cpufreq)
+			max_cpufreq = state->speed;
+
+		state->total_time = (uint64_t)0;
+
+		g_npstates++;
+		state++;
+	}
+
+	if (token != NULL)
+		pt_error("%s : exceeded NSTATES\n", __FILE__);
+
+	(void) kstat_close(kc);
+
+	/*
+	 * Return if speed transition is not supported
+	 */
+	if (g_npstates < 2)
+		return (-1);
+
+	/*
+	 * Setup DTrace to look for CPU frequency changes
+	 */
+	if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
+		pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
+		    dtrace_errmsg(NULL, err));
+		return (-2);
+	}
+
+	/*
+	 * Execute different scripts (defined above) depending on
+	 * user specified options. Default mode uses dtp_cpufreq.
+	 */
+	if (PTOP_ON_CPU)
+		prog_ptr = (char *)dtp_cpufreq_c;
+	else
+		prog_ptr = (char *)dtp_cpufreq;
+
+	if ((prog = dtrace_program_strcompile(dtp, prog_ptr,
+	    DTRACE_PROBESPEC_NAME, 0, (1 + g_argc), dtp_argv)) == NULL) {
+		pt_error("%s : cpu-change-speed probe unavailable\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_program_exec(dtp, prog, &info) == -1) {
+		pt_error("%s : failed to enable speed probe\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_setopt(dtp, "aggsize", "128k") == -1) {
+		pt_error("%s : failed to set speed 'aggsize'\n", __FILE__);
+	}
+
+	if (dtrace_setopt(dtp, "aggrate", "0") == -1) {
+		pt_error("%s : failed to set speed 'aggrate'\n", __FILE__);
+	}
+
+	if (dtrace_setopt(dtp, "aggpercpu", 0) == -1) {
+		pt_error("%s : failed to set speed 'aggpercpu'\n", __FILE__);
+	}
+
+	if (dtrace_go(dtp) != 0) {
+		pt_error("%s : failed to start speed observation", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_getopt(dtp, "statusrate", &statustime) == -1) {
+		pt_error("%s : failed to get speed 'statusrate'\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	return (0);
+}
+
+/*
+ * The DTrace probes have already been enabled, and are tracking
+ * CPU speed transitions. Take a snapshot of the aggregations, and
+ * look for any CPUs that have made a speed transition over the last
+ * sampling interval. Note that the aggregations may be empty if no
+ * speed transitions took place over the last interval. In that case,
+ * notate that we have already accounted for the time, so that when
+ * we do encounter a speed transition in a future sampling interval
+ * we can subtract that time back out.
+ */
+int
+pt_cpufreq_stat_collect(double interval)
+{
+	int	i, ret;
+
+	/*
+	 * Zero out the interval time reported by DTrace for
+	 * this interval
+	 */
+	for (i = 0; i < g_npstates; i++)
+		g_pstate_info[i].total_time = 0;
+
+	for (i = 0; i < g_ncpus; i++)
+		g_cpu_power_states[i].dtrace_time = 0;
+
+	if (dtrace_status(dtp) == -1)
+		return (-1);
+
+	if (dtrace_aggregate_snap(dtp) != 0)
+		pt_error("%s : failed to add to stats aggregation", __FILE__);
+
+	if (dtrace_aggregate_walk_keyvarsorted(dtp, pt_cpufreq_dtrace_walk,
+	    NULL) != 0)
+		pt_error("%s : failed to sort stats aggregation", __FILE__);
+
+	dtrace_aggregate_clear(dtp);
+
+	if ((ret = pt_cpufreq_snapshot()) != 0) {
+		pt_error("%s : failed to add to stats aggregation", __FILE__);
+		return (ret);
+	}
+
+	switch (g_op_mode) {
+	case PTOP_MODE_CPU:
+		pt_cpufreq_stat_account(interval, g_observed_cpu);
+		break;
+	case PTOP_MODE_DEFAULT:
+	default:
+		for (i = 0; i < g_ncpus_observed; i++)
+			pt_cpufreq_stat_account(interval, i);
+		break;
+	}
+
+	return (0);
+}
+
+static void
+pt_cpufreq_stat_account(double interval, uint_t cpu)
+{
+	uint64_t 		speed;
+	hrtime_t 		duration;
+	cpu_power_info_t 	*cpu_pow;
+	int			i;
+
+	cpu_pow = &g_cpu_power_states[cpu];
+	speed = cpu_pow->current_pstate;
+
+	duration = (hrtime_t)((interval * NANOSEC)) - cpu_pow->dtrace_time;
+
+	for (i = 0; i < g_npstates; i++) {
+		if (g_pstate_info[i].speed == speed) {
+			g_pstate_info[i].total_time += duration;
+			cpu_pow->time_accounted += duration;
+		}
+	}
+}
+
+/*
+ * Take a snapshot of each CPU's speed by looking through the cpu_info kstats.
+ */
+static int
+pt_cpufreq_snapshot(void)
+{
+	kstat_ctl_t 		*kc;
+	int 			ret;
+	uint_t			i;
+
+	if ((kc = kstat_open()) == NULL)
+		return (errno);
+
+	switch (g_op_mode) {
+	case PTOP_MODE_CPU:
+		ret = pt_cpufreq_snapshot_cpu(kc, g_observed_cpu);
+		break;
+	case PTOP_MODE_DEFAULT:
+	default:
+		for (i = 0; i < g_ncpus_observed; i++)
+			if ((ret = pt_cpufreq_snapshot_cpu(kc, i)) != 0)
+				break;
+		break;
+	}
+
+	if (kstat_close(kc) != 0)
+		pt_error("%s : couldn't close kstat\n", __FILE__);
+
+	return (ret);
+}
+
+static int
+pt_cpufreq_snapshot_cpu(kstat_ctl_t *kc, uint_t cpu)
+{
+	kstat_t 		*ksp;
+	kstat_named_t 		*knp;
+
+	ksp = kstat_lookup(kc, "cpu_info", g_cpu_table[cpu], NULL);
+	if (ksp == NULL) {
+		pt_error("%s : couldn't find cpu_info kstat for CPU "
+		"%d\n", __FILE__, cpu);
+		return (1);
+	}
+
+	if (kstat_read(kc, ksp, NULL) == -1) {
+		pt_error("%s : couldn't read cpu_info kstat for "
+		    "CPU %d\n", __FILE__, cpu);
+		return (2);
+	}
+
+	knp = kstat_data_lookup(ksp, "current_clock_Hz");
+	if (knp == NULL) {
+		pt_error("%s : couldn't find current_clock_Hz "
+		    "kstat for CPU %d\n", __FILE__, cpu);
+		return (3);
+	}
+
+	g_cpu_power_states[cpu].current_pstate = HZ2MHZ(knp->value.ui64);
+
+	return (0);
+}
+
+/*
+ * DTrace aggregation walker that sorts through a snapshot of the
+ * aggregation data collected during firings of the cpu-change-speed
+ * probe.
+ */
+/*ARGSUSED*/
+static int
+pt_cpufreq_dtrace_walk(const dtrace_aggdata_t *data, void *arg)
+{
+	dtrace_aggdesc_t 	*aggdesc = data->dtada_desc;
+	dtrace_recdesc_t 	*cpu_rec, *speed_rec;
+	cpu_power_info_t 	*cpu_pow;
+	int32_t 		cpu;
+	uint64_t 		speed;
+	hrtime_t 		dt_state_time = 0;
+	int 			i;
+
+	if (strcmp(aggdesc->dtagd_name, "times") == 0) {
+		cpu_rec = &aggdesc->dtagd_rec[1];
+		speed_rec = &aggdesc->dtagd_rec[2];
+
+		for (i = 0; i < g_ncpus; i++) {
+			/* LINTED - alignment */
+			dt_state_time += *((hrtime_t *)(data->dtada_percpu[i]));
+		}
+
+		/* LINTED - alignment */
+		cpu = *(int32_t *)(data->dtada_data + cpu_rec->dtrd_offset);
+		/* LINTED - alignment */
+		speed = *(uint64_t *)(data->dtada_data +
+		    speed_rec->dtrd_offset);
+
+		if (speed == 0) {
+			speed = max_cpufreq;
+		}
+
+		/*
+		 * We have an aggregation record for "cpu" being at "speed"
+		 * for an interval of "n" nanoseconds. The reported interval
+		 * may exceed the powertop sampling interval, since we only
+		 * notice during potentially infrequent firings of the
+		 * "speed change" DTrace probe. In this case powertop would
+		 * have already accounted for the portions of the interval
+		 * that happened during prior powertop samplings, so subtract
+		 * out time already accounted.
+		 */
+		cpu_pow = &g_cpu_power_states[cpu];
+
+		for (i = 0; i < g_npstates; i++) {
+			if (g_pstate_info[i].speed == speed) {
+				if (cpu_pow->time_accounted > 0) {
+					if (dt_state_time == 0)
+						continue;
+					if (dt_state_time >
+					    cpu_pow->time_accounted) {
+						dt_state_time -=
+						    cpu_pow->time_accounted;
+						cpu_pow->time_accounted = 0;
+					}
+				}
+				g_pstate_info[i].total_time += dt_state_time;
+				cpu_pow->dtrace_time += dt_state_time;
+			}
+		}
+	}
+	return (DTRACE_AGGWALK_NEXT);
+}
+
+/*
+ * Used as a suggestion, sets PM in /etc/power.conf and
+ * a 1sec threshold, then calls /usr/sbin/pmconfig
+ */
+void
+enable_p_state(void)
+{
+	(void) system(cpupm_enable);
+	(void) system(cpupm_treshold);
+	(void) system(default_pmconf);
+}
+
+/*
+ * Checks if PM is enabled in /etc/power.conf, enabling if not
+ */
+void
+suggest_p_state(void)
+{
+	char 	line[1024];
+	FILE 	*file;
+
+	/*
+	 * Return if speed transition is not supported
+	 */
+	if (g_npstates < 2)
+		return;
+
+	file = fopen(default_conf, "r");
+
+	if (!file)
+		return;
+
+	(void) memset(line, 0, 1024);
+
+	while (fgets(line, 1023, file)) {
+		if (strstr(line, "cpupm")) {
+			if (strstr(line, "enable")) {
+				(void) fclose(file);
+				return;
+			}
+		}
+	}
+
+	add_suggestion("Suggestion: enable CPU power management by "
+	    "pressing the P key",  40, 'P', "P - Enable p-state",
+	    enable_p_state);
+
+	(void) fclose(file);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/cpuidle.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <string.h>
+#include <dtrace.h>
+#include "powertop.h"
+
+static dtrace_hdl_t 	*dtp;
+
+/*
+ * Buffer containing DTrace program to track CPU idle state transitions
+ */
+static const char *dtp_cpuidle =
+":::idle-state-transition"
+"/arg0 != 0/"
+"{"
+"	self->start = timestamp;"
+"	self->state = arg0;"
+"}"
+""
+":::idle-state-transition"
+"/arg0 == 0 && self->start/"
+"{"
+"	@number[self->state] = count();"
+"	@times[self->state] = sum((timestamp - self->start)/1000000);"
+"	self->start = 0;"
+"	self->state = 0;"
+"}";
+
+/*
+ * Same as above but only for a specific CPU
+ */
+static const char *dtp_cpuidle_c =
+":::idle-state-transition"
+"/cpu == $0 &&"
+" arg0 != 0/"
+"{"
+"	self->start = timestamp;"
+"	self->state = arg0;"
+"}"
+""
+":::idle-state-transition"
+"/cpu == $0 &&"
+" arg0 == 0 && self->start/"
+"{"
+"	@number[self->state] = count();"
+"	@times[self->state] = sum((timestamp - self->start)/1000000);"
+"	self->start = 0;"
+"	self->state = 0;"
+"}";
+
+static int 	pt_cpuidle_dtrace_walk(const dtrace_aggdata_t *, void *);
+
+/*
+ * Perform setup necessary to track CPU idle state transitions
+ */
+int
+pt_cpuidle_stat_prepare(void)
+{
+	dtrace_prog_t 		*prog;
+	dtrace_proginfo_t 	info;
+	dtrace_optval_t 	statustime;
+	int 			err;
+	char			*prog_ptr;
+
+	if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
+		pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
+		    dtrace_errmsg(NULL, err));
+		return (-1);
+	}
+
+	/*
+	 * Execute different scripts (defined above) depending on
+	 * user specified options.
+	 */
+	if (PTOP_ON_CPU)
+		prog_ptr = (char *)dtp_cpuidle_c;
+	else
+		prog_ptr = (char *)dtp_cpuidle;
+
+	if ((prog = dtrace_program_strcompile(dtp, prog_ptr,
+	    DTRACE_PROBESPEC_NAME, 0, g_argc, g_argv)) == NULL) {
+		pt_error("%s : C-State DTrace probes unavailable\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_program_exec(dtp, prog, &info) == -1) {
+		pt_error("%s : failed to enable C State probes\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_setopt(dtp, "aggsize", "128k") == -1) {
+		pt_error("%s : failed to set C-state 'aggsize'\n", __FILE__);
+	}
+
+	if (dtrace_setopt(dtp, "aggrate", "0") == -1) {
+		pt_error("%s : failed to set C-state'aggrate'\n", __FILE__);
+	}
+
+	if (dtrace_setopt(dtp, "aggpercpu", 0) == -1) {
+		pt_error("%s : failed to set C-state 'aggpercpu'\n", __FILE__);
+	}
+
+	if (dtrace_go(dtp) != 0) {
+		pt_error("%s : failed to start C-state observation", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_getopt(dtp, "statusrate", &statustime) == -1) {
+		pt_error("%s : failed to get C-state 'statusrate'\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	return (0);
+}
+
+/*
+ * The DTrace probes have been enabled, and are tracking CPU idle state
+ * transitions. Take a snapshot of the aggregations, and invoke the aggregation
+ * walker to process any records. The walker does most of the accounting work
+ * chalking up time spent into the g_cstate_info structure.
+ */
+int
+pt_cpuidle_stat_collect(double interval)
+{
+	int 		i;
+	hrtime_t	t = 0;
+
+	/*
+	 * Zero out the interval time reported by DTrace for
+	 * this interval
+	 */
+	for (i = 0; i < NSTATES; i++) {
+		g_cstate_info[i].total_time = 0;
+		g_cstate_info[i].events = 0;
+	}
+
+	/*
+	 * Assume that all the time spent in this interval will
+	 * be the default "0" state. The DTrace walker will reallocate
+	 * time out of the default bucket as it processes aggregation
+	 * records for time spent in other states.
+	 */
+	g_cstate_info[0].total_time = (long)(interval * g_ncpus_observed *
+	    1000);
+
+	if (dtrace_status(dtp) == -1)
+		return (-1);
+
+	if (dtrace_aggregate_snap(dtp) != 0)
+		pt_error("%s : failed to add to aggregation", __FILE__);
+
+	if (dtrace_aggregate_walk_keyvarsorted(dtp, pt_cpuidle_dtrace_walk,
+	    NULL) != 0)
+		pt_error("%s : failed to sort aggregation", __FILE__);
+
+	dtrace_aggregate_clear(dtp);
+
+	/*
+	 * Populate g_cstate_info with the correct amount of time spent
+	 * in each C state and update the number of C states in g_max_cstate
+	 */
+	g_total_c_time = 0;
+	for (i = 0; i < NSTATES; i++) {
+		if (g_cstate_info[i].total_time > 0) {
+			g_total_c_time += g_cstate_info[i].total_time;
+			if (i > g_max_cstate)
+				g_max_cstate = i;
+			if (g_cstate_info[i].last_time > t) {
+				t = g_cstate_info[i].last_time;
+				g_longest_cstate = i;
+			}
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * DTrace aggregation walker that sorts through a snapshot of data records
+ * collected during firings of the idle-state-transition probe.
+ *
+ * XXX A way of querying the current idle state for a CPU is needed in addition
+ *     to logic similar to that in cpufreq.c
+ */
+/*ARGSUSED*/
+static int
+pt_cpuidle_dtrace_walk(const dtrace_aggdata_t *data, void *arg)
+{
+	dtrace_aggdesc_t 	*aggdesc = data->dtada_desc;
+	dtrace_recdesc_t 	*rec;
+	uint64_t 		n = 0;
+	int32_t 		state;
+	int 			i;
+
+	rec = &aggdesc->dtagd_rec[1];
+	/* LINTED - alignment */
+	state = *(int32_t *)(data->dtada_data + rec->dtrd_offset);
+
+	if (strcmp(aggdesc->dtagd_name, "number") == 0) {
+		for (i = 0; i < g_ncpus; i++) {
+			/* LINTED - alignment */
+			n += *((uint64_t *)(data->dtada_percpu[i]));
+		}
+		g_total_events += n;
+		g_cstate_info[state].events += n;
+	}
+	else
+		if (strcmp(aggdesc->dtagd_name, "times") == 0) {
+			for (i = 0; i < g_ncpus; i++) {
+				/* LINTED - alignment */
+				n += *((uint64_t *)(data->dtada_percpu[i]));
+			}
+			g_cstate_info[state].last_time = n;
+			g_cstate_info[state].total_time += n;
+			if (g_cstate_info[0].total_time >= n)
+				g_cstate_info[0].total_time -= n;
+		}
+
+	return (DTRACE_AGGWALK_NEXT);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/display.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,477 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <curses.h>
+#include "powertop.h"
+
+static WINDOW 	*title_bar_window;
+static WINDOW 	*cstate_window;
+static WINDOW 	*wakeup_window;
+static WINDOW 	*acpi_power_window;
+static WINDOW 	*eventstat_window;
+static WINDOW 	*suggestion_window;
+static WINDOW 	*status_bar_window;
+
+#define	print(win, y, x, fmt, args...)				\
+	if (PTOP_ON_DUMP)					\
+		(void) printf(fmt, ## args);			\
+	else							\
+		(void) mvwprintw(win, y, x, fmt, ## args);
+
+char 		g_status_bar_slots[PTOP_BAR_NSLOTS][PTOP_BAR_LENGTH];
+char 		g_suggestion_key;
+
+static int	maxx, maxy;
+
+static void
+zap_windows(void)
+{
+	if (title_bar_window) {
+		(void) delwin(title_bar_window);
+		title_bar_window = NULL;
+	}
+	if (cstate_window) {
+		(void) delwin(cstate_window);
+		cstate_window = NULL;
+	}
+	if (wakeup_window) {
+		(void) delwin(wakeup_window);
+		wakeup_window = NULL;
+	}
+	if (acpi_power_window) {
+		(void) delwin(acpi_power_window);
+		acpi_power_window = NULL;
+	}
+	if (eventstat_window) {
+		(void) delwin(eventstat_window);
+		eventstat_window = NULL;
+	}
+	if (suggestion_window) {
+		(void) delwin(suggestion_window);
+		suggestion_window = NULL;
+	}
+	if (status_bar_window) {
+		(void) delwin(status_bar_window);
+		status_bar_window = NULL;
+	}
+}
+
+void
+cleanup_curses(void)
+{
+	(void) endwin();
+}
+
+/*
+ * This part was re-written to be human readable and easy to modify. Please
+ * try to keep it that way and help us save some time.
+ *
+ * Friendly reminder:
+ * 	subwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x)
+ */
+void
+setup_windows(void)
+{
+	/*
+	 * These variables are used to properly set the initial y position and
+	 * number of lines in each subwindow, as the number of supported CPU
+	 * states affects their placement.
+	 */
+	int cstate_lines, event_lines, pos_y;
+
+	getmaxyx(stdscr, maxy, maxx);
+
+	zap_windows();
+
+	cstate_lines 	= TITLE_LINE + max((g_max_cstate+1), g_npstates);
+
+	pos_y = 0;
+	title_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+	pos_y += NEXT_LINE + BLANK_LINE;
+	cstate_window = subwin(stdscr, cstate_lines, maxx, pos_y, 0);
+
+	pos_y += cstate_lines + BLANK_LINE;
+	wakeup_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+	pos_y += NEXT_LINE;
+	acpi_power_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+	pos_y += NEXT_LINE + BLANK_LINE;
+	event_lines = maxy - SINGLE_LINE_SW - NEXT_LINE - LENGTH_SUGG_SW -
+	    pos_y;
+	eventstat_window = subwin(stdscr, event_lines, maxx, pos_y, 0);
+
+	pos_y += event_lines + NEXT_LINE;
+	suggestion_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+	pos_y += BLANK_LINE + NEXT_LINE;
+	status_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+	(void) strcpy(g_status_bar_slots[0], _(" Q - Quit "));
+	(void) strcpy(g_status_bar_slots[1], _(" R - Refresh "));
+
+	(void) werase(stdscr);
+	(void) wrefresh(status_bar_window);
+}
+
+void
+initialize_curses(void)
+{
+	(void) initscr();
+	(void) start_color();
+
+	/*
+	 * Enable keyboard mapping
+	 */
+	(void) keypad(stdscr, TRUE);
+
+	/*
+	 * Tell curses not to do NL->CR/NL on output
+	 */
+	(void) nonl();
+
+	/*
+	 * Take input chars one at a time, no wait for \n
+	 */
+	(void) cbreak();
+
+	/*
+	 * Dont echo input
+	 */
+	(void) noecho();
+
+	/*
+	 * Turn off cursor
+	 */
+	(void) curs_set(0);
+
+	(void) init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK);
+	(void) init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE);
+	(void) init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED);
+	(void) init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED);
+	(void) init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW);
+	(void) init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN);
+	(void) init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE);
+	(void) init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK);
+
+	(void) atexit(cleanup_curses);
+}
+
+void
+show_title_bar(void)
+{
+	int 	i, x = 0, y = 0;
+	char	title_pad[10];
+
+	(void) wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
+	(void) wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
+	(void) werase(title_bar_window);
+
+	(void) snprintf(title_pad, 10, "%%%ds",
+	    (maxx - strlen(TITLE))/2 + strlen(TITLE));
+	/* LINTED: E_SEC_PRINTF_VAR_FMT */
+	print(title_bar_window, y, x, title_pad, TITLE);
+
+	(void) wrefresh(title_bar_window);
+	(void) werase(status_bar_window);
+
+	for (i = 0; i < PTOP_BAR_NSLOTS; i++) {
+		if (strlen(g_status_bar_slots[i]) == 0)
+			continue;
+		(void) wattron(status_bar_window, A_REVERSE);
+		print(status_bar_window, y, x, "%s", g_status_bar_slots[i]);
+		(void) wattroff(status_bar_window, A_REVERSE);
+		x += strlen(g_status_bar_slots[i]) + 1;
+	}
+	(void) wnoutrefresh(status_bar_window);
+}
+
+void
+show_cstates(void)
+{
+	char		c[100];
+	int		i;
+	double		total_pstates = 0.0, avg, res;
+	uint64_t	p0_speed, p1_speed;
+
+	if (!PTOP_ON_DUMP) {
+		(void) werase(cstate_window);
+		(void) wattrset(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT));
+		(void) wbkgd(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT));
+	}
+
+	print(cstate_window, 0, 0, "%s\tAvg residency\n", g_msg_idle_state);
+	res =  (((double)g_cstate_info[0].total_time / g_total_c_time)) * 100;
+	(void) sprintf(c, "C0 (cpu running)\t\t(%.1f%%)\n", (float)res);
+	print(cstate_window, 1, 0, "%s", c);
+
+	for (i = 1; i <= g_max_cstate; i++) {
+		/*
+		 * In situations where the load is too intensive, the system
+		 * might not transition at all.
+		 */
+		if (g_cstate_info[i].events > 0)
+			avg = (((double)g_cstate_info[i].total_time/
+			    g_ncpus_observed)/g_cstate_info[i].events);
+		else
+			avg = 0;
+
+		res = ((double)g_cstate_info[i].total_time/g_total_c_time)
+		    * 100;
+
+		(void) sprintf(c, "C%d\t\t\t%.1fms\t(%.1f%%)\n", i, (float)avg,
+		    (float)res);
+		print(cstate_window, i + 1, 0, "%s", c);
+	}
+
+	print(cstate_window, 0, 48, "%s", g_msg_freq_state);
+
+	if (g_npstates < 2) {
+		(void) sprintf(c, "%4lu Mhz\t%.1f%%",
+		    (long)g_pstate_info[0].speed, 100.0);
+		print(cstate_window, 1, 48, "%s\n", c);
+	} else {
+		for (i = 0; i < g_npstates; i++) {
+			total_pstates += (double)(g_pstate_info[i].total_time/
+			    g_ncpus_observed/1000000);
+		}
+
+		/*
+		 * display ACPI_PSTATE from P(n) to P(1)
+		 */
+		for (i = 0;  i < g_npstates - 1; i++) {
+			(void) sprintf(c, "%4lu Mhz\t%.1f%%",
+			    (long)g_pstate_info[i].speed,
+			    100 * (g_pstate_info[i].total_time/g_ncpus_observed/
+			    1000000/total_pstates));
+			print(cstate_window, i+1, 48, "%s\n", c);
+		}
+
+		/*
+		 * Display ACPI_PSTATE P0 according to if turbo
+		 * mode is supported
+		 */
+		if (g_turbo_supported) {
+			p1_speed = g_pstate_info[g_npstates - 2].speed;
+
+			/*
+			 * If g_turbo_ratio <= 1.0, it will be ignored.
+			 * we display P(0) as P(1) + 1.
+			 */
+			if (g_turbo_ratio <= 1.0) {
+				p0_speed = p1_speed + 1;
+			} else {
+				/*
+				 * If g_turbo_ratio > 1.0, that means turbo
+				 * mode works. So, P(0) = ratio * P(1);
+				 */
+				p0_speed = (uint64_t)(p1_speed * g_turbo_ratio);
+				if (p0_speed < (p1_speed + 1))
+				p0_speed = p1_speed + 1;
+			}
+			/*
+			 * Reset the ratio for the next round
+			 */
+			g_turbo_ratio = 0.0;
+
+			/*
+			 * Setup the string for the display
+			 */
+			(void) sprintf(c, "%4lu Mhz(turbo)\t%.1f%%",
+			    (long)p0_speed,
+			    100 * (g_pstate_info[i].total_time/
+			    g_ncpus_observed/1000000/total_pstates));
+		} else {
+			(void) sprintf(c, "%4lu Mhz\t%.1f%%",
+			    (long)g_pstate_info[i].speed,
+			    100 * (g_pstate_info[i].total_time/
+			    g_ncpus_observed/1000000/total_pstates));
+		}
+		print(cstate_window, i+1, 48, "%s\n", c);
+	}
+
+	if (!PTOP_ON_DUMP)
+		(void) wnoutrefresh(cstate_window);
+}
+
+void
+show_acpi_power_line(uint32_t flag, double rate, double rem_cap, double cap,
+    uint32_t state)
+{
+	char	buffer[1024];
+
+	(void) sprintf(buffer,  _("no ACPI power usage estimate available"));
+
+	if (!PTOP_ON_DUMP)
+		(void) werase(acpi_power_window);
+	if (flag) {
+		char *c;
+		(void) sprintf(buffer, "Power usage (ACPI estimate): %.3fW",
+		    rate);
+		(void) strcat(buffer, " ");
+		c = &buffer[strlen(buffer)];
+		switch (state) {
+		case 0:
+			(void) sprintf(c, "(running on AC power, fully "
+			    "charged)");
+			break;
+		case 1:
+			(void) sprintf(c, "(discharging: %3.1f hours)",
+			    (uint32_t)rem_cap/rate);
+			break;
+		case 2:
+			(void) sprintf(c, "(charging: %3.1f hours)",
+			    (uint32_t)(cap - rem_cap)/rate);
+			break;
+		case 4:
+			(void) sprintf(c, "(##critically low battery power##)");
+			break;
+		}
+
+	}
+	print(acpi_power_window, 0, 0, "%s\n", buffer);
+	if (!PTOP_ON_DUMP)
+		(void) wnoutrefresh(acpi_power_window);
+}
+
+void
+show_wakeups(double interval)
+{
+	char		c[100];
+	int		i, event_sum = 0;
+	event_info_t	*g_p_event = g_event_info;
+
+	if (!PTOP_ON_DUMP) {
+		(void) werase(wakeup_window);
+		(void) wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED));
+		(void) wattron(wakeup_window, A_BOLD);
+	}
+
+	/*
+	 * calculate the actual total event number
+	 */
+	for (i = 0; i < g_tog_p_events; i++, g_p_event++)
+		event_sum += g_p_event->total_count;
+
+	/*
+	 * g_total_events is the sum of the number of Cx->C0 transition,
+	 * So when the system is very busy, the idle thread will have no
+	 * chance or very seldom to be scheduled, this could cause >100%
+	 * event report. Re-assign g_total_events to the actual event
+	 * number is a way to avoid this issue.
+	 */
+	if (event_sum > g_total_events)
+		g_total_events = event_sum;
+
+	(void) sprintf(c, "Wakeups-from-idle per second: %4.1f\tinterval: "
+	    "%.1fs", (double)(g_total_events/interval), interval);
+	print(wakeup_window, 0, 0, "%s\n", c);
+
+	if (!PTOP_ON_DUMP)
+		(void) wnoutrefresh(wakeup_window);
+}
+
+void
+show_eventstats(double interval)
+{
+	char		c[100];
+	int		i;
+	double		events;
+	event_info_t	*g_p_event = g_event_info;
+
+	if (!PTOP_ON_DUMP) {
+		(void) werase(eventstat_window);
+		(void) wattrset(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT));
+		(void) wbkgd(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT));
+	}
+
+	/*
+	 * Sort the event report list
+	 */
+	if (g_tog_p_events > EVENT_NUM_MAX)
+		g_tog_p_events = EVENT_NUM_MAX;
+
+	qsort((void *)g_event_info, g_tog_p_events, sizeof (event_info_t),
+	    event_compare);
+
+	if (PTOP_ON_CPU)
+		(void) sprintf(c, "Top causes for wakeups on CPU %d:\n",
+		    g_observed_cpu);
+	else
+		(void) sprintf(c, "Top causes for wakeups:\n");
+
+	print(eventstat_window, 0, 0, "%s", c);
+
+	for (i = 0; i < g_tog_p_events; i++, g_p_event++) {
+
+		if (g_total_events > 0 && g_p_event->total_count > 0)
+			events = (double)g_p_event->total_count/
+			    (double)g_total_events;
+		else
+			continue;
+
+		(void) sprintf(c, "%4.1f%% (%5.1f)", 100 * events,
+		    (double)g_p_event->total_count/interval);
+		print(eventstat_window, i+1, 0, "%s", c);
+		print(eventstat_window, i+1, 16, "%20s :",
+		    g_p_event->offender_name);
+		print(eventstat_window, i+1, 40, "%-64s\n",
+		    g_p_event->offense_name);
+	}
+
+	if (!PTOP_ON_DUMP)
+		(void) wnoutrefresh(eventstat_window);
+}
+
+void
+show_suggestion(char *sug)
+{
+	(void) werase(suggestion_window);
+	print(suggestion_window, 0, 0, "%s", sug);
+	(void) wnoutrefresh(suggestion_window);
+}
+
+void
+update_windows(void)
+{
+	(void) doupdate();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/events.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <dtrace.h>
+#include "powertop.h"
+
+static dtrace_hdl_t *dtp;
+
+/*ARGSUSED*/
+static int
+walk(const dtrace_aggdata_t *data, void *arg)
+{
+	dtrace_aggdesc_t 	*aggdesc = data->dtada_desc;
+	dtrace_recdesc_t 	*rec1, *rec2, *rec3;
+	dtrace_syminfo_t 	dts;
+	char 			*offense_name;
+	uint64_t		offender_addr;
+	int32_t 		*instance, *offender_cpu;
+	int 			i;
+	uint64_t 		n = 0;
+	GElf_Sym 		sym;
+
+	if (g_tog_p_events >= EVENT_NUM_MAX)
+		return (0);
+
+	rec1 = &aggdesc->dtagd_rec[1];
+	rec2 = &aggdesc->dtagd_rec[2];
+
+	/*
+	 * Report interrupts
+	 */
+	if (strcmp(aggdesc->dtagd_name, "interrupts") == 0) {
+		offense_name = data->dtada_data + rec1->dtrd_offset;
+
+		/* LINTED - alignment */
+		instance = (int32_t *)(data->dtada_data + rec2->dtrd_offset);
+		(void) snprintf((char *)(g_p_event->offender_name),
+		    EVENT_NAME_MAX, "%s", "<interrupt>");
+		(void) snprintf((char *)(g_p_event->offense_name),
+		    EVENT_NAME_MAX, "%s#%d", offense_name, *instance);
+	/*
+	 * Report kernel events
+	 */
+	} else if (strcmp(aggdesc->dtagd_name, "events_k") == 0) {
+
+		(void) snprintf((char *)(g_p_event->offender_name),
+		    EVENT_NAME_MAX, "%s", "<kernel>");
+
+		/*
+		 * Casting offender_addr to the wrong type will cause
+		 * dtrace_lookup_by_addr to return 0 and the report
+		 * to show an address instead of a name.
+		 */
+		switch (g_bit_depth) {
+		case 32:
+			/* LINTED - alignment */
+			offender_addr = *(uint32_t *)(data->dtada_data +
+			    rec1->dtrd_offset);
+			break;
+		case 64:
+			/* LINTED - alignment */
+			offender_addr = *(uint64_t *)(data->dtada_data +
+			    rec1->dtrd_offset);
+			break;
+		}
+
+		/*
+		 * We have the address of the kernel callout.
+		 * Try to resolve it into a meaningful symbol
+		 */
+		if (offender_addr != NULL && dtrace_lookup_by_addr(dtp,
+		    offender_addr, &sym, &dts) == 0) {
+			(void) snprintf((char *)(g_p_event->offense_name),
+			    EVENT_NAME_MAX, "%s`%s", dts.dts_object,
+			    dts.dts_name);
+		} else {
+			(void) snprintf((char *)(g_p_event->offense_name),
+			    EVENT_NAME_MAX, "0x%llx", offender_addr);
+		}
+	/*
+	 * Report user events
+	 */
+	} else if (strcmp(aggdesc->dtagd_name, "events_u") == 0) {
+		offense_name = data->dtada_data + rec1->dtrd_offset;
+
+		(void) snprintf((char *)(g_p_event->offender_name),
+		    EVENT_NAME_MAX, "%s", offense_name);
+		(void) snprintf((char *)(g_p_event->offense_name),
+		    EVENT_NAME_MAX, "<scheduled timeout expiration>");
+	/*
+	 * Report cross calls
+	 */
+	} else if (strcmp(aggdesc->dtagd_name, "events_x") == 0) {
+		offense_name = data->dtada_data + rec1->dtrd_offset;
+
+		(void) snprintf((char *)(g_p_event->offender_name),
+		    EVENT_NAME_MAX, "%s", offense_name);
+
+		switch (g_bit_depth) {
+		case 32:
+			/* LINTED - alignment */
+			offender_addr = *(uint32_t *)(data->dtada_data +
+			    rec2->dtrd_offset);
+			break;
+		case 64:
+			/* LINTED - alignment */
+			offender_addr = *(uint64_t *)(data->dtada_data +
+			    rec2->dtrd_offset);
+			break;
+		}
+
+		/*
+		 * Try to resolve the address of the cross call function.
+		 */
+		if (offender_addr != NULL && dtrace_lookup_by_addr(dtp,
+		    offender_addr, &sym, &dts) == 0) {
+			(void) snprintf((char *)(g_p_event->offense_name),
+			    EVENT_NAME_MAX, "<xcalls> %s`%s",
+			    dts.dts_object, dts.dts_name);
+		} else {
+			(void) snprintf((char *)(g_p_event->offense_name),
+			    EVENT_NAME_MAX, "<xcalls>");
+		}
+	/*
+	 * Report cross calls from other CPUs than the one we're observing
+	 * with the -C option
+	 */
+	} else if (strcmp(aggdesc->dtagd_name, "events_xc") == 0) {
+		rec3 = &aggdesc->dtagd_rec[3];
+		offense_name = data->dtada_data + rec1->dtrd_offset;
+
+		(void) snprintf((char *)(g_p_event->offender_name),
+		    EVENT_NAME_MAX, "%s", offense_name);
+
+		switch (g_bit_depth) {
+		case 32:
+			/* LINTED - alignment */
+			offender_addr = *(uint32_t *)(data->dtada_data +
+			    rec2->dtrd_offset);
+			break;
+		case 64:
+			/* LINTED - alignment */
+			offender_addr = *(uint64_t *)(data->dtada_data +
+			    rec2->dtrd_offset);
+			break;
+		}
+		/* LINTED - alignment */
+		offender_cpu = (int32_t *)(data->dtada_data +
+		    rec3->dtrd_offset);
+
+		/*
+		 * Try to resolve the address of the cross call function.
+		 */
+		if (offender_addr != NULL && dtrace_lookup_by_addr(dtp,
+		    offender_addr, &sym, &dts) == 0) {
+			(void) snprintf((char *)(g_p_event->offense_name),
+			    EVENT_NAME_MAX, "<xcalls> %s`%s (CPU %d)",
+			    dts.dts_object, dts.dts_name, *offender_cpu);
+		} else {
+			(void) snprintf((char *)(g_p_event->offense_name),
+			    EVENT_NAME_MAX, "<xcalls> (CPU %d)",
+			    *offender_cpu);
+		}
+	/*
+	 * Report unknown events
+	 */
+	} else {
+		(void) snprintf((char *)(g_p_event->offender_name),
+		    EVENT_NAME_MAX, "%s", "<unknown>");
+		(void) snprintf((char *)(g_p_event->offense_name),
+		    EVENT_NAME_MAX, "%s", "<unknown>");
+	}
+
+	for (i = 0; i < g_ncpus; i++)
+		/* LINTED - alignment */
+		n += *((uint64_t *)(data->dtada_percpu[i]));
+
+	g_p_event->total_count = n;
+
+	g_p_event++;
+	g_tog_p_events++;
+
+	return (DTRACE_AGGWALK_NEXT);
+}
+
+int
+pt_events_stat_prepare(void)
+{
+	dtrace_prog_t 		*prog;
+	dtrace_proginfo_t 	info;
+	int 			err;
+	dtrace_optval_t 	statustime;
+	char			*prog_ptr;
+
+	g_p_event = g_event_info;
+
+	if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
+		pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
+		    dtrace_errmsg(NULL, err));
+		return (-1);
+	}
+
+	/*
+	 * Execute different scripts (defined in the platform specific file)
+	 * depending on user specified options.
+	 */
+	if (PTOP_ON_VERBOSE) {
+		prog_ptr = (char *)g_dtp_events_v;
+	} else {
+		if (PTOP_ON_CPU)
+			prog_ptr = (char *)g_dtp_events_c;
+		else
+			prog_ptr = (char *)g_dtp_events;
+	}
+
+	if ((prog = dtrace_program_strcompile(dtp, prog_ptr,
+	    DTRACE_PROBESPEC_NAME, 0, g_argc, g_argv)) == NULL) {
+		pt_error("%s : failed to compile DTrace program\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_program_exec(dtp, prog, &info) == -1) {
+		pt_error("%s : failed to enable probes\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_setopt(dtp, "aggsize", "128k") == -1) {
+		pt_error("%s : failed to set 'aggsize'\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_setopt(dtp, "aggrate", "0") == -1) {
+		pt_error("%s : failed to set 'aggrate'\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_setopt(dtp, "aggpercpu", 0) == -1) {
+		pt_error("%s : failed to set 'aggpercpu'\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_go(dtp) != 0) {
+		pt_error("%s : dtrace_go() failed\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	if (dtrace_getopt(dtp, "statusrate", &statustime) == -1) {
+		pt_error("%s : failed to get 'statusrate'\n", __FILE__);
+		return (dtrace_errno(dtp));
+	}
+
+	return (0);
+}
+
+int
+pt_events_stat_collect(void)
+{
+	g_p_event 	= g_event_info;
+	g_tog_p_events 	= 0;
+
+	if (dtrace_status(dtp) == -1)
+		return (-1);
+
+	if (dtrace_aggregate_snap(dtp) != 0)
+		pt_error("%s : failed to add to aggregate", __FILE__);
+
+	if (dtrace_aggregate_walk_keyvarsorted(dtp, walk, NULL) != 0)
+		pt_error("%s : failed to sort aggregate", __FILE__);
+
+	dtrace_aggregate_clear(dtp);
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/powertop.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <getopt.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <locale.h>
+#include "powertop.h"
+
+/*
+ * Global variables, see powertop.h for comments and extern declarations.
+ * These are ordered by type, grouped by usage.
+ */
+double 			g_ticktime, g_ticktime_usr;
+double 			g_interval;
+double			g_displaytime;
+
+int			g_bit_depth;
+int 			g_total_events, g_tog_p_events;
+int			g_npstates, g_max_cstate, g_longest_cstate;
+uint_t			g_ncpus;
+uint_t			g_ncpus_observed;
+
+processorid_t 		*g_cpu_table;
+
+hrtime_t		g_total_c_time;
+
+uchar_t			g_op_mode;
+boolean_t		g_gui;
+uint_t			g_observed_cpu;
+
+event_info_t    	g_event_info[EVENT_NUM_MAX];
+event_info_t		*g_p_event;
+state_info_t		g_cstate_info[NSTATES];
+freq_state_info_t	g_pstate_info[NSTATES];
+cpu_power_info_t	*g_cpu_power_states;
+suggestion_func 	*g_suggestion_activate;
+
+boolean_t		g_turbo_supported;
+
+uint_t			g_argc;
+char			**g_argv;
+
+char			*optarg;
+
+static const int	true = 1;
+
+int
+main(int argc, char **argv)
+{
+	hrtime_t 	last, now;
+	uint_t		features = 0, user_interval = 0;
+	int		ncursesinited = 0, index2 = 0, c, ret, dump_count = 0;
+	double		last_time;
+	char		*endptr;
+
+	static struct option opts[] = {
+		{ "dump", 1, NULL, 'd' },
+		{ "time", 1, NULL, 't' },
+		{ "help", 0, NULL, 'h' },
+		{ "cpu", 1, NULL, 'c' },
+		{ "verbose", 0, NULL, 'v' },
+		{ 0, 0, NULL, 0 }
+	};
+
+	(void) setlocale(LC_ALL, "");
+	(void) bindtextdomain("powertop", "/usr/share/locale");
+	(void) textdomain("powertop");
+
+	pt_set_progname(argv[0]);
+
+	/*
+	 * Enumerate the system's CPUs
+	 * Populate cpu_table, g_ncpus
+	 */
+	if ((g_ncpus = g_ncpus_observed = enumerate_cpus()) == 0)
+		exit(EXIT_FAILURE);
+
+	if ((g_bit_depth = get_bit_depth()) < 0)
+		exit(EXIT_FAILURE);
+
+	g_ticktime = g_ticktime_usr = INTERVAL_DEFAULT;
+	g_displaytime 	= 0.0;
+	g_op_mode	= PTOP_MODE_DEFAULT;
+	g_gui		= B_FALSE;
+	g_max_cstate	= 0;
+	g_argv		= NULL;
+	g_argc		= 0;
+	g_observed_cpu	= 0;
+	g_turbo_supported = B_FALSE;
+
+	while ((c = getopt_long(argc, argv, "d:t:h:vc:", opts, &index2))
+	    != EOF) {
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'd':
+			if (PTOP_ON_DUMP)
+				usage();
+
+			g_op_mode |= PTOP_MODE_DUMP;
+			dump_count = (int)strtod(optarg, &endptr);
+
+			if (dump_count <= 0 || *endptr != NULL)
+				usage();
+			break;
+		case 't':
+			if (user_interval)
+				usage();
+
+			user_interval = 1;
+			g_ticktime = g_ticktime_usr = (double)strtod(optarg,
+			    &endptr);
+
+			if (*endptr != NULL || g_ticktime < 1 ||
+			    g_ticktime > INTERVAL_MAX)
+				usage();
+			break;
+		case 'v':
+			if (PTOP_ON_CPU || PTOP_ON_VERBOSE)
+				usage();
+
+			g_op_mode |= PTOP_MODE_VERBOSE;
+			break;
+		case 'c':
+			if (PTOP_ON_CPU || PTOP_ON_VERBOSE)
+				usage();
+
+			g_op_mode |= PTOP_MODE_CPU;
+			g_observed_cpu = (uint_t)strtod(optarg, &endptr);
+
+			if (g_observed_cpu >= g_ncpus)
+				usage();
+
+			g_argc = 1;
+			g_ncpus_observed = 1;
+
+			if ((g_argv = malloc(sizeof (char *))) == NULL)
+				return (EXIT_FAILURE);
+
+			if ((*g_argv = malloc(sizeof (char) * 5)) == NULL)
+				return (EXIT_FAILURE);
+
+			(void) snprintf(*g_argv, 5, "%d\0", g_observed_cpu);
+			break;
+		case 'h':
+		default:
+			usage();
+			return (EXIT_USAGE);
+		}
+	}
+
+	if (optind < argc) {
+		usage();
+	}
+
+	(void) printf("%s   %s\n\n", TITLE, COPYRIGHT_INTEL);
+
+	/*
+	 * If the system is running on battery, find out what's
+	 * the kstat module for it
+	 */
+	battery_mod_lookup();
+
+	/* Prepare C-state statistics */
+	ret = pt_cpuidle_stat_prepare();
+	if (ret == 0)
+		features |= FEATURE_CSTATE;
+	else
+		/*
+		 * PowerTop was unable to run a DTrace program,
+		 * most likely for lack of permissions.
+		 */
+		exit(EXIT_FAILURE);
+
+	/* Prepare P-state statistics */
+	if (pt_cpufreq_stat_prepare() == 0)
+		features |= FEATURE_PSTATE;
+
+	/* Prepare event statistics */
+	if (pt_events_stat_prepare() != -1)
+		features |= FEATURE_EVENTS;
+
+	/* Prepare turbo statistics */
+	if (pt_turbo_stat_prepare() == 0) {
+		features |= FEATURE_TURBO;
+	}
+
+	(void) printf(_("Collecting data for %.2f second(s) \n"),
+	    (float)g_ticktime);
+
+	if (!PTOP_ON_DUMP)
+		g_gui = B_TRUE;
+
+	last = gethrtime();
+
+	while (true) {
+		fd_set 	rfds;
+		struct 	timeval tv;
+		int 	key, reinit = 0;
+		char 	keychar;
+
+		/*
+		 * Sleep for a while waiting either for input (if we're not
+		 * in dump mode) or for the timeout to elapse
+		 */
+		FD_ZERO(&rfds);
+		FD_SET(0, &rfds);
+
+		tv.tv_sec 	= (long)g_ticktime;
+		tv.tv_usec 	= (long)((g_ticktime - tv.tv_sec) * 1000000);
+
+		if (!PTOP_ON_DUMP)
+			key = select(1, &rfds, NULL, NULL, &tv);
+		else
+			key = select(1, NULL, NULL, NULL, &tv);
+
+		now 		= gethrtime();
+
+		g_interval 	= (double)(now - last)/NANOSEC;
+		last 		= now;
+
+		g_tog_p_events 	= 0;
+		g_total_events 	= 0;
+
+		(void) memset(g_event_info,
+		    EVENT_NUM_MAX * sizeof (event_info_t), 0);
+		(void) memset(g_cstate_info, 2 * sizeof (state_info_t), 0);
+
+		/* Collect idle state transition stats */
+		if (features & FEATURE_CSTATE &&
+		    pt_cpuidle_stat_collect(g_interval) < 0) {
+			/* Reinitialize C-state statistics */
+			if (pt_cpuidle_stat_prepare() != 0)
+				exit(EXIT_FAILURE);
+
+			reinit = 1;
+		}
+
+		/* Collect frequency change stats */
+		if (features & FEATURE_PSTATE &&
+		    pt_cpufreq_stat_collect(g_interval) < 0) {
+			/* Reinitialize P-state statistics */
+			if (pt_cpufreq_stat_prepare() != 0)
+				exit(EXIT_FAILURE);
+
+			reinit = 1;
+		}
+
+		/* Collect event statistics */
+		if (features & FEATURE_EVENTS &&
+		    pt_events_stat_collect() < 0) {
+			/* Reinitialize event statistics */
+			if (pt_events_stat_prepare() != 0)
+				exit(EXIT_FAILURE);
+
+			reinit = 1;
+		}
+
+		if (reinit)
+			continue;
+
+		/* Collect turbo statistics */
+		if (features & FEATURE_TURBO &&
+		    pt_turbo_stat_collect() < 0) {
+			exit(EXIT_FAILURE);
+		}
+
+		/*
+		 * Initialize curses if we're not dumping and
+		 * haven't already done it
+		 */
+		if (!PTOP_ON_DUMP) {
+			if (!ncursesinited) {
+				initialize_curses();
+				ncursesinited++;
+			}
+			setup_windows();
+			show_title_bar();
+		}
+
+		/* Show CPU power states */
+		if (features & FEATURE_CSTATE)
+			show_cstates();
+
+		/* Show wakeups events affecting PM */
+		if (features & FEATURE_EVENTS) {
+			show_wakeups(g_interval);
+			show_eventstats(g_interval);
+		}
+
+		print_battery();
+
+		g_displaytime = g_displaytime - g_ticktime;
+
+		if (key && !PTOP_ON_DUMP) {
+			keychar = toupper(fgetc(stdin));
+
+			switch (keychar) {
+			case 'Q':
+				cleanup_curses();
+				exit(EXIT_SUCCESS);
+				break;
+			case 'R':
+				g_ticktime = 3;
+				break;
+			}
+			if (keychar == g_suggestion_key &&
+			    g_suggestion_activate) {
+				g_suggestion_activate();
+				g_displaytime = -1.0;
+			}
+		}
+		reset_suggestions();
+
+		/* suggests PM */
+		if (geteuid() == 0) {
+			suggest_p_state();
+		} else {
+			suggest_as_root();
+		}
+
+		if (dump_count)
+			dump_count--;
+
+		/* Exits if user requested a dump */
+		if (PTOP_ON_DUMP && !dump_count) {
+			print_all_suggestions();
+			exit(EXIT_SUCCESS);
+		}
+
+		/* No key pressed, will suggest something */
+		if (!key && !dump_count)
+			pick_suggestion();
+
+		/* Refresh display */
+		if (!PTOP_ON_DUMP) {
+			show_title_bar();
+			update_windows();
+		}
+
+		/*
+		 * Update the interval based on how long the CPU was in the
+		 * longest c-state during the last snapshot. If the user
+		 * specified an interval we skip this bit and keep it fixed.
+		 */
+		last_time = (((double)g_cstate_info[g_longest_cstate].total_time
+		    /g_ncpus)/g_cstate_info[g_longest_cstate].events);
+
+		if (!user_interval)
+			if (last_time < INTERVAL_DEFAULT ||
+			    (g_total_events/g_ticktime) < 1)
+				g_ticktime = INTERVAL_DEFAULT;
+			else
+				g_ticktime = INTERVAL_UPDATE(last_time);
+
+		/*
+		 * Restore user specified interval after a refresh
+		 */
+		if (keychar == 'R' && user_interval)
+			g_ticktime = g_ticktime_usr;
+	}
+	return (EXIT_SUCCESS);
+}
+
+void
+suggest_as_root(void)
+{
+	add_suggestion("Suggestion: run as root to get suggestions"
+	    " for reducing system power consumption",  40, NULL, NULL,
+	    NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/powertop.h	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#ifndef __INCLUDE_GUARD_POWERTOP_H_
+#define	__INCLUDE_GUARD_POWERTOP_H_
+
+#include <sys/types.h>
+#include <libintl.h>
+#include <sys/processor.h>
+
+#define	max(A, B)		(((A) < (B)) ? (B) : (A))
+
+#define	_(STRING)		gettext(STRING)
+
+#define	TITLE			"OpenSolaris PowerTOP version 1.1"
+#define	COPYRIGHT_INTEL		"(C) 2009 Intel Corporation"
+
+/*
+ * Exit values. stdlib.h defines EXIT_SUCCESS as 0 and
+ * EXIT_FAILURE as 1
+ */
+#define	EXIT_USAGE		2
+
+/*
+ * PowerTOP Features
+ * These may not be available everywhere
+ */
+#define	FEATURE_CSTATE		0x01
+#define	FEATURE_PSTATE		0x02
+#define	FEATURE_EVENTS		0x04
+#define	FEATURE_TURBO		0x08
+
+#define	BIT_DEPTH_BUF		10
+
+#define	INTERVAL_DEFAULT	5.0
+#define	INTERVAL_MAX		100.0
+#define	INTERVAL_UPDATE(l)						\
+	((l/INTERVAL_DEFAULT) * INTERVAL_DEFAULT + INTERVAL_DEFAULT)
+
+#define	STATE_NAME_MAX		16
+#define	EVENT_NAME_MAX 		64
+#define	EVENT_NUM_MAX 		100
+#define	NSTATES			32
+
+/*
+ * Display colors
+ */
+#define	PT_COLOR_DEFAULT	1
+#define	PT_COLOR_HEADER_BAR	2
+#define	PT_COLOR_ERROR		3
+#define	PT_COLOR_RED		4
+#define	PT_COLOR_YELLOW		5
+#define	PT_COLOR_GREEN		6
+#define	PT_COLOR_BRIGHT		7
+#define	PT_COLOR_BLUE		8
+
+/*
+ * Constants for setup_windows()
+ */
+#define	SINGLE_LINE_SW 		1
+#define	LENGTH_SUGG_SW		2
+#define	TITLE_LINE		1
+#define	BLANK_LINE		1
+#define	NEXT_LINE		1
+#define	PTOP_BAR_NSLOTS		10
+#define	PTOP_BAR_LENGTH		40
+
+/*
+ * Available op modes
+ */
+#define	PTOP_MODE_DEFAULT	0x01
+#define	PTOP_MODE_DUMP		0x02
+#define	PTOP_MODE_VERBOSE	0x04
+#define	PTOP_MODE_CPU		0x08
+
+#define	PTOP_ON_DEFAULT		(g_op_mode & PTOP_MODE_DEFAULT)
+#define	PTOP_ON_DUMP		(g_op_mode & PTOP_MODE_DUMP)
+#define	PTOP_ON_VERBOSE		(g_op_mode & PTOP_MODE_VERBOSE)
+#define	PTOP_ON_CPU		(g_op_mode & PTOP_MODE_CPU)
+
+/*
+ * Structures and typedefs
+ */
+struct line {
+	char		*string;
+	int		count;
+};
+
+typedef struct event_info {
+	char		offender_name[EVENT_NAME_MAX];
+	char		offense_name[EVENT_NAME_MAX];
+	uint64_t	total_count;
+} event_info_t;
+
+/*
+ * P/C state information
+ */
+typedef struct state_info {
+	char		name[STATE_NAME_MAX];
+	hrtime_t	total_time;
+	hrtime_t	last_time;
+	double		events;
+} state_info_t;
+
+typedef struct freq_state_info {
+	uint64_t	speed;
+	hrtime_t	total_time;
+} freq_state_info_t;
+
+typedef struct cpu_power_info {
+	uint64_t	current_pstate;
+	hrtime_t	time_accounted;
+	hrtime_t	dtrace_time;
+} cpu_power_info_t;
+
+/*
+ * Turbo mode information
+ */
+typedef struct turbo_info {
+	uint64_t	t_mcnt;
+	uint64_t	t_acnt;
+} turbo_info_t;
+
+typedef	void		(suggestion_func)(void);
+
+/*
+ * Global variables
+ */
+extern double			g_displaytime;
+
+extern int			g_bit_depth;
+
+/*
+ * Event accounting
+ */
+extern int 			g_total_events;
+extern int 			g_tog_p_events;
+
+/*
+ * Interval
+ */
+extern double 			g_ticktime, g_ticktime_usr;
+extern double 			g_interval;
+
+/*
+ * Command line arguments
+ */
+extern uchar_t			g_op_mode;
+extern uint_t			g_observed_cpu;
+extern boolean_t		g_gui;
+/*
+ * Event info array
+ */
+extern event_info_t    		g_event_info[EVENT_NUM_MAX];
+extern event_info_t		*g_p_event;
+
+/*
+ * Lookup table, sequential CPU id to Solaris CPU id
+ */
+extern processorid_t 		*g_cpu_table;
+
+/*
+ * Number of idle/frequency states
+ */
+extern int			g_npstates;
+extern int			g_max_cstate;
+extern int			g_longest_cstate;
+
+/*
+ * Total time, used to display different idle states
+ */
+extern hrtime_t			g_total_c_time;
+
+/*
+ * P/C state info arrays
+ */
+extern state_info_t		g_cstate_info[NSTATES];
+extern freq_state_info_t	g_pstate_info[NSTATES];
+
+extern uint_t			g_ncpus;
+extern uint_t			g_ncpus_observed;
+
+extern char 			g_status_bar_slots[PTOP_BAR_NSLOTS]
+	[PTOP_BAR_LENGTH];
+
+extern cpu_power_info_t		*g_cpu_power_states;
+
+/*
+ * Turbo mode related information
+ */
+extern boolean_t	g_turbo_supported;
+extern double		g_turbo_ratio;
+
+extern char 			g_suggestion_key;
+extern suggestion_func 		*g_suggestion_activate;
+
+/*
+ * DTrace scripts for the events report
+ */
+extern const char		*g_dtp_events;
+extern const char		*g_dtp_events_v;
+extern const char		*g_dtp_events_c;
+
+/*
+ * Arguments for dtrace_program_strcompile(). Contents vary according to
+ * the specified operation mode.
+ */
+extern uint_t			g_argc;
+extern char			**g_argv;
+
+/*
+ * Platform specific messages
+ */
+extern const char *g_msg_idle_state;
+extern const char *g_msg_freq_state;
+/*
+ * Suggestions related
+ */
+extern void 		suggest_p_state(void);
+extern void		suggest_as_root(void);
+
+/*
+ * See util.c
+ */
+extern void 		pt_error(char *, ...);
+extern void 		pt_set_progname(char *);
+extern uint_t		enumerate_cpus(void);
+extern void		usage(void);
+extern int		get_bit_depth(void);
+extern void		battery_mod_lookup(void);
+extern int		event_compare(const void *, const void *);
+
+/*
+ * Display/curses related
+ */
+extern void 		show_title_bar(void);
+extern void 		setup_windows(void);
+extern void 		initialize_curses(void);
+extern void		show_acpi_power_line(uint32_t flag, double rate,
+    double rem_cap, double cap, uint32_t state);
+extern void 		show_cstates();
+extern void 		show_wakeups(double interval);
+extern void 		show_eventstats(double interval);
+extern void 		show_suggestion(char *sug);
+extern void 		cleanup_curses(void);
+extern void		update_windows(void);
+
+/*
+ * Suggestions
+ */
+extern void 		pick_suggestion(void);
+extern void 		add_suggestion(char *text, int weight, char key,
+    char *keystring, suggestion_func *func);
+extern void 		reset_suggestions(void);
+extern void 		print_all_suggestions(void);
+extern void 		print_battery(void);
+
+/*
+ * DTrace stats
+ */
+extern int 		pt_cpufreq_stat_prepare(void);
+extern int 		pt_cpufreq_stat_collect(double interval);
+extern int 		pt_cpuidle_stat_prepare(void);
+extern int 		pt_cpuidle_stat_collect(double interval);
+extern int 		pt_events_stat_prepare(void);
+extern int 		pt_events_stat_collect(void);
+
+/*
+ * Turbo mode related routines
+ */
+extern int		pt_turbo_stat_prepare(void);
+extern int		pt_turbo_stat_collect(void);
+
+#endif /* __INCLUDE_GUARD_POWERTOP_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/suggestions.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *      Arjan van de Ven <[email protected]>
+ *      Eric C Saxe <[email protected]>
+ *      Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "powertop.h"
+
+struct suggestion;
+
+struct suggestion {
+	struct suggestion *next;
+
+	char 	*string;
+	int	weight;
+	char 	key;
+	char 	*keystring;
+
+	suggestion_func *func;
+};
+
+static struct suggestion 	*suggestions;
+static int 			total_weight;
+
+static char 	previous[1024];
+
+void
+reset_suggestions(void)
+{
+	struct suggestion *ptr;
+
+	ptr = suggestions;
+
+	while (ptr) {
+		struct suggestion *next;
+
+		next = ptr->next;
+		free(ptr->string);
+		free(ptr->keystring);
+		free(ptr);
+		ptr = next;
+	}
+
+	suggestions = NULL;
+	(void) strcpy(g_status_bar_slots[8], "");
+
+	g_suggestion_key 	= -1;
+	g_suggestion_activate 	= NULL;
+	total_weight 		= 0;
+}
+
+void
+add_suggestion(char *text, int weight, char key, char *keystring,
+    suggestion_func *func)
+{
+	struct suggestion *new;
+
+	if (!text)
+		return;
+
+	new = malloc(sizeof (struct suggestion));
+
+	if (!new)
+		return;
+
+	(void) memset(new, 0, sizeof (struct suggestion));
+
+	new->string = strdup(text);
+	new->weight = weight;
+	new->key = key;
+
+	if (keystring)
+		new->keystring = strdup(keystring);
+
+	new->next 	= suggestions;
+	new->func 	= func;
+	suggestions 	= new;
+	total_weight 	+= weight;
+}
+
+void
+pick_suggestion(void)
+{
+	int			weight, value, running = 0;
+	struct suggestion 	*ptr;
+
+	(void) strcpy(g_status_bar_slots[8], "");
+	g_suggestion_key 	= -1;
+	g_suggestion_activate 	= NULL;
+
+	if (total_weight == 0 || suggestions == NULL) {
+		show_suggestion("");
+		return;
+	}
+
+	weight = total_weight;
+
+	if (strlen(previous) && g_displaytime > 0.0)
+		weight += 50;
+
+	value 	= rand() % weight;
+	ptr 	= suggestions;
+
+	while (ptr) {
+		running += ptr->weight;
+
+		if (strcmp(ptr->string, previous) == 0 && g_displaytime > 0.0)
+			running += 50;
+
+		if (running > value) {
+			if (ptr->keystring)
+				(void) strncpy(g_status_bar_slots[8],
+				    ptr->keystring, PTOP_BAR_LENGTH);
+
+			g_suggestion_key 	= ptr->key;
+			g_suggestion_activate 	= ptr->func;
+
+			show_suggestion(ptr->string);
+
+			if (strcmp(ptr->string, previous)) {
+				g_displaytime = 30.0;
+				(void) strcpy(previous, ptr->string);
+			}
+			return;
+		}
+		ptr = ptr->next;
+	}
+
+	show_suggestion("");
+	(void) memset(previous, 0, sizeof (previous));
+	g_displaytime = -1.0;
+}
+
+void
+print_all_suggestions(void)
+{
+	struct suggestion *ptr;
+
+	for (ptr = suggestions; ptr; ptr = ptr->next)
+		(void) printf("\n%s\n", ptr->string);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/turbo.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <dtrace.h>
+#include <kstat.h>
+#include <errno.h>
+#include "powertop.h"
+
+/*
+ * Global turbo related variables definitions
+ */
+boolean_t		g_turbo_supported;
+double			g_turbo_ratio;
+
+/*
+ * The variables to store kstat snapshot
+ */
+static turbo_info_t	*cpu_turbo_info = NULL;
+static turbo_info_t	*t_new = NULL;
+
+/*
+ * Perform setup necessary to enumerate and track CPU turbo information
+ */
+static int
+pt_turbo_init(void)
+{
+	kstat_ctl_t 		*kc;
+	kstat_t 		*ksp;
+	kstat_named_t 		*knp;
+
+	/*
+	 * check if the CPU turbo is supported
+	 */
+	if ((kc = kstat_open()) == NULL) {
+		g_turbo_supported = B_FALSE;
+		return (errno);
+	}
+
+	ksp = kstat_lookup(kc, "turbo", 0, NULL);
+	if (ksp == NULL) {
+		g_turbo_supported = B_FALSE;
+		(void) kstat_close(kc);
+		return (-1);
+	}
+
+	(void) kstat_read(kc, ksp, NULL);
+
+	knp = kstat_data_lookup(ksp, "turbo_supported");
+	if (knp == NULL) {
+		pt_error("%s : couldn't find item turbo_supported\n", __FILE__);
+		g_turbo_supported = B_FALSE;
+		(void) kstat_close(kc);
+		return (-2);
+	}
+
+	/*
+	 * Initialize turbo information structure if turbo mode is supported
+	 */
+	if (knp->value.ui32) {
+		g_turbo_supported = B_TRUE;
+		cpu_turbo_info = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
+		t_new = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
+	}
+
+	(void) kstat_close(kc);
+	return (0);
+}
+
+/*
+ * Take a snapshot of each CPU's turbo information
+ * by looking through the turbo kstats.
+ */
+static int
+pt_turbo_snapshot(turbo_info_t *turbo_snapshot)
+{
+	kstat_ctl_t 		*kc;
+	kstat_t 		*ksp;
+	kstat_named_t 		*knp;
+	int 			cpu;
+	turbo_info_t		*turbo_info;
+
+	if ((kc = kstat_open()) == NULL)
+		return (errno);
+
+	for (cpu = 0; cpu < g_ncpus; cpu++) {
+		turbo_info = &turbo_snapshot[cpu];
+		ksp = kstat_lookup(kc, "turbo", g_cpu_table[cpu], NULL);
+		if (ksp == NULL) {
+			pt_error("%s : couldn't find turbo kstat for CPU "
+			"%d\n", __FILE__, cpu);
+			(void) kstat_close(kc);
+			return (-1);
+		}
+
+		if (kstat_read(kc, ksp, NULL) == -1) {
+			pt_error("%s : couldn't read turbo kstat for "
+			    "CPU %d\n", __FILE__, cpu);
+			(void) kstat_close(kc);
+			return (-2);
+		}
+
+		knp = kstat_data_lookup(ksp, "turbo_mcnt");
+		if (knp == NULL) {
+			pt_error("%s : couldn't find turbo mcnt "
+			    "kstat for CPU %d\n", __FILE__, cpu);
+			(void) kstat_close(kc);
+			return (-3);
+		}
+
+		/*
+		 * snapshot IA32_MPERF_MSR
+		 */
+		turbo_info->t_mcnt = knp->value.ui64;
+
+		knp = kstat_data_lookup(ksp, "turbo_acnt");
+		if (knp == NULL) {
+			pt_error("%s : couldn't find turbo acnt "
+			    "kstat for CPU %d\n", __FILE__, cpu);
+			(void) kstat_close(kc);
+			return (-4);
+		}
+
+		/*
+		 * snapshot IA32_APERF_MSR
+		 */
+		turbo_info->t_acnt = knp->value.ui64;
+	}
+
+	if (kstat_close(kc) != 0)
+		pt_error("%s : couldn't close kstat\n", __FILE__);
+
+	return (0);
+}
+
+/*
+ * Turbo support checking and information initialization
+ */
+int
+pt_turbo_stat_prepare(void)
+{
+	int	ret;
+
+	ret = pt_turbo_init();
+
+	if (ret != 0) {
+		return (ret);
+	}
+
+	ret = pt_turbo_snapshot(cpu_turbo_info);
+
+	if (ret != 0) {
+		pt_error("%s : turbo snapshot failed\n", __FILE__);
+	}
+
+	return (ret);
+}
+
+/*
+ * When doing the statistics collection, we compare two kstat snapshot
+ * and get a delta. the final ratio of performance boost will be worked
+ * out according to the kstat delta
+ */
+int
+pt_turbo_stat_collect(void)
+{
+	int		cpu;
+	uint64_t	delta_mcnt, delta_acnt;
+	double		ratio;
+	int		ret;
+
+	/*
+	 * Take a snapshot of turbo information to setup turbo_info_t
+	 * structure
+	 */
+	ret = pt_turbo_snapshot(t_new);
+	if (ret != 0) {
+		pt_error("%s : turbo stat collection failed\n", __FILE__);
+		return (ret);
+	}
+
+	/*
+	 * Calculate the kstat delta and work out the performance boost ratio
+	 */
+	for (cpu = 0; cpu < g_ncpus; cpu++) {
+		delta_mcnt = t_new[cpu].t_mcnt - cpu_turbo_info[cpu].t_mcnt;
+		delta_acnt = t_new[cpu].t_acnt - cpu_turbo_info[cpu].t_acnt;
+
+		if ((delta_mcnt > delta_acnt) || (delta_mcnt == 0))
+			ratio = 1.0;
+		else
+			ratio = (double)delta_acnt / (double)delta_mcnt;
+		g_turbo_ratio += ratio;
+	}
+
+	g_turbo_ratio = g_turbo_ratio / (double)g_ncpus;
+
+	/*
+	 * Update the structure of the kstat for the next time calculation
+	 */
+	(void) memcpy(cpu_turbo_info, t_new, g_ncpus * (sizeof (turbo_info_t)));
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/util.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <strings.h>
+#include <sys/systeminfo.h>
+#include <kstat.h>
+#include <errno.h>
+#include "powertop.h"
+
+static char 	PROG_FMT[] = "%s: ";
+static char 	ERR_FMT[] = ": %s";
+static char 	*progname;
+
+void
+pt_set_progname(char *name)
+{
+	progname = basename(name);
+}
+
+/*PRINTFLIKE1*/
+void
+pt_error(char *format, ...)
+{
+	int 	err = errno;
+	va_list alist;
+
+	if (g_gui)
+		return;
+
+	if (progname != NULL)
+		(void) fprintf(stderr, PROG_FMT, progname);
+
+	va_start(alist, format);
+	(void) vfprintf(stderr, format, alist);
+	va_end(alist);
+
+	if (strchr(format, '\n') == NULL)
+		(void) fprintf(stderr, gettext(ERR_FMT), strerror(err));
+}
+
+/*
+ * Returns the number of online CPUs.
+ */
+uint_t
+enumerate_cpus(void)
+{
+	int	cpuid;
+	int	max, cpus_conf;
+	uint_t	ncpus = 0;
+
+	max 		= sysconf(_SC_CPUID_MAX);
+	cpus_conf	= sysconf(_SC_NPROCESSORS_CONF);
+
+	/* Fall back to one CPU if any of the sysconf calls above failed */
+	if (max == -1 || cpus_conf == -1) {
+		max = cpus_conf = 1;
+	}
+
+	if ((g_cpu_table = malloc(cpus_conf * sizeof (processorid_t))) == NULL)
+		return (0);
+
+	for (cpuid = 0; cpuid < max; cpuid++) {
+		if (p_online(cpuid, P_STATUS) != -1) {
+			g_cpu_table[ncpus] = cpuid;
+			ncpus++;
+		}
+	}
+	return (ncpus);
+}
+
+void
+usage(void)
+{
+	(void) fprintf(stderr, "%s   %s\n\n", TITLE, COPYRIGHT_INTEL);
+	(void) fprintf(stderr, "Usage: powertop [option]\n");
+	(void) fprintf(stderr, "  -d, --dump [count]	Read wakeups count "
+	    "times and print list of top offenders\n");
+	(void) fprintf(stderr, "  -t, --time [interval]	Default time to gather "
+	    "data in seconds [1-100s]\n");
+	(void) fprintf(stderr, "  -v, --verbose		Verbose mode, reports "
+	    "kernel cyclic activity\n");
+	(void) fprintf(stderr, "  -c, --cpu [CPU]	Only observe a specific"
+	    " CPU\n");
+	(void) fprintf(stderr, "  -h, --help		Show this help "
+	    "message\n");
+
+	exit(EXIT_USAGE);
+}
+
+int
+get_bit_depth(void)
+{
+	/*
+	 * This little routine was derived from isainfo.c to look up
+	 * the system's bit depth. It feeds a 10 byte long buffer to
+	 * sysinfo (we only need the first word, sysinfo truncates and
+	 * \0 terminates the rest) from which we figure out which isa
+	 * we're running on.
+	 */
+	char	buf[BIT_DEPTH_BUF];
+
+	if (sysinfo(SI_ARCHITECTURE_64, buf, BIT_DEPTH_BUF) == -1)
+		if (sysinfo(SI_ARCHITECTURE_32, buf, BIT_DEPTH_BUF) == -1)
+			return (-2);
+
+	if (strcmp(buf, "sparc") == 0 || strcmp(buf, "i386") == 0)
+		return (32);
+
+	if (strcmp(buf, "sparcv9") == 0 || strcmp(buf, "amd64") == 0)
+		return (64);
+
+	return (-3);
+}
+
+/*
+ * Simple integer comparison routine for the event report qsort(3C).
+ */
+int
+event_compare(const void *p1, const void *p2)
+{
+	event_info_t i = *((event_info_t *)p1);
+	event_info_t j = *((event_info_t *)p2);
+
+	if (i.total_count > j.total_count)
+		return (-1);
+
+	if (i.total_count < j.total_count)
+		return (1);
+
+	return (0);
+}
--- a/usr/src/cmd/powertop/cpufreq.c	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,425 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *	Arjan van de Ven <[email protected]>
- *	Eric C Saxe <[email protected]>
- *	Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <dtrace.h>
-#include <kstat.h>
-#include <errno.h>
-#include "powertop.h"
-
-#define	HZ2MHZ(speed)	((speed) / 1000000)
-
-static uint64_t		max_cpufreq = 0;
-static dtrace_hdl_t	*g_dtp;
-
-/*
- * Enabling PM through /etc/power.conf
- * See suggest_p_state()
- */
-static char default_conf[]	= "/etc/power.conf";
-static char default_pmconf[]	= "/usr/sbin/pmconfig";
-static char cpupm_enable[]	= " echo cpupm enable >> /etc/power.conf";
-static char cpupm_treshold[]	= " echo cpu-threshold 1s >> /etc/power.conf";
-
-/*
- * Buffer containing DTrace program to track CPU frequency transitions
- */
-static const char 	*pt_cpufreq_dtrace_prog =
-""
-"hrtime_t last[int];"
-""
-"BEGIN"
-"{"
-"	begin = timestamp;"
-"}"
-""
-":::cpu-change-speed"
-"/last[(processorid_t)arg0] != 0/"
-"{"
-"	this->cpu = (processorid_t)arg0;"
-"	this->oldspeed = (uint32_t)(arg1/1000000);"
-"	@times[this->cpu, this->oldspeed] = sum(timestamp - last[this->cpu]);"
-"	last[this->cpu] = timestamp;"
-"}"
-":::cpu-change-speed"
-"/last[(processorid_t)arg0] == 0/"
-"{"
-"	this->cpu = (processorid_t)arg0;"
-"	this->oldspeed = (uint32_t)(arg1/1000000);"
-"	@times[this->cpu, this->oldspeed] = sum(timestamp - begin);"
-"	last[this->cpu] = timestamp;"
-"}";
-
-static int	pt_cpufreq_snapshot(void);
-static int	pt_cpufreq_dtrace_walk(const dtrace_aggdata_t *, void *);
-
-/*
- * Perform setup necessary to enumerate and track CPU speed changes
- */
-int
-pt_cpufreq_stat_prepare(void)
-{
-	dtrace_prog_t 		*prog;
-	dtrace_proginfo_t 	info;
-	dtrace_optval_t 	statustime;
-
-	kstat_ctl_t 		*kc;
-	kstat_t 		*ksp;
-	kstat_named_t 		*knp;
-
-	pstate_info_t 		*state;
-	char 			*s, *token;
-	int 			err;
-
-	state = pstate_info;
-	cpu_power_states = calloc((size_t)g_ncpus, sizeof (cpu_power_info_t));
-
-	/*
-	 * Enumerate the CPU frequencies
-	 */
-	if ((kc = kstat_open()) == NULL)
-		return (errno);
-
-	ksp = kstat_lookup(kc, "cpu_info", cpu_table[0], NULL);
-
-	if (ksp == NULL)
-		return (errno);
-
-	(void) kstat_read(kc, ksp, NULL);
-
-	knp = kstat_data_lookup(ksp, "supported_frequencies_Hz");
-	s = knp->value.str.addr.ptr;
-
-	npstates = 0;
-
-	for (token = strtok(s, ":"), s = NULL;
-	    NULL != token && npstates < NSTATES;
-	    token = strtok(NULL, ":")) {
-
-		state->speed = HZ2MHZ(atoll(token));
-
-		if (state->speed > max_cpufreq)
-			max_cpufreq = state->speed;
-
-		state->total_time = (uint64_t)0;
-
-		npstates++;
-		state++;
-	}
-
-	if (token != NULL)
-		pt_error("%s : exceeded NSTATES\n", __FILE__);
-
-	(void) kstat_close(kc);
-
-	/*
-	 * Return if speed transition is not supported
-	 */
-	if (npstates < 2)
-		return (-1);
-
-	/*
-	 * Setup DTrace to look for CPU frequency changes
-	 */
-	if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
-		pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
-		    dtrace_errmsg(NULL, err));
-		return (-2);
-	}
-	if ((prog = dtrace_program_strcompile(g_dtp, pt_cpufreq_dtrace_prog,
-	    DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) {
-		pt_error("%s : cpu-change-speed probe unavailable\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
-		pt_error("%s : failed to enable speed probe\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_setopt(g_dtp, "aggsize", "128k") == -1) {
-		pt_error("%s : failed to set speed 'aggsize'\n", __FILE__);
-	}
-	if (dtrace_setopt(g_dtp, "aggrate", "0") == -1) {
-		pt_error("%s : failed to set speed 'aggrate'\n", __FILE__);
-	}
-	if (dtrace_setopt(g_dtp, "aggpercpu", 0) == -1) {
-		pt_error("%s : failed to set speed 'aggpercpu'\n", __FILE__);
-	}
-	if (dtrace_go(g_dtp) != 0) {
-		pt_error("%s : failed to start speed observation", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_getopt(g_dtp, "statusrate", &statustime) == -1) {
-		pt_error("%s : failed to get speed 'statusrate'\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-
-	return (0);
-}
-
-/*
- * The DTrace probes have already been enabled, and are tracking
- * CPU speed transitions. Take a snapshot of the aggregations, and
- * look for any CPUs that have made a speed transition over the last
- * sampling interval. Note that the aggregations may be empty if no
- * speed transitions took place over the last interval. In that case,
- * notate that we have already accounted for the time, so that when
- * we do encounter a speed transition in a future sampling interval
- * we can subtract that time back out.
- */
-int
-pt_cpufreq_stat_collect(double interval)
-{
-	int 			cpu, i, ret;
-	uint64_t 		speed;
-	hrtime_t 		duration;
-	cpu_power_info_t 	*cpu_pow;
-
-	/*
-	 * Zero out the interval time reported by DTrace for
-	 * this interval
-	 */
-	for (i = 0; i < npstates; i++)
-		pstate_info[i].total_time = 0;
-
-	for (i = 0; i < g_ncpus; i++)
-		cpu_power_states[i].dtrace_time = 0;
-
-	if (dtrace_status(g_dtp) == -1)
-		return (-1);
-
-	if (dtrace_aggregate_snap(g_dtp) != 0)
-		pt_error("%s : failed to add to stats aggregation", __FILE__);
-
-	if (dtrace_aggregate_walk_keyvarsorted(g_dtp, pt_cpufreq_dtrace_walk,
-	    NULL) != 0)
-		pt_error("%s : failed to sort stats aggregation", __FILE__);
-
-	dtrace_aggregate_clear(g_dtp);
-
-	if ((ret = pt_cpufreq_snapshot()) != 0) {
-		pt_error("%s : failed to add to stats aggregation", __FILE__);
-		return (ret);
-	}
-
-	for (cpu = 0; cpu < g_ncpus; cpu++) {
-		cpu_pow = &cpu_power_states[cpu];
-
-		speed = cpu_pow->current_pstate;
-
-		duration = (hrtime_t)((interval * NANOSEC)) -
-		    cpu_pow->dtrace_time;
-
-		for (i = 0; i < npstates; i++) {
-			if (pstate_info[i].speed == speed) {
-				pstate_info[i].total_time += duration;
-				cpu_pow->time_accounted += duration;
-			}
-		}
-	}
-
-	return (0);
-}
-
-/*
- * Take a snapshot of each CPU's speed by looking through the cpu_info kstats.
- */
-static int
-pt_cpufreq_snapshot(void)
-{
-	kstat_ctl_t 		*kc;
-	kstat_t 		*ksp;
-	kstat_named_t 		*knp;
-	int 			cpu;
-	cpu_power_info_t 	*state;
-
-	if ((kc = kstat_open()) == NULL)
-		return (errno);
-
-	for (cpu = 0; cpu < g_ncpus; cpu++) {
-		ksp = kstat_lookup(kc, "cpu_info", cpu_table[cpu], NULL);
-		if (ksp == NULL) {
-			pt_error("%s : couldn't find cpu_info kstat for CPU "
-			"%d\n", __FILE__, cpu);
-			(void) kstat_close(kc);
-			return (1);
-		}
-
-		if (kstat_read(kc, ksp, NULL) == -1) {
-			pt_error("%s : couldn't read cpu_info kstat for "
-			    "CPU %d\n", __FILE__, cpu);
-			(void) kstat_close(kc);
-			return (2);
-		}
-
-		knp = kstat_data_lookup(ksp, "current_clock_Hz");
-		if (knp == NULL) {
-			pt_error("%s : couldn't find current_clock_Hz "
-			    "kstat for CPU %d\n", __FILE__, cpu);
-			(void) kstat_close(kc);
-			return (3);
-		}
-
-		state = &cpu_power_states[cpu];
-		state->current_pstate = HZ2MHZ(knp->value.ui64);
-	}
-
-	if (kstat_close(kc) != 0)
-		pt_error("%s : couldn't close kstat\n", __FILE__);
-
-	return (0);
-}
-
-/*
- * DTrace aggregation walker that sorts through a snapshot of the
- * aggregation data collected during firings of the cpu-change-speed
- * probe.
- */
-/*ARGSUSED*/
-static int
-pt_cpufreq_dtrace_walk(const dtrace_aggdata_t *data, void *arg)
-{
-	dtrace_aggdesc_t 	*aggdesc = data->dtada_desc;
-	dtrace_recdesc_t 	*cpu_rec, *speed_rec;
-	cpu_power_info_t 	*cpu_pow;
-	int32_t 		cpu;
-	uint64_t 		speed;
-	hrtime_t 		dt_state_time = 0;
-	int 			i;
-
-	if (strcmp(aggdesc->dtagd_name, "times") == 0) {
-		cpu_rec = &aggdesc->dtagd_rec[1];
-		speed_rec = &aggdesc->dtagd_rec[2];
-
-		for (i = 0; i < g_ncpus; i++) {
-			/* LINTED - alignment */
-			dt_state_time += *((hrtime_t *)(data->dtada_percpu[i]));
-		}
-
-		/* LINTED - alignment */
-		cpu = *(int32_t *)(data->dtada_data + cpu_rec->dtrd_offset);
-		/* LINTED - alignment */
-		speed = *(uint64_t *)(data->dtada_data +
-		    speed_rec->dtrd_offset);
-
-		if (speed == 0) {
-			speed = max_cpufreq;
-		}
-
-		/*
-		 * We have an aggregation record for "cpu" being at "speed"
-		 * for an interval of "n" nanoseconds. The reported interval
-		 * may exceed the powertop sampling interval, since we only
-		 * notice during potentially infrequent firings of the
-		 * "speed change" DTrace probe. In this case powertop would
-		 * have already accounted for the portions of the interval
-		 * that happened during prior powertop sampings, so subtract
-		 * out time already accounted.
-		 */
-		cpu_pow = &cpu_power_states[cpu];
-
-		for (i = 0; i < npstates; i++) {
-			if (pstate_info[i].speed == speed) {
-				if (cpu_pow->time_accounted > 0) {
-					if (dt_state_time == 0)
-						continue;
-					if (dt_state_time >
-					    cpu_pow->time_accounted) {
-						dt_state_time -=
-						    cpu_pow->time_accounted;
-						cpu_pow->time_accounted = 0;
-					}
-				}
-				pstate_info[i].total_time += dt_state_time;
-				cpu_pow->dtrace_time += dt_state_time;
-			}
-		}
-	}
-	return (DTRACE_AGGWALK_NEXT);
-}
-
-/*
- * Used as a suggestion, sets PM in /etc/power.conf and
- * a 1sec threshold, then calls /usr/sbin/pmconfig
- */
-void
-enable_p_state(void)
-{
-	(void) system(cpupm_enable);
-	(void) system(cpupm_treshold);
-	(void) system(default_pmconf);
-}
-
-/*
- * Checks if PM is enabled in /etc/power.conf, enabling if not
- */
-void
-suggest_p_state(void)
-{
-	char 	line[1024];
-	FILE 	*file;
-
-	/*
-	 * Return if speed transition is not supported
-	 */
-	if (npstates < 2)
-		return;
-
-	file = fopen(default_conf, "r");
-
-	if (!file)
-		return;
-
-	(void) memset(line, 0, 1024);
-
-	while (fgets(line, 1023, file)) {
-		if (strstr(line, "cpupm")) {
-			if (strstr(line, "enable")) {
-				(void) fclose(file);
-				return;
-			}
-		}
-	}
-
-	add_suggestion("Suggestion: enable CPU power management by "
-	    "pressing the P key",  40, 'P', "P - Enable p-state",
-	    enable_p_state);
-
-	(void) fclose(file);
-}
--- a/usr/src/cmd/powertop/cpuidle.c	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *	Arjan van de Ven <[email protected]>
- *	Eric C Saxe <[email protected]>
- *	Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <string.h>
-#include <dtrace.h>
-#include "powertop.h"
-
-static dtrace_hdl_t 	*g_dtp;
-
-/*
- * Buffer containing DTrace program to track CPU idle state transitions
- */
-static const char *pt_cpuidle_dtrace_prog =
-":::idle-state-transition"
-"/arg0 != 0/"
-"{"
-"	self->start = timestamp;"
-"	self->state = arg0;"
-"}"
-""
-":::idle-state-transition"
-"/arg0 == 0 && self->start/"
-"{"
-"	@number[self->state] = count();"
-"	@times[self->state] = sum((timestamp - self->start)/1000000);"
-"	self->start = 0;"
-"	self->state = 0;"
-"}";
-
-static int 	pt_cpuidle_dtrace_walk(const dtrace_aggdata_t *, void *);
-
-/*
- * Perform setup necessary to track CPU idle state transitions
- */
-int
-pt_cpuidle_stat_prepare(void)
-{
-	dtrace_prog_t 		*prog;
-	dtrace_proginfo_t 	info;
-	dtrace_optval_t 	statustime;
-	int 			err;
-
-	if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
-		pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
-		    dtrace_errmsg(NULL, err));
-		return (-1);
-	}
-	if ((prog = dtrace_program_strcompile(g_dtp, pt_cpuidle_dtrace_prog,
-	    DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) {
-		pt_error("%s : C-State DTrace probes unavailable\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
-		pt_error("%s : failed to enable C State probes\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_setopt(g_dtp, "aggsize", "128k") == -1) {
-		pt_error("%s : failed to set C-state 'aggsize'\n", __FILE__);
-	}
-	if (dtrace_setopt(g_dtp, "aggrate", "0") == -1) {
-		pt_error("%s : failed to set C-state'aggrate'\n", __FILE__);
-	}
-	if (dtrace_setopt(g_dtp, "aggpercpu", 0) == -1) {
-		pt_error("%s : failed to set C-state 'aggpercpu'\n", __FILE__);
-	}
-	if (dtrace_go(g_dtp) != 0) {
-		pt_error("%s : failed to start C-state observation", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_getopt(g_dtp, "statusrate", &statustime) == -1) {
-		pt_error("%s : failed to get C-state 'statusrate'\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	return (0);
-}
-
-/*
- * The DTrace probes have been enabled, and are tracking CPU idle state
- * transitions. Take a snapshot of the aggregations, and invoke the aggregation
- * walker to process any records. The walker does most of the accounting work
- * chalking up time spent into the cstate_info structure.
- */
-int
-pt_cpuidle_stat_collect(double interval)
-{
-	int 		i;
-	hrtime_t	t = 0;
-
-	/*
-	 * Zero out the interval time reported by DTrace for
-	 * this interval
-	 */
-	for (i = 0; i < NSTATES; i++) {
-		cstate_info[i].total_time = 0;
-		cstate_info[i].events = 0;
-	}
-
-	/*
-	 * Assume that all the time spent in this interval will
-	 * be the default "0" state. The DTrace walker will reallocate
-	 * time out of the default bucket as it processes aggregation
-	 * records for time spent in other states.
-	 */
-	cstate_info[0].total_time = (long)(interval * g_ncpus * 1000);
-
-	if (dtrace_status(g_dtp) == -1)
-		return (-1);
-
-	if (dtrace_aggregate_snap(g_dtp) != 0)
-		pt_error("%s : failed to add to aggregation", __FILE__);
-
-	if (dtrace_aggregate_walk_keyvarsorted(g_dtp, pt_cpuidle_dtrace_walk,
-	    NULL) != 0)
-		pt_error("%s : failed to sort aggregation", __FILE__);
-
-	dtrace_aggregate_clear(g_dtp);
-
-	/*
-	 * Populate cstate_info with the correct amount of time spent
-	 * in each C state and update the number of C states in max_cstate
-	 */
-	total_c_time = 0;
-	for (i = 0; i < NSTATES; i++) {
-		if (cstate_info[i].total_time > 0) {
-			total_c_time += cstate_info[i].total_time;
-			if (i > max_cstate)
-				max_cstate = i;
-			if (cstate_info[i].last_time > t) {
-				t = cstate_info[i].last_time;
-				longest_cstate = i;
-			}
-		}
-	}
-
-	return (0);
-}
-
-/*
- * DTrace aggregation walker that sorts through a snapshot of data records
- * collected during firings of the idle-state-transition probe.
- *
- * XXX A way of querying the current idle state for a CPU is needed in addition
- *     to logic similar to that in cpufreq.c
- */
-/*ARGSUSED*/
-static int
-pt_cpuidle_dtrace_walk(const dtrace_aggdata_t *data, void *arg)
-{
-	dtrace_aggdesc_t 	*aggdesc = data->dtada_desc;
-	dtrace_recdesc_t 	*rec;
-	uint64_t 		n = 0;
-	int32_t 		state;
-	int 			i;
-
-	rec = &aggdesc->dtagd_rec[1];
-	/* LINTED - alignment */
-	state = *(int32_t *)(data->dtada_data + rec->dtrd_offset);
-
-	if (strcmp(aggdesc->dtagd_name, "number") == 0) {
-		for (i = 0; i < g_ncpus; i++) {
-			/* LINTED - alignment */
-			n += *((uint64_t *)(data->dtada_percpu[i]));
-		}
-		total_events += n;
-		cstate_info[state].events += n;
-	}
-	else
-		if (strcmp(aggdesc->dtagd_name, "times") == 0) {
-			for (i = 0; i < g_ncpus; i++) {
-				/* LINTED - alignment */
-				n += *((uint64_t *)(data->dtada_percpu[i]));
-			}
-			cstate_info[state].last_time = n;
-			cstate_info[state].total_time += n;
-			if (cstate_info[0].total_time >= n)
-				cstate_info[0].total_time -= n;
-		}
-
-	return (DTRACE_AGGWALK_NEXT);
-}
--- a/usr/src/cmd/powertop/display.c	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,448 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *	Arjan van de Ven <[email protected]>
- *	Eric C Saxe <[email protected]>
- *	Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <curses.h>
-#include "powertop.h"
-
-static WINDOW 	*title_bar_window;
-static WINDOW 	*cstate_window;
-static WINDOW 	*wakeup_window;
-static WINDOW 	*acpi_power_window;
-static WINDOW 	*eventstat_window;
-static WINDOW 	*suggestion_window;
-static WINDOW 	*status_bar_window;
-
-#define	print(win, y, x, fmt, args...)				\
-	if (dump)						\
-		(void) printf(fmt, ## args);			\
-	else							\
-		(void) mvwprintw(win, y, x, fmt, ## args);
-
-char	status_bar_slots[10][40];
-int	maxx, maxy;
-
-static void
-zap_windows(void)
-{
-	if (title_bar_window) {
-		(void) delwin(title_bar_window);
-		title_bar_window = NULL;
-	}
-	if (cstate_window) {
-		(void) delwin(cstate_window);
-		cstate_window = NULL;
-	}
-	if (wakeup_window) {
-		(void) delwin(wakeup_window);
-		wakeup_window = NULL;
-	}
-	if (acpi_power_window) {
-		(void) delwin(acpi_power_window);
-		acpi_power_window = NULL;
-	}
-	if (eventstat_window) {
-		(void) delwin(eventstat_window);
-		eventstat_window = NULL;
-	}
-	if (suggestion_window) {
-		(void) delwin(suggestion_window);
-		suggestion_window = NULL;
-	}
-	if (status_bar_window) {
-		(void) delwin(status_bar_window);
-		status_bar_window = NULL;
-	}
-}
-
-void
-cleanup_curses(void)
-{
-	(void) endwin();
-}
-
-/*
- * This part was re-written to be human readable and easy to modify. Please
- * try to keep it that way and help us save some time.
- *
- * Friendly reminder:
- * 	subwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x)
- */
-void
-setup_windows(void)
-{
-	/*
-	 * These variables are used to properly set the initial y position and
-	 * number of lines in each subwindow, as the number of supported CPU
-	 * states affects their placement.
-	 */
-	int cstate_lines, event_lines, pos_y;
-
-	getmaxyx(stdscr, maxy, maxx);
-
-	zap_windows();
-
-	cstate_lines 	= TITLE_LINE + max((max_cstate+1), npstates);
-
-	pos_y = 0;
-	title_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
-	pos_y += NEXT_LINE + BLANK_LINE;
-	cstate_window = subwin(stdscr, cstate_lines, maxx, pos_y, 0);
-
-	pos_y += cstate_lines + BLANK_LINE;
-	wakeup_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
-	pos_y += NEXT_LINE;
-	acpi_power_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
-	pos_y += NEXT_LINE + BLANK_LINE;
-	event_lines = maxy - SINGLE_LINE_SW - NEXT_LINE - LENGTH_SUGG_SW -
-	    pos_y;
-	eventstat_window = subwin(stdscr, event_lines, maxx, pos_y, 0);
-
-	pos_y += event_lines + NEXT_LINE;
-	suggestion_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
-	pos_y += BLANK_LINE + NEXT_LINE;
-	status_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
-	(void) strcpy(status_bar_slots[0], _(" Q - Quit "));
-	(void) strcpy(status_bar_slots[1], _(" R - Refresh "));
-
-	(void) werase(stdscr);
-	(void) wrefresh(status_bar_window);
-}
-
-void
-initialize_curses(void)
-{
-	(void) initscr();
-	(void) start_color();
-
-	/*
-	 * Enable keyboard mapping
-	 */
-	(void) keypad(stdscr, TRUE);
-
-	/*
-	 * Tell curses not to do NL->CR/NL on output
-	 */
-	(void) nonl();
-
-	/*
-	 * Take input chars one at a time, no wait for \n
-	 */
-	(void) cbreak();
-
-	/*
-	 * Dont echo input
-	 */
-	(void) noecho();
-
-	/*
-	 * Turn off cursor
-	 */
-	(void) curs_set(0);
-
-	(void) init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK);
-	(void) init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE);
-	(void) init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED);
-	(void) init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED);
-	(void) init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW);
-	(void) init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN);
-	(void) init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE);
-	(void) init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK);
-
-	(void) atexit(cleanup_curses);
-}
-
-void
-show_title_bar(void)
-{
-	int 	i, x = 0, y = 0;
-	char	title_pad[10];
-
-	(void) wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
-	(void) wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
-	(void) werase(title_bar_window);
-
-	(void) snprintf(title_pad, 10, "%%%ds",
-	    (maxx - strlen(TITLE))/2 + strlen(TITLE));
-	/* LINTED: E_SEC_PRINTF_VAR_FMT */
-	print(title_bar_window, y, x, title_pad, TITLE);
-
-	(void) wrefresh(title_bar_window);
-	(void) werase(status_bar_window);
-
-	for (i = 0; i < 10; i++) {
-		if (strlen(status_bar_slots[i]) == 0)
-			continue;
-		(void) wattron(status_bar_window, A_REVERSE);
-		print(status_bar_window, y, x, "%s", status_bar_slots[i]);
-		(void) wattroff(status_bar_window, A_REVERSE);
-		x += strlen(status_bar_slots[i]) + 1;
-	}
-	(void) wnoutrefresh(status_bar_window);
-}
-
-void
-show_cstates(void)
-{
-	char		c[100];
-	int		i;
-	double		total_pstates = 0.0, avg, res;
-	uint64_t	p0_speed, p1_speed;
-
-	if (!dump) {
-		(void) werase(cstate_window);
-		(void) wattrset(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT));
-		(void) wbkgd(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT));
-	}
-
-	print(cstate_window, 0, 0, "%s", "Cn\t\t\tAvg	residency\n");
-
-	res =  (((double)cstate_info[0].total_time / total_c_time)) * 100;
-	(void) sprintf(c, "C0 (cpu running)\t\t(%.1f%%)\n", (float)res);
-	print(cstate_window, 1, 0, "%s", c);
-
-	for (i = 1; i <= max_cstate; i++) {
-		/*
-		 * In situations where the load is too intensive, the system
-		 * might not transition at all.
-		 */
-		if (cstate_info[i].events > 0)
-			avg = (((double)cstate_info[i].total_time/g_ncpus)/
-			    cstate_info[i].events);
-		else
-			avg = 0;
-
-		res = ((double)cstate_info[i].total_time/total_c_time) * 100;
-
-		(void) sprintf(c, "C%d\t\t\t%.1fms\t(%.1f%%)\n", i, (float)avg,
-		    (float)res);
-		print(cstate_window, i + 1, 0, "%s", c);
-	}
-
-	print(cstate_window, 0, 48, "%s", "P-states (frequencies)\n");
-
-	if (npstates < 2) {
-		(void) sprintf(c, "%4lu Mhz\t%.1f%%",
-		    (long)pstate_info[0].speed, 100.0);
-		print(cstate_window, 1, 48, "%s\n", c);
-	} else {
-		for (i = 0; i < npstates; i++) {
-			total_pstates += (double)(pstate_info[i].total_time/
-			    g_ncpus/1000000);
-		}
-
-		/*
-		 * display ACPI_PSTATE from P(n) to P(1)
-		 */
-		for (i = 0;  i < npstates - 1; i++) {
-			(void) sprintf(c, "%4lu Mhz\t%.1f%%",
-			    (long)pstate_info[i].speed,
-			    100 * (pstate_info[i].total_time/g_ncpus/1000000
-			    /total_pstates));
-			print(cstate_window, i+1, 48, "%s\n", c);
-		}
-
-		/*
-		 * display ACPI_PSTATE P0 according to if turbo
-		 * mode is supported
-		 */
-		if (g_turbo_supported) {
-			p1_speed = pstate_info[npstates - 2].speed;
-			/*
-			 * if g_turbo_ratio <= 1.0, it will be ignored.
-			 * we display P(0) as P(1) + 1.
-			 */
-			if (g_turbo_ratio <= 1.0) {
-				p0_speed = p1_speed + 1;
-			}
-			/*
-			 * if g_turbo_ratio > 1.0, that means turbo mode works.
-			 * So, P(0) = ratio * P(1);
-			 */
-			else {
-				p0_speed = (uint64_t)(p1_speed * g_turbo_ratio);
-				if (p0_speed < (p1_speed + 1))
-				p0_speed = p1_speed + 1;
-			}
-			/*
-			 * reset the ratio for the next round
-			 */
-			g_turbo_ratio = 0.0;
-
-			/*
-			 * setup the string for the display
-			 */
-			(void) sprintf(c, "%4lu Mhz(turbo)\t%.1f%%",
-			    (long)p0_speed,
-			    100 * (pstate_info[i].total_time/g_ncpus/1000000
-			    /total_pstates));
-		} else {
-			(void) sprintf(c, "%4lu Mhz\t%.1f%%",
-			    (long)pstate_info[i].speed,
-			    100 * (pstate_info[i].total_time/g_ncpus/1000000
-			    /total_pstates));
-		}
-		print(cstate_window, i+1, 48, "%s\n", c);
-
-	}
-	if (!dump)
-		(void) wnoutrefresh(cstate_window);
-}
-
-void
-show_acpi_power_line(uint32_t flag, double rate, double rem_cap, double cap,
-    uint32_t state)
-{
-	char	buffer[1024];
-
-	(void) sprintf(buffer,  _("no ACPI power usage estimate available"));
-
-	if (!dump)
-		(void) werase(acpi_power_window);
-	if (flag) {
-		char *c;
-		(void) sprintf(buffer, "Power usage (ACPI estimate): %.3fW",
-		    rate);
-		(void) strcat(buffer, " ");
-		c = &buffer[strlen(buffer)];
-		switch (state) {
-		case 0:
-			(void) sprintf(c, "(running on AC power, fully "
-			    "charged)");
-			break;
-		case 1:
-			(void) sprintf(c, "(discharging: %3.1f hours)",
-			    rem_cap/rate);
-			break;
-		case 2:
-			(void) sprintf(c, "(charging: %3.1f hours)",
-			    (cap - rem_cap)/rate);
-			break;
-		case 4:
-			(void) sprintf(c, "(##critically low battery power##)");
-			break;
-		}
-
-	}
-	print(acpi_power_window, 0, 0, "%s\n", buffer);
-	if (!dump)
-		(void) wnoutrefresh(acpi_power_window);
-}
-
-void
-show_wakeups(double interval)
-{
-	char 	c[100];
-
-	if (!dump) {
-		(void) werase(wakeup_window);
-		(void) wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED));
-		(void) wattron(wakeup_window, A_BOLD);
-	}
-	(void) sprintf(c, "Wakeups-from-idle per second: %4.1f\tinterval: "
-	    "%.1fs", (double)(total_events/interval), interval);
-	print(wakeup_window, 0, 0, "%s\n", c);
-	if (!dump)
-		(void) wnoutrefresh(wakeup_window);
-}
-
-void
-show_eventstats(double interval)
-{
-	char		c[100];
-	int		i;
-	double		events;
-	event_info_t	*p_event = event_info;
-
-	if (!dump) {
-		(void) werase(eventstat_window);
-		(void) wattrset(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT));
-		(void) wbkgd(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT));
-	}
-
-	/*
-	 * Sort the event report list
-	 */
-	if (top_events > EVENT_NUM_MAX)
-		top_events = EVENT_NUM_MAX;
-
-	qsort((void *)event_info, top_events, sizeof (event_info_t),
-	    event_compare);
-
-	print(eventstat_window, 0, 0, "%s", "Top causes for wakeups:\n");
-
-	for (i = 0; i < top_events; i++, p_event++) {
-
-		if (total_events > 0)
-			events = (double)p_event->total_count/
-			    (double)total_events;
-		else
-			events = 0;
-
-		(void) sprintf(c, "%4.1f%% (%5.1f)", 100 * events,
-		    (double)p_event->total_count/interval);
-		print(eventstat_window, i+1, 0, "%s", c);
-		print(eventstat_window, i+1, 16, "%20s :",
-		    p_event->offender_name);
-		print(eventstat_window, i+1, 40, "%-64s\n",
-		    p_event->offense_name);
-	}
-	if (!dump)
-		(void) wnoutrefresh(eventstat_window);
-}
-
-void
-show_suggestion(char *sug)
-{
-	(void) werase(suggestion_window);
-	print(suggestion_window, 0, 0, "%s", sug);
-	(void) wnoutrefresh(suggestion_window);
-}
-
-void
-update_windows(void)
-{
-	(void) doupdate();
-}
--- a/usr/src/cmd/powertop/events.c	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,321 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *	Arjan van de Ven <[email protected]>
- *	Eric C Saxe <[email protected]>
- *	Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <dtrace.h>
-#include "powertop.h"
-
-static dtrace_hdl_t *g_dtp;
-/*
- * DTrace scripts for observing interrupts, callouts and cyclic events
- * that cause CPU activity. Such activity prevents the processor from
- * entering lower power states and reducing power consumption.
- *
- * g_prog is the default script
- */
-static const char *g_prog =
-"interrupt-complete"
-"/arg0 != NULL && arg3 !=0/"
-"{"
-"	this->devi = (struct dev_info *)arg0;"
-"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
-"	     this->devi->devi_instance] = count();"
-"}"
-""
-"sdt:::callout-start"
-"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
-"{"
-"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
-"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
-"}"
-""
-"sdt:::callout-start"
-"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
-"{"
-"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
-"}"
-""
-"sdt:::cyclic-start"
-"/(caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
-"{"
-"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
-"}"
-""
-"sysinfo:::xcalls"
-"/pid != $pid/"
-"{"
-"       @events_x[execname] = sum(arg0);"
-"}";
-
-/*
- * g_prog_V is enabled through the -v option, it includes cyclic events
- * in the report, allowing a complete view of system activity
- */
-static const char *g_prog_v =
-"interrupt-complete"
-"/arg0 != NULL && arg3 !=0/"
-"{"
-"	this->devi = (struct dev_info *)arg0;"
-"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
-"	     this->devi->devi_instance] = count();"
-"}"
-""
-"sdt:::callout-start"
-"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
-"{"
-"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
-"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
-"}"
-""
-"sdt:::callout-start"
-"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
-"{"
-"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
-"}"
-""
-"sdt:::cyclic-start"
-"/(caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_deadman &&"
-" (caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_clean/"
-"{"
-"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
-"}"
-""
-"sysinfo:::xcalls"
-"/pid != $pid/"
-"{"
-"       @events_x[execname] = sum(arg0);"
-"}";
-
-/*ARGSUSED*/
-static int
-walk(const dtrace_aggdata_t *data, void *arg)
-{
-	dtrace_aggdesc_t 	*aggdesc = data->dtada_desc;
-	dtrace_recdesc_t 	*rec1, *rec2;
-	dtrace_syminfo_t 	dts;
-	char 			*offense_name;
-	uint64_t		offender_addr;
-	int32_t 		*instance;
-	int 			i;
-	uint64_t 		n = 0;
-	GElf_Sym 		sym;
-
-	if (top_events >= EVENT_NUM_MAX)
-		return (0);
-
-	rec1 = &aggdesc->dtagd_rec[1];
-	rec2 = &aggdesc->dtagd_rec[2];
-
-	/*
-	 * Report interrupts
-	 */
-	if (strcmp(aggdesc->dtagd_name, "interrupts") == 0) {
-		offense_name = data->dtada_data + rec1->dtrd_offset;
-
-		/* LINTED - alignment */
-		instance = (int32_t *)(data->dtada_data + rec2->dtrd_offset);
-		(void) snprintf((char *)(p_event->offender_name),
-		    EVENT_NAME_MAX, "%s", "<interrupt>");
-		(void) snprintf((char *)(p_event->offense_name), EVENT_NAME_MAX,
-		    "%s#%d", offense_name, *instance);
-	/*
-	 * Report kernel events
-	 */
-	} else if (strcmp(aggdesc->dtagd_name, "events_k") == 0) {
-
-		(void) snprintf((char *)(p_event->offender_name),
-		    EVENT_NAME_MAX, "%s", "<kernel>");
-
-		/*
-		 * Casting offender_addr to the wrong type will cause
-		 * dtrace_lookup_by_addr to return 0 and the report
-		 * to show an address instead of a name.
-		 */
-		switch (bit_depth) {
-		case 32:
-			/* LINTED - alignment */
-			offender_addr = *(uint32_t *)(data->dtada_data +
-			    rec1->dtrd_offset);
-			break;
-		case 64:
-			/* LINTED - alignment */
-			offender_addr = *(uint64_t *)(data->dtada_data +
-			    rec1->dtrd_offset);
-			break;
-		}
-
-		/*
-		 * We have the address of the kernel callout.
-		 * Try to resolve it into a meaningful symbol
-		 */
-		if (dtrace_lookup_by_addr(g_dtp, offender_addr,
-		    &sym, &dts) == 0) {
-			(void) snprintf((char *)(p_event->offense_name),
-			    EVENT_NAME_MAX, "%s`%s", dts.dts_object,
-			    dts.dts_name);
-		} else {
-			(void) snprintf((char *)(p_event->offense_name),
-			    EVENT_NAME_MAX, "0x%llx", offender_addr);
-		}
-	/*
-	 * Report user events
-	 */
-	} else if (strcmp(aggdesc->dtagd_name, "events_u") == 0) {
-		offense_name = data->dtada_data + rec1->dtrd_offset;
-
-		(void) snprintf((char *)(p_event->offender_name),
-		    EVENT_NAME_MAX, "%s", offense_name);
-		(void) snprintf((char *)(p_event->offense_name),
-		    EVENT_NAME_MAX, "<scheduled timeout expiration>");
-	/*
-	 * Report cross calls
-	 */
-	} else if (strcmp(aggdesc->dtagd_name, "events_x") == 0) {
-		offense_name = data->dtada_data + rec1->dtrd_offset;
-
-		(void) snprintf((char *)(p_event->offender_name),
-		    EVENT_NAME_MAX, "%s", offense_name);
-		(void) snprintf((char *)(p_event->offense_name),
-		    EVENT_NAME_MAX, "<cross calls>");
-	/*
-	 * Report unknown events
-	 */
-	} else {
-		(void) snprintf((char *)(p_event->offender_name),
-		    EVENT_NAME_MAX, "%s", "<unknown>");
-		(void) snprintf((char *)(p_event->offense_name),
-		    EVENT_NAME_MAX, "%s", "<unknown>");
-	}
-
-	for (i = 0; i < g_ncpus; i++)
-		/* LINTED - alignment */
-		n += *((uint64_t *)(data->dtada_percpu[i]));
-
-	p_event->total_count = n;
-
-	p_event++;
-	top_events++;
-
-	return (DTRACE_AGGWALK_NEXT);
-}
-
-int
-pt_events_stat_prepare(void)
-{
-	dtrace_prog_t 		*prog;
-	dtrace_proginfo_t 	info;
-	int 			err;
-	dtrace_optval_t 	statustime;
-
-	p_event = event_info;
-
-	if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
-		pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
-		    dtrace_errmsg(NULL, err));
-		return (-1);
-	}
-
-	/*
-	 * Execute different scripts (defined above) depending on
-	 * user specified options. Default mode has event_mode empty
-	 */
-	switch (event_mode) {
-	default:
-		if ((prog = dtrace_program_strcompile(g_dtp, g_prog,
-		    DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) {
-			pt_error("%s : failed to compile g_prog\n", __FILE__);
-			return (dtrace_errno(g_dtp));
-		}
-		break;
-	case 'v':
-		if ((prog = dtrace_program_strcompile(g_dtp, g_prog_v,
-		    DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) {
-			pt_error("%s : failed to compile g_prog_v\n", __FILE__);
-			return (dtrace_errno(g_dtp));
-		}
-		break;
-	}
-
-	if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
-		pt_error("%s : failed to enable probes\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_setopt(g_dtp, "aggsize", "128k") == -1) {
-		pt_error("%s : failed to set 'aggsize'\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_setopt(g_dtp, "aggrate", "0") == -1) {
-		pt_error("%s : failed to set 'aggrate'\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_setopt(g_dtp, "aggpercpu", 0) == -1) {
-		pt_error("%s : failed to set 'aggpercpu'\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_go(g_dtp) != 0) {
-		pt_error("%s : dtrace_go() failed\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	if (dtrace_getopt(g_dtp, "statusrate", &statustime) == -1) {
-		pt_error("%s : failed to get 'statusrate'\n", __FILE__);
-		return (dtrace_errno(g_dtp));
-	}
-	return (0);
-}
-
-int
-pt_events_stat_collect(void)
-{
-	p_event 	= event_info;
-	top_events 	= 0;
-
-	if (dtrace_status(g_dtp) == -1)
-		return (-1);
-
-	if (dtrace_aggregate_snap(g_dtp) != 0)
-		pt_error("%s : failed to add to aggregate", __FILE__);
-
-	if (dtrace_aggregate_walk_keyvarsorted(g_dtp, walk, NULL) != 0)
-		pt_error("%s : failed to sort aggregate", __FILE__);
-
-	dtrace_aggregate_clear(g_dtp);
-
-	return (0);
-}
--- a/usr/src/cmd/powertop/i386/Makefile	Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/i386/Makefile	Fri Apr 10 11:48:42 2009 -0700
@@ -18,10 +18,26 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
 include ../Makefile.com
 
+MACH_OBJS	= pt_i386.o
+SRCS		+= $(MACH_OBJS:%.o=%.c)
+
+.KEEP_STATE:
+
+CLEANFILES	+= $(MACH_OBJS)
+
+all: $(PROG)
+
+$(PROG): $(MACH_OBJS) $(COMMON_OBJS)
+	$(LINK.c) -o $@ $(MACH_OBJS) $(COMMON_OBJS) $(LDLIBS)
+	$(POST_PROCESS)
+
+%.o: ../common/%.c
+	$(COMPILE.c) -o $@ $<
+
 install: all $(ROOTPROG32)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/i386/pt_i386.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+/*
+ * DTrace scripts for observing interrupts, callouts and cyclic events
+ * that cause CPU activity. Such activity prevents the processor from
+ * entering lower power states and reducing power consumption.
+ *
+ * g_dtp_events is the default script
+ */
+const char *g_dtp_events =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+"	this->devi = (struct dev_info *)arg0;"
+"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+"	     this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"{"
+"	self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+"       @events_x[execname, self->xc_func] = sum(arg0);"
+"}"
+""
+"fbt::xc_common:return"
+"/self->xc_func/"
+"{"
+"	self->xc_func = 0;"
+"}";
+
+/*
+ * g_dtp_events_v is enabled through the -v option, it includes cyclic events
+ * in the report, allowing a complete view of system activity
+ */
+const char *g_dtp_events_v =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+"	this->devi = (struct dev_info *)arg0;"
+"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+"	     this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_deadman &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_clean/"
+"{"
+"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"{"
+"	self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+"       @events_x[execname, self->xc_func] = sum(arg0);"
+"}"
+""
+"fbt::xc_common:return"
+"/self->xc_func/"
+"{"
+"	self->xc_func = 0;"
+"}";
+
+/*
+ * This script is selected through the -c option, it takes the CPU id as
+ * argument and observes activity generated by that CPU
+ */
+const char *g_dtp_events_c =
+"interrupt-complete"
+"/cpu == $0 &&"
+" arg0 != NULL && arg3 != 0/"
+"{"
+"	this->devi = (struct dev_info *)arg0;"
+"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+"	     this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/cpu == $0 &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"/cpu == $0/"
+"{"
+"	self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid &&"
+" cpu == $0/"
+"{"
+"       @events_x[execname, self->xc_func] = count();"
+"}"
+""
+"fbt::xc_common:return"
+"/cpu == $0 &&"
+" self->xc_func/"
+"{"
+"	self->xc_func = 0;"
+"}"
+""
+"fbt::xc_common:entry"
+"/cpu != $0/"
+"{"
+"	self->xc_func = arg0;"
+"	self->xc_cpu = cpu;"
+"}"
+""
+"fbt::send_dirint:entry"
+"/pid != $pid &&"
+" self->xc_func &&"
+" arg0 == $0/"
+"{"
+"       @events_xc[execname, self->xc_func, self->xc_cpu] = count();"
+"	self->xc_func = 0;"
+"	self->xc_cpu = 0;"
+"}";
+
+/*
+ * i386 platform specific display messages
+ */
+const char *g_msg_idle_state = "C-states (idle power states)";
+const char *g_msg_freq_state = "P-states (frequencies)";
--- a/usr/src/cmd/powertop/powertop.c	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-/*
- * Copyright 2009, Intel Corporation
- * Copyright 2009, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *	Arjan van de Ven <[email protected]>
- *	Eric C Saxe <[email protected]>
- *	Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <getopt.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <locale.h>
-#include "powertop.h"
-
-int 		g_ncpus;
-processorid_t 	*cpu_table;
-const int	true = 1;
-boolean_t	gui;
-
-int
-main(int argc, char **argv)
-{
-	hrtime_t 	last, now;
-	uint_t		features = 0, user_interval = 0;
-	int		ncursesinited = 0, index2 = 0, c, ret, dump_count = 0;
-	double		last_time;
-	char		*endptr;
-
-	static struct option opts[] = {
-		{ "dump", 1, NULL, 'd' },
-		{ "time", 1, NULL, 't' },
-		{ "help", 0, NULL, 'h' },
-		{ "verbose", 0, NULL, 'v' },
-		{ 0, 0, NULL, 0 }
-	};
-
-	(void) setlocale(LC_ALL, "");
-	(void) bindtextdomain("powertop", "/usr/share/locale");
-	(void) textdomain("powertop");
-
-	pt_set_progname(argv[0]);
-
-	if ((bit_depth = get_bit_depth()) < 0)
-		exit(EXIT_FAILURE);
-
-	ticktime = ticktime_usr = INTERVAL_DEFAULT;
-	displaytime 	= 0.0;
-	dump 		= 0;
-	gui		= B_FALSE;
-	event_mode	= ' ';
-	max_cstate	= 0;
-	g_turbo_supported = B_FALSE;
-
-	while ((c = getopt_long(argc, argv, "d:vt:h", opts, &index2)) != EOF) {
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'd':
-			if (dump)
-				usage();
-
-			dump = 1;
-			dump_count = (int)strtod(optarg, &endptr);
-
-			if (dump_count <= 0 || *endptr != NULL)
-				usage();
-			break;
-		case 't':
-			if (user_interval)
-				usage();
-
-			user_interval = 1;
-			ticktime = ticktime_usr = (double)strtod(optarg,
-			    &endptr);
-
-			if (*endptr != NULL || ticktime < 1 ||
-			    ticktime > INTERVAL_MAX)
-				usage();
-			break;
-		case 'v':
-			if (event_mode == 'v')
-				usage();
-
-			event_mode = 'v';
-			break;
-		case 'h':
-		default:
-			usage();
-			return (EXIT_USAGE);
-		}
-	}
-
-	if (optind < argc) {
-		usage();
-	}
-
-	(void) printf("%s   (C) 2009 Intel Corporation\n\n", TITLE);
-
-	/*
-	 * Enumerate the system's CPUs
-	 * Populate cpu_table, g_ncpus
-	 */
-	enumerate_cpus();
-
-	/*
-	 * If the system is running on battery, find out what's
-	 * the kstat module for it
-	 */
-	battery_mod_lookup();
-
-	/* Prepare C-state statistics */
-	ret = pt_cpuidle_stat_prepare();
-	if (ret == 0)
-		features |= FEATURE_CSTATE;
-	else
-		/*
-		 * PowerTop was unable to run a DTrace program,
-		 * most likely for lack of permissions.
-		 */
-		exit(EXIT_FAILURE);
-
-	/* Prepare P-state statistics */
-	if (pt_cpufreq_stat_prepare() == 0)
-		features |= FEATURE_PSTATE;
-
-	/* Prepare event statistics */
-	if (pt_events_stat_prepare() != -1)
-		features |= FEATURE_EVENTS;
-
-	/* Prepare turbo statistics */
-	if (pt_turbo_stat_prepare() == 0) {
-		features |= FEATURE_TURBO;
-	}
-
-	(void) printf(_("Collecting data for %.2f second(s) \n"),
-	    (float)ticktime);
-
-	if (!dump)
-		gui = B_TRUE;
-
-	last = gethrtime();
-
-	while (true) {
-		fd_set 	rfds;
-		struct 	timeval tv;
-		int 	key, reinit = 0;
-		char 	keychar;
-
-		/*
-		 * Sleep for a while waiting either for input (if we're not
-		 * in dump mode) or for the timeout to elapse
-		 */
-		FD_ZERO(&rfds);
-		FD_SET(0, &rfds);
-
-		tv.tv_sec 	= (long)ticktime;
-		tv.tv_usec 	= (long)((ticktime - tv.tv_sec) * 1000000);
-
-		if (!dump)
-			key = select(1, &rfds, NULL, NULL, &tv);
-		else
-			key = select(1, NULL, NULL, NULL, &tv);
-
-		now 		= gethrtime();
-
-		g_interval 	= (double)(now - last)/NANOSEC;
-		last 		= now;
-
-		top_events 	= 0;
-		total_events 	= 0;
-
-		(void) memset(event_info, EVENT_NUM_MAX * sizeof (event_info_t),
-		    0);
-		(void) memset(cstate_info, 2 * sizeof (state_info_t), 0);
-
-		/* Collect idle state transition stats */
-		if (features & FEATURE_CSTATE &&
-		    pt_cpuidle_stat_collect(g_interval) < 0) {
-			/* Reinitialize C-state statistics */
-			if (pt_cpuidle_stat_prepare() != 0)
-				exit(EXIT_FAILURE);
-
-			reinit = 1;
-		}
-
-		/* Collect frequency change stats */
-		if (features & FEATURE_PSTATE &&
-		    pt_cpufreq_stat_collect(g_interval) < 0) {
-			/* Reinitialize P-state statistics */
-			if (pt_cpufreq_stat_prepare() != 0)
-				exit(EXIT_FAILURE);
-
-			reinit = 1;
-		}
-
-		/* Collect event statistics */
-		if (features & FEATURE_EVENTS &&
-		    pt_events_stat_collect() < 0) {
-			/* Reinitialize event statistics */
-			if (pt_events_stat_prepare() != 0)
-				exit(EXIT_FAILURE);
-
-			reinit = 1;
-		}
-
-		if (reinit)
-			continue;
-
-		/* Collect turbo statistics */
-		if (features & FEATURE_TURBO &&
-		    pt_turbo_stat_collect() < 0) {
-			exit(EXIT_FAILURE);
-		}
-
-		/*
-		 * Initialize curses if we're not dumping and
-		 * haven't already done it
-		 */
-		if (!dump) {
-			if (!ncursesinited) {
-				initialize_curses();
-				ncursesinited++;
-			}
-			setup_windows();
-			show_title_bar();
-		}
-
-		/* Show CPU power states */
-		if (features & FEATURE_CSTATE)
-			show_cstates();
-
-		/* Show wakeups events affecting PM */
-		if (features & FEATURE_EVENTS) {
-			show_wakeups(g_interval);
-			show_eventstats(g_interval);
-		}
-
-		print_battery();
-
-		displaytime = displaytime - ticktime;
-
-		if (key && !dump) {
-			keychar = toupper(fgetc(stdin));
-
-			switch (keychar) {
-			case 'Q':
-				cleanup_curses();
-				exit(EXIT_SUCCESS);
-				break;
-			case 'R':
-				ticktime = 3;
-				break;
-			}
-			if (keychar == suggestion_key && suggestion_activate) {
-				suggestion_activate();
-				displaytime = -1.0;
-			}
-		}
-		reset_suggestions();
-
-		/* suggests PM */
-		if (geteuid() == 0) {
-			suggest_p_state();
-		} else {
-			suggest_as_root();
-		}
-
-		if (dump_count)
-			dump_count--;
-
-		/* Exits if user requested a dump */
-		if (dump && !dump_count) {
-			print_all_suggestions();
-			exit(EXIT_SUCCESS);
-		}
-
-		/* No key pressed, will suggest something */
-		if (!key && !dump_count)
-			pick_suggestion();
-
-		/* Refresh display */
-		if (!dump) {
-			show_title_bar();
-			update_windows();
-		}
-
-		/*
-		 * Update the interval based on how long the CPU was in the
-		 * longest c-state during the last snapshot. If the user
-		 * specified an interval we skip this bit and keep it fixed.
-		 */
-		last_time = (((double)cstate_info[longest_cstate].total_time/
-		    g_ncpus)/cstate_info[longest_cstate].events);
-
-		if (!user_interval)
-			if (last_time < INTERVAL_DEFAULT ||
-			    (total_events/ticktime) < 1)
-				ticktime = INTERVAL_DEFAULT;
-			else
-				ticktime = INTERVAL_UPDATE(last_time);
-
-		/*
-		 * Restore user specified interval after a refresh
-		 */
-		if (keychar == 'R' && user_interval)
-			ticktime = ticktime_usr;
-	}
-	return (EXIT_SUCCESS);
-}
-
-void
-suggest_as_root(void)
-{
-	add_suggestion("Suggestion: run as root to get suggestions"
-	    " for reducing system power consumption",  40, NULL, NULL,
-	    NULL);
-}
--- a/usr/src/cmd/powertop/powertop.h	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,300 +0,0 @@
-/*
- * Copyright 2009, Intel Corporation
- * Copyright 2009, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *	Arjan van de Ven <[email protected]>
- *	Eric C Saxe <[email protected]>
- *	Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#ifndef __INCLUDE_GUARD_POWERTOP_H_
-#define	__INCLUDE_GUARD_POWERTOP_H_
-
-#include <sys/types.h>
-#include <libintl.h>
-#include <sys/processor.h>
-
-#define	max(A, B)		(((A) < (B)) ? (B) : (A))
-
-#define	_(STRING)		gettext(STRING)
-
-#define	TITLE			"OpenSolaris PowerTOP version 1.1"
-
-/*
- * Exit values. stdlib.h defines EXIT_SUCCESS as 0 and
- * EXIT_FAILURE as 1
- */
-#define	EXIT_USAGE		2
-
-/*
- * PowerTop Features
- * These may not be available everywhere
- */
-#define	FEATURE_CSTATE		0x1
-#define	FEATURE_PSTATE		0x2
-#define	FEATURE_EVENTS		0x4
-#define	FEATURE_TURBO		0x8
-
-#define	BIT_DEPTH_BUF		10
-
-#define	INTERVAL_DEFAULT	5.0
-#define	INTERVAL_MAX		100.0
-#define	INTERVAL_UPDATE(l)						\
-	((l/INTERVAL_DEFAULT) * INTERVAL_DEFAULT + INTERVAL_DEFAULT)
-
-#define	STATE_NAME_MAX		16
-#define	EVENT_NAME_MAX 		64
-#define	EVENT_NUM_MAX 		100
-#define	NSTATES			32
-
-/*
- * Display colors
- */
-#define	PT_COLOR_DEFAULT	1
-#define	PT_COLOR_HEADER_BAR	2
-#define	PT_COLOR_ERROR		3
-#define	PT_COLOR_RED		4
-#define	PT_COLOR_YELLOW		5
-#define	PT_COLOR_GREEN		6
-#define	PT_COLOR_BRIGHT		7
-#define	PT_COLOR_BLUE		8
-
-/*
- * Constants for setup_windows()
- */
-#define	SINGLE_LINE_SW 		1
-#define	LENGTH_SUGG_SW		2
-#define	TITLE_LINE		1
-#define	BLANK_LINE		1
-#define	NEXT_LINE		1
-
-/*
- * Structures and typedefs
- */
-struct line {
-	char		*string;
-	int		count;
-};
-
-typedef struct event_info {
-	char		offender_name[EVENT_NAME_MAX];
-	char		offense_name[EVENT_NAME_MAX];
-	uint64_t	total_count;
-} event_info_t;
-
-/*
- * P/C state information
- */
-typedef struct state_info {
-	char		name[STATE_NAME_MAX];
-	hrtime_t	total_time;
-	hrtime_t	last_time;
-	double		events;
-} state_info_t;
-
-typedef struct pstate_info {
-	uint64_t	speed;
-	hrtime_t	total_time;
-} pstate_info_t;
-
-typedef struct cpu_power_info {
-	uint64_t	current_pstate;
-	hrtime_t	time_accounted;
-	hrtime_t	dtrace_time;
-} cpu_power_info_t;
-
-/*
- * turbo information
- */
-typedef struct turbo_info {
-	uint64_t	t_mcnt;
-	uint64_t	t_acnt;
-} turbo_info_t;
-
-
-typedef	void		(suggestion_func)(void);
-
-/*
- * Global variables
- */
-double			displaytime;
-
-int			bit_depth;
-
-/*
- * Event accounting
- */
-int 			total_events;
-int 			top_events;
-
-/*
- * Interval
- */
-double 			ticktime, ticktime_usr;
-double 			g_interval;
-
-/*
- * Command line arguments
- */
-int 			dump;
-char			event_mode;
-extern boolean_t	gui;
-
-/*
- * Event info array
- */
-event_info_t    	event_info[EVENT_NUM_MAX];
-event_info_t		*p_event;
-
-/*
- * Lookup table, sequential CPU id to Solaris CPU id
- */
-processorid_t 		*cpu_table;
-
-/*
- * Number of idle/frequency states
- */
-int			npstates;
-int			max_cstate;
-int			longest_cstate;
-
-/*
- * Total time, used to display different idle states
- */
-hrtime_t		total_c_time;
-
-/*
- * P/C state info arrays
- */
-state_info_t		cstate_info[NSTATES];
-pstate_info_t		pstate_info[NSTATES];
-
-/*
- * Per CPU power state information
- */
-cpu_power_info_t	*cpu_power_states;
-
-/*
- * Turbo mode related information
- */
-extern boolean_t	g_turbo_supported;
-extern double		g_turbo_ratio;
-
-/*
- * Extern declarations
- */
-extern struct line	*lines;
-extern int		linehead;
-extern int		linesize;
-extern int		linectotal;
-
-extern	int		g_ncpus;
-
-/*
- * kstat's battery module
- */
-extern char		*kstat_batt_mod[3];
-extern uint_t		kstat_batt_idx;
-
-extern int 		topcstate;
-extern int 		topfreq;
-extern int 		dump;
-
-extern char 		*prog;
-
-extern char 		status_bar_slots[10][40];
-
-extern const int	true, false;
-
-extern char 		suggestion_key;
-extern suggestion_func 	*suggestion_activate;
-
-/*
- * Suggestions related
- */
-extern void 		suggest_p_state(void);
-extern void		suggest_as_root(void);
-
-/*
- * See util.c
- */
-extern void 		pt_error(char *, ...);
-extern void 		pt_set_progname(char *);
-extern void		enumerate_cpus(void);
-extern void		usage(void);
-extern	int		get_bit_depth(void);
-extern void		battery_mod_lookup(void);
-extern	int		event_compare(const void *, const void *);
-
-/*
- * Display/curses related
- */
-extern	void 		show_title_bar(void);
-extern	void 		setup_windows(void);
-extern	void 		initialize_curses(void);
-extern	void		show_acpi_power_line(uint32_t flag, double rate,
-    double rem_cap, double cap, uint32_t state);
-extern	void 		show_cstates();
-extern	void 		show_wakeups(double interval);
-extern	void 		show_eventstats(double interval);
-extern	void 		show_suggestion(char *sug);
-extern	void 		cleanup_curses(void);
-extern	void		update_windows(void);
-
-/*
- * Suggestions
- */
-extern	void 		pick_suggestion(void);
-extern	void 		add_suggestion(char *text, int weight, char key,
-    char *keystring, suggestion_func *func);
-extern	void 		reset_suggestions(void);
-extern	void 		print_all_suggestions(void);
-extern	void 		print_battery(void);
-
-/*
- * DTrace stats
- */
-extern	int 		pt_cpufreq_stat_prepare(void);
-extern	int 		pt_cpufreq_stat_collect(double interval);
-extern	int 		pt_cpuidle_stat_prepare(void);
-extern	int 		pt_cpuidle_stat_collect(double interval);
-extern	int 		pt_events_stat_prepare(void);
-extern	int 		pt_events_stat_collect(void);
-
-/*
- * turbo related
- */
-extern	int		pt_turbo_stat_prepare(void);
-extern	int		pt_turbo_stat_collect(void);
-
-#endif /* __INCLUDE_GUARD_POWERTOP_H_ */
--- a/usr/src/cmd/powertop/sparcv9/Makefile	Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/sparcv9/Makefile	Fri Apr 10 11:48:42 2009 -0700
@@ -18,11 +18,27 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
 include ../Makefile.com
 include ../../Makefile.cmd.64
 
+MACH_OBJS	= pt_sparcv9.o
+SRCS		+= $(MACH_OBJS:%.o=%.c)
+
+.KEEP_STATE:
+
+CLEANFILES	+= $(MACH_OBJS)
+
+all: $(PROG)
+
+$(PROG): $(MACH_OBJS) $(COMMON_OBJS)
+	$(LINK.c) -o $@ $(MACH_OBJS) $(COMMON_OBJS) $(LDLIBS)
+	$(POST_PROCESS)
+
+%.o: ../common/%.c
+	$(COMPILE.c) -o $@ $<
+
 install: all $(ROOTPROG64)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/sparcv9/pt_sparcv9.c	Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ *	Arjan van de Ven <[email protected]>
+ *	Eric C Saxe <[email protected]>
+ *	Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+/*
+ * DTrace scripts for observing interrupts, callouts and cyclic events
+ * that cause CPU activity. Such activity prevents the processor from
+ * entering lower power states and reducing power consumption.
+ *
+ * g_dtp_events is the default script
+ */
+const char *g_dtp_events =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+"	this->devi = (struct dev_info *)arg0;"
+"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+"	     this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xt_all:entry,"
+"fbt::xc_all:entry"
+"{"
+"	self->xc_func = arg0;"
+"}"
+""
+"fbt::xt_one_unchecked:entry,"
+"fbt::xt_some:entry,"
+"fbt::xc_one:entry,"
+"fbt::xc_some:entry"
+"{"
+"	self->xc_func = arg1;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+"       @events_x[execname, self->xc_func] = sum(arg0);"
+"	self->xc_func = 0;"
+"}";
+
+/*
+ * g_dtp_events_v is enabled through the -v option, it includes cyclic events
+ * in the report, allowing a complete view of system activity
+ */
+const char *g_dtp_events_v =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+"	this->devi = (struct dev_info *)arg0;"
+"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+"	     this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_deadman &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_clean/"
+"{"
+"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xt_all:entry,"
+"fbt::xc_all:entry"
+"{"
+"	self->xc_func = arg0;"
+"}"
+""
+"fbt::xt_one_unchecked:entry,"
+"fbt::xt_some:entry,"
+"fbt::xc_one:entry,"
+"fbt::xc_some:entry"
+"{"
+"	self->xc_func = arg1;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+"       @events_x[execname, self->xc_func] = sum(arg0);"
+"	self->xc_func = 0;"
+"}";
+
+/*
+ * This script is selected through the -c option, it takes the CPU id as
+ * argument and observes activity generated by that CPU
+ */
+const char *g_dtp_events_c =
+"interrupt-complete"
+"/cpu == $0 &&"
+" arg0 != NULL && arg3 != 0/"
+"{"
+"	this->devi = (struct dev_info *)arg0;"
+"	@interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+"	     this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+"       this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+"       @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+"       @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/cpu == $0 &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+"	@events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+/*
+ * xcalls to all CPUs. We're only interested in firings from other CPUs since
+ * the system doesn't xcall itself
+ */
+"fbt::xt_all:entry,"
+"fbt::xc_all:entry"
+"/pid != $pid &&"
+" cpu != $0/"
+"{"
+"	self->xc_func = arg0;"
+"	self->xc_cpu = cpu;"
+"	self->cpu_known = 1;"
+"}"
+""
+/*
+ * xcalls to a subset of CPUs. No way of knowing if the observed CPU is in
+ * it, so account it in the generic @events_x aggregation. Again, we don't
+ * xcall the current CPU.
+ */
+"fbt::xt_some:entry,"
+"fbt::xc_some:entry"
+"/pid != $pid &&"
+" cpu != $0/"
+"{"
+"	self->xc_func = arg1;"
+"}"
+""
+/*
+ * xcalls to a specific CPU, with all the necessary information
+ */
+"fbt::xt_one_unchecked:entry,"
+"fbt::xc_one:entry"
+"/arg0 == $0/"
+"{"
+"	self->xc_func = arg1;"
+"	self->xc_cpu = arg0;"
+"	self->cpu_known = 1;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid &&"
+" self->xc_func &&"
+" !self->cpu_known/"
+"{"
+"       @events_x[execname, self->xc_func] = sum(arg0);"
+"	self->xc_func = 0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid &&"
+" self->xc_func &&"
+" self->cpu_known/"
+"{"
+"       @events_xc[execname, self->xc_func, self->xc_cpu] = sum(arg0);"
+"	self->xc_func = 0;"
+"	self->xc_cpu = 0;"
+"	self->cpu_known = 0;"
+"}";
+
+/*
+ * sparcv9 platform specific display messages
+ */
+const char *g_msg_idle_state = "Idle Power States\t";
+const char *g_msg_freq_state = "Frequency Levels";
--- a/usr/src/cmd/powertop/suggestions.c	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *      Arjan van de Ven <[email protected]>
- *      Eric C Saxe <[email protected]>
- *      Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "powertop.h"
-
-char 			suggestion_key;
-suggestion_func 	*suggestion_activate;
-
-struct suggestion;
-
-struct suggestion {
-	struct suggestion *next;
-
-	char 	*string;
-	int	weight;
-	char 	key;
-	char 	*keystring;
-
-	suggestion_func *func;
-};
-
-static struct suggestion 	*suggestions;
-static int 			total_weight;
-
-static char 	previous[1024];
-
-void
-reset_suggestions(void)
-{
-	struct suggestion *ptr;
-
-	ptr = suggestions;
-
-	while (ptr) {
-		struct suggestion *next;
-
-		next = ptr->next;
-		free(ptr->string);
-		free(ptr->keystring);
-		free(ptr);
-		ptr = next;
-	}
-
-	suggestions = NULL;
-	(void) strcpy(status_bar_slots[8], "");
-
-	suggestion_key 		= -1;
-	suggestion_activate 	= NULL;
-	total_weight 		= 0;
-}
-
-void
-add_suggestion(char *text, int weight, char key, char *keystring,
-    suggestion_func *func)
-{
-	struct suggestion *new;
-
-	if (!text)
-		return;
-
-	new = malloc(sizeof (struct suggestion));
-
-	if (!new)
-		return;
-
-	(void) memset(new, 0, sizeof (struct suggestion));
-
-	new->string = strdup(text);
-	new->weight = weight;
-	new->key = key;
-
-	if (keystring)
-		new->keystring = strdup(keystring);
-
-	new->next 	= suggestions;
-	new->func 	= func;
-	suggestions 	= new;
-	total_weight 	+= weight;
-}
-
-void
-pick_suggestion(void)
-{
-	int			weight, value, running = 0;
-	struct suggestion 	*ptr;
-
-	(void) strcpy(status_bar_slots[8], "");
-	suggestion_key 		= -1;
-	suggestion_activate 	= NULL;
-
-	if (total_weight == 0 || suggestions == NULL) {
-		show_suggestion("");
-		return;
-	}
-
-	weight = total_weight;
-
-	if (strlen(previous) && displaytime > 0.0)
-		weight += 50;
-
-	value 	= rand() % weight;
-	ptr 	= suggestions;
-
-	while (ptr) {
-		running += ptr->weight;
-
-		if (strcmp(ptr->string, previous) == 0 && displaytime > 0.0)
-			running += 50;
-
-		if (running > value) {
-			if (ptr->keystring)
-				(void) strncpy(status_bar_slots[8],
-				    ptr->keystring, 40);
-
-			suggestion_key 		= ptr->key;
-			suggestion_activate 	= ptr->func;
-
-			show_suggestion(ptr->string);
-
-			if (strcmp(ptr->string, previous)) {
-				displaytime = 30.0;
-				(void) strcpy(previous, ptr->string);
-			}
-			return;
-		}
-		ptr = ptr->next;
-	}
-
-	show_suggestion("");
-	(void) memset(previous, 0, sizeof (previous));
-	displaytime = -1.0;
-}
-
-void
-print_all_suggestions(void)
-{
-	struct suggestion *ptr;
-
-	for (ptr = suggestions; ptr; ptr = ptr->next)
-		(void) printf("\n%s\n", ptr->string);
-}
--- a/usr/src/cmd/powertop/turbo.c	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright 2009, Intel Corporation
- * Copyright 2009, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *	Arjan van de Ven <[email protected]>
- *	Eric C Saxe <[email protected]>
- *	Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <dtrace.h>
-#include <kstat.h>
-#include <errno.h>
-#include "powertop.h"
-
-/*
- * global turbo related variables definitions
- */
-boolean_t		g_turbo_supported;
-double			g_turbo_ratio;
-
-/*
- * the variables to store kstat snapshot
- */
-static turbo_info_t	*cpu_turbo_info = NULL;
-static turbo_info_t	*t_new = NULL;
-
-/*
- * Perform setup necessary to enumerate and track CPU turbo information
- */
-static int
-pt_turbo_init(void)
-{
-	kstat_ctl_t 		*kc;
-	kstat_t 		*ksp;
-	kstat_named_t 		*knp;
-
-	/*
-	 * check if the CPU turbo is supported
-	 */
-	if ((kc = kstat_open()) == NULL) {
-		g_turbo_supported = B_FALSE;
-		return (errno);
-	}
-
-	ksp = kstat_lookup(kc, "turbo", 0, NULL);
-	if (ksp == NULL) {
-		g_turbo_supported = B_FALSE;
-		(void) kstat_close(kc);
-		return (-1);
-	}
-
-	(void) kstat_read(kc, ksp, NULL);
-
-	knp = kstat_data_lookup(ksp, "turbo_supported");
-	if (knp == NULL) {
-		pt_error("%s : couldn't find item turbo_supported\n", __FILE__);
-		g_turbo_supported = B_FALSE;
-		(void) kstat_close(kc);
-		return (-2);
-	}
-
-	/*
-	 * initialize turbo information structure if turbo mode is supported
-	 */
-	if (knp->value.ui32) {
-		g_turbo_supported = B_TRUE;
-		cpu_turbo_info = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
-		t_new = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
-	}
-
-	(void) kstat_close(kc);
-	return (0);
-}
-
-/*
- * Take a snapshot of each CPU's turbo information
- * by looking through the turbo kstats.
- */
-static int
-pt_turbo_snapshot(turbo_info_t *turbo_snapshot)
-{
-	kstat_ctl_t 		*kc;
-	kstat_t 		*ksp;
-	kstat_named_t 		*knp;
-	int 			cpu;
-	turbo_info_t		*turbo_info;
-
-	if ((kc = kstat_open()) == NULL)
-		return (errno);
-
-	for (cpu = 0; cpu < g_ncpus; cpu++) {
-		turbo_info = &turbo_snapshot[cpu];
-		ksp = kstat_lookup(kc, "turbo", cpu_table[cpu], NULL);
-		if (ksp == NULL) {
-			pt_error("%s : couldn't find turbo kstat for CPU "
-			"%d\n", __FILE__, cpu);
-			(void) kstat_close(kc);
-			return (-1);
-		}
-
-		if (kstat_read(kc, ksp, NULL) == -1) {
-			pt_error("%s : couldn't read turbo kstat for "
-			    "CPU %d\n", __FILE__, cpu);
-			(void) kstat_close(kc);
-			return (-2);
-		}
-
-		knp = kstat_data_lookup(ksp, "turbo_mcnt");
-		if (knp == NULL) {
-			pt_error("%s : couldn't find turbo mcnt "
-			    "kstat for CPU %d\n", __FILE__, cpu);
-			(void) kstat_close(kc);
-			return (-3);
-		}
-
-		/*
-		 * snapshot IA32_MPERF_MSR
-		 */
-		turbo_info->t_mcnt = knp->value.ui64;
-
-		knp = kstat_data_lookup(ksp, "turbo_acnt");
-		if (knp == NULL) {
-			pt_error("%s : couldn't find turbo acnt "
-			    "kstat for CPU %d\n", __FILE__, cpu);
-			(void) kstat_close(kc);
-			return (-4);
-		}
-
-		/*
-		 * snapshot IA32_APERF_MSR
-		 */
-		turbo_info->t_acnt = knp->value.ui64;
-	}
-
-	if (kstat_close(kc) != 0)
-		pt_error("%s : couldn't close kstat\n", __FILE__);
-
-	return (0);
-}
-
-/*
- * turbo support checking and information initialization
- */
-int
-pt_turbo_stat_prepare(void)
-{
-	int	ret;
-
-	ret = pt_turbo_init();
-
-	if (ret != 0) {
-		return (ret);
-	}
-
-	ret = pt_turbo_snapshot(cpu_turbo_info);
-
-	if (ret != 0) {
-		pt_error("%s : turbo snapshot failed\n", __FILE__);
-	}
-
-	return (ret);
-}
-
-/*
- * when doing the statistics collection, we compare two kstat snapshot
- * and get a delta. the final ratio of performance boost will be worked
- * out according to the kstat delta
- */
-int
-pt_turbo_stat_collect(void)
-{
-	int		cpu;
-	uint64_t	delta_mcnt, delta_acnt;
-	double		ratio;
-	int		ret;
-
-	/*
-	 * take a snapshot of turbo information to setup turbo_info_t
-	 * structure
-	 */
-	ret = pt_turbo_snapshot(t_new);
-	if (ret != 0) {
-		pt_error("%s : turbo stat collect failed\n", __FILE__);
-		return (ret);
-	}
-
-	/*
-	 * calculate the kstat delta and work out the performance boost ratio
-	 */
-	for (cpu = 0; cpu < g_ncpus; cpu++) {
-		delta_mcnt = t_new[cpu].t_mcnt - cpu_turbo_info[cpu].t_mcnt;
-		delta_acnt = t_new[cpu].t_acnt - cpu_turbo_info[cpu].t_acnt;
-
-		if ((delta_mcnt > delta_acnt) || (delta_mcnt == 0))
-			ratio = 1.0;
-		else
-			ratio = (double)delta_acnt / (double)delta_mcnt;
-		g_turbo_ratio += ratio;
-	}
-
-	g_turbo_ratio = g_turbo_ratio / (double)g_ncpus;
-
-	/*
-	 * update the structure of the kstat for the next time calculation
-	 */
-	(void) memcpy(cpu_turbo_info, t_new, g_ncpus * (sizeof (turbo_info_t)));
-
-	return (0);
-}
--- a/usr/src/cmd/powertop/util.c	Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*
- * Copyright 2009, Intel Corporation
- * Copyright 2009, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- *	Arjan van de Ven <[email protected]>
- *	Eric C Saxe <[email protected]>
- *	Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <unistd.h>
-#include <strings.h>
-#include <sys/systeminfo.h>
-#include <kstat.h>
-#include <errno.h>
-#include "powertop.h"
-
-static char 	PROG_FMT[] = "%s: ";
-static char 	ERR_FMT[] = ": %s";
-static char 	*progname;
-
-char 	*kstat_batt_mod[3] = {"NULL", "battery", "acpi_drv"};
-uint_t	kstat_batt_idx;
-
-void
-pt_set_progname(char *name)
-{
-	progname = basename(name);
-}
-
-/*PRINTFLIKE1*/
-void
-pt_error(char *format, ...)
-{
-	int 	err = errno;
-	va_list alist;
-
-	if (gui)
-		return;
-
-	if (progname != NULL)
-		(void) fprintf(stderr, PROG_FMT, progname);
-
-	va_start(alist, format);
-	(void) vfprintf(stderr, format, alist);
-	va_end(alist);
-
-	if (strchr(format, '\n') == NULL)
-		(void) fprintf(stderr, gettext(ERR_FMT), strerror(err));
-}
-
-void
-enumerate_cpus(void)
-{
-	int	cpuid;
-	int	ncpus = 0;
-	int	max, cpus_conf;
-
-	max 		= sysconf(_SC_CPUID_MAX);
-	cpus_conf	= sysconf(_SC_NPROCESSORS_CONF);
-	cpu_table 	= malloc(cpus_conf * sizeof (processorid_t));
-
-	for (cpuid = 0; cpuid < max; cpuid++) {
-		if (p_online(cpuid, P_STATUS) != -1) {
-			cpu_table[ncpus] = cpuid;
-			ncpus++;
-		}
-	}
-	g_ncpus = ncpus;
-}
-
-void
-usage(void)
-{
-	(void) fprintf(stderr, "%s   (C) 2009 Intel Corporation\n\n", TITLE);
-	(void) fprintf(stderr, "Usage: powertop [option]\n");
-	(void) fprintf(stderr, "  -d, --dump [count]	Read wakeups count "
-	    "times and print list of top offenders\n");
-	(void) fprintf(stderr, "  -t, --time [interval]	Default time to gather "
-	    "data in seconds [1-100s]\n");
-	(void) fprintf(stderr, "  -v, --verbose		Verbose mode, reports "
-	    "kernel cyclic activity\n");
-	(void) fprintf(stderr, "  -h, --help		Show this help "
-	    "message\n");
-
-	exit(EXIT_USAGE);
-}
-
-int
-get_bit_depth(void)
-{
-	/*
-	 * This little routine was derived from isainfo.c to look up
-	 * the system's bit depth. It feeds a 10 byte long buffer to
-	 * sysinfo (we only need the first word, sysinfo truncates and
-	 * \0 terminates the rest) from which we figure out which isa
-	 * we're running on.
-	 */
-	char	buf[BIT_DEPTH_BUF];
-
-	if (sysinfo(SI_ARCHITECTURE_64, buf, BIT_DEPTH_BUF) == -1)
-		if (sysinfo(SI_ARCHITECTURE_32, buf, BIT_DEPTH_BUF) == -1)
-			return (-2);
-
-	if (strcmp(buf, "sparc") == 0 || strcmp(buf, "i386") == 0)
-		return (32);
-
-	if (strcmp(buf, "sparcv9") == 0 || strcmp(buf, "amd64") == 0)
-		return (64);
-
-	return (-3);
-}
-
-/*
- * Checks if the kstat module for battery information is present and
- * whether it's called 'battery' or 'acpi_drv'
- */
-void
-battery_mod_lookup(void)
-{
-	kstat_ctl_t *kc = kstat_open();
-
-	if (kstat_lookup(kc, kstat_batt_mod[1], 0, NULL))
-		kstat_batt_idx = 1;
-	else
-		if (kstat_lookup(kc, kstat_batt_mod[2], 0, NULL))
-			kstat_batt_idx = 2;
-		else
-			kstat_batt_idx = 0;
-
-	(void) kstat_close(kc);
-}
-
-/*
- * Simple integer comparison routine for the event report qsort(3C).
- */
-int
-event_compare(const void *p1, const void *p2)
-{
-	event_info_t i = *((event_info_t *)p1);
-	event_info_t j = *((event_info_t *)p2);
-
-	if (i.total_count > j.total_count)
-		return (-1);
-
-	if (i.total_count < j.total_count)
-		return (1);
-
-	return (0);
-}