NOTICE: The Processors Wiki will End-of-Life on January 15, 2021. It is recommended to download any files or other content you may need that are hosted on processors.wiki.ti.com. The site is now set to read only.
Running PowerTOP on OMAP35x platform
Contents
Introduction[edit]
The Linux port on OMAP35x supports multiple C-states (idle states) corresponding to different levels of power savings that can be achieved. The amount of power saved depends upon optimal choice of idle state.
This is exactly where PowerTOP comes handy. It collates various kernel statistics to help us visualize the 'activities' when system is idle. We can, now, confirm if the system is behaving as expected. Or, identify 'rogue' tasks/ events that are stealing power.
This article describes the steps and changes to get PowerTOP running on the OMAP35x platforms. These steps can be replicated on other processors and EVMs as well.
Background[edit]
Until recently, timer-tick was a periodic event causing CPU to use power - even when the system is idle. The 'tickless kernel' has enabled systems to stay in low power mode for much longer - enabling better power savings.
PowerTOP is Linux tool that aims at identifying software components that are using power while the CPU is idle. It is one of Intel's "LessWatts.org" projects. It is based on (and driven by) the Intel Processors and released under the GNU General Public License (version 2).
Kernel Configuration[edit]
The Linux kernel needs to be instrumented to gather relavent statistics. This section describes changes to default configuration.
- Create default configuration for the OMAP3EVM.
- $ make omap3_evm_defconfig
- NOTE: In the Linux PSP versions earlier than version 1.0.x, this command will be:
make omap3evm_defconfig
.
- Invoke Linux Kernel Configuration tool
- $ make menuconfig
- On the first screen, select the option
Kernel hacking
.- Networking --->
- Device Drivers --->
- File systems --->
- Kernel hacking --->
- Security options --->
- Now select the option
Collect kernel timers statistics
.- [ ] Collect scheduler statistics
- [*] Collect kernel timers statistics
- [ ] Debug object operations
- [ ] Debug slab memory allocations
- Now, build the kernel as usual.
- $ make uImage
Getting necessary sources[edit]
- Download the PoweTOP from here.
- (Latest version at time of writing this article was 1.10)
- Extract the sources to your working directory.
- By default, PowerTOP uses
libncursesw
(wide character version of ncurses).- Since, wide character version is not necessary for us, we will use regular ncurses library)
- It can be download from here.
- (Latest version at time of writing this article was 5.6)
- Extract the sources to your working directory.
For simplicity, this article assumes that all sources are extracted besides the linux kernel sources as shown below:
/home/user/work | +-- linux | +-- ncurses | +-- powertop
Updates to PowerTOP[edit]
The changes are described here through "diff" between original and modified code. Consolidated patch containing the changes described below is available here.
Makefile[edit]
- Use CodeSourcery toolchain. (You will need to customize depending upon: the toolchain used, install location etc.)
-WARNFLAGS=-Wall -W -Wshadow -CFLAGS?=-O1 -g ${WARNFLAGS} -CC?=gcc +WARNFLAGS=-Wall -Wstrict-prototypes +INCPATH?=-I ../ncurses/include \ + -I ../ncurses/include/ncurses \ + -isystem /opt/codesourcery/2008q1/lib/gcc/arm-none-linux-gnueabi/4.2.3/include +LIBPATH?=-L ../ncurses/lib + +CFLAGS?=-march=armv7a -DOMAP3 -pipe -O1 -g ${WARNFLAGS} ${INCPATH} ${LIBPATH} + +CC=arm-none-linux-gnueabi-gcc
- Use
ncurses
instead ofncursesw
.
powertop: $(OBJS) Makefile powertop.h - $(CC) ${CFLAGS} $(OBJS) -lncursesw -o powertop + $(CC) ${CFLAGS} $(OBJS) -l ncurses -o powertop @(cd po/ && $(MAKE))
- Add new file
omapcstates.c
.
- sata.o xrandr.o ethernet.o cpufreqstats.o usb.o urbnum.o intelcstates.o + sata.o xrandr.o ethernet.o cpufreqstats.o usb.o urbnum.o intelcstates.o omapcstates.o
powertop.h[edit]
- Update maximum number of C-states and P-states supported in the Linux kernel.
#include <libintl.h> +#if defined(__I386__) +#define MAX_NUM_CSTATES 4 +#define MAX_NUM_PSTATES 5 + +#elif defined(OMAP3) +#define MAX_NUM_CSTATES 7 +#define MAX_NUM_PSTATES 5 + +#else +#error "No valid architecture is defined." +#endif
- Define number of lines required for C-state information.
+ +#define MAX_CSTATE_LINES (MAX_NUM_CSTATES + 3) +
- Use the constants defined above:
-extern char cstate_lines[12][200]; -extern char cpufreqstrings[5][80]; +extern char cstate_lines[MAX_CSTATE_LINES][200]; +extern char cpufreqstrings[MAX_NUM_PSTATES][80];
powertop.c[edit]
- Use constants defined in
powertop.h
instead of the magic numbers:
-char cstate_lines[12][200]; +char cstate_lines[MAX_CSTATE_LINES][200];
- topcstate = -4; + + topcstate = -(MAX_NUM_CSTATES); +
- for (i = 0; i < 8; i++) + + for (i = 0; i < MAX_NUM_CSTATES; i++)
- Insert function
print_omap3_cstates()
:
+ +#if defined (__I386__) print_intel_cstates(); +#elif defined (OMAP3) + print_omap3_cstates(); +#endif +
display.c[edit]
- Use constants defined in
powertop.h
instead of the magic numbers:
- for (i=0; i < 10; i++) { + for (i=0; i < MAX_CSTATE_LINES; i++) {
- if (strlen(cstate_lines[i]) && count <= 6) { + if (strlen(cstate_lines[i]) && count <= MAX_CSTATE_LINES) {
- for (i=0; i<5; i++) { + for (i=0; i < MAX_NUM_PSTATES; i++) {
- Use
MAX_NUM_CSTATES
to define sub-windows.
+ int yline = MAX_NUM_CSTATES; + getmaxyx(stdscr, maxy, maxx); zap_windows(); title_bar_window = subwin(stdscr, 1, maxx, 0, 0); - cstate_window = subwin(stdscr, 7, maxx, 2, 0); - wakeup_window = subwin(stdscr, 1, maxx, 9, 0); - acpi_power_window = subwin(stdscr, 2, maxx, 10, 0); - timerstat_window = subwin(stdscr, maxy-16, maxx, 12, 0); + + cstate_window = subwin(stdscr, (yline + 2), maxx, 2, 0); + wakeup_window = subwin(stdscr, 1, maxx, (yline + 5), 0); + acpi_power_window = subwin(stdscr, 2, maxx, (yline + 6), 0); + timerstat_window = subwin(stdscr, maxy-16, maxx, (yline + 8), 0); +
cpufreqstats.c[edit]
- Use constants defined in
powertop.h
:
-char cpufreqstrings[5][80]; +char cpufreqstrings[MAX_NUM_PSTATES][80]; +
omapcstates.c[edit]
- This is a new file.
/* * Copyright 2008, Texas Instruments Incorporated. * * This file prints the C states supported by the OMAP processor. * (Based on intelcstates.c) * * 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 */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <sys/types.h> #include <dirent.h> #include <ctype.h> #include "powertop.h" #if defined(OMAP3) /** * print_omap3_cstates() - Prints the list of supported C-states. * * This functions uses standard sysfs interface of the cpuidle framework * to extract the information of the C-states supported by the Linux * kernel. **/ void print_omap3_cstates(void) { DIR *dir; struct dirent *entry; dir = opendir("/sys/devices/system/cpu/cpu0/cpuidle"); if (dir) { printf(_("Supported C-states : ")); while ((entry = readdir(dir))) { if (strlen(entry->d_name) < 3) continue; printf("C%s ", entry->d_name); } printf("\n"); closedir(dir); } } #endif
Build[edit]
- Set the environment variables
CC
andCXX
.
$ setenv CC /opt/codesourcery/2008q1/bin/arm-none-linux-gnueabi-gcc $ setenv CXX /opt/codesourcery/2008q1/bin/arm-none-linux-gnueabi-g++
ncurses[edit]
- Change to directory
ncurses
and execute the command:
$ ./configure \ --host=arm-none-linux-gnueabi \ --target=arm-none-linux-gnueabi \ --with-shared \ --without-ada
- Build sources
$ make CROSS_COMPILE=arm-none-linux-gnueabi-
- Ready the package for installation on target system.
$ make install DESTDIR=/home/user/work/ncurses/_install
The contents of the directory _install
need to be copied on the
target filesystem.
PowerTOP[edit]
- Change to directory
powertop
and execute the command:
$ make CROSS_COMPILE=arm-none-linux-gnueabi-
The executable powertop
needs to be copied on target filesystem. The
directory /usr/local/bin
is a good choice for copying the executable.
Example session[edit]
Boot the OMAP3EVM with uImage
created earlier (with additional
instrumentation enabled).
- View list of supported arguments
$ powertop --help Usage: powertop [OPTION...] -d, --dump read wakeups once and print list of top offenders -t, --time=DOUBLE default time to gather data in seconds -h, --help Show this help message
- To start utility in interactive mode:
$ powertop