aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/hv/hv_kvp_daemon.c500
-rw-r--r--tools/perf/Documentation/perf-annotate.txt13
-rw-r--r--tools/perf/Documentation/perf-buildid-list.txt6
-rw-r--r--tools/perf/Documentation/perf-report.txt20
-rw-r--r--tools/perf/Documentation/perf-sched.txt6
-rw-r--r--tools/perf/Documentation/perf-script.txt7
-rw-r--r--tools/perf/Documentation/perf-stat.txt16
-rw-r--r--tools/perf/Documentation/perf-top.txt48
-rw-r--r--tools/perf/Documentation/perfconfig.example20
-rw-r--r--tools/perf/Makefile35
-rw-r--r--tools/perf/arch/arm/util/dwarf-regs.c3
-rw-r--r--tools/perf/arch/powerpc/Makefile1
-rw-r--r--tools/perf/arch/powerpc/util/header.c36
-rw-r--r--tools/perf/arch/x86/Makefile1
-rw-r--r--tools/perf/arch/x86/util/header.c59
-rw-r--r--tools/perf/builtin-annotate.c25
-rw-r--r--tools/perf/builtin-buildid-list.c52
-rw-r--r--tools/perf/builtin-diff.c2
-rw-r--r--tools/perf/builtin-lock.c8
-rw-r--r--tools/perf/builtin-probe.c14
-rw-r--r--tools/perf/builtin-record.c73
-rw-r--r--tools/perf/builtin-report.c43
-rw-r--r--tools/perf/builtin-sched.c24
-rw-r--r--tools/perf/builtin-script.c6
-rw-r--r--tools/perf/builtin-stat.c213
-rw-r--r--tools/perf/builtin-test.c8
-rw-r--r--tools/perf/builtin-top.c532
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/perf.c24
-rw-r--r--tools/perf/perf.h13
-rwxr-xr-xtools/perf/scripts/python/bin/net_dropmonitor-record2
-rwxr-xr-xtools/perf/scripts/python/bin/net_dropmonitor-report4
-rwxr-xr-xtools/perf/scripts/python/net_dropmonitor.py72
-rw-r--r--tools/perf/util/annotate.c20
-rw-r--r--tools/perf/util/annotate.h9
-rw-r--r--tools/perf/util/color.c2
-rw-r--r--tools/perf/util/config.c36
-rw-r--r--tools/perf/util/debug.c7
-rw-r--r--tools/perf/util/debug.h17
-rw-r--r--tools/perf/util/dwarf-aux.c210
-rw-r--r--tools/perf/util/dwarf-aux.h11
-rw-r--r--tools/perf/util/event.c5
-rw-r--r--tools/perf/util/event.h2
-rw-r--r--tools/perf/util/evlist.c73
-rw-r--r--tools/perf/util/evlist.h9
-rw-r--r--tools/perf/util/evsel.c101
-rw-r--r--tools/perf/util/evsel.h10
-rw-r--r--tools/perf/util/header.c1252
-rw-r--r--tools/perf/util/header.h29
-rw-r--r--tools/perf/util/hist.c446
-rw-r--r--tools/perf/util/hist.h62
-rw-r--r--tools/perf/util/include/linux/compiler.h2
-rw-r--r--tools/perf/util/map.c102
-rw-r--r--tools/perf/util/map.h42
-rw-r--r--tools/perf/util/parse-events.c8
-rw-r--r--tools/perf/util/probe-event.c16
-rw-r--r--tools/perf/util/probe-finder.c231
-rw-r--r--tools/perf/util/probe-finder.h2
-rw-r--r--tools/perf/util/python.c148
-rw-r--r--tools/perf/util/session.c65
-rw-r--r--tools/perf/util/session.h5
-rw-r--r--tools/perf/util/setup.py21
-rw-r--r--tools/perf/util/sort.c14
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/symbol.c224
-rw-r--r--tools/perf/util/symbol.h6
-rw-r--r--tools/perf/util/top.c141
-rw-r--r--tools/perf/util/top.h38
-rw-r--r--tools/perf/util/trace-event-info.c114
-rw-r--r--tools/perf/util/trace-event.h13
-rw-r--r--tools/perf/util/ui/browser.c429
-rw-r--r--tools/perf/util/ui/browser.h21
-rw-r--r--tools/perf/util/ui/browsers/annotate.c215
-rw-r--r--tools/perf/util/ui/browsers/hists.c351
-rw-r--r--tools/perf/util/ui/browsers/map.c6
-rw-r--r--tools/perf/util/ui/browsers/top.c213
-rw-r--r--tools/perf/util/ui/helpline.c16
-rw-r--r--tools/perf/util/ui/helpline.h5
-rw-r--r--tools/perf/util/ui/keysyms.h25
-rw-r--r--tools/perf/util/ui/libslang.h2
-rw-r--r--tools/perf/util/ui/progress.c65
-rw-r--r--tools/perf/util/ui/progress.h7
-rw-r--r--tools/perf/util/ui/setup.c121
-rw-r--r--tools/perf/util/ui/ui.h3
-rw-r--r--tools/perf/util/ui/util.c182
-rw-r--r--tools/perf/util/ui/util.h8
-rw-r--r--tools/power/cpupower/.gitignore22
-rw-r--r--tools/power/cpupower/Makefile280
-rw-r--r--tools/power/cpupower/README49
-rw-r--r--tools/power/cpupower/ToDo11
-rw-r--r--tools/power/cpupower/bench/Makefile29
-rw-r--r--tools/power/cpupower/bench/README-BENCH124
-rw-r--r--tools/power/cpupower/bench/benchmark.c194
-rw-r--r--tools/power/cpupower/bench/benchmark.h29
-rw-r--r--tools/power/cpupower/bench/config.h36
-rw-r--r--tools/power/cpupower/bench/cpufreq-bench_plot.sh104
-rw-r--r--tools/power/cpupower/bench/cpufreq-bench_script.sh101
-rw-r--r--tools/power/cpupower/bench/example.cfg11
-rw-r--r--tools/power/cpupower/bench/main.c202
-rw-r--r--tools/power/cpupower/bench/parse.c225
-rw-r--r--tools/power/cpupower/bench/parse.h53
-rw-r--r--tools/power/cpupower/bench/system.c191
-rw-r--r--tools/power/cpupower/bench/system.h29
-rw-r--r--tools/power/cpupower/debug/i386/Makefile20
-rw-r--r--tools/power/cpupower/debug/i386/centrino-decode.c113
-rw-r--r--tools/power/cpupower/debug/i386/dump_psb.c196
-rw-r--r--tools/power/cpupower/debug/i386/intel_gsic.c78
-rw-r--r--tools/power/cpupower/debug/i386/powernow-k8-decode.c96
-rw-r--r--tools/power/cpupower/debug/kernel/Makefile23
-rw-r--r--tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c113
-rw-r--r--tools/power/cpupower/debug/x86_64/Makefile14
-rw-r--r--tools/power/cpupower/lib/cpufreq.c208
-rw-r--r--tools/power/cpupower/lib/cpufreq.h223
-rw-r--r--tools/power/cpupower/lib/sysfs.c672
-rw-r--r--tools/power/cpupower/lib/sysfs.h31
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-info.176
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-set.154
-rw-r--r--tools/power/cpupower/man/cpupower-info.119
-rw-r--r--tools/power/cpupower/man/cpupower-monitor.1179
-rw-r--r--tools/power/cpupower/man/cpupower-set.1103
-rw-r--r--tools/power/cpupower/man/cpupower.172
-rw-r--r--tools/power/cpupower/po/cs.po944
-rw-r--r--tools/power/cpupower/po/de.po961
-rw-r--r--tools/power/cpupower/po/fr.po947
-rw-r--r--tools/power/cpupower/po/it.po961
-rw-r--r--tools/power/cpupower/po/pt.po957
-rw-r--r--tools/power/cpupower/utils/builtin.h11
-rw-r--r--tools/power/cpupower/utils/cpufreq-info.c668
-rw-r--r--tools/power/cpupower/utils/cpufreq-set.c331
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c222
-rw-r--r--tools/power/cpupower/utils/cpupower-info.c135
-rw-r--r--tools/power/cpupower/utils/cpupower-set.c134
-rw-r--r--tools/power/cpupower/utils/cpupower.c214
-rw-r--r--tools/power/cpupower/utils/helpers/amd.c137
-rw-r--r--tools/power/cpupower/utils/helpers/bitmask.c292
-rw-r--r--tools/power/cpupower/utils/helpers/bitmask.h33
-rw-r--r--tools/power/cpupower/utils/helpers/cpuid.c176
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h190
-rw-r--r--tools/power/cpupower/utils/helpers/misc.c27
-rw-r--r--tools/power/cpupower/utils/helpers/msr.c115
-rw-r--r--tools/power/cpupower/utils/helpers/pci.c44
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.c408
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.h30
-rw-r--r--tools/power/cpupower/utils/helpers/topology.c111
-rw-r--r--tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c338
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c196
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c440
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h68
-rw-r--r--tools/power/cpupower/utils/idle_monitor/idle_monitors.def7
-rw-r--r--tools/power/cpupower/utils/idle_monitor/idle_monitors.h18
-rw-r--r--tools/power/cpupower/utils/idle_monitor/mperf_monitor.c338
-rw-r--r--tools/power/cpupower/utils/idle_monitor/nhm_idle.c216
-rw-r--r--tools/power/cpupower/utils/idle_monitor/snb_idle.c190
-rwxr-xr-xtools/power/cpupower/utils/version-gen.sh35
-rw-r--r--tools/power/x86/turbostat/turbostat.c74
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c5
-rw-r--r--tools/slub/slabinfo.c69
-rwxr-xr-xtools/testing/ktest/ktest.pl1445
-rw-r--r--tools/testing/ktest/sample.conf288
159 files changed, 20835 insertions, 1971 deletions
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
new file mode 100644
index 000000000000..11224eddcdc2
--- /dev/null
+++ b/tools/hv/hv_kvp_daemon.c
@@ -0,0 +1,500 @@
1/*
2 * An implementation of key value pair (KVP) functionality for Linux.
3 *
4 *
5 * Copyright (C) 2010, Novell, Inc.
6 * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
15 * NON INFRINGEMENT. See the GNU General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/poll.h>
28#include <sys/utsname.h>
29#include <linux/types.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <unistd.h>
33#include <string.h>
34#include <errno.h>
35#include <arpa/inet.h>
36#include <linux/connector.h>
37#include <linux/netlink.h>
38#include <ifaddrs.h>
39#include <netdb.h>
40#include <syslog.h>
41
42/*
43 * KYS: TODO. Need to register these in the kernel.
44 *
45 * The following definitions are shared with the in-kernel component; do not
46 * change any of this without making the corresponding changes in
47 * the KVP kernel component.
48 */
49#define CN_KVP_IDX 0x9 /* MSFT KVP functionality */
50#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */
51#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */
52
53/*
54 * KVP protocol: The user mode component first registers with the
55 * the kernel component. Subsequently, the kernel component requests, data
56 * for the specified keys. In response to this message the user mode component
57 * fills in the value corresponding to the specified key. We overload the
58 * sequence field in the cn_msg header to define our KVP message types.
59 *
60 * We use this infrastructure for also supporting queries from user mode
61 * application for state that may be maintained in the KVP kernel component.
62 *
63 * XXXKYS: Have a shared header file between the user and kernel (TODO)
64 */
65
66enum kvp_op {
67 KVP_REGISTER = 0, /* Register the user mode component*/
68 KVP_KERNEL_GET, /*Kernel is requesting the value for the specified key*/
69 KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/
70 KVP_USER_GET, /*User is requesting the value for the specified key*/
71 KVP_USER_SET /*User is providing the value for the specified key*/
72};
73
74#define HV_KVP_EXCHANGE_MAX_KEY_SIZE 512
75#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE 2048
76
77struct hv_ku_msg {
78 __u32 kvp_index;
79 __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
80 __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */
81};
82
83enum key_index {
84 FullyQualifiedDomainName = 0,
85 IntegrationServicesVersion, /*This key is serviced in the kernel*/
86 NetworkAddressIPv4,
87 NetworkAddressIPv6,
88 OSBuildNumber,
89 OSName,
90 OSMajorVersion,
91 OSMinorVersion,
92 OSVersion,
93 ProcessorArchitecture
94};
95
96/*
97 * End of shared definitions.
98 */
99
100static char kvp_send_buffer[4096];
101static char kvp_recv_buffer[4096];
102static struct sockaddr_nl addr;
103
104static char *os_name = "";
105static char *os_major = "";
106static char *os_minor = "";
107static char *processor_arch;
108static char *os_build;
109static char *lic_version;
110static struct utsname uts_buf;
111
112void kvp_get_os_info(void)
113{
114 FILE *file;
115 char *p, buf[512];
116
117 uname(&uts_buf);
118 os_build = uts_buf.release;
119 processor_arch = uts_buf.machine;
120
121 /*
122 * The current windows host (win7) expects the build
123 * string to be of the form: x.y.z
124 * Strip additional information we may have.
125 */
126 p = strchr(os_build, '-');
127 if (p)
128 *p = '\0';
129
130 file = fopen("/etc/SuSE-release", "r");
131 if (file != NULL)
132 goto kvp_osinfo_found;
133 file = fopen("/etc/redhat-release", "r");
134 if (file != NULL)
135 goto kvp_osinfo_found;
136 /*
137 * Add code for other supported platforms.
138 */
139
140 /*
141 * We don't have information about the os.
142 */
143 os_name = uts_buf.sysname;
144 return;
145
146kvp_osinfo_found:
147 /* up to three lines */
148 p = fgets(buf, sizeof(buf), file);
149 if (p) {
150 p = strchr(buf, '\n');
151 if (p)
152 *p = '\0';
153 p = strdup(buf);
154 if (!p)
155 goto done;
156 os_name = p;
157
158 /* second line */
159 p = fgets(buf, sizeof(buf), file);
160 if (p) {
161 p = strchr(buf, '\n');
162 if (p)
163 *p = '\0';
164 p = strdup(buf);
165 if (!p)
166 goto done;
167 os_major = p;
168
169 /* third line */
170 p = fgets(buf, sizeof(buf), file);
171 if (p) {
172 p = strchr(buf, '\n');
173 if (p)
174 *p = '\0';
175 p = strdup(buf);
176 if (p)
177 os_minor = p;
178 }
179 }
180 }
181
182done:
183 fclose(file);
184 return;
185}
186
187static int
188kvp_get_ip_address(int family, char *buffer, int length)
189{
190 struct ifaddrs *ifap;
191 struct ifaddrs *curp;
192 int ipv4_len = strlen("255.255.255.255") + 1;
193 int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1;
194 int offset = 0;
195 const char *str;
196 char tmp[50];
197 int error = 0;
198
199 /*
200 * On entry into this function, the buffer is capable of holding the
201 * maximum key value (2048 bytes).
202 */
203
204 if (getifaddrs(&ifap)) {
205 strcpy(buffer, "getifaddrs failed\n");
206 return 1;
207 }
208
209 curp = ifap;
210 while (curp != NULL) {
211 if ((curp->ifa_addr != NULL) &&
212 (curp->ifa_addr->sa_family == family)) {
213 if (family == AF_INET) {
214 struct sockaddr_in *addr =
215 (struct sockaddr_in *) curp->ifa_addr;
216
217 str = inet_ntop(family, &addr->sin_addr,
218 tmp, 50);
219 if (str == NULL) {
220 strcpy(buffer, "inet_ntop failed\n");
221 error = 1;
222 goto getaddr_done;
223 }
224 if (offset == 0)
225 strcpy(buffer, tmp);
226 else
227 strcat(buffer, tmp);
228 strcat(buffer, ";");
229
230 offset += strlen(str) + 1;
231 if ((length - offset) < (ipv4_len + 1))
232 goto getaddr_done;
233
234 } else {
235
236 /*
237 * We only support AF_INET and AF_INET6
238 * and the list of addresses is separated by a ";".
239 */
240 struct sockaddr_in6 *addr =
241 (struct sockaddr_in6 *) curp->ifa_addr;
242
243 str = inet_ntop(family,
244 &addr->sin6_addr.s6_addr,
245 tmp, 50);
246 if (str == NULL) {
247 strcpy(buffer, "inet_ntop failed\n");
248 error = 1;
249 goto getaddr_done;
250 }
251 if (offset == 0)
252 strcpy(buffer, tmp);
253 else
254 strcat(buffer, tmp);
255 strcat(buffer, ";");
256 offset += strlen(str) + 1;
257 if ((length - offset) < (ipv6_len + 1))
258 goto getaddr_done;
259
260 }
261
262 }
263 curp = curp->ifa_next;
264 }
265
266getaddr_done:
267 freeifaddrs(ifap);
268 return error;
269}
270
271
272static int
273kvp_get_domain_name(char *buffer, int length)
274{
275 struct addrinfo hints, *info ;
276 int error = 0;
277
278 gethostname(buffer, length);
279 memset(&hints, 0, sizeof(hints));
280 hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */
281 hints.ai_socktype = SOCK_STREAM;
282 hints.ai_flags = AI_CANONNAME;
283
284 error = getaddrinfo(buffer, NULL, &hints, &info);
285 if (error != 0) {
286 strcpy(buffer, "getaddrinfo failed\n");
287 return error;
288 }
289 strcpy(buffer, info->ai_canonname);
290 freeaddrinfo(info);
291 return error;
292}
293
294static int
295netlink_send(int fd, struct cn_msg *msg)
296{
297 struct nlmsghdr *nlh;
298 unsigned int size;
299 struct msghdr message;
300 char buffer[64];
301 struct iovec iov[2];
302
303 size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
304
305 nlh = (struct nlmsghdr *)buffer;
306 nlh->nlmsg_seq = 0;
307 nlh->nlmsg_pid = getpid();
308 nlh->nlmsg_type = NLMSG_DONE;
309 nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
310 nlh->nlmsg_flags = 0;
311
312 iov[0].iov_base = nlh;
313 iov[0].iov_len = sizeof(*nlh);
314
315 iov[1].iov_base = msg;
316 iov[1].iov_len = size;
317
318 memset(&message, 0, sizeof(message));
319 message.msg_name = &addr;
320 message.msg_namelen = sizeof(addr);
321 message.msg_iov = iov;
322 message.msg_iovlen = 2;
323
324 return sendmsg(fd, &message, 0);
325}
326
327int main(void)
328{
329 int fd, len, sock_opt;
330 int error;
331 struct cn_msg *message;
332 struct pollfd pfd;
333 struct nlmsghdr *incoming_msg;
334 struct cn_msg *incoming_cn_msg;
335 struct hv_ku_msg *hv_msg;
336 char *p;
337 char *key_value;
338 char *key_name;
339
340 daemon(1, 0);
341 openlog("KVP", 0, LOG_USER);
342 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
343 /*
344 * Retrieve OS release information.
345 */
346 kvp_get_os_info();
347
348 fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
349 if (fd < 0) {
350 syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
351 exit(-1);
352 }
353 addr.nl_family = AF_NETLINK;
354 addr.nl_pad = 0;
355 addr.nl_pid = 0;
356 addr.nl_groups = CN_KVP_IDX;
357
358
359 error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
360 if (error < 0) {
361 syslog(LOG_ERR, "bind failed; error:%d", error);
362 close(fd);
363 exit(-1);
364 }
365 sock_opt = addr.nl_groups;
366 setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt));
367 /*
368 * Register ourselves with the kernel.
369 */
370 message = (struct cn_msg *)kvp_send_buffer;
371 message->id.idx = CN_KVP_IDX;
372 message->id.val = CN_KVP_VAL;
373 message->seq = KVP_REGISTER;
374 message->ack = 0;
375 message->len = 0;
376
377 len = netlink_send(fd, message);
378 if (len < 0) {
379 syslog(LOG_ERR, "netlink_send failed; error:%d", len);
380 close(fd);
381 exit(-1);
382 }
383
384 pfd.fd = fd;
385
386 while (1) {
387 pfd.events = POLLIN;
388 pfd.revents = 0;
389 poll(&pfd, 1, -1);
390
391 len = recv(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0);
392
393 if (len < 0) {
394 syslog(LOG_ERR, "recv failed; error:%d", len);
395 close(fd);
396 return -1;
397 }
398
399 incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
400 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
401
402 switch (incoming_cn_msg->seq) {
403 case KVP_REGISTER:
404 /*
405 * Driver is registering with us; stash away the version
406 * information.
407 */
408 p = (char *)incoming_cn_msg->data;
409 lic_version = malloc(strlen(p) + 1);
410 if (lic_version) {
411 strcpy(lic_version, p);
412 syslog(LOG_INFO, "KVP LIC Version: %s",
413 lic_version);
414 } else {
415 syslog(LOG_ERR, "malloc failed");
416 }
417 continue;
418
419 case KVP_KERNEL_GET:
420 break;
421 default:
422 continue;
423 }
424
425 hv_msg = (struct hv_ku_msg *)incoming_cn_msg->data;
426 key_name = (char *)hv_msg->kvp_key;
427 key_value = (char *)hv_msg->kvp_value;
428
429 switch (hv_msg->kvp_index) {
430 case FullyQualifiedDomainName:
431 kvp_get_domain_name(key_value,
432 HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
433 strcpy(key_name, "FullyQualifiedDomainName");
434 break;
435 case IntegrationServicesVersion:
436 strcpy(key_name, "IntegrationServicesVersion");
437 strcpy(key_value, lic_version);
438 break;
439 case NetworkAddressIPv4:
440 kvp_get_ip_address(AF_INET, key_value,
441 HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
442 strcpy(key_name, "NetworkAddressIPv4");
443 break;
444 case NetworkAddressIPv6:
445 kvp_get_ip_address(AF_INET6, key_value,
446 HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
447 strcpy(key_name, "NetworkAddressIPv6");
448 break;
449 case OSBuildNumber:
450 strcpy(key_value, os_build);
451 strcpy(key_name, "OSBuildNumber");
452 break;
453 case OSName:
454 strcpy(key_value, os_name);
455 strcpy(key_name, "OSName");
456 break;
457 case OSMajorVersion:
458 strcpy(key_value, os_major);
459 strcpy(key_name, "OSMajorVersion");
460 break;
461 case OSMinorVersion:
462 strcpy(key_value, os_minor);
463 strcpy(key_name, "OSMinorVersion");
464 break;
465 case OSVersion:
466 strcpy(key_value, os_build);
467 strcpy(key_name, "OSVersion");
468 break;
469 case ProcessorArchitecture:
470 strcpy(key_value, processor_arch);
471 strcpy(key_name, "ProcessorArchitecture");
472 break;
473 default:
474 strcpy(key_value, "Unknown Key");
475 /*
476 * We use a null key name to terminate enumeration.
477 */
478 strcpy(key_name, "");
479 break;
480 }
481 /*
482 * Send the value back to the kernel. The response is
483 * already in the receive buffer. Update the cn_msg header to
484 * reflect the key value that has been added to the message
485 */
486
487 incoming_cn_msg->id.idx = CN_KVP_IDX;
488 incoming_cn_msg->id.val = CN_KVP_VAL;
489 incoming_cn_msg->seq = KVP_USER_SET;
490 incoming_cn_msg->ack = 0;
491 incoming_cn_msg->len = sizeof(struct hv_ku_msg);
492
493 len = netlink_send(fd, incoming_cn_msg);
494 if (len < 0) {
495 syslog(LOG_ERR, "net_link send failed; error:%d", len);
496 exit(-1);
497 }
498 }
499
500}
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index 85c5f026930d..fe6762ed56bd 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -72,6 +72,19 @@ OPTIONS
72 CPUs are specified with -: 0-2. Default is to report samples on all 72 CPUs are specified with -: 0-2. Default is to report samples on all
73 CPUs. 73 CPUs.
74 74
75--asm-raw::
76 Show raw instruction encoding of assembly instructions.
77
78--source::
79 Interleave source code with assembly code. Enabled by default,
80 disable with --no-source.
81
82--symfs=<directory>::
83 Look for files with symbols relative to this directory.
84
85-M::
86--disassembler-style=:: Set disassembler style for objdump.
87
75SEE ALSO 88SEE ALSO
76-------- 89--------
77linkperf:perf-record[1], linkperf:perf-report[1] 90linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
index 5eaac6f26d51..cc22325ffd1b 100644
--- a/tools/perf/Documentation/perf-buildid-list.txt
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -16,6 +16,9 @@ This command displays the buildids found in a perf.data file, so that other
16tools can be used to fetch packages with matching symbol tables for use by 16tools can be used to fetch packages with matching symbol tables for use by
17perf report. 17perf report.
18 18
19It can also be used to show the build id of the running kernel or in an ELF
20file using -i/--input.
21
19OPTIONS 22OPTIONS
20------- 23-------
21-H:: 24-H::
@@ -27,6 +30,9 @@ OPTIONS
27-f:: 30-f::
28--force:: 31--force::
29 Don't do ownership validation. 32 Don't do ownership validation.
33-k::
34--kernel::
35 Show running kernel build id.
30-v:: 36-v::
31--verbose:: 37--verbose::
32 Be more verbose. 38 Be more verbose.
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 04253c07d19a..212f24d672e1 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -134,6 +134,24 @@ OPTIONS
134 CPUs are specified with -: 0-2. Default is to report samples on all 134 CPUs are specified with -: 0-2. Default is to report samples on all
135 CPUs. 135 CPUs.
136 136
137-M::
138--disassembler-style=:: Set disassembler style for objdump.
139
140--source::
141 Interleave source code with assembly code. Enabled by default,
142 disable with --no-source.
143
144--asm-raw::
145 Show raw instruction encoding of assembly instructions.
146
147--show-total-period:: Show a column with the sum of periods.
148
149-I::
150--show-info::
151 Display extended information about the perf.data file. This adds
152 information which may be very large and thus may clutter the display.
153 It currently includes: cpu and numa topology of the host system.
154
137SEE ALSO 155SEE ALSO
138-------- 156--------
139linkperf:perf-stat[1] 157linkperf:perf-stat[1], linkperf:perf-annotate[1]
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 46822d5fde1c..5b212b57f70b 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -8,7 +8,7 @@ perf-sched - Tool to trace/measure scheduler properties (latencies)
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf sched' {record|latency|map|replay|trace} 11'perf sched' {record|latency|map|replay|script}
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
@@ -20,8 +20,8 @@ There are five variants of perf sched:
20 'perf sched latency' to report the per task scheduling latencies 20 'perf sched latency' to report the per task scheduling latencies
21 and other scheduling properties of the workload. 21 and other scheduling properties of the workload.
22 22
23 'perf sched trace' to see a detailed trace of the workload that 23 'perf sched script' to see a detailed trace of the workload that
24 was recorded. 24 was recorded (aliased to 'perf script' for now).
25 25
26 'perf sched replay' to simulate the workload that was recorded 26 'perf sched replay' to simulate the workload that was recorded
27 via perf sched record. (this is done by starting up mockup threads 27 via perf sched record. (this is done by starting up mockup threads
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index db017867d9e8..dec87ecb530e 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -188,6 +188,13 @@ OPTIONS
188 CPUs are specified with -: 0-2. Default is to report samples on all 188 CPUs are specified with -: 0-2. Default is to report samples on all
189 CPUs. 189 CPUs.
190 190
191-I::
192--show-info::
193 Display extended information about the perf.data file. This adds
194 information which may be very large and thus may clutter the display.
195 It currently includes: cpu and numa topology of the host system.
196 It can only be used with the perf script report mode.
197
191SEE ALSO 198SEE ALSO
192-------- 199--------
193linkperf:perf-record[1], linkperf:perf-script-perl[1], 200linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 918cc38ee6d1..8966b9ab2014 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -94,6 +94,22 @@ an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must ha
94corresponding events, i.e., they always refer to events defined earlier on the command 94corresponding events, i.e., they always refer to events defined earlier on the command
95line. 95line.
96 96
97-o file::
98--output file::
99Print the output into the designated file.
100
101--append::
102Append to the output file designated with the -o option. Ignored if -o is not specified.
103
104--log-fd::
105
106Log output to fd, instead of stderr. Complementary to --output, and mutually exclusive
107with it. --append may be used here. Examples:
108 3>results perf stat --log-fd 3 -- $cmd
109 3>>results perf stat --log-fd 3 --append -- $cmd
110
111
112
97EXAMPLES 113EXAMPLES
98-------- 114--------
99 115
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index f6eb1cdafb77..b1a5bbbfebef 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -106,6 +106,51 @@ Default is to monitor all CPUS.
106--zero:: 106--zero::
107 Zero history across display updates. 107 Zero history across display updates.
108 108
109-s::
110--sort::
111 Sort by key(s): pid, comm, dso, symbol, parent
112
113-n::
114--show-nr-samples::
115 Show a column with the number of samples.
116
117--show-total-period::
118 Show a column with the sum of periods.
119
120--dsos::
121 Only consider symbols in these dsos.
122
123--comms::
124 Only consider symbols in these comms.
125
126--symbols::
127 Only consider these symbols.
128
129-M::
130--disassembler-style=:: Set disassembler style for objdump.
131
132--source::
133 Interleave source code with assembly code. Enabled by default,
134 disable with --no-source.
135
136--asm-raw::
137 Show raw instruction encoding of assembly instructions.
138
139-G [type,min,order]::
140--call-graph::
141 Display call chains using type, min percent threshold and order.
142 type can be either:
143 - flat: single column, linear exposure of call chains.
144 - graph: use a graph tree, displaying absolute overhead rates.
145 - fractal: like graph, but displays relative rates. Each branch of
146 the tree is considered as a new profiled object.
147
148 order can be either:
149 - callee: callee based call graph.
150 - caller: inverted caller based call graph.
151
152 Default: fractal,0.5,callee.
153
109INTERACTIVE PROMPTING KEYS 154INTERACTIVE PROMPTING KEYS
110-------------------------- 155--------------------------
111 156
@@ -130,9 +175,6 @@ INTERACTIVE PROMPTING KEYS
130[S]:: 175[S]::
131 Stop annotation, return to full profile display. 176 Stop annotation, return to full profile display.
132 177
133[w]::
134 Toggle between weighted sum and individual count[E]r profile.
135
136[z]:: 178[z]::
137 Toggle event count zeroing across display updates. 179 Toggle event count zeroing across display updates.
138 180
diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
new file mode 100644
index 000000000000..d1448668f4d4
--- /dev/null
+++ b/tools/perf/Documentation/perfconfig.example
@@ -0,0 +1,20 @@
1[colors]
2
3 # These were the old defaults
4 top = red, lightgray
5 medium = green, lightgray
6 normal = black, lightgray
7 selected = lightgray, magenta
8 code = blue, lightgray
9
10[tui]
11
12 # Defaults if linked with libslang
13 report = on
14 annotate = on
15 top = on
16
17[buildid]
18
19 # Default, disable using /dev/null
20 dir = /root/.debug
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 56d62d3fb167..b98e3075646b 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -30,6 +30,8 @@ endif
30# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. 30# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
31# 31#
32# Define NO_DWARF if you do not want debug-info analysis feature at all. 32# Define NO_DWARF if you do not want debug-info analysis feature at all.
33#
34# Define WERROR=0 to disable treating any warnings as errors.
33 35
34$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE 36$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
35 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) 37 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
@@ -63,6 +65,11 @@ ifeq ($(ARCH),x86_64)
63 endif 65 endif
64endif 66endif
65 67
68# Treat warnings as errors unless directed not to
69ifneq ($(WERROR),0)
70 CFLAGS_WERROR := -Werror
71endif
72
66# 73#
67# Include saner warnings here, which can catch bugs: 74# Include saner warnings here, which can catch bugs:
68# 75#
@@ -95,7 +102,7 @@ ifndef PERF_DEBUG
95 CFLAGS_OPTIMIZE = -O6 102 CFLAGS_OPTIMIZE = -O6
96endif 103endif
97 104
98CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 105CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
99EXTLIBS = -lpthread -lrt -lelf -lm 106EXTLIBS = -lpthread -lrt -lelf -lm
100ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 107ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
101ALL_LDFLAGS = $(LDFLAGS) 108ALL_LDFLAGS = $(LDFLAGS)
@@ -181,9 +188,9 @@ strip-libs = $(filter-out -l%,$(1))
181 188
182$(OUTPUT)python/perf.so: $(PYRF_OBJS) 189$(OUTPUT)python/perf.so: $(PYRF_OBJS)
183 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 190 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
184 --quiet build_ext \ 191 --quiet build_ext; \
185 --build-lib='$(OUTPUT)python' \ 192 mkdir -p $(OUTPUT)python && \
186 --build-temp='$(OUTPUT)python/temp' 193 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
187# 194#
188# No Perl scripts right now: 195# No Perl scripts right now:
189# 196#
@@ -459,13 +466,13 @@ else
459 LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o 466 LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o
460 LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o 467 LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o
461 LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o 468 LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o
462 LIB_OBJS += $(OUTPUT)util/ui/browsers/top.o
463 LIB_OBJS += $(OUTPUT)util/ui/helpline.o 469 LIB_OBJS += $(OUTPUT)util/ui/helpline.o
464 LIB_OBJS += $(OUTPUT)util/ui/progress.o 470 LIB_OBJS += $(OUTPUT)util/ui/progress.o
465 LIB_OBJS += $(OUTPUT)util/ui/util.o 471 LIB_OBJS += $(OUTPUT)util/ui/util.o
466 LIB_H += util/ui/browser.h 472 LIB_H += util/ui/browser.h
467 LIB_H += util/ui/browsers/map.h 473 LIB_H += util/ui/browsers/map.h
468 LIB_H += util/ui/helpline.h 474 LIB_H += util/ui/helpline.h
475 LIB_H += util/ui/keysyms.h
469 LIB_H += util/ui/libslang.h 476 LIB_H += util/ui/libslang.h
470 LIB_H += util/ui/progress.h 477 LIB_H += util/ui/progress.h
471 LIB_H += util/ui/util.h 478 LIB_H += util/ui/util.h
@@ -509,9 +516,13 @@ else
509 516
510 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 517 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
511 518
512 python-clean := $(PYTHON_WORD) util/setup.py clean \ 519 # python extension build directories
513 --build-lib='$(OUTPUT)python' \ 520 PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
514 --build-temp='$(OUTPUT)python/temp' 521 PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
522 PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
523 export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
524
525 python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
515 526
516 ifdef NO_LIBPYTHON 527 ifdef NO_LIBPYTHON
517 $(call disable-python) 528 $(call disable-python)
@@ -718,9 +729,6 @@ $(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS
718$(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS 729$(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
719 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 730 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
720 731
721$(OUTPUT)util/ui/browsers/top.o: util/ui/browsers/top.c $(OUTPUT)PERF-CFLAGS
722 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
723
724$(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS 732$(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
725 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 733 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
726 734
@@ -868,6 +876,9 @@ install: all
868 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python' 876 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
869 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 877 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
870 878
879install-python_ext:
880 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
881
871install-doc: 882install-doc:
872 $(MAKE) -C Documentation install 883 $(MAKE) -C Documentation install
873 884
@@ -895,7 +906,7 @@ quick-install-html:
895### Cleaning rules 906### Cleaning rules
896 907
897clean: 908clean:
898 $(RM) $(OUTPUT){*.o,*/*.o,*/*/*.o,*/*/*/*.o,$(LIB_FILE),perf-archive} 909 $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
899 $(RM) $(ALL_PROGRAMS) perf 910 $(RM) $(ALL_PROGRAMS) perf
900 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* 911 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
901 $(MAKE) -C Documentation/ clean 912 $(MAKE) -C Documentation/ clean
diff --git a/tools/perf/arch/arm/util/dwarf-regs.c b/tools/perf/arch/arm/util/dwarf-regs.c
index fff6450c8c99..e8d5c551c69c 100644
--- a/tools/perf/arch/arm/util/dwarf-regs.c
+++ b/tools/perf/arch/arm/util/dwarf-regs.c
@@ -8,7 +8,10 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <stdlib.h>
12#ifndef __UCLIBC__
11#include <libio.h> 13#include <libio.h>
14#endif
12#include <dwarf-regs.h> 15#include <dwarf-regs.h>
13 16
14struct pt_regs_dwarfnum { 17struct pt_regs_dwarfnum {
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 15130b50dfe3..744e629797be 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -2,3 +2,4 @@ ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 4endif
5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c
new file mode 100644
index 000000000000..eba80c292945
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/header.c
@@ -0,0 +1,36 @@
1#include <sys/types.h>
2#include <unistd.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7#include "../../util/header.h"
8
9#define __stringify_1(x) #x
10#define __stringify(x) __stringify_1(x)
11
12#define mfspr(rn) ({unsigned long rval; \
13 asm volatile("mfspr %0," __stringify(rn) \
14 : "=r" (rval)); rval; })
15
16#define SPRN_PVR 0x11F /* Processor Version Register */
17#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
18#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
19
20int
21get_cpuid(char *buffer, size_t sz)
22{
23 unsigned long pvr;
24 int nb;
25
26 pvr = mfspr(SPRN_PVR);
27
28 nb = snprintf(buffer, sz, "%lu,%lu$", PVR_VER(pvr), PVR_REV(pvr));
29
30 /* look for end marker to ensure the entire data fit */
31 if (strchr(buffer, '$')) {
32 buffer[nb-1] = '\0';
33 return 0;
34 }
35 return -1;
36}
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 15130b50dfe3..744e629797be 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -2,3 +2,4 @@ ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 4endif
5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
diff --git a/tools/perf/arch/x86/util/header.c b/tools/perf/arch/x86/util/header.c
new file mode 100644
index 000000000000..f94006068d2b
--- /dev/null
+++ b/tools/perf/arch/x86/util/header.c
@@ -0,0 +1,59 @@
1#include <sys/types.h>
2#include <unistd.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7#include "../../util/header.h"
8
9static inline void
10cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
11 unsigned int *d)
12{
13 __asm__ __volatile__ (".byte 0x53\n\tcpuid\n\t"
14 "movl %%ebx, %%esi\n\t.byte 0x5b"
15 : "=a" (*a),
16 "=S" (*b),
17 "=c" (*c),
18 "=d" (*d)
19 : "a" (op));
20}
21
22int
23get_cpuid(char *buffer, size_t sz)
24{
25 unsigned int a, b, c, d, lvl;
26 int family = -1, model = -1, step = -1;
27 int nb;
28 char vendor[16];
29
30 cpuid(0, &lvl, &b, &c, &d);
31 strncpy(&vendor[0], (char *)(&b), 4);
32 strncpy(&vendor[4], (char *)(&d), 4);
33 strncpy(&vendor[8], (char *)(&c), 4);
34 vendor[12] = '\0';
35
36 if (lvl >= 1) {
37 cpuid(1, &a, &b, &c, &d);
38
39 family = (a >> 8) & 0xf; /* bits 11 - 8 */
40 model = (a >> 4) & 0xf; /* Bits 7 - 4 */
41 step = a & 0xf;
42
43 /* extended family */
44 if (family == 0xf)
45 family += (a >> 20) & 0xff;
46
47 /* extended model */
48 if (family >= 0x6)
49 model += ((a >> 16) & 0xf) << 4;
50 }
51 nb = snprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step);
52
53 /* look for end marker to ensure the entire data fit */
54 if (strchr(buffer, '$')) {
55 buffer[nb-1] = '\0';
56 return 0;
57 }
58 return -1;
59}
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 555aefd7fe01..46b4c24f338e 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -114,10 +114,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
114 print_line, full_paths, 0, 0); 114 print_line, full_paths, 0, 0);
115} 115}
116 116
117static void hists__find_annotations(struct hists *self, int evidx) 117static void hists__find_annotations(struct hists *self, int evidx,
118 int nr_events)
118{ 119{
119 struct rb_node *nd = rb_first(&self->entries), *next; 120 struct rb_node *nd = rb_first(&self->entries), *next;
120 int key = KEY_RIGHT; 121 int key = K_RIGHT;
121 122
122 while (nd) { 123 while (nd) {
123 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); 124 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
@@ -129,7 +130,7 @@ static void hists__find_annotations(struct hists *self, int evidx)
129 notes = symbol__annotation(he->ms.sym); 130 notes = symbol__annotation(he->ms.sym);
130 if (notes->src == NULL) { 131 if (notes->src == NULL) {
131find_next: 132find_next:
132 if (key == KEY_LEFT) 133 if (key == K_LEFT)
133 nd = rb_prev(nd); 134 nd = rb_prev(nd);
134 else 135 else
135 nd = rb_next(nd); 136 nd = rb_next(nd);
@@ -137,12 +138,13 @@ find_next:
137 } 138 }
138 139
139 if (use_browser > 0) { 140 if (use_browser > 0) {
140 key = hist_entry__tui_annotate(he, evidx); 141 key = hist_entry__tui_annotate(he, evidx, nr_events,
142 NULL, NULL, 0);
141 switch (key) { 143 switch (key) {
142 case KEY_RIGHT: 144 case K_RIGHT:
143 next = rb_next(nd); 145 next = rb_next(nd);
144 break; 146 break;
145 case KEY_LEFT: 147 case K_LEFT:
146 next = rb_prev(nd); 148 next = rb_prev(nd);
147 break; 149 break;
148 default: 150 default:
@@ -215,7 +217,8 @@ static int __cmd_annotate(void)
215 total_nr_samples += nr_samples; 217 total_nr_samples += nr_samples;
216 hists__collapse_resort(hists); 218 hists__collapse_resort(hists);
217 hists__output_resort(hists); 219 hists__output_resort(hists);
218 hists__find_annotations(hists, pos->idx); 220 hists__find_annotations(hists, pos->idx,
221 session->evlist->nr_entries);
219 } 222 }
220 } 223 }
221 224
@@ -267,6 +270,14 @@ static const struct option options[] = {
267 OPT_BOOLEAN('P', "full-paths", &full_paths, 270 OPT_BOOLEAN('P', "full-paths", &full_paths,
268 "Don't shorten the displayed pathnames"), 271 "Don't shorten the displayed pathnames"),
269 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 272 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
273 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
274 "Look for files with symbols relative to this directory"),
275 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
276 "Interleave source code with assembly code (default)"),
277 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
278 "Display raw encoding of assembly instructions (default)"),
279 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
280 "Specify disassembler style (e.g. -M intel for intel syntax)"),
270 OPT_END() 281 OPT_END()
271}; 282};
272 283
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 5af32ae9031e..cb690a65bf02 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -1,7 +1,8 @@
1/* 1/*
2 * builtin-buildid-list.c 2 * builtin-buildid-list.c
3 * 3 *
4 * Builtin buildid-list command: list buildids in perf.data 4 * Builtin buildid-list command: list buildids in perf.data, in the running
5 * kernel and in ELF files.
5 * 6 *
6 * Copyright (C) 2009, Red Hat Inc. 7 * Copyright (C) 2009, Red Hat Inc.
7 * Copyright (C) 2009, Arnaldo Carvalho de Melo <acme@redhat.com> 8 * Copyright (C) 2009, Arnaldo Carvalho de Melo <acme@redhat.com>
@@ -15,8 +16,11 @@
15#include "util/session.h" 16#include "util/session.h"
16#include "util/symbol.h" 17#include "util/symbol.h"
17 18
19#include <libelf.h>
20
18static char const *input_name = "perf.data"; 21static char const *input_name = "perf.data";
19static bool force; 22static bool force;
23static bool show_kernel;
20static bool with_hits; 24static bool with_hits;
21 25
22static const char * const buildid_list_usage[] = { 26static const char * const buildid_list_usage[] = {
@@ -29,12 +33,13 @@ static const struct option options[] = {
29 OPT_STRING('i', "input", &input_name, "file", 33 OPT_STRING('i', "input", &input_name, "file",
30 "input file name"), 34 "input file name"),
31 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 35 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
36 OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
32 OPT_INCR('v', "verbose", &verbose, 37 OPT_INCR('v', "verbose", &verbose,
33 "be more verbose"), 38 "be more verbose"),
34 OPT_END() 39 OPT_END()
35}; 40};
36 41
37static int __cmd_buildid_list(void) 42static int perf_session__list_build_ids(void)
38{ 43{
39 struct perf_session *session; 44 struct perf_session *session;
40 45
@@ -52,6 +57,49 @@ static int __cmd_buildid_list(void)
52 return 0; 57 return 0;
53} 58}
54 59
60static int sysfs__fprintf_build_id(FILE *fp)
61{
62 u8 kallsyms_build_id[BUILD_ID_SIZE];
63 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
64
65 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
66 sizeof(kallsyms_build_id)) != 0)
67 return -1;
68
69 build_id__sprintf(kallsyms_build_id, sizeof(kallsyms_build_id),
70 sbuild_id);
71 fprintf(fp, "%s\n", sbuild_id);
72 return 0;
73}
74
75static int filename__fprintf_build_id(const char *name, FILE *fp)
76{
77 u8 build_id[BUILD_ID_SIZE];
78 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
79
80 if (filename__read_build_id(name, build_id,
81 sizeof(build_id)) != sizeof(build_id))
82 return 0;
83
84 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
85 return fprintf(fp, "%s\n", sbuild_id);
86}
87
88static int __cmd_buildid_list(void)
89{
90 if (show_kernel)
91 return sysfs__fprintf_build_id(stdout);
92
93 elf_version(EV_CURRENT);
94 /*
95 * See if this is an ELF file first:
96 */
97 if (filename__fprintf_build_id(input_name, stdout))
98 return 0;
99
100 return perf_session__list_build_ids();
101}
102
55int cmd_buildid_list(int argc, const char **argv, const char *prefix __used) 103int cmd_buildid_list(int argc, const char **argv, const char *prefix __used)
56{ 104{
57 argc = parse_options(argc, argv, options, buildid_list_usage, 0); 105 argc = parse_options(argc, argv, options, buildid_list_usage, 0);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index e8219990f8b8..b39f3a1ee7dc 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -162,7 +162,7 @@ static int __cmd_diff(void)
162 162
163 hists__match(&session[0]->hists, &session[1]->hists); 163 hists__match(&session[0]->hists, &session[1]->hists);
164 hists__fprintf(&session[1]->hists, &session[0]->hists, 164 hists__fprintf(&session[1]->hists, &session[0]->hists,
165 show_displacement, stdout); 165 show_displacement, true, 0, 0, stdout);
166out_delete: 166out_delete:
167 for (i = 0; i < 2; ++i) 167 for (i = 0; i < 2; ++i)
168 perf_session__delete(session[i]); 168 perf_session__delete(session[i]);
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 9ac05aafd9b2..899080ace267 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -942,10 +942,10 @@ static const char *record_args[] = {
942 "-f", 942 "-f",
943 "-m", "1024", 943 "-m", "1024",
944 "-c", "1", 944 "-c", "1",
945 "-e", "lock:lock_acquire:r", 945 "-e", "lock:lock_acquire",
946 "-e", "lock:lock_acquired:r", 946 "-e", "lock:lock_acquired",
947 "-e", "lock:lock_contended:r", 947 "-e", "lock:lock_contended",
948 "-e", "lock:lock_release:r", 948 "-e", "lock:lock_release",
949}; 949};
950 950
951static int __cmd_record(int argc, const char **argv) 951static int __cmd_record(int argc, const char **argv)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 5f2a5c7046df..710ae3d0a489 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -134,10 +134,18 @@ static int opt_show_lines(const struct option *opt __used,
134{ 134{
135 int ret = 0; 135 int ret = 0;
136 136
137 if (str) 137 if (!str)
138 ret = parse_line_range_desc(str, &params.line_range); 138 return 0;
139 INIT_LIST_HEAD(&params.line_range.line_list); 139
140 if (params.show_lines) {
141 pr_warning("Warning: more than one --line options are"
142 " detected. Only the first one is valid.\n");
143 return 0;
144 }
145
140 params.show_lines = true; 146 params.show_lines = true;
147 ret = parse_line_range_desc(str, &params.line_range);
148 INIT_LIST_HEAD(&params.line_range.line_list);
141 149
142 return ret; 150 return ret;
143} 151}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 80dc5b790e47..6ab58cc99d53 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -30,8 +30,6 @@
30#include <sched.h> 30#include <sched.h>
31#include <sys/mman.h> 31#include <sys/mman.h>
32 32
33#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
34
35enum write_mode_t { 33enum write_mode_t {
36 WRITE_FORCE, 34 WRITE_FORCE,
37 WRITE_APPEND 35 WRITE_APPEND
@@ -47,7 +45,7 @@ static int freq = 1000;
47static int output; 45static int output;
48static int pipe_output = 0; 46static int pipe_output = 0;
49static const char *output_name = NULL; 47static const char *output_name = NULL;
50static int group = 0; 48static bool group = false;
51static int realtime_prio = 0; 49static int realtime_prio = 0;
52static bool nodelay = false; 50static bool nodelay = false;
53static bool raw_samples = false; 51static bool raw_samples = false;
@@ -75,6 +73,7 @@ static off_t post_processing_offset;
75 73
76static struct perf_session *session; 74static struct perf_session *session;
77static const char *cpu_list; 75static const char *cpu_list;
76static const char *progname;
78 77
79static void advance_output(size_t size) 78static void advance_output(size_t size)
80{ 79{
@@ -139,17 +138,29 @@ static void mmap_read(struct perf_mmap *md)
139 138
140static volatile int done = 0; 139static volatile int done = 0;
141static volatile int signr = -1; 140static volatile int signr = -1;
141static volatile int child_finished = 0;
142 142
143static void sig_handler(int sig) 143static void sig_handler(int sig)
144{ 144{
145 if (sig == SIGCHLD)
146 child_finished = 1;
147
145 done = 1; 148 done = 1;
146 signr = sig; 149 signr = sig;
147} 150}
148 151
149static void sig_atexit(void) 152static void sig_atexit(void)
150{ 153{
151 if (child_pid > 0) 154 int status;
152 kill(child_pid, SIGTERM); 155
156 if (child_pid > 0) {
157 if (!child_finished)
158 kill(child_pid, SIGTERM);
159
160 wait(&status);
161 if (WIFSIGNALED(status))
162 psignal(WTERMSIG(status), progname);
163 }
153 164
154 if (signr == -1 || signr == SIGUSR1) 165 if (signr == -1 || signr == SIGUSR1)
155 return; 166 return;
@@ -163,6 +174,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
163 struct perf_event_attr *attr = &evsel->attr; 174 struct perf_event_attr *attr = &evsel->attr;
164 int track = !evsel->idx; /* only the first counter needs these */ 175 int track = !evsel->idx; /* only the first counter needs these */
165 176
177 attr->disabled = 1;
166 attr->inherit = !no_inherit; 178 attr->inherit = !no_inherit;
167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 179 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
168 PERF_FORMAT_TOTAL_TIME_RUNNING | 180 PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -250,13 +262,16 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
250 262
251static void open_counters(struct perf_evlist *evlist) 263static void open_counters(struct perf_evlist *evlist)
252{ 264{
253 struct perf_evsel *pos; 265 struct perf_evsel *pos, *first;
254 266
255 if (evlist->cpus->map[0] < 0) 267 if (evlist->cpus->map[0] < 0)
256 no_inherit = true; 268 no_inherit = true;
257 269
270 first = list_entry(evlist->entries.next, struct perf_evsel, node);
271
258 list_for_each_entry(pos, &evlist->entries, node) { 272 list_for_each_entry(pos, &evlist->entries, node) {
259 struct perf_event_attr *attr = &pos->attr; 273 struct perf_event_attr *attr = &pos->attr;
274 struct xyarray *group_fd = NULL;
260 /* 275 /*
261 * Check if parse_single_tracepoint_event has already asked for 276 * Check if parse_single_tracepoint_event has already asked for
262 * PERF_SAMPLE_TIME. 277 * PERF_SAMPLE_TIME.
@@ -271,15 +286,19 @@ static void open_counters(struct perf_evlist *evlist)
271 */ 286 */
272 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 287 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
273 288
289 if (group && pos != first)
290 group_fd = first->fd;
291
274 config_attr(pos, evlist); 292 config_attr(pos, evlist);
275retry_sample_id: 293retry_sample_id:
276 attr->sample_id_all = sample_id_all_avail ? 1 : 0; 294 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
277try_again: 295try_again:
278 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) { 296 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
297 group_fd) < 0) {
279 int err = errno; 298 int err = errno;
280 299
281 if (err == EPERM || err == EACCES) { 300 if (err == EPERM || err == EACCES) {
282 ui__warning_paranoid(); 301 ui__error_paranoid();
283 exit(EXIT_FAILURE); 302 exit(EXIT_FAILURE);
284 } else if (err == ENODEV && cpu_list) { 303 } else if (err == ENODEV && cpu_list) {
285 die("No such device - did you specify" 304 die("No such device - did you specify"
@@ -438,7 +457,6 @@ static void mmap_read_all(void)
438 457
439static int __cmd_record(int argc, const char **argv) 458static int __cmd_record(int argc, const char **argv)
440{ 459{
441 int i;
442 struct stat st; 460 struct stat st;
443 int flags; 461 int flags;
444 int err; 462 int err;
@@ -448,6 +466,8 @@ static int __cmd_record(int argc, const char **argv)
448 char buf; 466 char buf;
449 struct machine *machine; 467 struct machine *machine;
450 468
469 progname = argv[0];
470
451 page_size = sysconf(_SC_PAGE_SIZE); 471 page_size = sysconf(_SC_PAGE_SIZE);
452 472
453 atexit(sig_atexit); 473 atexit(sig_atexit);
@@ -516,6 +536,19 @@ static int __cmd_record(int argc, const char **argv)
516 if (have_tracepoints(&evsel_list->entries)) 536 if (have_tracepoints(&evsel_list->entries))
517 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 537 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
518 538
539 perf_header__set_feat(&session->header, HEADER_HOSTNAME);
540 perf_header__set_feat(&session->header, HEADER_OSRELEASE);
541 perf_header__set_feat(&session->header, HEADER_ARCH);
542 perf_header__set_feat(&session->header, HEADER_CPUDESC);
543 perf_header__set_feat(&session->header, HEADER_NRCPUS);
544 perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
545 perf_header__set_feat(&session->header, HEADER_CMDLINE);
546 perf_header__set_feat(&session->header, HEADER_VERSION);
547 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
548 perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
549 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
550 perf_header__set_feat(&session->header, HEADER_CPUID);
551
519 /* 512 kiB: default amount of unprivileged mlocked memory */ 552 /* 512 kiB: default amount of unprivileged mlocked memory */
520 if (mmap_pages == UINT_MAX) 553 if (mmap_pages == UINT_MAX)
521 mmap_pages = (512 * 1024) / page_size; 554 mmap_pages = (512 * 1024) / page_size;
@@ -674,6 +707,8 @@ static int __cmd_record(int argc, const char **argv)
674 } 707 }
675 } 708 }
676 709
710 perf_evlist__enable(evsel_list);
711
677 /* 712 /*
678 * Let the child rip 713 * Let the child rip
679 */ 714 */
@@ -682,7 +717,6 @@ static int __cmd_record(int argc, const char **argv)
682 717
683 for (;;) { 718 for (;;) {
684 int hits = samples; 719 int hits = samples;
685 int thread;
686 720
687 mmap_read_all(); 721 mmap_read_all();
688 722
@@ -693,19 +727,8 @@ static int __cmd_record(int argc, const char **argv)
693 waking++; 727 waking++;
694 } 728 }
695 729
696 if (done) { 730 if (done)
697 for (i = 0; i < evsel_list->cpus->nr; i++) { 731 perf_evlist__disable(evsel_list);
698 struct perf_evsel *pos;
699
700 list_for_each_entry(pos, &evsel_list->entries, node) {
701 for (thread = 0;
702 thread < evsel_list->threads->nr;
703 thread++)
704 ioctl(FD(pos, i, thread),
705 PERF_EVENT_IOC_DISABLE);
706 }
707 }
708 }
709 } 732 }
710 733
711 if (quiet || signr == SIGUSR1) 734 if (quiet || signr == SIGUSR1)
@@ -768,6 +791,8 @@ const struct option record_options[] = {
768 "child tasks do not inherit counters"), 791 "child tasks do not inherit counters"),
769 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), 792 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
770 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 793 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
794 OPT_BOOLEAN(0, "group", &group,
795 "put the counters into a counter group"),
771 OPT_BOOLEAN('g', "call-graph", &call_graph, 796 OPT_BOOLEAN('g', "call-graph", &call_graph,
772 "do call-graph (stack chain/backtrace) recording"), 797 "do call-graph (stack chain/backtrace) recording"),
773 OPT_INCR('v', "verbose", &verbose, 798 OPT_INCR('v', "verbose", &verbose,
@@ -795,6 +820,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
795 int err = -ENOMEM; 820 int err = -ENOMEM;
796 struct perf_evsel *pos; 821 struct perf_evsel *pos;
797 822
823 perf_header__set_cmdline(argc, argv);
824
798 evsel_list = perf_evlist__new(NULL, NULL); 825 evsel_list = perf_evlist__new(NULL, NULL);
799 if (evsel_list == NULL) 826 if (evsel_list == NULL)
800 return -ENOMEM; 827 return -ENOMEM;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f854efda7686..4d7c8340c326 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -40,6 +40,7 @@ static char const *input_name = "perf.data";
40static bool force, use_tui, use_stdio; 40static bool force, use_tui, use_stdio;
41static bool hide_unresolved; 41static bool hide_unresolved;
42static bool dont_use_callchains; 42static bool dont_use_callchains;
43static bool show_full_info;
43 44
44static bool show_threads; 45static bool show_threads;
45static struct perf_read_values show_threads_values; 46static struct perf_read_values show_threads_values;
@@ -162,23 +163,22 @@ static int perf_session__setup_sample_type(struct perf_session *self)
162{ 163{
163 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { 164 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
164 if (sort__has_parent) { 165 if (sort__has_parent) {
165 fprintf(stderr, "selected --sort parent, but no" 166 ui__warning("Selected --sort parent, but no "
166 " callchain data. Did you call" 167 "callchain data. Did you call "
167 " perf record without -g?\n"); 168 "'perf record' without -g?\n");
168 return -EINVAL; 169 return -EINVAL;
169 } 170 }
170 if (symbol_conf.use_callchain) { 171 if (symbol_conf.use_callchain) {
171 fprintf(stderr, "selected -g but no callchain data." 172 ui__warning("Selected -g but no callchain data. Did "
172 " Did you call perf record without" 173 "you call 'perf record' without -g?\n");
173 " -g?\n");
174 return -1; 174 return -1;
175 } 175 }
176 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE && 176 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE &&
177 !symbol_conf.use_callchain) { 177 !symbol_conf.use_callchain) {
178 symbol_conf.use_callchain = true; 178 symbol_conf.use_callchain = true;
179 if (callchain_register_param(&callchain_param) < 0) { 179 if (callchain_register_param(&callchain_param) < 0) {
180 fprintf(stderr, "Can't register callchain" 180 ui__warning("Can't register callchain "
181 " params\n"); 181 "params.\n");
182 return -EINVAL; 182 return -EINVAL;
183 } 183 }
184 } 184 }
@@ -230,13 +230,10 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
230 230
231 list_for_each_entry(pos, &evlist->entries, node) { 231 list_for_each_entry(pos, &evlist->entries, node) {
232 struct hists *hists = &pos->hists; 232 struct hists *hists = &pos->hists;
233 const char *evname = NULL; 233 const char *evname = event_name(pos);
234
235 if (rb_first(&hists->entries) != rb_last(&hists->entries))
236 evname = event_name(pos);
237 234
238 hists__fprintf_nr_sample_events(hists, evname, stdout); 235 hists__fprintf_nr_sample_events(hists, evname, stdout);
239 hists__fprintf(hists, NULL, false, stdout); 236 hists__fprintf(hists, NULL, false, true, 0, 0, stdout);
240 fprintf(stdout, "\n\n"); 237 fprintf(stdout, "\n\n");
241 } 238 }
242 239
@@ -277,6 +274,9 @@ static int __cmd_report(void)
277 goto out_delete; 274 goto out_delete;
278 } 275 }
279 276
277 if (use_browser <= 0)
278 perf_session__fprintf_info(session, stdout, show_full_info);
279
280 if (show_threads) 280 if (show_threads)
281 perf_read_values_init(&show_threads_values); 281 perf_read_values_init(&show_threads_values);
282 282
@@ -331,9 +331,10 @@ static int __cmd_report(void)
331 goto out_delete; 331 goto out_delete;
332 } 332 }
333 333
334 if (use_browser > 0) 334 if (use_browser > 0) {
335 perf_evlist__tui_browse_hists(session->evlist, help); 335 perf_evlist__tui_browse_hists(session->evlist, help,
336 else 336 NULL, NULL, 0);
337 } else
337 perf_evlist__tty_browse_hists(session->evlist, help); 338 perf_evlist__tty_browse_hists(session->evlist, help);
338 339
339out_delete: 340out_delete:
@@ -488,6 +489,16 @@ static const struct option options[] = {
488 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 489 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
489 "Look for files with symbols relative to this directory"), 490 "Look for files with symbols relative to this directory"),
490 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 491 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
492 OPT_BOOLEAN('I', "show-info", &show_full_info,
493 "Display extended information about perf.data file"),
494 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
495 "Interleave source code with assembly code (default)"),
496 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
497 "Display raw encoding of assembly instructions (default)"),
498 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
499 "Specify disassembler style (e.g. -M intel for intel syntax)"),
500 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
501 "Show a column with the sum of periods"),
491 OPT_END() 502 OPT_END()
492}; 503};
493 504
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index dcfe8873c9a1..5177964943e7 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1637,23 +1637,29 @@ static struct perf_event_ops event_ops = {
1637 .ordered_samples = true, 1637 .ordered_samples = true,
1638}; 1638};
1639 1639
1640static int read_events(void) 1640static void read_events(bool destroy, struct perf_session **psession)
1641{ 1641{
1642 int err = -EINVAL; 1642 int err = -EINVAL;
1643 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 1643 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1644 0, false, &event_ops); 1644 0, false, &event_ops);
1645 if (session == NULL) 1645 if (session == NULL)
1646 return -ENOMEM; 1646 die("No Memory");
1647 1647
1648 if (perf_session__has_traces(session, "record -R")) { 1648 if (perf_session__has_traces(session, "record -R")) {
1649 err = perf_session__process_events(session, &event_ops); 1649 err = perf_session__process_events(session, &event_ops);
1650 if (err)
1651 die("Failed to process events, error %d", err);
1652
1650 nr_events = session->hists.stats.nr_events[0]; 1653 nr_events = session->hists.stats.nr_events[0];
1651 nr_lost_events = session->hists.stats.total_lost; 1654 nr_lost_events = session->hists.stats.total_lost;
1652 nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; 1655 nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST];
1653 } 1656 }
1654 1657
1655 perf_session__delete(session); 1658 if (destroy)
1656 return err; 1659 perf_session__delete(session);
1660
1661 if (psession)
1662 *psession = session;
1657} 1663}
1658 1664
1659static void print_bad_events(void) 1665static void print_bad_events(void)
@@ -1689,9 +1695,10 @@ static void print_bad_events(void)
1689static void __cmd_lat(void) 1695static void __cmd_lat(void)
1690{ 1696{
1691 struct rb_node *next; 1697 struct rb_node *next;
1698 struct perf_session *session;
1692 1699
1693 setup_pager(); 1700 setup_pager();
1694 read_events(); 1701 read_events(false, &session);
1695 sort_lat(); 1702 sort_lat();
1696 1703
1697 printf("\n ---------------------------------------------------------------------------------------------------------------\n"); 1704 printf("\n ---------------------------------------------------------------------------------------------------------------\n");
@@ -1717,6 +1724,7 @@ static void __cmd_lat(void)
1717 print_bad_events(); 1724 print_bad_events();
1718 printf("\n"); 1725 printf("\n");
1719 1726
1727 perf_session__delete(session);
1720} 1728}
1721 1729
1722static struct trace_sched_handler map_ops = { 1730static struct trace_sched_handler map_ops = {
@@ -1731,7 +1739,7 @@ static void __cmd_map(void)
1731 max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1739 max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1732 1740
1733 setup_pager(); 1741 setup_pager();
1734 read_events(); 1742 read_events(true, NULL);
1735 print_bad_events(); 1743 print_bad_events();
1736} 1744}
1737 1745
@@ -1744,7 +1752,7 @@ static void __cmd_replay(void)
1744 1752
1745 test_calibrations(); 1753 test_calibrations();
1746 1754
1747 read_events(); 1755 read_events(true, NULL);
1748 1756
1749 printf("nr_run_events: %ld\n", nr_run_events); 1757 printf("nr_run_events: %ld\n", nr_run_events);
1750 printf("nr_sleep_events: %ld\n", nr_sleep_events); 1758 printf("nr_sleep_events: %ld\n", nr_sleep_events);
@@ -1769,7 +1777,7 @@ static void __cmd_replay(void)
1769 1777
1770 1778
1771static const char * const sched_usage[] = { 1779static const char * const sched_usage[] = {
1772 "perf sched [<options>] {record|latency|map|replay|trace}", 1780 "perf sched [<options>] {record|latency|map|replay|script}",
1773 NULL 1781 NULL
1774}; 1782};
1775 1783
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 09024ec2ab2e..2f62a2952269 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -22,6 +22,7 @@ static u64 last_timestamp;
22static u64 nr_unordered; 22static u64 nr_unordered;
23extern const struct option record_options[]; 23extern const struct option record_options[];
24static bool no_callchain; 24static bool no_callchain;
25static bool show_full_info;
25static const char *cpu_list; 26static const char *cpu_list;
26static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 27static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
27 28
@@ -1083,7 +1084,8 @@ static const struct option options[] = {
1083 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr", 1084 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
1084 parse_output_fields), 1085 parse_output_fields),
1085 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 1086 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
1086 1087 OPT_BOOLEAN('I', "show-info", &show_full_info,
1088 "display extended information from perf.data file"),
1087 OPT_END() 1089 OPT_END()
1088}; 1090};
1089 1091
@@ -1268,6 +1270,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1268 return -1; 1270 return -1;
1269 } 1271 }
1270 1272
1273 perf_session__fprintf_info(session, stdout, show_full_info);
1274
1271 if (!no_callchain) 1275 if (!no_callchain)
1272 symbol_conf.use_callchain = true; 1276 symbol_conf.use_callchain = true;
1273 else 1277 else
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1ad04ce29c34..7d98676808d8 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -193,6 +193,10 @@ static int big_num_opt = -1;
193static const char *cpu_list; 193static const char *cpu_list;
194static const char *csv_sep = NULL; 194static const char *csv_sep = NULL;
195static bool csv_output = false; 195static bool csv_output = false;
196static bool group = false;
197static const char *output_name = NULL;
198static FILE *output = NULL;
199static int output_fd;
196 200
197static volatile int done = 0; 201static volatile int done = 0;
198 202
@@ -250,8 +254,13 @@ static double avg_stats(struct stats *stats)
250 */ 254 */
251static double stddev_stats(struct stats *stats) 255static double stddev_stats(struct stats *stats)
252{ 256{
253 double variance = stats->M2 / (stats->n - 1); 257 double variance, variance_mean;
254 double variance_mean = variance / stats->n; 258
259 if (!stats->n)
260 return 0.0;
261
262 variance = stats->M2 / (stats->n - 1);
263 variance_mean = variance / stats->n;
255 264
256 return sqrt(variance_mean); 265 return sqrt(variance_mean);
257} 266}
@@ -269,9 +278,14 @@ struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
269struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; 278struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
270struct stats walltime_nsecs_stats; 279struct stats walltime_nsecs_stats;
271 280
272static int create_perf_stat_counter(struct perf_evsel *evsel) 281static int create_perf_stat_counter(struct perf_evsel *evsel,
282 struct perf_evsel *first)
273{ 283{
274 struct perf_event_attr *attr = &evsel->attr; 284 struct perf_event_attr *attr = &evsel->attr;
285 struct xyarray *group_fd = NULL;
286
287 if (group && evsel != first)
288 group_fd = first->fd;
275 289
276 if (scale) 290 if (scale)
277 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 291 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -280,14 +294,15 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
280 attr->inherit = !no_inherit; 294 attr->inherit = !no_inherit;
281 295
282 if (system_wide) 296 if (system_wide)
283 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false); 297 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
284 298 group, group_fd);
285 if (target_pid == -1 && target_tid == -1) { 299 if (target_pid == -1 && target_tid == -1) {
286 attr->disabled = 1; 300 attr->disabled = 1;
287 attr->enable_on_exec = 1; 301 attr->enable_on_exec = 1;
288 } 302 }
289 303
290 return perf_evsel__open_per_thread(evsel, evsel_list->threads, false); 304 return perf_evsel__open_per_thread(evsel, evsel_list->threads,
305 group, group_fd);
291} 306}
292 307
293/* 308/*
@@ -351,7 +366,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
351 update_stats(&ps->res_stats[i], count[i]); 366 update_stats(&ps->res_stats[i], count[i]);
352 367
353 if (verbose) { 368 if (verbose) {
354 fprintf(stderr, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 369 fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
355 event_name(counter), count[0], count[1], count[2]); 370 event_name(counter), count[0], count[1], count[2]);
356 } 371 }
357 372
@@ -387,7 +402,7 @@ static int read_counter(struct perf_evsel *counter)
387static int run_perf_stat(int argc __used, const char **argv) 402static int run_perf_stat(int argc __used, const char **argv)
388{ 403{
389 unsigned long long t0, t1; 404 unsigned long long t0, t1;
390 struct perf_evsel *counter; 405 struct perf_evsel *counter, *first;
391 int status = 0; 406 int status = 0;
392 int child_ready_pipe[2], go_pipe[2]; 407 int child_ready_pipe[2], go_pipe[2];
393 const bool forks = (argc > 0); 408 const bool forks = (argc > 0);
@@ -444,8 +459,10 @@ static int run_perf_stat(int argc __used, const char **argv)
444 close(child_ready_pipe[0]); 459 close(child_ready_pipe[0]);
445 } 460 }
446 461
462 first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
463
447 list_for_each_entry(counter, &evsel_list->entries, node) { 464 list_for_each_entry(counter, &evsel_list->entries, node) {
448 if (create_perf_stat_counter(counter) < 0) { 465 if (create_perf_stat_counter(counter, first) < 0) {
449 if (errno == EINVAL || errno == ENOSYS || errno == ENOENT) { 466 if (errno == EINVAL || errno == ENOSYS || errno == ENOENT) {
450 if (verbose) 467 if (verbose)
451 ui__warning("%s event is not supported by the kernel.\n", 468 ui__warning("%s event is not supported by the kernel.\n",
@@ -486,6 +503,8 @@ static int run_perf_stat(int argc __used, const char **argv)
486 if (forks) { 503 if (forks) {
487 close(go_pipe[1]); 504 close(go_pipe[1]);
488 wait(&status); 505 wait(&status);
506 if (WIFSIGNALED(status))
507 psignal(WTERMSIG(status), argv[0]);
489 } else { 508 } else {
490 while(!done) sleep(1); 509 while(!done) sleep(1);
491 } 510 }
@@ -518,9 +537,9 @@ static void print_noise_pct(double total, double avg)
518 pct = 100.0*total/avg; 537 pct = 100.0*total/avg;
519 538
520 if (csv_output) 539 if (csv_output)
521 fprintf(stderr, "%s%.2f%%", csv_sep, pct); 540 fprintf(output, "%s%.2f%%", csv_sep, pct);
522 else 541 else if (pct)
523 fprintf(stderr, " ( +-%6.2f%% )", pct); 542 fprintf(output, " ( +-%6.2f%% )", pct);
524} 543}
525 544
526static void print_noise(struct perf_evsel *evsel, double avg) 545static void print_noise(struct perf_evsel *evsel, double avg)
@@ -545,16 +564,17 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
545 csv_output ? 0 : -4, 564 csv_output ? 0 : -4,
546 evsel_list->cpus->map[cpu], csv_sep); 565 evsel_list->cpus->map[cpu], csv_sep);
547 566
548 fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel)); 567 fprintf(output, fmt, cpustr, msecs, csv_sep, event_name(evsel));
549 568
550 if (evsel->cgrp) 569 if (evsel->cgrp)
551 fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name); 570 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
552 571
553 if (csv_output) 572 if (csv_output)
554 return; 573 return;
555 574
556 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 575 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
557 fprintf(stderr, " # %8.3f CPUs utilized ", avg / avg_stats(&walltime_nsecs_stats)); 576 fprintf(output, " # %8.3f CPUs utilized ",
577 avg / avg_stats(&walltime_nsecs_stats));
558} 578}
559 579
560static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) 580static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg)
@@ -575,9 +595,9 @@ static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __us
575 else if (ratio > 10.0) 595 else if (ratio > 10.0)
576 color = PERF_COLOR_YELLOW; 596 color = PERF_COLOR_YELLOW;
577 597
578 fprintf(stderr, " # "); 598 fprintf(output, " # ");
579 color_fprintf(stderr, color, "%6.2f%%", ratio); 599 color_fprintf(output, color, "%6.2f%%", ratio);
580 fprintf(stderr, " frontend cycles idle "); 600 fprintf(output, " frontend cycles idle ");
581} 601}
582 602
583static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg) 603static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg)
@@ -598,9 +618,9 @@ static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __use
598 else if (ratio > 20.0) 618 else if (ratio > 20.0)
599 color = PERF_COLOR_YELLOW; 619 color = PERF_COLOR_YELLOW;
600 620
601 fprintf(stderr, " # "); 621 fprintf(output, " # ");
602 color_fprintf(stderr, color, "%6.2f%%", ratio); 622 color_fprintf(output, color, "%6.2f%%", ratio);
603 fprintf(stderr, " backend cycles idle "); 623 fprintf(output, " backend cycles idle ");
604} 624}
605 625
606static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) 626static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@@ -621,9 +641,9 @@ static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double
621 else if (ratio > 5.0) 641 else if (ratio > 5.0)
622 color = PERF_COLOR_YELLOW; 642 color = PERF_COLOR_YELLOW;
623 643
624 fprintf(stderr, " # "); 644 fprintf(output, " # ");
625 color_fprintf(stderr, color, "%6.2f%%", ratio); 645 color_fprintf(output, color, "%6.2f%%", ratio);
626 fprintf(stderr, " of all branches "); 646 fprintf(output, " of all branches ");
627} 647}
628 648
629static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 649static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@@ -644,9 +664,9 @@ static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, dou
644 else if (ratio > 5.0) 664 else if (ratio > 5.0)
645 color = PERF_COLOR_YELLOW; 665 color = PERF_COLOR_YELLOW;
646 666
647 fprintf(stderr, " # "); 667 fprintf(output, " # ");
648 color_fprintf(stderr, color, "%6.2f%%", ratio); 668 color_fprintf(output, color, "%6.2f%%", ratio);
649 fprintf(stderr, " of all L1-dcache hits "); 669 fprintf(output, " of all L1-dcache hits ");
650} 670}
651 671
652static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 672static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@@ -667,9 +687,9 @@ static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, dou
667 else if (ratio > 5.0) 687 else if (ratio > 5.0)
668 color = PERF_COLOR_YELLOW; 688 color = PERF_COLOR_YELLOW;
669 689
670 fprintf(stderr, " # "); 690 fprintf(output, " # ");
671 color_fprintf(stderr, color, "%6.2f%%", ratio); 691 color_fprintf(output, color, "%6.2f%%", ratio);
672 fprintf(stderr, " of all L1-icache hits "); 692 fprintf(output, " of all L1-icache hits ");
673} 693}
674 694
675static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 695static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@@ -690,9 +710,9 @@ static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
690 else if (ratio > 5.0) 710 else if (ratio > 5.0)
691 color = PERF_COLOR_YELLOW; 711 color = PERF_COLOR_YELLOW;
692 712
693 fprintf(stderr, " # "); 713 fprintf(output, " # ");
694 color_fprintf(stderr, color, "%6.2f%%", ratio); 714 color_fprintf(output, color, "%6.2f%%", ratio);
695 fprintf(stderr, " of all dTLB cache hits "); 715 fprintf(output, " of all dTLB cache hits ");
696} 716}
697 717
698static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 718static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@@ -713,9 +733,9 @@ static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
713 else if (ratio > 5.0) 733 else if (ratio > 5.0)
714 color = PERF_COLOR_YELLOW; 734 color = PERF_COLOR_YELLOW;
715 735
716 fprintf(stderr, " # "); 736 fprintf(output, " # ");
717 color_fprintf(stderr, color, "%6.2f%%", ratio); 737 color_fprintf(output, color, "%6.2f%%", ratio);
718 fprintf(stderr, " of all iTLB cache hits "); 738 fprintf(output, " of all iTLB cache hits ");
719} 739}
720 740
721static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 741static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@@ -736,9 +756,9 @@ static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, doub
736 else if (ratio > 5.0) 756 else if (ratio > 5.0)
737 color = PERF_COLOR_YELLOW; 757 color = PERF_COLOR_YELLOW;
738 758
739 fprintf(stderr, " # "); 759 fprintf(output, " # ");
740 color_fprintf(stderr, color, "%6.2f%%", ratio); 760 color_fprintf(output, color, "%6.2f%%", ratio);
741 fprintf(stderr, " of all LL-cache hits "); 761 fprintf(output, " of all LL-cache hits ");
742} 762}
743 763
744static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) 764static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
@@ -761,10 +781,10 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
761 else 781 else
762 cpu = 0; 782 cpu = 0;
763 783
764 fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel)); 784 fprintf(output, fmt, cpustr, avg, csv_sep, event_name(evsel));
765 785
766 if (evsel->cgrp) 786 if (evsel->cgrp)
767 fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name); 787 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
768 788
769 if (csv_output) 789 if (csv_output)
770 return; 790 return;
@@ -775,14 +795,14 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
775 if (total) 795 if (total)
776 ratio = avg / total; 796 ratio = avg / total;
777 797
778 fprintf(stderr, " # %5.2f insns per cycle ", ratio); 798 fprintf(output, " # %5.2f insns per cycle ", ratio);
779 799
780 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 800 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
781 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 801 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
782 802
783 if (total && avg) { 803 if (total && avg) {
784 ratio = total / avg; 804 ratio = total / avg;
785 fprintf(stderr, "\n # %5.2f stalled cycles per insn", ratio); 805 fprintf(output, "\n # %5.2f stalled cycles per insn", ratio);
786 } 806 }
787 807
788 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && 808 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
@@ -830,7 +850,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
830 if (total) 850 if (total)
831 ratio = avg * 100 / total; 851 ratio = avg * 100 / total;
832 852
833 fprintf(stderr, " # %8.3f %% of all cache refs ", ratio); 853 fprintf(output, " # %8.3f %% of all cache refs ", ratio);
834 854
835 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { 855 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
836 print_stalled_cycles_frontend(cpu, evsel, avg); 856 print_stalled_cycles_frontend(cpu, evsel, avg);
@@ -842,16 +862,16 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
842 if (total) 862 if (total)
843 ratio = 1.0 * avg / total; 863 ratio = 1.0 * avg / total;
844 864
845 fprintf(stderr, " # %8.3f GHz ", ratio); 865 fprintf(output, " # %8.3f GHz ", ratio);
846 } else if (runtime_nsecs_stats[cpu].n != 0) { 866 } else if (runtime_nsecs_stats[cpu].n != 0) {
847 total = avg_stats(&runtime_nsecs_stats[cpu]); 867 total = avg_stats(&runtime_nsecs_stats[cpu]);
848 868
849 if (total) 869 if (total)
850 ratio = 1000.0 * avg / total; 870 ratio = 1000.0 * avg / total;
851 871
852 fprintf(stderr, " # %8.3f M/sec ", ratio); 872 fprintf(output, " # %8.3f M/sec ", ratio);
853 } else { 873 } else {
854 fprintf(stderr, " "); 874 fprintf(output, " ");
855 } 875 }
856} 876}
857 877
@@ -866,7 +886,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
866 int scaled = counter->counts->scaled; 886 int scaled = counter->counts->scaled;
867 887
868 if (scaled == -1) { 888 if (scaled == -1) {
869 fprintf(stderr, "%*s%s%*s", 889 fprintf(output, "%*s%s%*s",
870 csv_output ? 0 : 18, 890 csv_output ? 0 : 18,
871 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 891 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
872 csv_sep, 892 csv_sep,
@@ -874,9 +894,9 @@ static void print_counter_aggr(struct perf_evsel *counter)
874 event_name(counter)); 894 event_name(counter));
875 895
876 if (counter->cgrp) 896 if (counter->cgrp)
877 fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name); 897 fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
878 898
879 fputc('\n', stderr); 899 fputc('\n', output);
880 return; 900 return;
881 } 901 }
882 902
@@ -888,7 +908,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
888 print_noise(counter, avg); 908 print_noise(counter, avg);
889 909
890 if (csv_output) { 910 if (csv_output) {
891 fputc('\n', stderr); 911 fputc('\n', output);
892 return; 912 return;
893 } 913 }
894 914
@@ -898,9 +918,9 @@ static void print_counter_aggr(struct perf_evsel *counter)
898 avg_enabled = avg_stats(&ps->res_stats[1]); 918 avg_enabled = avg_stats(&ps->res_stats[1]);
899 avg_running = avg_stats(&ps->res_stats[2]); 919 avg_running = avg_stats(&ps->res_stats[2]);
900 920
901 fprintf(stderr, " [%5.2f%%]", 100 * avg_running / avg_enabled); 921 fprintf(output, " [%5.2f%%]", 100 * avg_running / avg_enabled);
902 } 922 }
903 fprintf(stderr, "\n"); 923 fprintf(output, "\n");
904} 924}
905 925
906/* 926/*
@@ -917,7 +937,7 @@ static void print_counter(struct perf_evsel *counter)
917 ena = counter->counts->cpu[cpu].ena; 937 ena = counter->counts->cpu[cpu].ena;
918 run = counter->counts->cpu[cpu].run; 938 run = counter->counts->cpu[cpu].run;
919 if (run == 0 || ena == 0) { 939 if (run == 0 || ena == 0) {
920 fprintf(stderr, "CPU%*d%s%*s%s%*s", 940 fprintf(output, "CPU%*d%s%*s%s%*s",
921 csv_output ? 0 : -4, 941 csv_output ? 0 : -4,
922 evsel_list->cpus->map[cpu], csv_sep, 942 evsel_list->cpus->map[cpu], csv_sep,
923 csv_output ? 0 : 18, 943 csv_output ? 0 : 18,
@@ -927,9 +947,10 @@ static void print_counter(struct perf_evsel *counter)
927 event_name(counter)); 947 event_name(counter));
928 948
929 if (counter->cgrp) 949 if (counter->cgrp)
930 fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name); 950 fprintf(output, "%s%s",
951 csv_sep, counter->cgrp->name);
931 952
932 fputc('\n', stderr); 953 fputc('\n', output);
933 continue; 954 continue;
934 } 955 }
935 956
@@ -942,9 +963,10 @@ static void print_counter(struct perf_evsel *counter)
942 print_noise(counter, 1.0); 963 print_noise(counter, 1.0);
943 964
944 if (run != ena) 965 if (run != ena)
945 fprintf(stderr, " (%.2f%%)", 100.0 * run / ena); 966 fprintf(output, " (%.2f%%)",
967 100.0 * run / ena);
946 } 968 }
947 fputc('\n', stderr); 969 fputc('\n', output);
948 } 970 }
949} 971}
950 972
@@ -956,21 +978,21 @@ static void print_stat(int argc, const char **argv)
956 fflush(stdout); 978 fflush(stdout);
957 979
958 if (!csv_output) { 980 if (!csv_output) {
959 fprintf(stderr, "\n"); 981 fprintf(output, "\n");
960 fprintf(stderr, " Performance counter stats for "); 982 fprintf(output, " Performance counter stats for ");
961 if(target_pid == -1 && target_tid == -1) { 983 if(target_pid == -1 && target_tid == -1) {
962 fprintf(stderr, "\'%s", argv[0]); 984 fprintf(output, "\'%s", argv[0]);
963 for (i = 1; i < argc; i++) 985 for (i = 1; i < argc; i++)
964 fprintf(stderr, " %s", argv[i]); 986 fprintf(output, " %s", argv[i]);
965 } else if (target_pid != -1) 987 } else if (target_pid != -1)
966 fprintf(stderr, "process id \'%d", target_pid); 988 fprintf(output, "process id \'%d", target_pid);
967 else 989 else
968 fprintf(stderr, "thread id \'%d", target_tid); 990 fprintf(output, "thread id \'%d", target_tid);
969 991
970 fprintf(stderr, "\'"); 992 fprintf(output, "\'");
971 if (run_count > 1) 993 if (run_count > 1)
972 fprintf(stderr, " (%d runs)", run_count); 994 fprintf(output, " (%d runs)", run_count);
973 fprintf(stderr, ":\n\n"); 995 fprintf(output, ":\n\n");
974 } 996 }
975 997
976 if (no_aggr) { 998 if (no_aggr) {
@@ -983,15 +1005,15 @@ static void print_stat(int argc, const char **argv)
983 1005
984 if (!csv_output) { 1006 if (!csv_output) {
985 if (!null_run) 1007 if (!null_run)
986 fprintf(stderr, "\n"); 1008 fprintf(output, "\n");
987 fprintf(stderr, " %17.9f seconds time elapsed", 1009 fprintf(output, " %17.9f seconds time elapsed",
988 avg_stats(&walltime_nsecs_stats)/1e9); 1010 avg_stats(&walltime_nsecs_stats)/1e9);
989 if (run_count > 1) { 1011 if (run_count > 1) {
990 fprintf(stderr, " "); 1012 fprintf(output, " ");
991 print_noise_pct(stddev_stats(&walltime_nsecs_stats), 1013 print_noise_pct(stddev_stats(&walltime_nsecs_stats),
992 avg_stats(&walltime_nsecs_stats)); 1014 avg_stats(&walltime_nsecs_stats));
993 } 1015 }
994 fprintf(stderr, "\n\n"); 1016 fprintf(output, "\n\n");
995 } 1017 }
996} 1018}
997 1019
@@ -1029,6 +1051,8 @@ static int stat__set_big_num(const struct option *opt __used,
1029 return 0; 1051 return 0;
1030} 1052}
1031 1053
1054static bool append_file;
1055
1032static const struct option options[] = { 1056static const struct option options[] = {
1033 OPT_CALLBACK('e', "event", &evsel_list, "event", 1057 OPT_CALLBACK('e', "event", &evsel_list, "event",
1034 "event selector. use 'perf list' to list available events", 1058 "event selector. use 'perf list' to list available events",
@@ -1043,6 +1067,8 @@ static const struct option options[] = {
1043 "stat events on existing thread id"), 1067 "stat events on existing thread id"),
1044 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1068 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1045 "system-wide collection from all CPUs"), 1069 "system-wide collection from all CPUs"),
1070 OPT_BOOLEAN('g', "group", &group,
1071 "put the counters into a counter group"),
1046 OPT_BOOLEAN('c', "scale", &scale, 1072 OPT_BOOLEAN('c', "scale", &scale,
1047 "scale/normalize counters"), 1073 "scale/normalize counters"),
1048 OPT_INCR('v', "verbose", &verbose, 1074 OPT_INCR('v', "verbose", &verbose,
@@ -1067,6 +1093,11 @@ static const struct option options[] = {
1067 OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 1093 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1068 "monitor event in cgroup name only", 1094 "monitor event in cgroup name only",
1069 parse_cgroups), 1095 parse_cgroups),
1096 OPT_STRING('o', "output", &output_name, "file",
1097 "output file name"),
1098 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1099 OPT_INTEGER(0, "log-fd", &output_fd,
1100 "log output to fd, instead of stderr"),
1070 OPT_END() 1101 OPT_END()
1071}; 1102};
1072 1103
@@ -1138,6 +1169,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1138{ 1169{
1139 struct perf_evsel *pos; 1170 struct perf_evsel *pos;
1140 int status = -ENOMEM; 1171 int status = -ENOMEM;
1172 const char *mode;
1141 1173
1142 setlocale(LC_ALL, ""); 1174 setlocale(LC_ALL, "");
1143 1175
@@ -1148,16 +1180,46 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1148 argc = parse_options(argc, argv, options, stat_usage, 1180 argc = parse_options(argc, argv, options, stat_usage,
1149 PARSE_OPT_STOP_AT_NON_OPTION); 1181 PARSE_OPT_STOP_AT_NON_OPTION);
1150 1182
1151 if (csv_sep) 1183 output = stderr;
1184 if (output_name && strcmp(output_name, "-"))
1185 output = NULL;
1186
1187 if (output_name && output_fd) {
1188 fprintf(stderr, "cannot use both --output and --log-fd\n");
1189 usage_with_options(stat_usage, options);
1190 }
1191 if (!output) {
1192 struct timespec tm;
1193 mode = append_file ? "a" : "w";
1194
1195 output = fopen(output_name, mode);
1196 if (!output) {
1197 perror("failed to create output file");
1198 exit(-1);
1199 }
1200 clock_gettime(CLOCK_REALTIME, &tm);
1201 fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
1202 } else if (output_fd != 2) {
1203 mode = append_file ? "a" : "w";
1204 output = fdopen(output_fd, mode);
1205 if (!output) {
1206 perror("Failed opening logfd");
1207 return -errno;
1208 }
1209 }
1210
1211 if (csv_sep) {
1152 csv_output = true; 1212 csv_output = true;
1153 else 1213 if (!strcmp(csv_sep, "\\t"))
1214 csv_sep = "\t";
1215 } else
1154 csv_sep = DEFAULT_SEPARATOR; 1216 csv_sep = DEFAULT_SEPARATOR;
1155 1217
1156 /* 1218 /*
1157 * let the spreadsheet do the pretty-printing 1219 * let the spreadsheet do the pretty-printing
1158 */ 1220 */
1159 if (csv_output) { 1221 if (csv_output) {
1160 /* User explicitely passed -B? */ 1222 /* User explicitly passed -B? */
1161 if (big_num_opt == 1) { 1223 if (big_num_opt == 1) {
1162 fprintf(stderr, "-B option not supported with -x\n"); 1224 fprintf(stderr, "-B option not supported with -x\n");
1163 usage_with_options(stat_usage, options); 1225 usage_with_options(stat_usage, options);
@@ -1223,7 +1285,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1223 status = 0; 1285 status = 0;
1224 for (run_idx = 0; run_idx < run_count; run_idx++) { 1286 for (run_idx = 0; run_idx < run_count; run_idx++) {
1225 if (run_count != 1 && verbose) 1287 if (run_count != 1 && verbose)
1226 fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); 1288 fprintf(output, "[ perf stat: executing run #%d ... ]\n",
1289 run_idx + 1);
1227 1290
1228 if (sync_run) 1291 if (sync_run)
1229 sync(); 1292 sync();
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 55f4c76f2821..831d1baeac37 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -291,7 +291,7 @@ static int test__open_syscall_event(void)
291 goto out_thread_map_delete; 291 goto out_thread_map_delete;
292 } 292 }
293 293
294 if (perf_evsel__open_per_thread(evsel, threads, false) < 0) { 294 if (perf_evsel__open_per_thread(evsel, threads, false, NULL) < 0) {
295 pr_debug("failed to open counter: %s, " 295 pr_debug("failed to open counter: %s, "
296 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 296 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
297 strerror(errno)); 297 strerror(errno));
@@ -366,7 +366,7 @@ static int test__open_syscall_event_on_all_cpus(void)
366 goto out_thread_map_delete; 366 goto out_thread_map_delete;
367 } 367 }
368 368
369 if (perf_evsel__open(evsel, cpus, threads, false) < 0) { 369 if (perf_evsel__open(evsel, cpus, threads, false, NULL) < 0) {
370 pr_debug("failed to open counter: %s, " 370 pr_debug("failed to open counter: %s, "
371 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 371 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
372 strerror(errno)); 372 strerror(errno));
@@ -531,7 +531,7 @@ static int test__basic_mmap(void)
531 531
532 perf_evlist__add(evlist, evsels[i]); 532 perf_evlist__add(evlist, evsels[i]);
533 533
534 if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) { 534 if (perf_evsel__open(evsels[i], cpus, threads, false, NULL) < 0) {
535 pr_debug("failed to open counter: %s, " 535 pr_debug("failed to open counter: %s, "
536 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 536 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
537 strerror(errno)); 537 strerror(errno));
@@ -561,7 +561,7 @@ static int test__basic_mmap(void)
561 } 561 }
562 562
563 err = perf_event__parse_sample(event, attr.sample_type, sample_size, 563 err = perf_event__parse_sample(event, attr.sample_type, sample_size,
564 false, &sample); 564 false, &sample, false);
565 if (err) { 565 if (err) {
566 pr_err("Can't parse sample, err = %d\n", err); 566 pr_err("Can't parse sample, err = %d\n", err);
567 goto out_munmap; 567 goto out_munmap;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index a43433f08300..c9cdedb58134 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -5,6 +5,7 @@
5 * any workload, CPU or specific PID. 5 * any workload, CPU or specific PID.
6 * 6 *
7 * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 7 * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
8 * 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
8 * 9 *
9 * Improvements and fixes by: 10 * Improvements and fixes by:
10 * 11 *
@@ -36,6 +37,7 @@
36#include "util/parse-events.h" 37#include "util/parse-events.h"
37#include "util/cpumap.h" 38#include "util/cpumap.h"
38#include "util/xyarray.h" 39#include "util/xyarray.h"
40#include "util/sort.h"
39 41
40#include "util/debug.h" 42#include "util/debug.h"
41 43
@@ -65,12 +67,8 @@
65static struct perf_top top = { 67static struct perf_top top = {
66 .count_filter = 5, 68 .count_filter = 5,
67 .delay_secs = 2, 69 .delay_secs = 2,
68 .display_weighted = -1,
69 .target_pid = -1, 70 .target_pid = -1,
70 .target_tid = -1, 71 .target_tid = -1,
71 .active_symbols = LIST_HEAD_INIT(top.active_symbols),
72 .active_symbols_lock = PTHREAD_MUTEX_INITIALIZER,
73 .active_symbols_cond = PTHREAD_COND_INITIALIZER,
74 .freq = 1000, /* 1 KHz */ 72 .freq = 1000, /* 1 KHz */
75}; 73};
76 74
@@ -78,6 +76,12 @@ static bool system_wide = false;
78 76
79static bool use_tui, use_stdio; 77static bool use_tui, use_stdio;
80 78
79static bool sort_has_symbols;
80
81static bool dont_use_callchains;
82static char callchain_default_opt[] = "fractal,0.5,callee";
83
84
81static int default_interval = 0; 85static int default_interval = 0;
82 86
83static bool kptr_restrict_warned; 87static bool kptr_restrict_warned;
@@ -85,7 +89,7 @@ static bool vmlinux_warned;
85static bool inherit = false; 89static bool inherit = false;
86static int realtime_prio = 0; 90static int realtime_prio = 0;
87static bool group = false; 91static bool group = false;
88static unsigned int page_size; 92static bool sample_id_all_avail = true;
89static unsigned int mmap_pages = 128; 93static unsigned int mmap_pages = 128;
90 94
91static bool dump_symtab = false; 95static bool dump_symtab = false;
@@ -93,7 +97,6 @@ static bool dump_symtab = false;
93static struct winsize winsize; 97static struct winsize winsize;
94 98
95static const char *sym_filter = NULL; 99static const char *sym_filter = NULL;
96struct sym_entry *sym_filter_entry_sched = NULL;
97static int sym_pcnt_filter = 5; 100static int sym_pcnt_filter = 5;
98 101
99/* 102/*
@@ -136,18 +139,18 @@ static void sig_winch_handler(int sig __used)
136 update_print_entries(&winsize); 139 update_print_entries(&winsize);
137} 140}
138 141
139static int parse_source(struct sym_entry *syme) 142static int parse_source(struct hist_entry *he)
140{ 143{
141 struct symbol *sym; 144 struct symbol *sym;
142 struct annotation *notes; 145 struct annotation *notes;
143 struct map *map; 146 struct map *map;
144 int err = -1; 147 int err = -1;
145 148
146 if (!syme) 149 if (!he || !he->ms.sym)
147 return -1; 150 return -1;
148 151
149 sym = sym_entry__symbol(syme); 152 sym = he->ms.sym;
150 map = syme->map; 153 map = he->ms.map;
151 154
152 /* 155 /*
153 * We can't annotate with just /proc/kallsyms 156 * We can't annotate with just /proc/kallsyms
@@ -175,52 +178,63 @@ static int parse_source(struct sym_entry *syme)
175 return err; 178 return err;
176 } 179 }
177 180
178 err = symbol__annotate(sym, syme->map, 0); 181 err = symbol__annotate(sym, map, 0);
179 if (err == 0) { 182 if (err == 0) {
180out_assign: 183out_assign:
181 top.sym_filter_entry = syme; 184 top.sym_filter_entry = he;
182 } 185 }
183 186
184 pthread_mutex_unlock(&notes->lock); 187 pthread_mutex_unlock(&notes->lock);
185 return err; 188 return err;
186} 189}
187 190
188static void __zero_source_counters(struct sym_entry *syme) 191static void __zero_source_counters(struct hist_entry *he)
189{ 192{
190 struct symbol *sym = sym_entry__symbol(syme); 193 struct symbol *sym = he->ms.sym;
191 symbol__annotate_zero_histograms(sym); 194 symbol__annotate_zero_histograms(sym);
192} 195}
193 196
194static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) 197static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
195{ 198{
196 struct annotation *notes; 199 struct annotation *notes;
197 struct symbol *sym; 200 struct symbol *sym;
198 201
199 if (syme != top.sym_filter_entry) 202 if (he == NULL || he->ms.sym == NULL ||
203 ((top.sym_filter_entry == NULL ||
204 top.sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1))
200 return; 205 return;
201 206
202 sym = sym_entry__symbol(syme); 207 sym = he->ms.sym;
203 notes = symbol__annotation(sym); 208 notes = symbol__annotation(sym);
204 209
205 if (pthread_mutex_trylock(&notes->lock)) 210 if (pthread_mutex_trylock(&notes->lock))
206 return; 211 return;
207 212
208 ip = syme->map->map_ip(syme->map, ip); 213 if (notes->src == NULL &&
209 symbol__inc_addr_samples(sym, syme->map, counter, ip); 214 symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
215 pthread_mutex_unlock(&notes->lock);
216 pr_err("Not enough memory for annotating '%s' symbol!\n",
217 sym->name);
218 sleep(1);
219 return;
220 }
221
222 ip = he->ms.map->map_ip(he->ms.map, ip);
223 symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
210 224
211 pthread_mutex_unlock(&notes->lock); 225 pthread_mutex_unlock(&notes->lock);
212} 226}
213 227
214static void show_details(struct sym_entry *syme) 228static void show_details(struct hist_entry *he)
215{ 229{
216 struct annotation *notes; 230 struct annotation *notes;
217 struct symbol *symbol; 231 struct symbol *symbol;
218 int more; 232 int more;
219 233
220 if (!syme) 234 if (!he)
221 return; 235 return;
222 236
223 symbol = sym_entry__symbol(syme); 237 symbol = he->ms.sym;
224 notes = symbol__annotation(symbol); 238 notes = symbol__annotation(symbol);
225 239
226 pthread_mutex_lock(&notes->lock); 240 pthread_mutex_lock(&notes->lock);
@@ -231,7 +245,7 @@ static void show_details(struct sym_entry *syme)
231 printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name); 245 printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name);
232 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 246 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
233 247
234 more = symbol__annotate_printf(symbol, syme->map, top.sym_evsel->idx, 248 more = symbol__annotate_printf(symbol, he->ms.map, top.sym_evsel->idx,
235 0, sym_pcnt_filter, top.print_entries, 4); 249 0, sym_pcnt_filter, top.print_entries, 4);
236 if (top.zero) 250 if (top.zero)
237 symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx); 251 symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx);
@@ -245,21 +259,28 @@ out_unlock:
245 259
246static const char CONSOLE_CLEAR[] = ""; 260static const char CONSOLE_CLEAR[] = "";
247 261
248static void __list_insert_active_sym(struct sym_entry *syme) 262static struct hist_entry *
263 perf_session__add_hist_entry(struct perf_session *session,
264 struct addr_location *al,
265 struct perf_sample *sample,
266 struct perf_evsel *evsel)
249{ 267{
250 list_add(&syme->node, &top.active_symbols); 268 struct hist_entry *he;
269
270 he = __hists__add_entry(&evsel->hists, al, NULL, sample->period);
271 if (he == NULL)
272 return NULL;
273
274 session->hists.stats.total_period += sample->period;
275 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
276 return he;
251} 277}
252 278
253static void print_sym_table(struct perf_session *session) 279static void print_sym_table(void)
254{ 280{
255 char bf[160]; 281 char bf[160];
256 int printed = 0; 282 int printed = 0;
257 struct rb_node *nd;
258 struct sym_entry *syme;
259 struct rb_root tmp = RB_ROOT;
260 const int win_width = winsize.ws_col - 1; 283 const int win_width = winsize.ws_col - 1;
261 int sym_width, dso_width, dso_short_width;
262 float sum_ksamples = perf_top__decay_samples(&top, &tmp);
263 284
264 puts(CONSOLE_CLEAR); 285 puts(CONSOLE_CLEAR);
265 286
@@ -270,10 +291,14 @@ static void print_sym_table(struct perf_session *session)
270 291
271 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 292 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
272 293
273 if (session->hists.stats.total_lost != 0) { 294 if (top.sym_evsel->hists.stats.nr_lost_warned !=
274 color_fprintf(stdout, PERF_COLOR_RED, "WARNING:"); 295 top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) {
275 printf(" LOST %" PRIu64 " events, Check IO/CPU overload\n", 296 top.sym_evsel->hists.stats.nr_lost_warned =
276 session->hists.stats.total_lost); 297 top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST];
298 color_fprintf(stdout, PERF_COLOR_RED,
299 "WARNING: LOST %d chunks, Check IO/CPU overload",
300 top.sym_evsel->hists.stats.nr_lost_warned);
301 ++printed;
277 } 302 }
278 303
279 if (top.sym_filter_entry) { 304 if (top.sym_filter_entry) {
@@ -281,58 +306,15 @@ static void print_sym_table(struct perf_session *session)
281 return; 306 return;
282 } 307 }
283 308
284 perf_top__find_widths(&top, &tmp, &dso_width, &dso_short_width, 309 hists__collapse_resort_threaded(&top.sym_evsel->hists);
285 &sym_width); 310 hists__output_resort_threaded(&top.sym_evsel->hists);
286 311 hists__decay_entries_threaded(&top.sym_evsel->hists,
287 if (sym_width + dso_width > winsize.ws_col - 29) { 312 top.hide_user_symbols,
288 dso_width = dso_short_width; 313 top.hide_kernel_symbols);
289 if (sym_width + dso_width > winsize.ws_col - 29) 314 hists__output_recalc_col_len(&top.sym_evsel->hists, winsize.ws_row - 3);
290 sym_width = winsize.ws_col - dso_width - 29;
291 }
292 putchar('\n'); 315 putchar('\n');
293 if (top.evlist->nr_entries == 1) 316 hists__fprintf(&top.sym_evsel->hists, NULL, false, false,
294 printf(" samples pcnt"); 317 winsize.ws_row - 4 - printed, win_width, stdout);
295 else
296 printf(" weight samples pcnt");
297
298 if (verbose)
299 printf(" RIP ");
300 printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
301 printf(" %s _______ _____",
302 top.evlist->nr_entries == 1 ? " " : "______");
303 if (verbose)
304 printf(" ________________");
305 printf(" %-*.*s", sym_width, sym_width, graph_line);
306 printf(" %-*.*s", dso_width, dso_width, graph_line);
307 puts("\n");
308
309 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
310 struct symbol *sym;
311 double pcnt;
312
313 syme = rb_entry(nd, struct sym_entry, rb_node);
314 sym = sym_entry__symbol(syme);
315 if (++printed > top.print_entries ||
316 (int)syme->snap_count < top.count_filter)
317 continue;
318
319 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
320 sum_ksamples));
321
322 if (top.evlist->nr_entries == 1 || !top.display_weighted)
323 printf("%20.2f ", syme->weight);
324 else
325 printf("%9.1f %10ld ", syme->weight, syme->snap_count);
326
327 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
328 if (verbose)
329 printf(" %016" PRIx64, sym->start);
330 printf(" %-*.*s", sym_width, sym_width, sym->name);
331 printf(" %-*.*s\n", dso_width, dso_width,
332 dso_width >= syme->map->dso->long_name_len ?
333 syme->map->dso->long_name :
334 syme->map->dso->short_name);
335 }
336} 318}
337 319
338static void prompt_integer(int *target, const char *msg) 320static void prompt_integer(int *target, const char *msg)
@@ -370,10 +352,11 @@ static void prompt_percent(int *target, const char *msg)
370 *target = tmp; 352 *target = tmp;
371} 353}
372 354
373static void prompt_symbol(struct sym_entry **target, const char *msg) 355static void prompt_symbol(struct hist_entry **target, const char *msg)
374{ 356{
375 char *buf = malloc(0), *p; 357 char *buf = malloc(0), *p;
376 struct sym_entry *syme = *target, *n, *found = NULL; 358 struct hist_entry *syme = *target, *n, *found = NULL;
359 struct rb_node *next;
377 size_t dummy = 0; 360 size_t dummy = 0;
378 361
379 /* zero counters of active symbol */ 362 /* zero counters of active symbol */
@@ -390,17 +373,14 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
390 if (p) 373 if (p)
391 *p = 0; 374 *p = 0;
392 375
393 pthread_mutex_lock(&top.active_symbols_lock); 376 next = rb_first(&top.sym_evsel->hists.entries);
394 syme = list_entry(top.active_symbols.next, struct sym_entry, node); 377 while (next) {
395 pthread_mutex_unlock(&top.active_symbols_lock); 378 n = rb_entry(next, struct hist_entry, rb_node);
396 379 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
397 list_for_each_entry_safe_from(syme, n, &top.active_symbols, node) { 380 found = n;
398 struct symbol *sym = sym_entry__symbol(syme);
399
400 if (!strcmp(buf, sym->name)) {
401 found = syme;
402 break; 381 break;
403 } 382 }
383 next = rb_next(&n->rb_node);
404 } 384 }
405 385
406 if (!found) { 386 if (!found) {
@@ -419,7 +399,7 @@ static void print_mapped_keys(void)
419 char *name = NULL; 399 char *name = NULL;
420 400
421 if (top.sym_filter_entry) { 401 if (top.sym_filter_entry) {
422 struct symbol *sym = sym_entry__symbol(top.sym_filter_entry); 402 struct symbol *sym = top.sym_filter_entry->ms.sym;
423 name = sym->name; 403 name = sym->name;
424 } 404 }
425 405
@@ -436,9 +416,6 @@ static void print_mapped_keys(void)
436 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 416 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
437 fprintf(stdout, "\t[S] stop annotation.\n"); 417 fprintf(stdout, "\t[S] stop annotation.\n");
438 418
439 if (top.evlist->nr_entries > 1)
440 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", top.display_weighted ? 1 : 0);
441
442 fprintf(stdout, 419 fprintf(stdout,
443 "\t[K] hide kernel_symbols symbols. \t(%s)\n", 420 "\t[K] hide kernel_symbols symbols. \t(%s)\n",
444 top.hide_kernel_symbols ? "yes" : "no"); 421 top.hide_kernel_symbols ? "yes" : "no");
@@ -465,7 +442,6 @@ static int key_mapped(int c)
465 case 'S': 442 case 'S':
466 return 1; 443 return 1;
467 case 'E': 444 case 'E':
468 case 'w':
469 return top.evlist->nr_entries > 1 ? 1 : 0; 445 return top.evlist->nr_entries > 1 ? 1 : 0;
470 default: 446 default:
471 break; 447 break;
@@ -474,7 +450,7 @@ static int key_mapped(int c)
474 return 0; 450 return 0;
475} 451}
476 452
477static void handle_keypress(struct perf_session *session, int c) 453static void handle_keypress(int c)
478{ 454{
479 if (!key_mapped(c)) { 455 if (!key_mapped(c)) {
480 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 456 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
@@ -550,7 +526,7 @@ static void handle_keypress(struct perf_session *session, int c)
550 case 'Q': 526 case 'Q':
551 printf("exiting.\n"); 527 printf("exiting.\n");
552 if (dump_symtab) 528 if (dump_symtab)
553 perf_session__fprintf_dsos(session, stderr); 529 perf_session__fprintf_dsos(top.session, stderr);
554 exit(0); 530 exit(0);
555 case 's': 531 case 's':
556 prompt_symbol(&top.sym_filter_entry, "Enter details symbol"); 532 prompt_symbol(&top.sym_filter_entry, "Enter details symbol");
@@ -559,7 +535,7 @@ static void handle_keypress(struct perf_session *session, int c)
559 if (!top.sym_filter_entry) 535 if (!top.sym_filter_entry)
560 break; 536 break;
561 else { 537 else {
562 struct sym_entry *syme = top.sym_filter_entry; 538 struct hist_entry *syme = top.sym_filter_entry;
563 539
564 top.sym_filter_entry = NULL; 540 top.sym_filter_entry = NULL;
565 __zero_source_counters(syme); 541 __zero_source_counters(syme);
@@ -568,9 +544,6 @@ static void handle_keypress(struct perf_session *session, int c)
568 case 'U': 544 case 'U':
569 top.hide_user_symbols = !top.hide_user_symbols; 545 top.hide_user_symbols = !top.hide_user_symbols;
570 break; 546 break;
571 case 'w':
572 top.display_weighted = ~top.display_weighted;
573 break;
574 case 'z': 547 case 'z':
575 top.zero = !top.zero; 548 top.zero = !top.zero;
576 break; 549 break;
@@ -579,19 +552,30 @@ static void handle_keypress(struct perf_session *session, int c)
579 } 552 }
580} 553}
581 554
555static void perf_top__sort_new_samples(void *arg)
556{
557 struct perf_top *t = arg;
558 perf_top__reset_sample_counters(t);
559
560 if (t->evlist->selected != NULL)
561 t->sym_evsel = t->evlist->selected;
562
563 hists__collapse_resort_threaded(&t->sym_evsel->hists);
564 hists__output_resort_threaded(&t->sym_evsel->hists);
565 hists__decay_entries_threaded(&t->sym_evsel->hists,
566 top.hide_user_symbols,
567 top.hide_kernel_symbols);
568}
569
582static void *display_thread_tui(void *arg __used) 570static void *display_thread_tui(void *arg __used)
583{ 571{
584 int err = 0; 572 const char *help = "For a higher level overview, try: perf top --sort comm,dso";
585 pthread_mutex_lock(&top.active_symbols_lock); 573
586 while (list_empty(&top.active_symbols)) { 574 perf_top__sort_new_samples(&top);
587 err = pthread_cond_wait(&top.active_symbols_cond, 575 perf_evlist__tui_browse_hists(top.evlist, help,
588 &top.active_symbols_lock); 576 perf_top__sort_new_samples,
589 if (err) 577 &top, top.delay_secs);
590 break; 578
591 }
592 pthread_mutex_unlock(&top.active_symbols_lock);
593 if (!err)
594 perf_top__tui_browser(&top);
595 exit_browser(0); 579 exit_browser(0);
596 exit(0); 580 exit(0);
597 return NULL; 581 return NULL;
@@ -602,7 +586,6 @@ static void *display_thread(void *arg __used)
602 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 586 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
603 struct termios tc, save; 587 struct termios tc, save;
604 int delay_msecs, c; 588 int delay_msecs, c;
605 struct perf_session *session = (struct perf_session *) arg;
606 589
607 tcgetattr(0, &save); 590 tcgetattr(0, &save);
608 tc = save; 591 tc = save;
@@ -610,20 +593,35 @@ static void *display_thread(void *arg __used)
610 tc.c_cc[VMIN] = 0; 593 tc.c_cc[VMIN] = 0;
611 tc.c_cc[VTIME] = 0; 594 tc.c_cc[VTIME] = 0;
612 595
596 pthread__unblock_sigwinch();
613repeat: 597repeat:
614 delay_msecs = top.delay_secs * 1000; 598 delay_msecs = top.delay_secs * 1000;
615 tcsetattr(0, TCSANOW, &tc); 599 tcsetattr(0, TCSANOW, &tc);
616 /* trash return*/ 600 /* trash return*/
617 getc(stdin); 601 getc(stdin);
618 602
619 do { 603 while (1) {
620 print_sym_table(session); 604 print_sym_table();
621 } while (!poll(&stdin_poll, 1, delay_msecs) == 1); 605 /*
622 606 * Either timeout expired or we got an EINTR due to SIGWINCH,
607 * refresh screen in both cases.
608 */
609 switch (poll(&stdin_poll, 1, delay_msecs)) {
610 case 0:
611 continue;
612 case -1:
613 if (errno == EINTR)
614 continue;
615 /* Fall trhu */
616 default:
617 goto process_hotkey;
618 }
619 }
620process_hotkey:
623 c = getc(stdin); 621 c = getc(stdin);
624 tcsetattr(0, TCSAFLUSH, &save); 622 tcsetattr(0, TCSAFLUSH, &save);
625 623
626 handle_keypress(session, c); 624 handle_keypress(c);
627 goto repeat; 625 goto repeat;
628 626
629 return NULL; 627 return NULL;
@@ -644,9 +642,8 @@ static const char *skip_symbols[] = {
644 NULL 642 NULL
645}; 643};
646 644
647static int symbol_filter(struct map *map, struct symbol *sym) 645static int symbol_filter(struct map *map __used, struct symbol *sym)
648{ 646{
649 struct sym_entry *syme;
650 const char *name = sym->name; 647 const char *name = sym->name;
651 int i; 648 int i;
652 649
@@ -666,16 +663,6 @@ static int symbol_filter(struct map *map, struct symbol *sym)
666 strstr(name, "_text_end")) 663 strstr(name, "_text_end"))
667 return 1; 664 return 1;
668 665
669 syme = symbol__priv(sym);
670 syme->map = map;
671 symbol__annotate_init(map, sym);
672
673 if (!top.sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) {
674 /* schedule initial sym_filter_entry setup */
675 sym_filter_entry_sched = syme;
676 sym_filter = NULL;
677 }
678
679 for (i = 0; skip_symbols[i]; i++) { 666 for (i = 0; skip_symbols[i]; i++) {
680 if (!strcmp(skip_symbols[i], name)) { 667 if (!strcmp(skip_symbols[i], name)) {
681 sym->ignore = true; 668 sym->ignore = true;
@@ -687,13 +674,15 @@ static int symbol_filter(struct map *map, struct symbol *sym)
687} 674}
688 675
689static void perf_event__process_sample(const union perf_event *event, 676static void perf_event__process_sample(const union perf_event *event,
677 struct perf_evsel *evsel,
690 struct perf_sample *sample, 678 struct perf_sample *sample,
691 struct perf_session *session) 679 struct perf_session *session)
692{ 680{
681 struct symbol *parent = NULL;
693 u64 ip = event->ip.ip; 682 u64 ip = event->ip.ip;
694 struct sym_entry *syme;
695 struct addr_location al; 683 struct addr_location al;
696 struct machine *machine; 684 struct machine *machine;
685 int err;
697 u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 686 u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
698 687
699 ++top.samples; 688 ++top.samples;
@@ -782,51 +771,43 @@ static void perf_event__process_sample(const union perf_event *event,
782 sleep(5); 771 sleep(5);
783 vmlinux_warned = true; 772 vmlinux_warned = true;
784 } 773 }
785
786 return;
787 } 774 }
788 775
789 /* let's see, whether we need to install initial sym_filter_entry */ 776 if (al.sym == NULL || !al.sym->ignore) {
790 if (sym_filter_entry_sched) { 777 struct hist_entry *he;
791 top.sym_filter_entry = sym_filter_entry_sched; 778
792 sym_filter_entry_sched = NULL; 779 if ((sort__has_parent || symbol_conf.use_callchain) &&
793 if (parse_source(top.sym_filter_entry) < 0) { 780 sample->callchain) {
794 struct symbol *sym = sym_entry__symbol(top.sym_filter_entry); 781 err = perf_session__resolve_callchain(session, al.thread,
795 782 sample->callchain, &parent);
796 pr_err("Can't annotate %s", sym->name); 783 if (err)
797 if (top.sym_filter_entry->map->dso->symtab_type == SYMTAB__KALLSYMS) { 784 return;
798 pr_err(": No vmlinux file was found in the path:\n");
799 machine__fprintf_vmlinux_path(machine, stderr);
800 } else
801 pr_err(".\n");
802 exit(1);
803 } 785 }
804 }
805 786
806 syme = symbol__priv(al.sym); 787 he = perf_session__add_hist_entry(session, &al, sample, evsel);
807 if (!al.sym->ignore) { 788 if (he == NULL) {
808 struct perf_evsel *evsel; 789 pr_err("Problem incrementing symbol period, skipping event\n");
790 return;
791 }
809 792
810 evsel = perf_evlist__id2evsel(top.evlist, sample->id); 793 if (symbol_conf.use_callchain) {
811 assert(evsel != NULL); 794 err = callchain_append(he->callchain, &session->callchain_cursor,
812 syme->count[evsel->idx]++; 795 sample->period);
813 record_precise_ip(syme, evsel->idx, ip); 796 if (err)
814 pthread_mutex_lock(&top.active_symbols_lock); 797 return;
815 if (list_empty(&syme->node) || !syme->node.next) {
816 static bool first = true;
817 __list_insert_active_sym(syme);
818 if (first) {
819 pthread_cond_broadcast(&top.active_symbols_cond);
820 first = false;
821 }
822 } 798 }
823 pthread_mutex_unlock(&top.active_symbols_lock); 799
800 if (sort_has_symbols)
801 record_precise_ip(he, evsel->idx, ip);
824 } 802 }
803
804 return;
825} 805}
826 806
827static void perf_session__mmap_read_idx(struct perf_session *self, int idx) 807static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
828{ 808{
829 struct perf_sample sample; 809 struct perf_sample sample;
810 struct perf_evsel *evsel;
830 union perf_event *event; 811 union perf_event *event;
831 int ret; 812 int ret;
832 813
@@ -837,10 +818,16 @@ static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
837 continue; 818 continue;
838 } 819 }
839 820
821 evsel = perf_evlist__id2evsel(self->evlist, sample.id);
822 assert(evsel != NULL);
823
840 if (event->header.type == PERF_RECORD_SAMPLE) 824 if (event->header.type == PERF_RECORD_SAMPLE)
841 perf_event__process_sample(event, &sample, self); 825 perf_event__process_sample(event, evsel, &sample, self);
842 else 826 else if (event->header.type < PERF_RECORD_MAX) {
827 hists__inc_nr_events(&evsel->hists, event->header.type);
843 perf_event__process(event, &sample, self); 828 perf_event__process(event, &sample, self);
829 } else
830 ++self->hists.stats.nr_unknown_events;
844 } 831 }
845} 832}
846 833
@@ -854,10 +841,16 @@ static void perf_session__mmap_read(struct perf_session *self)
854 841
855static void start_counters(struct perf_evlist *evlist) 842static void start_counters(struct perf_evlist *evlist)
856{ 843{
857 struct perf_evsel *counter; 844 struct perf_evsel *counter, *first;
845
846 first = list_entry(evlist->entries.next, struct perf_evsel, node);
858 847
859 list_for_each_entry(counter, &evlist->entries, node) { 848 list_for_each_entry(counter, &evlist->entries, node) {
860 struct perf_event_attr *attr = &counter->attr; 849 struct perf_event_attr *attr = &counter->attr;
850 struct xyarray *group_fd = NULL;
851
852 if (group && counter != first)
853 group_fd = first->fd;
861 854
862 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 855 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
863 856
@@ -872,16 +865,29 @@ static void start_counters(struct perf_evlist *evlist)
872 attr->read_format |= PERF_FORMAT_ID; 865 attr->read_format |= PERF_FORMAT_ID;
873 } 866 }
874 867
868 if (symbol_conf.use_callchain)
869 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
870
875 attr->mmap = 1; 871 attr->mmap = 1;
872 attr->comm = 1;
876 attr->inherit = inherit; 873 attr->inherit = inherit;
874retry_sample_id:
875 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
877try_again: 876try_again:
878 if (perf_evsel__open(counter, top.evlist->cpus, 877 if (perf_evsel__open(counter, top.evlist->cpus,
879 top.evlist->threads, group) < 0) { 878 top.evlist->threads, group,
879 group_fd) < 0) {
880 int err = errno; 880 int err = errno;
881 881
882 if (err == EPERM || err == EACCES) { 882 if (err == EPERM || err == EACCES) {
883 ui__warning_paranoid(); 883 ui__error_paranoid();
884 goto out_err; 884 goto out_err;
885 } else if (err == EINVAL && sample_id_all_avail) {
886 /*
887 * Old kernel, no attr->sample_id_type_all field
888 */
889 sample_id_all_avail = false;
890 goto retry_sample_id;
885 } 891 }
886 /* 892 /*
887 * If it's cycles then fall back to hrtimer 893 * If it's cycles then fall back to hrtimer
@@ -927,35 +933,56 @@ out_err:
927 exit(0); 933 exit(0);
928} 934}
929 935
936static int setup_sample_type(void)
937{
938 if (!sort_has_symbols) {
939 if (symbol_conf.use_callchain) {
940 ui__warning("Selected -g but \"sym\" not present in --sort/-s.");
941 return -EINVAL;
942 }
943 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE) {
944 if (callchain_register_param(&callchain_param) < 0) {
945 ui__warning("Can't register callchain params.\n");
946 return -EINVAL;
947 }
948 }
949
950 return 0;
951}
952
930static int __cmd_top(void) 953static int __cmd_top(void)
931{ 954{
932 pthread_t thread; 955 pthread_t thread;
933 int ret __used; 956 int ret;
934 /* 957 /*
935 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 958 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
936 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 959 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
937 */ 960 */
938 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL); 961 top.session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
939 if (session == NULL) 962 if (top.session == NULL)
940 return -ENOMEM; 963 return -ENOMEM;
941 964
965 ret = setup_sample_type();
966 if (ret)
967 goto out_delete;
968
942 if (top.target_tid != -1) 969 if (top.target_tid != -1)
943 perf_event__synthesize_thread_map(top.evlist->threads, 970 perf_event__synthesize_thread_map(top.evlist->threads,
944 perf_event__process, session); 971 perf_event__process, top.session);
945 else 972 else
946 perf_event__synthesize_threads(perf_event__process, session); 973 perf_event__synthesize_threads(perf_event__process, top.session);
947 974
948 start_counters(top.evlist); 975 start_counters(top.evlist);
949 session->evlist = top.evlist; 976 top.session->evlist = top.evlist;
950 perf_session__update_sample_type(session); 977 perf_session__update_sample_type(top.session);
951 978
952 /* Wait for a minimal set of events before starting the snapshot */ 979 /* Wait for a minimal set of events before starting the snapshot */
953 poll(top.evlist->pollfd, top.evlist->nr_fds, 100); 980 poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
954 981
955 perf_session__mmap_read(session); 982 perf_session__mmap_read(top.session);
956 983
957 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : 984 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
958 display_thread), session)) { 985 display_thread), NULL)) {
959 printf("Could not create display thread.\n"); 986 printf("Could not create display thread.\n");
960 exit(-1); 987 exit(-1);
961 } 988 }
@@ -973,12 +1000,96 @@ static int __cmd_top(void)
973 while (1) { 1000 while (1) {
974 u64 hits = top.samples; 1001 u64 hits = top.samples;
975 1002
976 perf_session__mmap_read(session); 1003 perf_session__mmap_read(top.session);
977 1004
978 if (hits == top.samples) 1005 if (hits == top.samples)
979 ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100); 1006 ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
980 } 1007 }
981 1008
1009out_delete:
1010 perf_session__delete(top.session);
1011 top.session = NULL;
1012
1013 return 0;
1014}
1015
1016static int
1017parse_callchain_opt(const struct option *opt __used, const char *arg,
1018 int unset)
1019{
1020 char *tok, *tok2;
1021 char *endptr;
1022
1023 /*
1024 * --no-call-graph
1025 */
1026 if (unset) {
1027 dont_use_callchains = true;
1028 return 0;
1029 }
1030
1031 symbol_conf.use_callchain = true;
1032
1033 if (!arg)
1034 return 0;
1035
1036 tok = strtok((char *)arg, ",");
1037 if (!tok)
1038 return -1;
1039
1040 /* get the output mode */
1041 if (!strncmp(tok, "graph", strlen(arg)))
1042 callchain_param.mode = CHAIN_GRAPH_ABS;
1043
1044 else if (!strncmp(tok, "flat", strlen(arg)))
1045 callchain_param.mode = CHAIN_FLAT;
1046
1047 else if (!strncmp(tok, "fractal", strlen(arg)))
1048 callchain_param.mode = CHAIN_GRAPH_REL;
1049
1050 else if (!strncmp(tok, "none", strlen(arg))) {
1051 callchain_param.mode = CHAIN_NONE;
1052 symbol_conf.use_callchain = false;
1053
1054 return 0;
1055 }
1056
1057 else
1058 return -1;
1059
1060 /* get the min percentage */
1061 tok = strtok(NULL, ",");
1062 if (!tok)
1063 goto setup;
1064
1065 callchain_param.min_percent = strtod(tok, &endptr);
1066 if (tok == endptr)
1067 return -1;
1068
1069 /* get the print limit */
1070 tok2 = strtok(NULL, ",");
1071 if (!tok2)
1072 goto setup;
1073
1074 if (tok2[0] != 'c') {
1075 callchain_param.print_limit = strtod(tok2, &endptr);
1076 tok2 = strtok(NULL, ",");
1077 if (!tok2)
1078 goto setup;
1079 }
1080
1081 /* get the call chain order */
1082 if (!strcmp(tok2, "caller"))
1083 callchain_param.order = ORDER_CALLER;
1084 else if (!strcmp(tok2, "callee"))
1085 callchain_param.order = ORDER_CALLEE;
1086 else
1087 return -1;
1088setup:
1089 if (callchain_register_param(&callchain_param) < 0) {
1090 fprintf(stderr, "Can't register callchain params\n");
1091 return -1;
1092 }
982 return 0; 1093 return 0;
983} 1094}
984 1095
@@ -1018,7 +1129,7 @@ static const struct option options[] = {
1018 "put the counters into a counter group"), 1129 "put the counters into a counter group"),
1019 OPT_BOOLEAN('i', "inherit", &inherit, 1130 OPT_BOOLEAN('i', "inherit", &inherit,
1020 "child tasks inherit counters"), 1131 "child tasks inherit counters"),
1021 OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name", 1132 OPT_STRING(0, "sym-annotate", &sym_filter, "symbol name",
1022 "symbol to annotate"), 1133 "symbol to annotate"),
1023 OPT_BOOLEAN('z', "zero", &top.zero, 1134 OPT_BOOLEAN('z', "zero", &top.zero,
1024 "zero history across updates"), 1135 "zero history across updates"),
@@ -1032,6 +1143,28 @@ static const struct option options[] = {
1032 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 1143 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
1033 OPT_INCR('v', "verbose", &verbose, 1144 OPT_INCR('v', "verbose", &verbose,
1034 "be more verbose (show counter open errors, etc)"), 1145 "be more verbose (show counter open errors, etc)"),
1146 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1147 "sort by key(s): pid, comm, dso, symbol, parent"),
1148 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1149 "Show a column with the number of samples"),
1150 OPT_CALLBACK_DEFAULT('G', "call-graph", NULL, "output_type,min_percent, call_order",
1151 "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. "
1152 "Default: fractal,0.5,callee", &parse_callchain_opt,
1153 callchain_default_opt),
1154 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1155 "Show a column with the sum of periods"),
1156 OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
1157 "only consider symbols in these dsos"),
1158 OPT_STRING(0, "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
1159 "only consider symbols in these comms"),
1160 OPT_STRING(0, "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
1161 "only consider these symbols"),
1162 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
1163 "Interleave source code with assembly code (default)"),
1164 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
1165 "Display raw encoding of assembly instructions (default)"),
1166 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1167 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1035 OPT_END() 1168 OPT_END()
1036}; 1169};
1037 1170
@@ -1044,18 +1177,16 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1044 if (top.evlist == NULL) 1177 if (top.evlist == NULL)
1045 return -ENOMEM; 1178 return -ENOMEM;
1046 1179
1047 page_size = sysconf(_SC_PAGE_SIZE); 1180 symbol_conf.exclude_other = false;
1048 1181
1049 argc = parse_options(argc, argv, options, top_usage, 0); 1182 argc = parse_options(argc, argv, options, top_usage, 0);
1050 if (argc) 1183 if (argc)
1051 usage_with_options(top_usage, options); 1184 usage_with_options(top_usage, options);
1052 1185
1053 /* 1186 if (sort_order == default_sort_order)
1054 * XXX For now start disabled, only using TUI if explicitely asked for. 1187 sort_order = "dso,symbol";
1055 * Change that when handle_keys equivalent gets written, live annotation 1188
1056 * done, etc. 1189 setup_sorting(top_usage, options);
1057 */
1058 use_browser = 0;
1059 1190
1060 if (use_stdio) 1191 if (use_stdio)
1061 use_browser = 0; 1192 use_browser = 0;
@@ -1118,13 +1249,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1118 1249
1119 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 1250 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
1120 1251
1121 symbol_conf.priv_size = (sizeof(struct sym_entry) + sizeof(struct annotation) + 1252 symbol_conf.priv_size = sizeof(struct annotation);
1122 (top.evlist->nr_entries + 1) * sizeof(unsigned long));
1123 1253
1124 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1254 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1125 if (symbol__init() < 0) 1255 if (symbol__init() < 0)
1126 return -1; 1256 return -1;
1127 1257
1258 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
1259 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
1260 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
1261
1262 /*
1263 * Avoid annotation data structures overhead when symbols aren't on the
1264 * sort list.
1265 */
1266 sort_has_symbols = sort_sym.list.next != NULL;
1267
1128 get_term_dimensions(&winsize); 1268 get_term_dimensions(&winsize);
1129 if (top.print_entries == 0) { 1269 if (top.print_entries == 0) {
1130 update_print_entries(&winsize); 1270 update_print_entries(&winsize);
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 4702e2443a8e..b382bd551aac 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -4,7 +4,6 @@
4#include "util/util.h" 4#include "util/util.h"
5#include "util/strbuf.h" 5#include "util/strbuf.h"
6 6
7extern const char perf_version_string[];
8extern const char perf_usage_string[]; 7extern const char perf_usage_string[];
9extern const char perf_more_info_string[]; 8extern const char perf_more_info_string[];
10 9
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index ec635b7cc8ea..73d0cac8b67e 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -427,6 +427,24 @@ static void get_debugfs_mntpt(void)
427 debugfs_mntpt[0] = '\0'; 427 debugfs_mntpt[0] = '\0';
428} 428}
429 429
430static void pthread__block_sigwinch(void)
431{
432 sigset_t set;
433
434 sigemptyset(&set);
435 sigaddset(&set, SIGWINCH);
436 pthread_sigmask(SIG_BLOCK, &set, NULL);
437}
438
439void pthread__unblock_sigwinch(void)
440{
441 sigset_t set;
442
443 sigemptyset(&set);
444 sigaddset(&set, SIGWINCH);
445 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
446}
447
430int main(int argc, const char **argv) 448int main(int argc, const char **argv)
431{ 449{
432 const char *cmd; 450 const char *cmd;
@@ -480,6 +498,12 @@ int main(int argc, const char **argv)
480 * time. 498 * time.
481 */ 499 */
482 setup_path(); 500 setup_path();
501 /*
502 * Block SIGWINCH notifications so that the thread that wants it can
503 * unblock and get syscalls like select interrupted instead of waiting
504 * forever while the signal goes to some other non interested thread.
505 */
506 pthread__block_sigwinch();
483 507
484 while (1) { 508 while (1) {
485 static int done_help; 509 static int done_help;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index a5fc660c1f12..914c895510f7 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -9,18 +9,21 @@ void get_term_dimensions(struct winsize *ws);
9#include "../../arch/x86/include/asm/unistd.h" 9#include "../../arch/x86/include/asm/unistd.h"
10#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 10#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
11#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 11#define cpu_relax() asm volatile("rep; nop" ::: "memory");
12#define CPUINFO_PROC "model name"
12#endif 13#endif
13 14
14#if defined(__x86_64__) 15#if defined(__x86_64__)
15#include "../../arch/x86/include/asm/unistd.h" 16#include "../../arch/x86/include/asm/unistd.h"
16#define rmb() asm volatile("lfence" ::: "memory") 17#define rmb() asm volatile("lfence" ::: "memory")
17#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 18#define cpu_relax() asm volatile("rep; nop" ::: "memory");
19#define CPUINFO_PROC "model name"
18#endif 20#endif
19 21
20#ifdef __powerpc__ 22#ifdef __powerpc__
21#include "../../arch/powerpc/include/asm/unistd.h" 23#include "../../arch/powerpc/include/asm/unistd.h"
22#define rmb() asm volatile ("sync" ::: "memory") 24#define rmb() asm volatile ("sync" ::: "memory")
23#define cpu_relax() asm volatile ("" ::: "memory"); 25#define cpu_relax() asm volatile ("" ::: "memory");
26#define CPUINFO_PROC "cpu"
24#endif 27#endif
25 28
26#ifdef __s390__ 29#ifdef __s390__
@@ -37,30 +40,35 @@ void get_term_dimensions(struct winsize *ws);
37# define rmb() asm volatile("" ::: "memory") 40# define rmb() asm volatile("" ::: "memory")
38#endif 41#endif
39#define cpu_relax() asm volatile("" ::: "memory") 42#define cpu_relax() asm volatile("" ::: "memory")
43#define CPUINFO_PROC "cpu type"
40#endif 44#endif
41 45
42#ifdef __hppa__ 46#ifdef __hppa__
43#include "../../arch/parisc/include/asm/unistd.h" 47#include "../../arch/parisc/include/asm/unistd.h"
44#define rmb() asm volatile("" ::: "memory") 48#define rmb() asm volatile("" ::: "memory")
45#define cpu_relax() asm volatile("" ::: "memory"); 49#define cpu_relax() asm volatile("" ::: "memory");
50#define CPUINFO_PROC "cpu"
46#endif 51#endif
47 52
48#ifdef __sparc__ 53#ifdef __sparc__
49#include "../../arch/sparc/include/asm/unistd.h" 54#include "../../arch/sparc/include/asm/unistd.h"
50#define rmb() asm volatile("":::"memory") 55#define rmb() asm volatile("":::"memory")
51#define cpu_relax() asm volatile("":::"memory") 56#define cpu_relax() asm volatile("":::"memory")
57#define CPUINFO_PROC "cpu"
52#endif 58#endif
53 59
54#ifdef __alpha__ 60#ifdef __alpha__
55#include "../../arch/alpha/include/asm/unistd.h" 61#include "../../arch/alpha/include/asm/unistd.h"
56#define rmb() asm volatile("mb" ::: "memory") 62#define rmb() asm volatile("mb" ::: "memory")
57#define cpu_relax() asm volatile("" ::: "memory") 63#define cpu_relax() asm volatile("" ::: "memory")
64#define CPUINFO_PROC "cpu model"
58#endif 65#endif
59 66
60#ifdef __ia64__ 67#ifdef __ia64__
61#include "../../arch/ia64/include/asm/unistd.h" 68#include "../../arch/ia64/include/asm/unistd.h"
62#define rmb() asm volatile ("mf" ::: "memory") 69#define rmb() asm volatile ("mf" ::: "memory")
63#define cpu_relax() asm volatile ("hint @pause" ::: "memory") 70#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
71#define CPUINFO_PROC "model name"
64#endif 72#endif
65 73
66#ifdef __arm__ 74#ifdef __arm__
@@ -71,6 +79,7 @@ void get_term_dimensions(struct winsize *ws);
71 */ 79 */
72#define rmb() ((void(*)(void))0xffff0fa0)() 80#define rmb() ((void(*)(void))0xffff0fa0)()
73#define cpu_relax() asm volatile("":::"memory") 81#define cpu_relax() asm volatile("":::"memory")
82#define CPUINFO_PROC "Processor"
74#endif 83#endif
75 84
76#ifdef __mips__ 85#ifdef __mips__
@@ -83,6 +92,7 @@ void get_term_dimensions(struct winsize *ws);
83 : /* no input */ \ 92 : /* no input */ \
84 : "memory") 93 : "memory")
85#define cpu_relax() asm volatile("" ::: "memory") 94#define cpu_relax() asm volatile("" ::: "memory")
95#define CPUINFO_PROC "cpu model"
86#endif 96#endif
87 97
88#include <time.h> 98#include <time.h>
@@ -171,5 +181,8 @@ struct ip_callchain {
171}; 181};
172 182
173extern bool perf_host, perf_guest; 183extern bool perf_host, perf_guest;
184extern const char perf_version_string[];
185
186void pthread__unblock_sigwinch(void);
174 187
175#endif 188#endif
diff --git a/tools/perf/scripts/python/bin/net_dropmonitor-record b/tools/perf/scripts/python/bin/net_dropmonitor-record
new file mode 100755
index 000000000000..423fb81dadae
--- /dev/null
+++ b/tools/perf/scripts/python/bin/net_dropmonitor-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -e skb:kfree_skb $@
diff --git a/tools/perf/scripts/python/bin/net_dropmonitor-report b/tools/perf/scripts/python/bin/net_dropmonitor-report
new file mode 100755
index 000000000000..8d698f5a06aa
--- /dev/null
+++ b/tools/perf/scripts/python/bin/net_dropmonitor-report
@@ -0,0 +1,4 @@
1#!/bin/bash
2# description: display a table of dropped frames
3
4perf script -s "$PERF_EXEC_PATH"/scripts/python/net_dropmonitor.py $@
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
new file mode 100755
index 000000000000..a4ffc9500023
--- /dev/null
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -0,0 +1,72 @@
1# Monitor the system for dropped packets and proudce a report of drop locations and counts
2
3import os
4import sys
5
6sys.path.append(os.environ['PERF_EXEC_PATH'] + \
7 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
8
9from perf_trace_context import *
10from Core import *
11from Util import *
12
13drop_log = {}
14kallsyms = []
15
16def get_kallsyms_table():
17 global kallsyms
18 try:
19 f = open("/proc/kallsyms", "r")
20 linecount = 0
21 for line in f:
22 linecount = linecount+1
23 f.seek(0)
24 except:
25 return
26
27
28 j = 0
29 for line in f:
30 loc = int(line.split()[0], 16)
31 name = line.split()[2]
32 j = j +1
33 if ((j % 100) == 0):
34 print "\r" + str(j) + "/" + str(linecount),
35 kallsyms.append({ 'loc': loc, 'name' : name})
36
37 print "\r" + str(j) + "/" + str(linecount)
38 kallsyms.sort()
39 return
40
41def get_sym(sloc):
42 loc = int(sloc)
43 for i in kallsyms:
44 if (i['loc'] >= loc):
45 return (i['name'], i['loc']-loc)
46 return (None, 0)
47
48def print_drop_table():
49 print "%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT")
50 for i in drop_log.keys():
51 (sym, off) = get_sym(i)
52 if sym == None:
53 sym = i
54 print "%25s %25s %25s" % (sym, off, drop_log[i])
55
56
57def trace_begin():
58 print "Starting trace (Ctrl-C to dump results)"
59
60def trace_end():
61 print "Gathering kallsyms data"
62 get_kallsyms_table()
63 print_drop_table()
64
65# called from perf, when it finds a correspoinding event
66def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
67 skbaddr, protocol, location):
68 slocation = str(location)
69 try:
70 drop_log[slocation] = drop_log[slocation] + 1
71 except:
72 drop_log[slocation] = 1
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index e01af2b1a469..119e996035c8 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -16,6 +16,8 @@
16#include "annotate.h" 16#include "annotate.h"
17#include <pthread.h> 17#include <pthread.h>
18 18
19const char *disassembler_style;
20
19int symbol__annotate_init(struct map *map __used, struct symbol *sym) 21int symbol__annotate_init(struct map *map __used, struct symbol *sym)
20{ 22{
21 struct annotation *notes = symbol__annotation(sym); 23 struct annotation *notes = symbol__annotation(sym);
@@ -308,9 +310,12 @@ fallback:
308 } 310 }
309 err = -ENOENT; 311 err = -ENOENT;
310 dso->annotate_warned = 1; 312 dso->annotate_warned = 1;
311 pr_err("Can't annotate %s: No vmlinux file%s was found in the " 313 pr_err("Can't annotate %s:\n\n"
312 "path.\nPlease use 'perf buildid-cache -av vmlinux' or " 314 "No vmlinux file%s\nwas found in the path.\n\n"
313 "--vmlinux vmlinux.\n", 315 "Please use:\n\n"
316 " perf buildid-cache -av vmlinux\n\n"
317 "or:\n\n"
318 " --vmlinux vmlinux",
314 sym->name, build_id_msg ?: ""); 319 sym->name, build_id_msg ?: "");
315 goto out_free_filename; 320 goto out_free_filename;
316 } 321 }
@@ -323,10 +328,15 @@ fallback:
323 dso, dso->long_name, sym, sym->name); 328 dso, dso->long_name, sym, sym->name);
324 329
325 snprintf(command, sizeof(command), 330 snprintf(command, sizeof(command),
326 "objdump --start-address=0x%016" PRIx64 331 "objdump %s%s --start-address=0x%016" PRIx64
327 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand", 332 " --stop-address=0x%016" PRIx64
333 " -d %s %s -C %s|grep -v %s|expand",
334 disassembler_style ? "-M " : "",
335 disassembler_style ? disassembler_style : "",
328 map__rip_2objdump(map, sym->start), 336 map__rip_2objdump(map, sym->start),
329 map__rip_2objdump(map, sym->end), 337 map__rip_2objdump(map, sym->end),
338 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
339 symbol_conf.annotate_src ? "-S" : "",
330 symfs_filename, filename); 340 symfs_filename, filename);
331 341
332 pr_debug("Executing: %s\n", command); 342 pr_debug("Executing: %s\n", command);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index c2c286896801..d9072523d342 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -91,13 +91,18 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
91#ifdef NO_NEWT_SUPPORT 91#ifdef NO_NEWT_SUPPORT
92static inline int symbol__tui_annotate(struct symbol *sym __used, 92static inline int symbol__tui_annotate(struct symbol *sym __used,
93 struct map *map __used, 93 struct map *map __used,
94 int evidx __used, int refresh __used) 94 int evidx __used,
95 void(*timer)(void *arg) __used,
96 void *arg __used, int delay_secs __used)
95{ 97{
96 return 0; 98 return 0;
97} 99}
98#else 100#else
99int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 101int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
100 int refresh); 102 int nr_events, void(*timer)(void *arg), void *arg,
103 int delay_secs);
101#endif 104#endif
102 105
106extern const char *disassembler_style;
107
103#endif /* __PERF_ANNOTATE_H */ 108#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index e191eb9a667f..521c38a79190 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -200,7 +200,7 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
200 * Auto-detect: 200 * Auto-detect:
201 */ 201 */
202 if (perf_use_color_default < 0) { 202 if (perf_use_color_default < 0) {
203 if (isatty(1) || pager_in_use()) 203 if (isatty(fileno(fp)) || pager_in_use())
204 perf_use_color_default = 1; 204 perf_use_color_default = 1;
205 else 205 else
206 perf_use_color_default = 0; 206 perf_use_color_default = 0;
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index e02d78cae70f..80d9598db31a 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -341,7 +341,7 @@ const char *perf_config_dirname(const char *name, const char *value)
341 341
342static int perf_default_core_config(const char *var __used, const char *value __used) 342static int perf_default_core_config(const char *var __used, const char *value __used)
343{ 343{
344 /* Add other config variables here and to Documentation/config.txt. */ 344 /* Add other config variables here. */
345 return 0; 345 return 0;
346} 346}
347 347
@@ -350,7 +350,7 @@ int perf_default_config(const char *var, const char *value, void *dummy __used)
350 if (!prefixcmp(var, "core.")) 350 if (!prefixcmp(var, "core."))
351 return perf_default_core_config(var, value); 351 return perf_default_core_config(var, value);
352 352
353 /* Add other config variables here and to Documentation/config.txt. */ 353 /* Add other config variables here. */
354 return 0; 354 return 0;
355} 355}
356 356
@@ -399,7 +399,6 @@ static int perf_config_global(void)
399int perf_config(config_fn_t fn, void *data) 399int perf_config(config_fn_t fn, void *data)
400{ 400{
401 int ret = 0, found = 0; 401 int ret = 0, found = 0;
402 char *repo_config = NULL;
403 const char *home = NULL; 402 const char *home = NULL;
404 403
405 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ 404 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
@@ -414,19 +413,32 @@ int perf_config(config_fn_t fn, void *data)
414 home = getenv("HOME"); 413 home = getenv("HOME");
415 if (perf_config_global() && home) { 414 if (perf_config_global() && home) {
416 char *user_config = strdup(mkpath("%s/.perfconfig", home)); 415 char *user_config = strdup(mkpath("%s/.perfconfig", home));
417 if (!access(user_config, R_OK)) { 416 struct stat st;
418 ret += perf_config_from_file(fn, user_config, data); 417
419 found += 1; 418 if (user_config == NULL) {
419 warning("Not enough memory to process %s/.perfconfig, "
420 "ignoring it.", home);
421 goto out;
420 } 422 }
421 free(user_config);
422 }
423 423
424 repo_config = perf_pathdup("config"); 424 if (stat(user_config, &st) < 0)
425 if (!access(repo_config, R_OK)) { 425 goto out_free;
426 ret += perf_config_from_file(fn, repo_config, data); 426
427 if (st.st_uid && (st.st_uid != geteuid())) {
428 warning("File %s not owned by current user or root, "
429 "ignoring it.", user_config);
430 goto out_free;
431 }
432
433 if (!st.st_size)
434 goto out_free;
435
436 ret += perf_config_from_file(fn, user_config, data);
427 found += 1; 437 found += 1;
438out_free:
439 free(user_config);
428 } 440 }
429 free(repo_config); 441out:
430 if (found == 0) 442 if (found == 0)
431 return -1; 443 return -1;
432 return ret; 444 return ret;
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 155749d74350..26817daa2961 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -47,19 +47,20 @@ int dump_printf(const char *fmt, ...)
47} 47}
48 48
49#ifdef NO_NEWT_SUPPORT 49#ifdef NO_NEWT_SUPPORT
50void ui__warning(const char *format, ...) 50int ui__warning(const char *format, ...)
51{ 51{
52 va_list args; 52 va_list args;
53 53
54 va_start(args, format); 54 va_start(args, format);
55 vfprintf(stderr, format, args); 55 vfprintf(stderr, format, args);
56 va_end(args); 56 va_end(args);
57 return 0;
57} 58}
58#endif 59#endif
59 60
60void ui__warning_paranoid(void) 61int ui__error_paranoid(void)
61{ 62{
62 ui__warning("Permission error - are you root?\n" 63 return ui__error("Permission error - are you root?\n"
63 "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" 64 "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
64 " -1 - Not paranoid at all\n" 65 " -1 - Not paranoid at all\n"
65 " 0 - Disallow raw tracepoint access for unpriv\n" 66 " 0 - Disallow raw tracepoint access for unpriv\n"
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index fd53db47e3de..f2ce88d04f54 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -19,23 +19,18 @@ static inline int ui_helpline__show_help(const char *format __used, va_list ap _
19 return 0; 19 return 0;
20} 20}
21 21
22static inline struct ui_progress *ui_progress__new(const char *title __used, 22static inline void ui_progress__update(u64 curr __used, u64 total __used,
23 u64 total __used) 23 const char *title __used) {}
24{
25 return (struct ui_progress *)1;
26}
27
28static inline void ui_progress__update(struct ui_progress *self __used,
29 u64 curr __used) {}
30 24
31static inline void ui_progress__delete(struct ui_progress *self __used) {} 25#define ui__error(format, arg...) ui__warning(format, ##arg)
32#else 26#else
33extern char ui_helpline__last_msg[]; 27extern char ui_helpline__last_msg[];
34int ui_helpline__show_help(const char *format, va_list ap); 28int ui_helpline__show_help(const char *format, va_list ap);
35#include "ui/progress.h" 29#include "ui/progress.h"
30int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
36#endif 31#endif
37 32
38void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 33int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
39void ui__warning_paranoid(void); 34int ui__error_paranoid(void);
40 35
41#endif /* __PERF_DEBUG_H */ 36#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index fddf40f30d3e..ee51e9b4dc09 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -96,6 +96,39 @@ int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
96 return *lineno ?: -ENOENT; 96 return *lineno ?: -ENOENT;
97} 97}
98 98
99static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
100
101/**
102 * cu_walk_functions_at - Walk on function DIEs at given address
103 * @cu_die: A CU DIE
104 * @addr: An address
105 * @callback: A callback which called with found DIEs
106 * @data: A user data
107 *
108 * Walk on function DIEs at given @addr in @cu_die. Passed DIEs
109 * should be subprogram or inlined-subroutines.
110 */
111int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
112 int (*callback)(Dwarf_Die *, void *), void *data)
113{
114 Dwarf_Die die_mem;
115 Dwarf_Die *sc_die;
116 int ret = -ENOENT;
117
118 /* Inlined function could be recursive. Trace it until fail */
119 for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
120 sc_die != NULL;
121 sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
122 &die_mem)) {
123 ret = callback(sc_die, data);
124 if (ret)
125 break;
126 }
127
128 return ret;
129
130}
131
99/** 132/**
100 * die_compare_name - Compare diename and tname 133 * die_compare_name - Compare diename and tname
101 * @dw_die: a DIE 134 * @dw_die: a DIE
@@ -198,6 +231,19 @@ static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
198 return 0; 231 return 0;
199} 232}
200 233
234/* Get attribute and translate it as a sdata */
235static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
236 Dwarf_Sword *result)
237{
238 Dwarf_Attribute attr;
239
240 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
241 dwarf_formsdata(&attr, result) != 0)
242 return -ENOENT;
243
244 return 0;
245}
246
201/** 247/**
202 * die_is_signed_type - Check whether a type DIE is signed or not 248 * die_is_signed_type - Check whether a type DIE is signed or not
203 * @tp_die: a DIE of a type 249 * @tp_die: a DIE of a type
@@ -250,6 +296,50 @@ int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
250 return 0; 296 return 0;
251} 297}
252 298
299/* Get the call file index number in CU DIE */
300static int die_get_call_fileno(Dwarf_Die *in_die)
301{
302 Dwarf_Sword idx;
303
304 if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
305 return (int)idx;
306 else
307 return -ENOENT;
308}
309
310/* Get the declared file index number in CU DIE */
311static int die_get_decl_fileno(Dwarf_Die *pdie)
312{
313 Dwarf_Sword idx;
314
315 if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
316 return (int)idx;
317 else
318 return -ENOENT;
319}
320
321/**
322 * die_get_call_file - Get callsite file name of inlined function instance
323 * @in_die: a DIE of an inlined function instance
324 *
325 * Get call-site file name of @in_die. This means from which file the inline
326 * function is called.
327 */
328const char *die_get_call_file(Dwarf_Die *in_die)
329{
330 Dwarf_Die cu_die;
331 Dwarf_Files *files;
332 int idx;
333
334 idx = die_get_call_fileno(in_die);
335 if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
336 dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
337 return NULL;
338
339 return dwarf_filesrc(files, idx, NULL, NULL);
340}
341
342
253/** 343/**
254 * die_find_child - Generic DIE search function in DIE tree 344 * die_find_child - Generic DIE search function in DIE tree
255 * @rt_die: a root DIE 345 * @rt_die: a root DIE
@@ -374,9 +464,78 @@ Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
374 return die_mem; 464 return die_mem;
375} 465}
376 466
467struct __instance_walk_param {
468 void *addr;
469 int (*callback)(Dwarf_Die *, void *);
470 void *data;
471 int retval;
472};
473
474static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
475{
476 struct __instance_walk_param *iwp = data;
477 Dwarf_Attribute attr_mem;
478 Dwarf_Die origin_mem;
479 Dwarf_Attribute *attr;
480 Dwarf_Die *origin;
481 int tmp;
482
483 attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
484 if (attr == NULL)
485 return DIE_FIND_CB_CONTINUE;
486
487 origin = dwarf_formref_die(attr, &origin_mem);
488 if (origin == NULL || origin->addr != iwp->addr)
489 return DIE_FIND_CB_CONTINUE;
490
491 /* Ignore redundant instances */
492 if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
493 dwarf_decl_line(origin, &tmp);
494 if (die_get_call_lineno(inst) == tmp) {
495 tmp = die_get_decl_fileno(origin);
496 if (die_get_call_fileno(inst) == tmp)
497 return DIE_FIND_CB_CONTINUE;
498 }
499 }
500
501 iwp->retval = iwp->callback(inst, iwp->data);
502
503 return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
504}
505
506/**
507 * die_walk_instances - Walk on instances of given DIE
508 * @or_die: an abstract original DIE
509 * @callback: a callback function which is called with instance DIE
510 * @data: user data
511 *
512 * Walk on the instances of give @in_die. @in_die must be an inlined function
513 * declartion. This returns the return value of @callback if it returns
514 * non-zero value, or -ENOENT if there is no instance.
515 */
516int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
517 void *data)
518{
519 Dwarf_Die cu_die;
520 Dwarf_Die die_mem;
521 struct __instance_walk_param iwp = {
522 .addr = or_die->addr,
523 .callback = callback,
524 .data = data,
525 .retval = -ENOENT,
526 };
527
528 if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
529 return -ENOENT;
530
531 die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
532
533 return iwp.retval;
534}
535
377/* Line walker internal parameters */ 536/* Line walker internal parameters */
378struct __line_walk_param { 537struct __line_walk_param {
379 const char *fname; 538 bool recursive;
380 line_walk_callback_t callback; 539 line_walk_callback_t callback;
381 void *data; 540 void *data;
382 int retval; 541 int retval;
@@ -385,39 +544,56 @@ struct __line_walk_param {
385static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) 544static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
386{ 545{
387 struct __line_walk_param *lw = data; 546 struct __line_walk_param *lw = data;
388 Dwarf_Addr addr; 547 Dwarf_Addr addr = 0;
548 const char *fname;
389 int lineno; 549 int lineno;
390 550
391 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) { 551 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
552 fname = die_get_call_file(in_die);
392 lineno = die_get_call_lineno(in_die); 553 lineno = die_get_call_lineno(in_die);
393 if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) { 554 if (fname && lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
394 lw->retval = lw->callback(lw->fname, lineno, addr, 555 lw->retval = lw->callback(fname, lineno, addr, lw->data);
395 lw->data);
396 if (lw->retval != 0) 556 if (lw->retval != 0)
397 return DIE_FIND_CB_END; 557 return DIE_FIND_CB_END;
398 } 558 }
399 } 559 }
400 return DIE_FIND_CB_SIBLING; 560 if (!lw->recursive)
561 /* Don't need to search recursively */
562 return DIE_FIND_CB_SIBLING;
563
564 if (addr) {
565 fname = dwarf_decl_file(in_die);
566 if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
567 lw->retval = lw->callback(fname, lineno, addr, lw->data);
568 if (lw->retval != 0)
569 return DIE_FIND_CB_END;
570 }
571 }
572
573 /* Continue to search nested inlined function call-sites */
574 return DIE_FIND_CB_CONTINUE;
401} 575}
402 576
403/* Walk on lines of blocks included in given DIE */ 577/* Walk on lines of blocks included in given DIE */
404static int __die_walk_funclines(Dwarf_Die *sp_die, 578static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
405 line_walk_callback_t callback, void *data) 579 line_walk_callback_t callback, void *data)
406{ 580{
407 struct __line_walk_param lw = { 581 struct __line_walk_param lw = {
582 .recursive = recursive,
408 .callback = callback, 583 .callback = callback,
409 .data = data, 584 .data = data,
410 .retval = 0, 585 .retval = 0,
411 }; 586 };
412 Dwarf_Die die_mem; 587 Dwarf_Die die_mem;
413 Dwarf_Addr addr; 588 Dwarf_Addr addr;
589 const char *fname;
414 int lineno; 590 int lineno;
415 591
416 /* Handle function declaration line */ 592 /* Handle function declaration line */
417 lw.fname = dwarf_decl_file(sp_die); 593 fname = dwarf_decl_file(sp_die);
418 if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 && 594 if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
419 dwarf_entrypc(sp_die, &addr) == 0) { 595 dwarf_entrypc(sp_die, &addr) == 0) {
420 lw.retval = callback(lw.fname, lineno, addr, data); 596 lw.retval = callback(fname, lineno, addr, data);
421 if (lw.retval != 0) 597 if (lw.retval != 0)
422 goto done; 598 goto done;
423 } 599 }
@@ -430,7 +606,7 @@ static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
430{ 606{
431 struct __line_walk_param *lw = data; 607 struct __line_walk_param *lw = data;
432 608
433 lw->retval = __die_walk_funclines(sp_die, lw->callback, lw->data); 609 lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
434 if (lw->retval != 0) 610 if (lw->retval != 0)
435 return DWARF_CB_ABORT; 611 return DWARF_CB_ABORT;
436 612
@@ -439,7 +615,7 @@ static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
439 615
440/** 616/**
441 * die_walk_lines - Walk on lines inside given DIE 617 * die_walk_lines - Walk on lines inside given DIE
442 * @rt_die: a root DIE (CU or subprogram) 618 * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)
443 * @callback: callback routine 619 * @callback: callback routine
444 * @data: user data 620 * @data: user data
445 * 621 *
@@ -460,12 +636,12 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
460 size_t nlines, i; 636 size_t nlines, i;
461 637
462 /* Get the CU die */ 638 /* Get the CU die */
463 if (dwarf_tag(rt_die) == DW_TAG_subprogram) 639 if (dwarf_tag(rt_die) != DW_TAG_compile_unit)
464 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL); 640 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
465 else 641 else
466 cu_die = rt_die; 642 cu_die = rt_die;
467 if (!cu_die) { 643 if (!cu_die) {
468 pr_debug2("Failed to get CU from subprogram\n"); 644 pr_debug2("Failed to get CU from given DIE.\n");
469 return -EINVAL; 645 return -EINVAL;
470 } 646 }
471 647
@@ -509,7 +685,11 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
509 * subroutines. We have to check functions list or given function. 685 * subroutines. We have to check functions list or given function.
510 */ 686 */
511 if (rt_die != cu_die) 687 if (rt_die != cu_die)
512 ret = __die_walk_funclines(rt_die, callback, data); 688 /*
689 * Don't need walk functions recursively, because nested
690 * inlined functions don't have lines of the specified DIE.
691 */
692 ret = __die_walk_funclines(rt_die, false, callback, data);
513 else { 693 else {
514 struct __line_walk_param param = { 694 struct __line_walk_param param = {
515 .callback = callback, 695 .callback = callback,
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index bc3b21167e70..6ce1717784b7 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -34,12 +34,19 @@ extern const char *cu_get_comp_dir(Dwarf_Die *cu_die);
34extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, 34extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
35 const char **fname, int *lineno); 35 const char **fname, int *lineno);
36 36
37/* Walk on funcitons at given address */
38extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
39 int (*callback)(Dwarf_Die *, void *), void *data);
40
37/* Compare diename and tname */ 41/* Compare diename and tname */
38extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); 42extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
39 43
40/* Get callsite line number of inline-function instance */ 44/* Get callsite line number of inline-function instance */
41extern int die_get_call_lineno(Dwarf_Die *in_die); 45extern int die_get_call_lineno(Dwarf_Die *in_die);
42 46
47/* Get callsite file name of inlined function instance */
48extern const char *die_get_call_file(Dwarf_Die *in_die);
49
43/* Get type die */ 50/* Get type die */
44extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); 51extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
45 52
@@ -73,6 +80,10 @@ extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
73extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 80extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
74 Dwarf_Die *die_mem); 81 Dwarf_Die *die_mem);
75 82
83/* Walk on the instances of given DIE */
84extern int die_walk_instances(Dwarf_Die *in_die,
85 int (*callback)(Dwarf_Die *, void *), void *data);
86
76/* Walker on lines (Note: line number will not be sorted) */ 87/* Walker on lines (Note: line number will not be sorted) */
77typedef int (* line_walk_callback_t) (const char *fname, int lineno, 88typedef int (* line_walk_callback_t) (const char *fname, int lineno,
78 Dwarf_Addr addr, void *data); 89 Dwarf_Addr addr, void *data);
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 3c1b8a632101..437f8ca679a0 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -169,12 +169,17 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
169 continue; 169 continue;
170 pbf += n + 3; 170 pbf += n + 3;
171 if (*pbf == 'x') { /* vm_exec */ 171 if (*pbf == 'x') { /* vm_exec */
172 char anonstr[] = "//anon\n";
172 char *execname = strchr(bf, '/'); 173 char *execname = strchr(bf, '/');
173 174
174 /* Catch VDSO */ 175 /* Catch VDSO */
175 if (execname == NULL) 176 if (execname == NULL)
176 execname = strstr(bf, "[vdso]"); 177 execname = strstr(bf, "[vdso]");
177 178
179 /* Catch anonymous mmaps */
180 if ((execname == NULL) && !strstr(bf, "["))
181 execname = anonstr;
182
178 if (execname == NULL) 183 if (execname == NULL)
179 continue; 184 continue;
180 185
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1d7f66488a88..357a85b85248 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -186,6 +186,6 @@ const char *perf_event__name(unsigned int id);
186 186
187int perf_event__parse_sample(const union perf_event *event, u64 type, 187int perf_event__parse_sample(const union perf_event *event, u64 type,
188 int sample_size, bool sample_id_all, 188 int sample_size, bool sample_id_all,
189 struct perf_sample *sample); 189 struct perf_sample *sample, bool swapped);
190 190
191#endif /* __PERF_RECORD_H */ 191#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b021ea9265c3..fbb4b4ab9cc6 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -85,10 +85,45 @@ int perf_evlist__add_default(struct perf_evlist *evlist)
85 struct perf_evsel *evsel = perf_evsel__new(&attr, 0); 85 struct perf_evsel *evsel = perf_evsel__new(&attr, 0);
86 86
87 if (evsel == NULL) 87 if (evsel == NULL)
88 return -ENOMEM; 88 goto error;
89
90 /* use strdup() because free(evsel) assumes name is allocated */
91 evsel->name = strdup("cycles");
92 if (!evsel->name)
93 goto error_free;
89 94
90 perf_evlist__add(evlist, evsel); 95 perf_evlist__add(evlist, evsel);
91 return 0; 96 return 0;
97error_free:
98 perf_evsel__delete(evsel);
99error:
100 return -ENOMEM;
101}
102
103void perf_evlist__disable(struct perf_evlist *evlist)
104{
105 int cpu, thread;
106 struct perf_evsel *pos;
107
108 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
109 list_for_each_entry(pos, &evlist->entries, node) {
110 for (thread = 0; thread < evlist->threads->nr; thread++)
111 ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_DISABLE);
112 }
113 }
114}
115
116void perf_evlist__enable(struct perf_evlist *evlist)
117{
118 int cpu, thread;
119 struct perf_evsel *pos;
120
121 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
122 list_for_each_entry(pos, &evlist->entries, node) {
123 for (thread = 0; thread < evlist->threads->nr; thread++)
124 ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_ENABLE);
125 }
126 }
92} 127}
93 128
94int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 129int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
@@ -498,3 +533,39 @@ bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
498 first = list_entry(evlist->entries.next, struct perf_evsel, node); 533 first = list_entry(evlist->entries.next, struct perf_evsel, node);
499 return first->attr.sample_id_all; 534 return first->attr.sample_id_all;
500} 535}
536
537void perf_evlist__set_selected(struct perf_evlist *evlist,
538 struct perf_evsel *evsel)
539{
540 evlist->selected = evsel;
541}
542
543int perf_evlist__open(struct perf_evlist *evlist, bool group)
544{
545 struct perf_evsel *evsel, *first;
546 int err, ncpus, nthreads;
547
548 first = list_entry(evlist->entries.next, struct perf_evsel, node);
549
550 list_for_each_entry(evsel, &evlist->entries, node) {
551 struct xyarray *group_fd = NULL;
552
553 if (group && evsel != first)
554 group_fd = first->fd;
555
556 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads,
557 group, group_fd);
558 if (err < 0)
559 goto out_err;
560 }
561
562 return 0;
563out_err:
564 ncpus = evlist->cpus ? evlist->cpus->nr : 1;
565 nthreads = evlist->threads ? evlist->threads->nr : 1;
566
567 list_for_each_entry_reverse(evsel, &evlist->entries, node)
568 perf_evsel__close(evsel, ncpus, nthreads);
569
570 return err;
571}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index b2b862374f37..1779ffef7828 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -25,6 +25,7 @@ struct perf_evlist {
25 struct pollfd *pollfd; 25 struct pollfd *pollfd;
26 struct thread_map *threads; 26 struct thread_map *threads;
27 struct cpu_map *cpus; 27 struct cpu_map *cpus;
28 struct perf_evsel *selected;
28}; 29};
29 30
30struct perf_evsel; 31struct perf_evsel;
@@ -49,10 +50,18 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
49 50
50union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); 51union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
51 52
53int perf_evlist__open(struct perf_evlist *evlist, bool group);
54
52int perf_evlist__alloc_mmap(struct perf_evlist *evlist); 55int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
53int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); 56int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
54void perf_evlist__munmap(struct perf_evlist *evlist); 57void perf_evlist__munmap(struct perf_evlist *evlist);
55 58
59void perf_evlist__disable(struct perf_evlist *evlist);
60void perf_evlist__enable(struct perf_evlist *evlist);
61
62void perf_evlist__set_selected(struct perf_evlist *evlist,
63 struct perf_evsel *evsel);
64
56static inline void perf_evlist__set_maps(struct perf_evlist *evlist, 65static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
57 struct cpu_map *cpus, 66 struct cpu_map *cpus,
58 struct thread_map *threads) 67 struct thread_map *threads)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index a03a36b7908a..e42626422587 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -7,6 +7,8 @@
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9 9
10#include <byteswap.h>
11#include "asm/bug.h"
10#include "evsel.h" 12#include "evsel.h"
11#include "evlist.h" 13#include "evlist.h"
12#include "util.h" 14#include "util.h"
@@ -14,6 +16,7 @@
14#include "thread_map.h" 16#include "thread_map.h"
15 17
16#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 18#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
19#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
17 20
18int __perf_evsel__sample_size(u64 sample_type) 21int __perf_evsel__sample_size(u64 sample_type)
19{ 22{
@@ -37,6 +40,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
37 evsel->idx = idx; 40 evsel->idx = idx;
38 evsel->attr = *attr; 41 evsel->attr = *attr;
39 INIT_LIST_HEAD(&evsel->node); 42 INIT_LIST_HEAD(&evsel->node);
43 hists__init(&evsel->hists);
40} 44}
41 45
42struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) 46struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
@@ -201,15 +205,16 @@ int __perf_evsel__read(struct perf_evsel *evsel,
201} 205}
202 206
203static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 207static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
204 struct thread_map *threads, bool group) 208 struct thread_map *threads, bool group,
209 struct xyarray *group_fds)
205{ 210{
206 int cpu, thread; 211 int cpu, thread;
207 unsigned long flags = 0; 212 unsigned long flags = 0;
208 int pid = -1; 213 int pid = -1, err;
209 214
210 if (evsel->fd == NULL && 215 if (evsel->fd == NULL &&
211 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 216 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
212 return -1; 217 return -ENOMEM;
213 218
214 if (evsel->cgrp) { 219 if (evsel->cgrp) {
215 flags = PERF_FLAG_PID_CGROUP; 220 flags = PERF_FLAG_PID_CGROUP;
@@ -217,7 +222,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
217 } 222 }
218 223
219 for (cpu = 0; cpu < cpus->nr; cpu++) { 224 for (cpu = 0; cpu < cpus->nr; cpu++) {
220 int group_fd = -1; 225 int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;
221 226
222 for (thread = 0; thread < threads->nr; thread++) { 227 for (thread = 0; thread < threads->nr; thread++) {
223 228
@@ -228,8 +233,10 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
228 pid, 233 pid,
229 cpus->map[cpu], 234 cpus->map[cpu],
230 group_fd, flags); 235 group_fd, flags);
231 if (FD(evsel, cpu, thread) < 0) 236 if (FD(evsel, cpu, thread) < 0) {
237 err = -errno;
232 goto out_close; 238 goto out_close;
239 }
233 240
234 if (group && group_fd == -1) 241 if (group && group_fd == -1)
235 group_fd = FD(evsel, cpu, thread); 242 group_fd = FD(evsel, cpu, thread);
@@ -246,7 +253,17 @@ out_close:
246 } 253 }
247 thread = threads->nr; 254 thread = threads->nr;
248 } while (--cpu >= 0); 255 } while (--cpu >= 0);
249 return -1; 256 return err;
257}
258
259void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
260{
261 if (evsel->fd == NULL)
262 return;
263
264 perf_evsel__close_fd(evsel, ncpus, nthreads);
265 perf_evsel__free_fd(evsel);
266 evsel->fd = NULL;
250} 267}
251 268
252static struct { 269static struct {
@@ -266,7 +283,8 @@ static struct {
266}; 283};
267 284
268int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 285int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
269 struct thread_map *threads, bool group) 286 struct thread_map *threads, bool group,
287 struct xyarray *group_fd)
270{ 288{
271 if (cpus == NULL) { 289 if (cpus == NULL) {
272 /* Work around old compiler warnings about strict aliasing */ 290 /* Work around old compiler warnings about strict aliasing */
@@ -276,19 +294,23 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
276 if (threads == NULL) 294 if (threads == NULL)
277 threads = &empty_thread_map.map; 295 threads = &empty_thread_map.map;
278 296
279 return __perf_evsel__open(evsel, cpus, threads, group); 297 return __perf_evsel__open(evsel, cpus, threads, group, group_fd);
280} 298}
281 299
282int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 300int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
283 struct cpu_map *cpus, bool group) 301 struct cpu_map *cpus, bool group,
302 struct xyarray *group_fd)
284{ 303{
285 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group); 304 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group,
305 group_fd);
286} 306}
287 307
288int perf_evsel__open_per_thread(struct perf_evsel *evsel, 308int perf_evsel__open_per_thread(struct perf_evsel *evsel,
289 struct thread_map *threads, bool group) 309 struct thread_map *threads, bool group,
310 struct xyarray *group_fd)
290{ 311{
291 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group); 312 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group,
313 group_fd);
292} 314}
293 315
294static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 316static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
@@ -342,10 +364,20 @@ static bool sample_overlap(const union perf_event *event,
342 364
343int perf_event__parse_sample(const union perf_event *event, u64 type, 365int perf_event__parse_sample(const union perf_event *event, u64 type,
344 int sample_size, bool sample_id_all, 366 int sample_size, bool sample_id_all,
345 struct perf_sample *data) 367 struct perf_sample *data, bool swapped)
346{ 368{
347 const u64 *array; 369 const u64 *array;
348 370
371 /*
372 * used for cross-endian analysis. See git commit 65014ab3
373 * for why this goofiness is needed.
374 */
375 union {
376 u64 val64;
377 u32 val32[2];
378 } u;
379
380
349 data->cpu = data->pid = data->tid = -1; 381 data->cpu = data->pid = data->tid = -1;
350 data->stream_id = data->id = data->time = -1ULL; 382 data->stream_id = data->id = data->time = -1ULL;
351 383
@@ -366,9 +398,16 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
366 } 398 }
367 399
368 if (type & PERF_SAMPLE_TID) { 400 if (type & PERF_SAMPLE_TID) {
369 u32 *p = (u32 *)array; 401 u.val64 = *array;
370 data->pid = p[0]; 402 if (swapped) {
371 data->tid = p[1]; 403 /* undo swap of u64, then swap on individual u32s */
404 u.val64 = bswap_64(u.val64);
405 u.val32[0] = bswap_32(u.val32[0]);
406 u.val32[1] = bswap_32(u.val32[1]);
407 }
408
409 data->pid = u.val32[0];
410 data->tid = u.val32[1];
372 array++; 411 array++;
373 } 412 }
374 413
@@ -395,8 +434,15 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
395 } 434 }
396 435
397 if (type & PERF_SAMPLE_CPU) { 436 if (type & PERF_SAMPLE_CPU) {
398 u32 *p = (u32 *)array; 437
399 data->cpu = *p; 438 u.val64 = *array;
439 if (swapped) {
440 /* undo swap of u64, then swap on individual u32s */
441 u.val64 = bswap_64(u.val64);
442 u.val32[0] = bswap_32(u.val32[0]);
443 }
444
445 data->cpu = u.val32[0];
400 array++; 446 array++;
401 } 447 }
402 448
@@ -423,18 +469,27 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
423 } 469 }
424 470
425 if (type & PERF_SAMPLE_RAW) { 471 if (type & PERF_SAMPLE_RAW) {
426 u32 *p = (u32 *)array; 472 const u64 *pdata;
473
474 u.val64 = *array;
475 if (WARN_ONCE(swapped,
476 "Endianness of raw data not corrected!\n")) {
477 /* undo swap of u64, then swap on individual u32s */
478 u.val64 = bswap_64(u.val64);
479 u.val32[0] = bswap_32(u.val32[0]);
480 u.val32[1] = bswap_32(u.val32[1]);
481 }
427 482
428 if (sample_overlap(event, array, sizeof(u32))) 483 if (sample_overlap(event, array, sizeof(u32)))
429 return -EFAULT; 484 return -EFAULT;
430 485
431 data->raw_size = *p; 486 data->raw_size = u.val32[0];
432 p++; 487 pdata = (void *) array + sizeof(u32);
433 488
434 if (sample_overlap(event, p, data->raw_size)) 489 if (sample_overlap(event, pdata, data->raw_size))
435 return -EFAULT; 490 return -EFAULT;
436 491
437 data->raw_data = p; 492 data->raw_data = (void *) pdata;
438 } 493 }
439 494
440 return 0; 495 return 0;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index e9a31554e265..b1d15e6f7ae3 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -82,11 +82,15 @@ void perf_evsel__free_id(struct perf_evsel *evsel);
82void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 82void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
83 83
84int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 84int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
85 struct cpu_map *cpus, bool group); 85 struct cpu_map *cpus, bool group,
86 struct xyarray *group_fds);
86int perf_evsel__open_per_thread(struct perf_evsel *evsel, 87int perf_evsel__open_per_thread(struct perf_evsel *evsel,
87 struct thread_map *threads, bool group); 88 struct thread_map *threads, bool group,
89 struct xyarray *group_fds);
88int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 90int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
89 struct thread_map *threads, bool group); 91 struct thread_map *threads, bool group,
92 struct xyarray *group_fds);
93void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
90 94
91#define perf_evsel__match(evsel, t, c) \ 95#define perf_evsel__match(evsel, t, c) \
92 (evsel->attr.type == PERF_TYPE_##t && \ 96 (evsel->attr.type == PERF_TYPE_##t && \
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index cb2959a3fb43..bcd05d05b4f0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1,5 +1,6 @@
1#define _FILE_OFFSET_BITS 64 1#define _FILE_OFFSET_BITS 64
2 2
3#include "util.h"
3#include <sys/types.h> 4#include <sys/types.h>
4#include <byteswap.h> 5#include <byteswap.h>
5#include <unistd.h> 6#include <unistd.h>
@@ -7,22 +8,29 @@
7#include <stdlib.h> 8#include <stdlib.h>
8#include <linux/list.h> 9#include <linux/list.h>
9#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <sys/utsname.h>
10 12
11#include "evlist.h" 13#include "evlist.h"
12#include "evsel.h" 14#include "evsel.h"
13#include "util.h"
14#include "header.h" 15#include "header.h"
15#include "../perf.h" 16#include "../perf.h"
16#include "trace-event.h" 17#include "trace-event.h"
17#include "session.h" 18#include "session.h"
18#include "symbol.h" 19#include "symbol.h"
19#include "debug.h" 20#include "debug.h"
21#include "cpumap.h"
20 22
21static bool no_buildid_cache = false; 23static bool no_buildid_cache = false;
22 24
23static int event_count; 25static int event_count;
24static struct perf_trace_event_type *events; 26static struct perf_trace_event_type *events;
25 27
28static u32 header_argc;
29static const char **header_argv;
30
31static int dsos__write_buildid_table(struct perf_header *header, int fd);
32static int perf_session__cache_build_ids(struct perf_session *session);
33
26int perf_header__push_event(u64 id, const char *name) 34int perf_header__push_event(u64 id, const char *name)
27{ 35{
28 if (strlen(name) > MAX_EVENT_NAME) 36 if (strlen(name) > MAX_EVENT_NAME)
@@ -110,6 +118,1020 @@ static int write_padded(int fd, const void *bf, size_t count,
110 return err; 118 return err;
111} 119}
112 120
121static int do_write_string(int fd, const char *str)
122{
123 u32 len, olen;
124 int ret;
125
126 olen = strlen(str) + 1;
127 len = ALIGN(olen, NAME_ALIGN);
128
129 /* write len, incl. \0 */
130 ret = do_write(fd, &len, sizeof(len));
131 if (ret < 0)
132 return ret;
133
134 return write_padded(fd, str, olen, len);
135}
136
137static char *do_read_string(int fd, struct perf_header *ph)
138{
139 ssize_t sz, ret;
140 u32 len;
141 char *buf;
142
143 sz = read(fd, &len, sizeof(len));
144 if (sz < (ssize_t)sizeof(len))
145 return NULL;
146
147 if (ph->needs_swap)
148 len = bswap_32(len);
149
150 buf = malloc(len);
151 if (!buf)
152 return NULL;
153
154 ret = read(fd, buf, len);
155 if (ret == (ssize_t)len) {
156 /*
157 * strings are padded by zeroes
158 * thus the actual strlen of buf
159 * may be less than len
160 */
161 return buf;
162 }
163
164 free(buf);
165 return NULL;
166}
167
168int
169perf_header__set_cmdline(int argc, const char **argv)
170{
171 int i;
172
173 header_argc = (u32)argc;
174
175 /* do not include NULL termination */
176 header_argv = calloc(argc, sizeof(char *));
177 if (!header_argv)
178 return -ENOMEM;
179
180 /*
181 * must copy argv contents because it gets moved
182 * around during option parsing
183 */
184 for (i = 0; i < argc ; i++)
185 header_argv[i] = argv[i];
186
187 return 0;
188}
189
190static int write_trace_info(int fd, struct perf_header *h __used,
191 struct perf_evlist *evlist)
192{
193 return read_tracing_data(fd, &evlist->entries);
194}
195
196
197static int write_build_id(int fd, struct perf_header *h,
198 struct perf_evlist *evlist __used)
199{
200 struct perf_session *session;
201 int err;
202
203 session = container_of(h, struct perf_session, header);
204
205 err = dsos__write_buildid_table(h, fd);
206 if (err < 0) {
207 pr_debug("failed to write buildid table\n");
208 return err;
209 }
210 if (!no_buildid_cache)
211 perf_session__cache_build_ids(session);
212
213 return 0;
214}
215
216static int write_hostname(int fd, struct perf_header *h __used,
217 struct perf_evlist *evlist __used)
218{
219 struct utsname uts;
220 int ret;
221
222 ret = uname(&uts);
223 if (ret < 0)
224 return -1;
225
226 return do_write_string(fd, uts.nodename);
227}
228
229static int write_osrelease(int fd, struct perf_header *h __used,
230 struct perf_evlist *evlist __used)
231{
232 struct utsname uts;
233 int ret;
234
235 ret = uname(&uts);
236 if (ret < 0)
237 return -1;
238
239 return do_write_string(fd, uts.release);
240}
241
242static int write_arch(int fd, struct perf_header *h __used,
243 struct perf_evlist *evlist __used)
244{
245 struct utsname uts;
246 int ret;
247
248 ret = uname(&uts);
249 if (ret < 0)
250 return -1;
251
252 return do_write_string(fd, uts.machine);
253}
254
255static int write_version(int fd, struct perf_header *h __used,
256 struct perf_evlist *evlist __used)
257{
258 return do_write_string(fd, perf_version_string);
259}
260
261static int write_cpudesc(int fd, struct perf_header *h __used,
262 struct perf_evlist *evlist __used)
263{
264#ifndef CPUINFO_PROC
265#define CPUINFO_PROC NULL
266#endif
267 FILE *file;
268 char *buf = NULL;
269 char *s, *p;
270 const char *search = CPUINFO_PROC;
271 size_t len = 0;
272 int ret = -1;
273
274 if (!search)
275 return -1;
276
277 file = fopen("/proc/cpuinfo", "r");
278 if (!file)
279 return -1;
280
281 while (getline(&buf, &len, file) > 0) {
282 ret = strncmp(buf, search, strlen(search));
283 if (!ret)
284 break;
285 }
286
287 if (ret)
288 goto done;
289
290 s = buf;
291
292 p = strchr(buf, ':');
293 if (p && *(p+1) == ' ' && *(p+2))
294 s = p + 2;
295 p = strchr(s, '\n');
296 if (p)
297 *p = '\0';
298
299 /* squash extra space characters (branding string) */
300 p = s;
301 while (*p) {
302 if (isspace(*p)) {
303 char *r = p + 1;
304 char *q = r;
305 *p = ' ';
306 while (*q && isspace(*q))
307 q++;
308 if (q != (p+1))
309 while ((*r++ = *q++));
310 }
311 p++;
312 }
313 ret = do_write_string(fd, s);
314done:
315 free(buf);
316 fclose(file);
317 return ret;
318}
319
320static int write_nrcpus(int fd, struct perf_header *h __used,
321 struct perf_evlist *evlist __used)
322{
323 long nr;
324 u32 nrc, nra;
325 int ret;
326
327 nr = sysconf(_SC_NPROCESSORS_CONF);
328 if (nr < 0)
329 return -1;
330
331 nrc = (u32)(nr & UINT_MAX);
332
333 nr = sysconf(_SC_NPROCESSORS_ONLN);
334 if (nr < 0)
335 return -1;
336
337 nra = (u32)(nr & UINT_MAX);
338
339 ret = do_write(fd, &nrc, sizeof(nrc));
340 if (ret < 0)
341 return ret;
342
343 return do_write(fd, &nra, sizeof(nra));
344}
345
346static int write_event_desc(int fd, struct perf_header *h __used,
347 struct perf_evlist *evlist)
348{
349 struct perf_evsel *attr;
350 u32 nre = 0, nri, sz;
351 int ret;
352
353 list_for_each_entry(attr, &evlist->entries, node)
354 nre++;
355
356 /*
357 * write number of events
358 */
359 ret = do_write(fd, &nre, sizeof(nre));
360 if (ret < 0)
361 return ret;
362
363 /*
364 * size of perf_event_attr struct
365 */
366 sz = (u32)sizeof(attr->attr);
367 ret = do_write(fd, &sz, sizeof(sz));
368 if (ret < 0)
369 return ret;
370
371 list_for_each_entry(attr, &evlist->entries, node) {
372
373 ret = do_write(fd, &attr->attr, sz);
374 if (ret < 0)
375 return ret;
376 /*
377 * write number of unique id per event
378 * there is one id per instance of an event
379 *
380 * copy into an nri to be independent of the
381 * type of ids,
382 */
383 nri = attr->ids;
384 ret = do_write(fd, &nri, sizeof(nri));
385 if (ret < 0)
386 return ret;
387
388 /*
389 * write event string as passed on cmdline
390 */
391 ret = do_write_string(fd, attr->name);
392 if (ret < 0)
393 return ret;
394 /*
395 * write unique ids for this event
396 */
397 ret = do_write(fd, attr->id, attr->ids * sizeof(u64));
398 if (ret < 0)
399 return ret;
400 }
401 return 0;
402}
403
404static int write_cmdline(int fd, struct perf_header *h __used,
405 struct perf_evlist *evlist __used)
406{
407 char buf[MAXPATHLEN];
408 char proc[32];
409 u32 i, n;
410 int ret;
411
412 /*
413 * actual atual path to perf binary
414 */
415 sprintf(proc, "/proc/%d/exe", getpid());
416 ret = readlink(proc, buf, sizeof(buf));
417 if (ret <= 0)
418 return -1;
419
420 /* readlink() does not add null termination */
421 buf[ret] = '\0';
422
423 /* account for binary path */
424 n = header_argc + 1;
425
426 ret = do_write(fd, &n, sizeof(n));
427 if (ret < 0)
428 return ret;
429
430 ret = do_write_string(fd, buf);
431 if (ret < 0)
432 return ret;
433
434 for (i = 0 ; i < header_argc; i++) {
435 ret = do_write_string(fd, header_argv[i]);
436 if (ret < 0)
437 return ret;
438 }
439 return 0;
440}
441
442#define CORE_SIB_FMT \
443 "/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
444#define THRD_SIB_FMT \
445 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
446
447struct cpu_topo {
448 u32 core_sib;
449 u32 thread_sib;
450 char **core_siblings;
451 char **thread_siblings;
452};
453
454static int build_cpu_topo(struct cpu_topo *tp, int cpu)
455{
456 FILE *fp;
457 char filename[MAXPATHLEN];
458 char *buf = NULL, *p;
459 size_t len = 0;
460 u32 i = 0;
461 int ret = -1;
462
463 sprintf(filename, CORE_SIB_FMT, cpu);
464 fp = fopen(filename, "r");
465 if (!fp)
466 return -1;
467
468 if (getline(&buf, &len, fp) <= 0)
469 goto done;
470
471 fclose(fp);
472
473 p = strchr(buf, '\n');
474 if (p)
475 *p = '\0';
476
477 for (i = 0; i < tp->core_sib; i++) {
478 if (!strcmp(buf, tp->core_siblings[i]))
479 break;
480 }
481 if (i == tp->core_sib) {
482 tp->core_siblings[i] = buf;
483 tp->core_sib++;
484 buf = NULL;
485 len = 0;
486 }
487
488 sprintf(filename, THRD_SIB_FMT, cpu);
489 fp = fopen(filename, "r");
490 if (!fp)
491 goto done;
492
493 if (getline(&buf, &len, fp) <= 0)
494 goto done;
495
496 p = strchr(buf, '\n');
497 if (p)
498 *p = '\0';
499
500 for (i = 0; i < tp->thread_sib; i++) {
501 if (!strcmp(buf, tp->thread_siblings[i]))
502 break;
503 }
504 if (i == tp->thread_sib) {
505 tp->thread_siblings[i] = buf;
506 tp->thread_sib++;
507 buf = NULL;
508 }
509 ret = 0;
510done:
511 if(fp)
512 fclose(fp);
513 free(buf);
514 return ret;
515}
516
517static void free_cpu_topo(struct cpu_topo *tp)
518{
519 u32 i;
520
521 if (!tp)
522 return;
523
524 for (i = 0 ; i < tp->core_sib; i++)
525 free(tp->core_siblings[i]);
526
527 for (i = 0 ; i < tp->thread_sib; i++)
528 free(tp->thread_siblings[i]);
529
530 free(tp);
531}
532
533static struct cpu_topo *build_cpu_topology(void)
534{
535 struct cpu_topo *tp;
536 void *addr;
537 u32 nr, i;
538 size_t sz;
539 long ncpus;
540 int ret = -1;
541
542 ncpus = sysconf(_SC_NPROCESSORS_CONF);
543 if (ncpus < 0)
544 return NULL;
545
546 nr = (u32)(ncpus & UINT_MAX);
547
548 sz = nr * sizeof(char *);
549
550 addr = calloc(1, sizeof(*tp) + 2 * sz);
551 if (!addr)
552 return NULL;
553
554 tp = addr;
555
556 addr += sizeof(*tp);
557 tp->core_siblings = addr;
558 addr += sz;
559 tp->thread_siblings = addr;
560
561 for (i = 0; i < nr; i++) {
562 ret = build_cpu_topo(tp, i);
563 if (ret < 0)
564 break;
565 }
566 if (ret) {
567 free_cpu_topo(tp);
568 tp = NULL;
569 }
570 return tp;
571}
572
573static int write_cpu_topology(int fd, struct perf_header *h __used,
574 struct perf_evlist *evlist __used)
575{
576 struct cpu_topo *tp;
577 u32 i;
578 int ret;
579
580 tp = build_cpu_topology();
581 if (!tp)
582 return -1;
583
584 ret = do_write(fd, &tp->core_sib, sizeof(tp->core_sib));
585 if (ret < 0)
586 goto done;
587
588 for (i = 0; i < tp->core_sib; i++) {
589 ret = do_write_string(fd, tp->core_siblings[i]);
590 if (ret < 0)
591 goto done;
592 }
593 ret = do_write(fd, &tp->thread_sib, sizeof(tp->thread_sib));
594 if (ret < 0)
595 goto done;
596
597 for (i = 0; i < tp->thread_sib; i++) {
598 ret = do_write_string(fd, tp->thread_siblings[i]);
599 if (ret < 0)
600 break;
601 }
602done:
603 free_cpu_topo(tp);
604 return ret;
605}
606
607
608
609static int write_total_mem(int fd, struct perf_header *h __used,
610 struct perf_evlist *evlist __used)
611{
612 char *buf = NULL;
613 FILE *fp;
614 size_t len = 0;
615 int ret = -1, n;
616 uint64_t mem;
617
618 fp = fopen("/proc/meminfo", "r");
619 if (!fp)
620 return -1;
621
622 while (getline(&buf, &len, fp) > 0) {
623 ret = strncmp(buf, "MemTotal:", 9);
624 if (!ret)
625 break;
626 }
627 if (!ret) {
628 n = sscanf(buf, "%*s %"PRIu64, &mem);
629 if (n == 1)
630 ret = do_write(fd, &mem, sizeof(mem));
631 }
632 free(buf);
633 fclose(fp);
634 return ret;
635}
636
637static int write_topo_node(int fd, int node)
638{
639 char str[MAXPATHLEN];
640 char field[32];
641 char *buf = NULL, *p;
642 size_t len = 0;
643 FILE *fp;
644 u64 mem_total, mem_free, mem;
645 int ret = -1;
646
647 sprintf(str, "/sys/devices/system/node/node%d/meminfo", node);
648 fp = fopen(str, "r");
649 if (!fp)
650 return -1;
651
652 while (getline(&buf, &len, fp) > 0) {
653 /* skip over invalid lines */
654 if (!strchr(buf, ':'))
655 continue;
656 if (sscanf(buf, "%*s %*d %s %"PRIu64, field, &mem) != 2)
657 goto done;
658 if (!strcmp(field, "MemTotal:"))
659 mem_total = mem;
660 if (!strcmp(field, "MemFree:"))
661 mem_free = mem;
662 }
663
664 fclose(fp);
665
666 ret = do_write(fd, &mem_total, sizeof(u64));
667 if (ret)
668 goto done;
669
670 ret = do_write(fd, &mem_free, sizeof(u64));
671 if (ret)
672 goto done;
673
674 ret = -1;
675 sprintf(str, "/sys/devices/system/node/node%d/cpulist", node);
676
677 fp = fopen(str, "r");
678 if (!fp)
679 goto done;
680
681 if (getline(&buf, &len, fp) <= 0)
682 goto done;
683
684 p = strchr(buf, '\n');
685 if (p)
686 *p = '\0';
687
688 ret = do_write_string(fd, buf);
689done:
690 free(buf);
691 fclose(fp);
692 return ret;
693}
694
695static int write_numa_topology(int fd, struct perf_header *h __used,
696 struct perf_evlist *evlist __used)
697{
698 char *buf = NULL;
699 size_t len = 0;
700 FILE *fp;
701 struct cpu_map *node_map = NULL;
702 char *c;
703 u32 nr, i, j;
704 int ret = -1;
705
706 fp = fopen("/sys/devices/system/node/online", "r");
707 if (!fp)
708 return -1;
709
710 if (getline(&buf, &len, fp) <= 0)
711 goto done;
712
713 c = strchr(buf, '\n');
714 if (c)
715 *c = '\0';
716
717 node_map = cpu_map__new(buf);
718 if (!node_map)
719 goto done;
720
721 nr = (u32)node_map->nr;
722
723 ret = do_write(fd, &nr, sizeof(nr));
724 if (ret < 0)
725 goto done;
726
727 for (i = 0; i < nr; i++) {
728 j = (u32)node_map->map[i];
729 ret = do_write(fd, &j, sizeof(j));
730 if (ret < 0)
731 break;
732
733 ret = write_topo_node(fd, i);
734 if (ret < 0)
735 break;
736 }
737done:
738 free(buf);
739 fclose(fp);
740 free(node_map);
741 return ret;
742}
743
744/*
745 * default get_cpuid(): nothing gets recorded
746 * actual implementation must be in arch/$(ARCH)/util/header.c
747 */
748int __attribute__((weak)) get_cpuid(char *buffer __used, size_t sz __used)
749{
750 return -1;
751}
752
753static int write_cpuid(int fd, struct perf_header *h __used,
754 struct perf_evlist *evlist __used)
755{
756 char buffer[64];
757 int ret;
758
759 ret = get_cpuid(buffer, sizeof(buffer));
760 if (!ret)
761 goto write_it;
762
763 return -1;
764write_it:
765 return do_write_string(fd, buffer);
766}
767
768static void print_hostname(struct perf_header *ph, int fd, FILE *fp)
769{
770 char *str = do_read_string(fd, ph);
771 fprintf(fp, "# hostname : %s\n", str);
772 free(str);
773}
774
775static void print_osrelease(struct perf_header *ph, int fd, FILE *fp)
776{
777 char *str = do_read_string(fd, ph);
778 fprintf(fp, "# os release : %s\n", str);
779 free(str);
780}
781
782static void print_arch(struct perf_header *ph, int fd, FILE *fp)
783{
784 char *str = do_read_string(fd, ph);
785 fprintf(fp, "# arch : %s\n", str);
786 free(str);
787}
788
789static void print_cpudesc(struct perf_header *ph, int fd, FILE *fp)
790{
791 char *str = do_read_string(fd, ph);
792 fprintf(fp, "# cpudesc : %s\n", str);
793 free(str);
794}
795
796static void print_nrcpus(struct perf_header *ph, int fd, FILE *fp)
797{
798 ssize_t ret;
799 u32 nr;
800
801 ret = read(fd, &nr, sizeof(nr));
802 if (ret != (ssize_t)sizeof(nr))
803 nr = -1; /* interpreted as error */
804
805 if (ph->needs_swap)
806 nr = bswap_32(nr);
807
808 fprintf(fp, "# nrcpus online : %u\n", nr);
809
810 ret = read(fd, &nr, sizeof(nr));
811 if (ret != (ssize_t)sizeof(nr))
812 nr = -1; /* interpreted as error */
813
814 if (ph->needs_swap)
815 nr = bswap_32(nr);
816
817 fprintf(fp, "# nrcpus avail : %u\n", nr);
818}
819
820static void print_version(struct perf_header *ph, int fd, FILE *fp)
821{
822 char *str = do_read_string(fd, ph);
823 fprintf(fp, "# perf version : %s\n", str);
824 free(str);
825}
826
827static void print_cmdline(struct perf_header *ph, int fd, FILE *fp)
828{
829 ssize_t ret;
830 char *str;
831 u32 nr, i;
832
833 ret = read(fd, &nr, sizeof(nr));
834 if (ret != (ssize_t)sizeof(nr))
835 return;
836
837 if (ph->needs_swap)
838 nr = bswap_32(nr);
839
840 fprintf(fp, "# cmdline : ");
841
842 for (i = 0; i < nr; i++) {
843 str = do_read_string(fd, ph);
844 fprintf(fp, "%s ", str);
845 free(str);
846 }
847 fputc('\n', fp);
848}
849
850static void print_cpu_topology(struct perf_header *ph, int fd, FILE *fp)
851{
852 ssize_t ret;
853 u32 nr, i;
854 char *str;
855
856 ret = read(fd, &nr, sizeof(nr));
857 if (ret != (ssize_t)sizeof(nr))
858 return;
859
860 if (ph->needs_swap)
861 nr = bswap_32(nr);
862
863 for (i = 0; i < nr; i++) {
864 str = do_read_string(fd, ph);
865 fprintf(fp, "# sibling cores : %s\n", str);
866 free(str);
867 }
868
869 ret = read(fd, &nr, sizeof(nr));
870 if (ret != (ssize_t)sizeof(nr))
871 return;
872
873 if (ph->needs_swap)
874 nr = bswap_32(nr);
875
876 for (i = 0; i < nr; i++) {
877 str = do_read_string(fd, ph);
878 fprintf(fp, "# sibling threads : %s\n", str);
879 free(str);
880 }
881}
882
883static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
884{
885 struct perf_event_attr attr;
886 uint64_t id;
887 void *buf = NULL;
888 char *str;
889 u32 nre, sz, nr, i, j, msz;
890 int ret;
891
892 /* number of events */
893 ret = read(fd, &nre, sizeof(nre));
894 if (ret != (ssize_t)sizeof(nre))
895 goto error;
896
897 if (ph->needs_swap)
898 nre = bswap_32(nre);
899
900 ret = read(fd, &sz, sizeof(sz));
901 if (ret != (ssize_t)sizeof(sz))
902 goto error;
903
904 if (ph->needs_swap)
905 sz = bswap_32(sz);
906
907 /*
908 * ensure it is at least to our ABI rev
909 */
910 if (sz < (u32)sizeof(attr))
911 goto error;
912
913 memset(&attr, 0, sizeof(attr));
914
915 /* read entire region to sync up to next field */
916 buf = malloc(sz);
917 if (!buf)
918 goto error;
919
920 msz = sizeof(attr);
921 if (sz < msz)
922 msz = sz;
923
924 for (i = 0 ; i < nre; i++) {
925
926 ret = read(fd, buf, sz);
927 if (ret != (ssize_t)sz)
928 goto error;
929
930 if (ph->needs_swap)
931 perf_event__attr_swap(buf);
932
933 memcpy(&attr, buf, msz);
934
935 ret = read(fd, &nr, sizeof(nr));
936 if (ret != (ssize_t)sizeof(nr))
937 goto error;
938
939 if (ph->needs_swap)
940 nr = bswap_32(nr);
941
942 str = do_read_string(fd, ph);
943 fprintf(fp, "# event : name = %s, ", str);
944 free(str);
945
946 fprintf(fp, "type = %d, config = 0x%"PRIx64
947 ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
948 attr.type,
949 (u64)attr.config,
950 (u64)attr.config1,
951 (u64)attr.config2);
952
953 fprintf(fp, ", excl_usr = %d, excl_kern = %d",
954 attr.exclude_user,
955 attr.exclude_kernel);
956
957 if (nr)
958 fprintf(fp, ", id = {");
959
960 for (j = 0 ; j < nr; j++) {
961 ret = read(fd, &id, sizeof(id));
962 if (ret != (ssize_t)sizeof(id))
963 goto error;
964
965 if (ph->needs_swap)
966 id = bswap_64(id);
967
968 if (j)
969 fputc(',', fp);
970
971 fprintf(fp, " %"PRIu64, id);
972 }
973 if (nr && j == nr)
974 fprintf(fp, " }");
975 fputc('\n', fp);
976 }
977 free(buf);
978 return;
979error:
980 fprintf(fp, "# event desc: not available or unable to read\n");
981}
982
983static void print_total_mem(struct perf_header *h __used, int fd, FILE *fp)
984{
985 uint64_t mem;
986 ssize_t ret;
987
988 ret = read(fd, &mem, sizeof(mem));
989 if (ret != sizeof(mem))
990 goto error;
991
992 if (h->needs_swap)
993 mem = bswap_64(mem);
994
995 fprintf(fp, "# total memory : %"PRIu64" kB\n", mem);
996 return;
997error:
998 fprintf(fp, "# total memory : unknown\n");
999}
1000
1001static void print_numa_topology(struct perf_header *h __used, int fd, FILE *fp)
1002{
1003 ssize_t ret;
1004 u32 nr, c, i;
1005 char *str;
1006 uint64_t mem_total, mem_free;
1007
1008 /* nr nodes */
1009 ret = read(fd, &nr, sizeof(nr));
1010 if (ret != (ssize_t)sizeof(nr))
1011 goto error;
1012
1013 if (h->needs_swap)
1014 nr = bswap_32(nr);
1015
1016 for (i = 0; i < nr; i++) {
1017
1018 /* node number */
1019 ret = read(fd, &c, sizeof(c));
1020 if (ret != (ssize_t)sizeof(c))
1021 goto error;
1022
1023 if (h->needs_swap)
1024 c = bswap_32(c);
1025
1026 ret = read(fd, &mem_total, sizeof(u64));
1027 if (ret != sizeof(u64))
1028 goto error;
1029
1030 ret = read(fd, &mem_free, sizeof(u64));
1031 if (ret != sizeof(u64))
1032 goto error;
1033
1034 if (h->needs_swap) {
1035 mem_total = bswap_64(mem_total);
1036 mem_free = bswap_64(mem_free);
1037 }
1038
1039 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB,"
1040 " free = %"PRIu64" kB\n",
1041 c,
1042 mem_total,
1043 mem_free);
1044
1045 str = do_read_string(fd, h);
1046 fprintf(fp, "# node%u cpu list : %s\n", c, str);
1047 free(str);
1048 }
1049 return;
1050error:
1051 fprintf(fp, "# numa topology : not available\n");
1052}
1053
1054static void print_cpuid(struct perf_header *ph, int fd, FILE *fp)
1055{
1056 char *str = do_read_string(fd, ph);
1057 fprintf(fp, "# cpuid : %s\n", str);
1058 free(str);
1059}
1060
1061struct feature_ops {
1062 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1063 void (*print)(struct perf_header *h, int fd, FILE *fp);
1064 const char *name;
1065 bool full_only;
1066};
1067
1068#define FEAT_OPA(n, w, p) \
1069 [n] = { .name = #n, .write = w, .print = p }
1070#define FEAT_OPF(n, w, p) \
1071 [n] = { .name = #n, .write = w, .print = p, .full_only = true }
1072
1073static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1074 FEAT_OPA(HEADER_TRACE_INFO, write_trace_info, NULL),
1075 FEAT_OPA(HEADER_BUILD_ID, write_build_id, NULL),
1076 FEAT_OPA(HEADER_HOSTNAME, write_hostname, print_hostname),
1077 FEAT_OPA(HEADER_OSRELEASE, write_osrelease, print_osrelease),
1078 FEAT_OPA(HEADER_VERSION, write_version, print_version),
1079 FEAT_OPA(HEADER_ARCH, write_arch, print_arch),
1080 FEAT_OPA(HEADER_NRCPUS, write_nrcpus, print_nrcpus),
1081 FEAT_OPA(HEADER_CPUDESC, write_cpudesc, print_cpudesc),
1082 FEAT_OPA(HEADER_CPUID, write_cpuid, print_cpuid),
1083 FEAT_OPA(HEADER_TOTAL_MEM, write_total_mem, print_total_mem),
1084 FEAT_OPA(HEADER_EVENT_DESC, write_event_desc, print_event_desc),
1085 FEAT_OPA(HEADER_CMDLINE, write_cmdline, print_cmdline),
1086 FEAT_OPF(HEADER_CPU_TOPOLOGY, write_cpu_topology, print_cpu_topology),
1087 FEAT_OPF(HEADER_NUMA_TOPOLOGY, write_numa_topology, print_numa_topology),
1088};
1089
1090struct header_print_data {
1091 FILE *fp;
1092 bool full; /* extended list of headers */
1093};
1094
1095static int perf_file_section__fprintf_info(struct perf_file_section *section,
1096 struct perf_header *ph,
1097 int feat, int fd, void *data)
1098{
1099 struct header_print_data *hd = data;
1100
1101 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
1102 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
1103 "%d, continuing...\n", section->offset, feat);
1104 return 0;
1105 }
1106 if (feat < HEADER_TRACE_INFO || feat >= HEADER_LAST_FEATURE) {
1107 pr_warning("unknown feature %d\n", feat);
1108 return -1;
1109 }
1110 if (!feat_ops[feat].print)
1111 return 0;
1112
1113 if (!feat_ops[feat].full_only || hd->full)
1114 feat_ops[feat].print(ph, fd, hd->fp);
1115 else
1116 fprintf(hd->fp, "# %s info available, use -I to display\n",
1117 feat_ops[feat].name);
1118
1119 return 0;
1120}
1121
1122int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
1123{
1124 struct header_print_data hd;
1125 struct perf_header *header = &session->header;
1126 int fd = session->fd;
1127 hd.fp = fp;
1128 hd.full = full;
1129
1130 perf_header__process_sections(header, fd, &hd,
1131 perf_file_section__fprintf_info);
1132 return 0;
1133}
1134
113#define dsos__for_each_with_build_id(pos, head) \ 1135#define dsos__for_each_with_build_id(pos, head) \
114 list_for_each_entry(pos, head, node) \ 1136 list_for_each_entry(pos, head, node) \
115 if (!pos->has_build_id) \ 1137 if (!pos->has_build_id) \
@@ -189,8 +1211,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
189 const char *name, bool is_kallsyms) 1211 const char *name, bool is_kallsyms)
190{ 1212{
191 const size_t size = PATH_MAX; 1213 const size_t size = PATH_MAX;
192 char *realname, *filename = malloc(size), 1214 char *realname, *filename = zalloc(size),
193 *linkname = malloc(size), *targetname; 1215 *linkname = zalloc(size), *targetname;
194 int len, err = -1; 1216 int len, err = -1;
195 1217
196 if (is_kallsyms) { 1218 if (is_kallsyms) {
@@ -254,8 +1276,8 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
254int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) 1276int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
255{ 1277{
256 const size_t size = PATH_MAX; 1278 const size_t size = PATH_MAX;
257 char *filename = malloc(size), 1279 char *filename = zalloc(size),
258 *linkname = malloc(size); 1280 *linkname = zalloc(size);
259 int err = -1; 1281 int err = -1;
260 1282
261 if (filename == NULL || linkname == NULL) 1283 if (filename == NULL || linkname == NULL)
@@ -267,7 +1289,7 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
267 if (access(linkname, F_OK)) 1289 if (access(linkname, F_OK))
268 goto out_free; 1290 goto out_free;
269 1291
270 if (readlink(linkname, filename, size) < 0) 1292 if (readlink(linkname, filename, size - 1) < 0)
271 goto out_free; 1293 goto out_free;
272 1294
273 if (unlink(linkname)) 1295 if (unlink(linkname))
@@ -356,15 +1378,41 @@ static bool perf_session__read_build_ids(struct perf_session *session, bool with
356 return ret; 1378 return ret;
357} 1379}
358 1380
1381static int do_write_feat(int fd, struct perf_header *h, int type,
1382 struct perf_file_section **p,
1383 struct perf_evlist *evlist)
1384{
1385 int err;
1386 int ret = 0;
1387
1388 if (perf_header__has_feat(h, type)) {
1389
1390 (*p)->offset = lseek(fd, 0, SEEK_CUR);
1391
1392 err = feat_ops[type].write(fd, h, evlist);
1393 if (err < 0) {
1394 pr_debug("failed to write feature %d\n", type);
1395
1396 /* undo anything written */
1397 lseek(fd, (*p)->offset, SEEK_SET);
1398
1399 return -1;
1400 }
1401 (*p)->size = lseek(fd, 0, SEEK_CUR) - (*p)->offset;
1402 (*p)++;
1403 }
1404 return ret;
1405}
1406
359static int perf_header__adds_write(struct perf_header *header, 1407static int perf_header__adds_write(struct perf_header *header,
360 struct perf_evlist *evlist, int fd) 1408 struct perf_evlist *evlist, int fd)
361{ 1409{
362 int nr_sections; 1410 int nr_sections;
363 struct perf_session *session; 1411 struct perf_session *session;
364 struct perf_file_section *feat_sec; 1412 struct perf_file_section *feat_sec, *p;
365 int sec_size; 1413 int sec_size;
366 u64 sec_start; 1414 u64 sec_start;
367 int idx = 0, err; 1415 int err;
368 1416
369 session = container_of(header, struct perf_session, header); 1417 session = container_of(header, struct perf_session, header);
370 1418
@@ -376,7 +1424,7 @@ static int perf_header__adds_write(struct perf_header *header,
376 if (!nr_sections) 1424 if (!nr_sections)
377 return 0; 1425 return 0;
378 1426
379 feat_sec = calloc(sizeof(*feat_sec), nr_sections); 1427 feat_sec = p = calloc(sizeof(*feat_sec), nr_sections);
380 if (feat_sec == NULL) 1428 if (feat_sec == NULL)
381 return -ENOMEM; 1429 return -ENOMEM;
382 1430
@@ -385,36 +1433,69 @@ static int perf_header__adds_write(struct perf_header *header,
385 sec_start = header->data_offset + header->data_size; 1433 sec_start = header->data_offset + header->data_size;
386 lseek(fd, sec_start + sec_size, SEEK_SET); 1434 lseek(fd, sec_start + sec_size, SEEK_SET);
387 1435
388 if (perf_header__has_feat(header, HEADER_TRACE_INFO)) { 1436 err = do_write_feat(fd, header, HEADER_TRACE_INFO, &p, evlist);
389 struct perf_file_section *trace_sec; 1437 if (err)
390 1438 goto out_free;
391 trace_sec = &feat_sec[idx++];
392 1439
393 /* Write trace info */ 1440 err = do_write_feat(fd, header, HEADER_BUILD_ID, &p, evlist);
394 trace_sec->offset = lseek(fd, 0, SEEK_CUR); 1441 if (err) {
395 read_tracing_data(fd, &evlist->entries); 1442 perf_header__clear_feat(header, HEADER_BUILD_ID);
396 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; 1443 goto out_free;
397 } 1444 }
398 1445
399 if (perf_header__has_feat(header, HEADER_BUILD_ID)) { 1446 err = do_write_feat(fd, header, HEADER_HOSTNAME, &p, evlist);
400 struct perf_file_section *buildid_sec; 1447 if (err)
1448 perf_header__clear_feat(header, HEADER_HOSTNAME);
401 1449
402 buildid_sec = &feat_sec[idx++]; 1450 err = do_write_feat(fd, header, HEADER_OSRELEASE, &p, evlist);
1451 if (err)
1452 perf_header__clear_feat(header, HEADER_OSRELEASE);
403 1453
404 /* Write build-ids */ 1454 err = do_write_feat(fd, header, HEADER_VERSION, &p, evlist);
405 buildid_sec->offset = lseek(fd, 0, SEEK_CUR); 1455 if (err)
406 err = dsos__write_buildid_table(header, fd); 1456 perf_header__clear_feat(header, HEADER_VERSION);
407 if (err < 0) { 1457
408 pr_debug("failed to write buildid table\n"); 1458 err = do_write_feat(fd, header, HEADER_ARCH, &p, evlist);
409 goto out_free; 1459 if (err)
410 } 1460 perf_header__clear_feat(header, HEADER_ARCH);
411 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - 1461
412 buildid_sec->offset; 1462 err = do_write_feat(fd, header, HEADER_NRCPUS, &p, evlist);
413 if (!no_buildid_cache) 1463 if (err)
414 perf_session__cache_build_ids(session); 1464 perf_header__clear_feat(header, HEADER_NRCPUS);
415 } 1465
1466 err = do_write_feat(fd, header, HEADER_CPUDESC, &p, evlist);
1467 if (err)
1468 perf_header__clear_feat(header, HEADER_CPUDESC);
1469
1470 err = do_write_feat(fd, header, HEADER_CPUID, &p, evlist);
1471 if (err)
1472 perf_header__clear_feat(header, HEADER_CPUID);
1473
1474 err = do_write_feat(fd, header, HEADER_TOTAL_MEM, &p, evlist);
1475 if (err)
1476 perf_header__clear_feat(header, HEADER_TOTAL_MEM);
1477
1478 err = do_write_feat(fd, header, HEADER_CMDLINE, &p, evlist);
1479 if (err)
1480 perf_header__clear_feat(header, HEADER_CMDLINE);
1481
1482 err = do_write_feat(fd, header, HEADER_EVENT_DESC, &p, evlist);
1483 if (err)
1484 perf_header__clear_feat(header, HEADER_EVENT_DESC);
1485
1486 err = do_write_feat(fd, header, HEADER_CPU_TOPOLOGY, &p, evlist);
1487 if (err)
1488 perf_header__clear_feat(header, HEADER_CPU_TOPOLOGY);
1489
1490 err = do_write_feat(fd, header, HEADER_NUMA_TOPOLOGY, &p, evlist);
1491 if (err)
1492 perf_header__clear_feat(header, HEADER_NUMA_TOPOLOGY);
416 1493
417 lseek(fd, sec_start, SEEK_SET); 1494 lseek(fd, sec_start, SEEK_SET);
1495 /*
1496 * may write more than needed due to dropped feature, but
1497 * this is okay, reader will skip the mising entries
1498 */
418 err = do_write(fd, feat_sec, sec_size); 1499 err = do_write(fd, feat_sec, sec_size);
419 if (err < 0) 1500 if (err < 0)
420 pr_debug("failed to write feature section\n"); 1501 pr_debug("failed to write feature section\n");
@@ -554,9 +1635,10 @@ static int perf_header__getbuffer64(struct perf_header *header,
554} 1635}
555 1636
556int perf_header__process_sections(struct perf_header *header, int fd, 1637int perf_header__process_sections(struct perf_header *header, int fd,
1638 void *data,
557 int (*process)(struct perf_file_section *section, 1639 int (*process)(struct perf_file_section *section,
558 struct perf_header *ph, 1640 struct perf_header *ph,
559 int feat, int fd)) 1641 int feat, int fd, void *data))
560{ 1642{
561 struct perf_file_section *feat_sec; 1643 struct perf_file_section *feat_sec;
562 int nr_sections; 1644 int nr_sections;
@@ -584,7 +1666,7 @@ int perf_header__process_sections(struct perf_header *header, int fd,
584 if (perf_header__has_feat(header, feat)) { 1666 if (perf_header__has_feat(header, feat)) {
585 struct perf_file_section *sec = &feat_sec[idx++]; 1667 struct perf_file_section *sec = &feat_sec[idx++];
586 1668
587 err = process(sec, header, feat, fd); 1669 err = process(sec, header, feat, fd, data);
588 if (err < 0) 1670 if (err < 0)
589 break; 1671 break;
590 } 1672 }
@@ -621,21 +1703,41 @@ int perf_file_header__read(struct perf_file_header *header,
621 bitmap_zero(header->adds_features, HEADER_FEAT_BITS); 1703 bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
622 else 1704 else
623 return -1; 1705 return -1;
1706 } else if (ph->needs_swap) {
1707 unsigned int i;
1708 /*
1709 * feature bitmap is declared as an array of unsigned longs --
1710 * not good since its size can differ between the host that
1711 * generated the data file and the host analyzing the file.
1712 *
1713 * We need to handle endianness, but we don't know the size of
1714 * the unsigned long where the file was generated. Take a best
1715 * guess at determining it: try 64-bit swap first (ie., file
1716 * created on a 64-bit host), and check if the hostname feature
1717 * bit is set (this feature bit is forced on as of fbe96f2).
1718 * If the bit is not, undo the 64-bit swap and try a 32-bit
1719 * swap. If the hostname bit is still not set (e.g., older data
1720 * file), punt and fallback to the original behavior --
1721 * clearing all feature bits and setting buildid.
1722 */
1723 for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i)
1724 header->adds_features[i] = bswap_64(header->adds_features[i]);
1725
1726 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
1727 for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) {
1728 header->adds_features[i] = bswap_64(header->adds_features[i]);
1729 header->adds_features[i] = bswap_32(header->adds_features[i]);
1730 }
1731 }
1732
1733 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
1734 bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
1735 set_bit(HEADER_BUILD_ID, header->adds_features);
1736 }
624 } 1737 }
625 1738
626 memcpy(&ph->adds_features, &header->adds_features, 1739 memcpy(&ph->adds_features, &header->adds_features,
627 sizeof(ph->adds_features)); 1740 sizeof(ph->adds_features));
628 /*
629 * FIXME: hack that assumes that if we need swap the perf.data file
630 * may be coming from an arch with a different word-size, ergo different
631 * DEFINE_BITMAP format, investigate more later, but for now its mostly
632 * safe to assume that we have a build-id section. Trace files probably
633 * have several other issues in this realm anyway...
634 */
635 if (ph->needs_swap) {
636 memset(&ph->adds_features, 0, sizeof(ph->adds_features));
637 perf_header__set_feat(ph, HEADER_BUILD_ID);
638 }
639 1741
640 ph->event_offset = header->event_types.offset; 1742 ph->event_offset = header->event_types.offset;
641 ph->event_size = header->event_types.size; 1743 ph->event_size = header->event_types.size;
@@ -726,7 +1828,16 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
726 return -1; 1828 return -1;
727 1829
728 bev.header = old_bev.header; 1830 bev.header = old_bev.header;
729 bev.pid = 0; 1831
1832 /*
1833 * As the pid is the missing value, we need to fill
1834 * it properly. The header.misc value give us nice hint.
1835 */
1836 bev.pid = HOST_KERNEL_ID;
1837 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1838 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1839 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1840
730 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id)); 1841 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
731 __event_process_build_id(&bev, filename, session); 1842 __event_process_build_id(&bev, filename, session);
732 1843
@@ -787,7 +1898,7 @@ out:
787 1898
788static int perf_file_section__process(struct perf_file_section *section, 1899static int perf_file_section__process(struct perf_file_section *section,
789 struct perf_header *ph, 1900 struct perf_header *ph,
790 int feat, int fd) 1901 int feat, int fd, void *data __used)
791{ 1902{
792 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { 1903 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
793 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 1904 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -804,6 +1915,21 @@ static int perf_file_section__process(struct perf_file_section *section,
804 if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) 1915 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
805 pr_debug("Failed to read buildids, continuing...\n"); 1916 pr_debug("Failed to read buildids, continuing...\n");
806 break; 1917 break;
1918
1919 case HEADER_HOSTNAME:
1920 case HEADER_OSRELEASE:
1921 case HEADER_VERSION:
1922 case HEADER_ARCH:
1923 case HEADER_NRCPUS:
1924 case HEADER_CPUDESC:
1925 case HEADER_CPUID:
1926 case HEADER_TOTAL_MEM:
1927 case HEADER_CMDLINE:
1928 case HEADER_EVENT_DESC:
1929 case HEADER_CPU_TOPOLOGY:
1930 case HEADER_NUMA_TOPOLOGY:
1931 break;
1932
807 default: 1933 default:
808 pr_debug("unknown feature %d, continuing...\n", feat); 1934 pr_debug("unknown feature %d, continuing...\n", feat);
809 } 1935 }
@@ -926,7 +2052,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
926 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 2052 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
927 } 2053 }
928 2054
929 perf_header__process_sections(header, fd, perf_file_section__process); 2055 perf_header__process_sections(header, fd, NULL,
2056 perf_file_section__process);
930 2057
931 lseek(fd, header->data_offset, SEEK_SET); 2058 lseek(fd, header->data_offset, SEEK_SET);
932 2059
@@ -1091,15 +2218,29 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
1091 struct perf_session *session __unused) 2218 struct perf_session *session __unused)
1092{ 2219{
1093 union perf_event ev; 2220 union perf_event ev;
2221 struct tracing_data *tdata;
1094 ssize_t size = 0, aligned_size = 0, padding; 2222 ssize_t size = 0, aligned_size = 0, padding;
1095 int err __used = 0; 2223 int err __used = 0;
1096 2224
2225 /*
2226 * We are going to store the size of the data followed
2227 * by the data contents. Since the fd descriptor is a pipe,
2228 * we cannot seek back to store the size of the data once
2229 * we know it. Instead we:
2230 *
2231 * - write the tracing data to the temp file
2232 * - get/write the data size to pipe
2233 * - write the tracing data from the temp file
2234 * to the pipe
2235 */
2236 tdata = tracing_data_get(&evlist->entries, fd, true);
2237 if (!tdata)
2238 return -1;
2239
1097 memset(&ev, 0, sizeof(ev)); 2240 memset(&ev, 0, sizeof(ev));
1098 2241
1099 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; 2242 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
1100 size = read_tracing_data_size(fd, &evlist->entries); 2243 size = tdata->size;
1101 if (size <= 0)
1102 return size;
1103 aligned_size = ALIGN(size, sizeof(u64)); 2244 aligned_size = ALIGN(size, sizeof(u64));
1104 padding = aligned_size - size; 2245 padding = aligned_size - size;
1105 ev.tracing_data.header.size = sizeof(ev.tracing_data); 2246 ev.tracing_data.header.size = sizeof(ev.tracing_data);
@@ -1107,7 +2248,12 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
1107 2248
1108 process(&ev, NULL, session); 2249 process(&ev, NULL, session);
1109 2250
1110 err = read_tracing_data(fd, &evlist->entries); 2251 /*
2252 * The put function will copy all the tracing data
2253 * stored in temp file to the pipe.
2254 */
2255 tracing_data_put(tdata);
2256
1111 write_padded(fd, NULL, 0, padding); 2257 write_padded(fd, NULL, 0, padding);
1112 2258
1113 return aligned_size; 2259 return aligned_size;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 1886256768a1..3d5a742f4a2a 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -12,6 +12,20 @@
12enum { 12enum {
13 HEADER_TRACE_INFO = 1, 13 HEADER_TRACE_INFO = 1,
14 HEADER_BUILD_ID, 14 HEADER_BUILD_ID,
15
16 HEADER_HOSTNAME,
17 HEADER_OSRELEASE,
18 HEADER_VERSION,
19 HEADER_ARCH,
20 HEADER_NRCPUS,
21 HEADER_CPUDESC,
22 HEADER_CPUID,
23 HEADER_TOTAL_MEM,
24 HEADER_CMDLINE,
25 HEADER_EVENT_DESC,
26 HEADER_CPU_TOPOLOGY,
27 HEADER_NUMA_TOPOLOGY,
28
15 HEADER_LAST_FEATURE, 29 HEADER_LAST_FEATURE,
16}; 30};
17 31
@@ -68,10 +82,15 @@ void perf_header__set_feat(struct perf_header *header, int feat);
68void perf_header__clear_feat(struct perf_header *header, int feat); 82void perf_header__clear_feat(struct perf_header *header, int feat);
69bool perf_header__has_feat(const struct perf_header *header, int feat); 83bool perf_header__has_feat(const struct perf_header *header, int feat);
70 84
85int perf_header__set_cmdline(int argc, const char **argv);
86
71int perf_header__process_sections(struct perf_header *header, int fd, 87int perf_header__process_sections(struct perf_header *header, int fd,
88 void *data,
72 int (*process)(struct perf_file_section *section, 89 int (*process)(struct perf_file_section *section,
73 struct perf_header *ph, 90 struct perf_header *ph,
74 int feat, int fd)); 91 int feat, int fd, void *data));
92
93int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
75 94
76int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 95int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
77 const char *name, bool is_kallsyms); 96 const char *name, bool is_kallsyms);
@@ -104,4 +123,10 @@ int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
104 struct perf_session *session); 123 struct perf_session *session);
105int perf_event__process_build_id(union perf_event *event, 124int perf_event__process_build_id(union perf_event *event,
106 struct perf_session *session); 125 struct perf_session *session);
126
127/*
128 * arch specific callback
129 */
130int get_cpuid(char *buffer, size_t sz);
131
107#endif /* __PERF_HEADER_H */ 132#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 677e1da6bb3e..a36a3fa81ffb 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -6,6 +6,11 @@
6#include "sort.h" 6#include "sort.h"
7#include <math.h> 7#include <math.h>
8 8
9static bool hists__filter_entry_by_dso(struct hists *hists,
10 struct hist_entry *he);
11static bool hists__filter_entry_by_thread(struct hists *hists,
12 struct hist_entry *he);
13
9enum hist_filter { 14enum hist_filter {
10 HIST_FILTER__DSO, 15 HIST_FILTER__DSO,
11 HIST_FILTER__THREAD, 16 HIST_FILTER__THREAD,
@@ -18,56 +23,56 @@ struct callchain_param callchain_param = {
18 .order = ORDER_CALLEE 23 .order = ORDER_CALLEE
19}; 24};
20 25
21u16 hists__col_len(struct hists *self, enum hist_column col) 26u16 hists__col_len(struct hists *hists, enum hist_column col)
22{ 27{
23 return self->col_len[col]; 28 return hists->col_len[col];
24} 29}
25 30
26void hists__set_col_len(struct hists *self, enum hist_column col, u16 len) 31void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len)
27{ 32{
28 self->col_len[col] = len; 33 hists->col_len[col] = len;
29} 34}
30 35
31bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len) 36bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len)
32{ 37{
33 if (len > hists__col_len(self, col)) { 38 if (len > hists__col_len(hists, col)) {
34 hists__set_col_len(self, col, len); 39 hists__set_col_len(hists, col, len);
35 return true; 40 return true;
36 } 41 }
37 return false; 42 return false;
38} 43}
39 44
40static void hists__reset_col_len(struct hists *self) 45static void hists__reset_col_len(struct hists *hists)
41{ 46{
42 enum hist_column col; 47 enum hist_column col;
43 48
44 for (col = 0; col < HISTC_NR_COLS; ++col) 49 for (col = 0; col < HISTC_NR_COLS; ++col)
45 hists__set_col_len(self, col, 0); 50 hists__set_col_len(hists, col, 0);
46} 51}
47 52
48static void hists__calc_col_len(struct hists *self, struct hist_entry *h) 53static void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
49{ 54{
50 u16 len; 55 u16 len;
51 56
52 if (h->ms.sym) 57 if (h->ms.sym)
53 hists__new_col_len(self, HISTC_SYMBOL, h->ms.sym->namelen); 58 hists__new_col_len(hists, HISTC_SYMBOL, h->ms.sym->namelen);
54 else { 59 else {
55 const unsigned int unresolved_col_width = BITS_PER_LONG / 4; 60 const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
56 61
57 if (hists__col_len(self, HISTC_DSO) < unresolved_col_width && 62 if (hists__col_len(hists, HISTC_DSO) < unresolved_col_width &&
58 !symbol_conf.col_width_list_str && !symbol_conf.field_sep && 63 !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
59 !symbol_conf.dso_list) 64 !symbol_conf.dso_list)
60 hists__set_col_len(self, HISTC_DSO, 65 hists__set_col_len(hists, HISTC_DSO,
61 unresolved_col_width); 66 unresolved_col_width);
62 } 67 }
63 68
64 len = thread__comm_len(h->thread); 69 len = thread__comm_len(h->thread);
65 if (hists__new_col_len(self, HISTC_COMM, len)) 70 if (hists__new_col_len(hists, HISTC_COMM, len))
66 hists__set_col_len(self, HISTC_THREAD, len + 6); 71 hists__set_col_len(hists, HISTC_THREAD, len + 6);
67 72
68 if (h->ms.map) { 73 if (h->ms.map) {
69 len = dso__name_len(h->ms.map->dso); 74 len = dso__name_len(h->ms.map->dso);
70 hists__new_col_len(self, HISTC_DSO, len); 75 hists__new_col_len(hists, HISTC_DSO, len);
71 } 76 }
72} 77}
73 78
@@ -92,6 +97,67 @@ static void hist_entry__add_cpumode_period(struct hist_entry *self,
92 } 97 }
93} 98}
94 99
100static void hist_entry__decay(struct hist_entry *he)
101{
102 he->period = (he->period * 7) / 8;
103 he->nr_events = (he->nr_events * 7) / 8;
104}
105
106static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
107{
108 u64 prev_period = he->period;
109
110 if (prev_period == 0)
111 return true;
112
113 hist_entry__decay(he);
114
115 if (!he->filtered)
116 hists->stats.total_period -= prev_period - he->period;
117
118 return he->period == 0;
119}
120
121static void __hists__decay_entries(struct hists *hists, bool zap_user,
122 bool zap_kernel, bool threaded)
123{
124 struct rb_node *next = rb_first(&hists->entries);
125 struct hist_entry *n;
126
127 while (next) {
128 n = rb_entry(next, struct hist_entry, rb_node);
129 next = rb_next(&n->rb_node);
130 /*
131 * We may be annotating this, for instance, so keep it here in
132 * case some it gets new samples, we'll eventually free it when
133 * the user stops browsing and it agains gets fully decayed.
134 */
135 if (((zap_user && n->level == '.') ||
136 (zap_kernel && n->level != '.') ||
137 hists__decay_entry(hists, n)) &&
138 !n->used) {
139 rb_erase(&n->rb_node, &hists->entries);
140
141 if (sort__need_collapse || threaded)
142 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
143
144 hist_entry__free(n);
145 --hists->nr_entries;
146 }
147 }
148}
149
150void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
151{
152 return __hists__decay_entries(hists, zap_user, zap_kernel, false);
153}
154
155void hists__decay_entries_threaded(struct hists *hists,
156 bool zap_user, bool zap_kernel)
157{
158 return __hists__decay_entries(hists, zap_user, zap_kernel, true);
159}
160
95/* 161/*
96 * histogram, sorted on item, collects periods 162 * histogram, sorted on item, collects periods
97 */ 163 */
@@ -113,11 +179,12 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
113 return self; 179 return self;
114} 180}
115 181
116static void hists__inc_nr_entries(struct hists *self, struct hist_entry *h) 182static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
117{ 183{
118 if (!h->filtered) { 184 if (!h->filtered) {
119 hists__calc_col_len(self, h); 185 hists__calc_col_len(hists, h);
120 ++self->nr_entries; 186 ++hists->nr_entries;
187 hists->stats.total_period += h->period;
121 } 188 }
122} 189}
123 190
@@ -128,11 +195,11 @@ static u8 symbol__parent_filter(const struct symbol *parent)
128 return 0; 195 return 0;
129} 196}
130 197
131struct hist_entry *__hists__add_entry(struct hists *self, 198struct hist_entry *__hists__add_entry(struct hists *hists,
132 struct addr_location *al, 199 struct addr_location *al,
133 struct symbol *sym_parent, u64 period) 200 struct symbol *sym_parent, u64 period)
134{ 201{
135 struct rb_node **p = &self->entries.rb_node; 202 struct rb_node **p;
136 struct rb_node *parent = NULL; 203 struct rb_node *parent = NULL;
137 struct hist_entry *he; 204 struct hist_entry *he;
138 struct hist_entry entry = { 205 struct hist_entry entry = {
@@ -150,9 +217,13 @@ struct hist_entry *__hists__add_entry(struct hists *self,
150 }; 217 };
151 int cmp; 218 int cmp;
152 219
220 pthread_mutex_lock(&hists->lock);
221
222 p = &hists->entries_in->rb_node;
223
153 while (*p != NULL) { 224 while (*p != NULL) {
154 parent = *p; 225 parent = *p;
155 he = rb_entry(parent, struct hist_entry, rb_node); 226 he = rb_entry(parent, struct hist_entry, rb_node_in);
156 227
157 cmp = hist_entry__cmp(&entry, he); 228 cmp = hist_entry__cmp(&entry, he);
158 229
@@ -170,12 +241,14 @@ struct hist_entry *__hists__add_entry(struct hists *self,
170 241
171 he = hist_entry__new(&entry); 242 he = hist_entry__new(&entry);
172 if (!he) 243 if (!he)
173 return NULL; 244 goto out_unlock;
174 rb_link_node(&he->rb_node, parent, p); 245
175 rb_insert_color(&he->rb_node, &self->entries); 246 rb_link_node(&he->rb_node_in, parent, p);
176 hists__inc_nr_entries(self, he); 247 rb_insert_color(&he->rb_node_in, hists->entries_in);
177out: 248out:
178 hist_entry__add_cpumode_period(he, al->cpumode, period); 249 hist_entry__add_cpumode_period(he, al->cpumode, period);
250out_unlock:
251 pthread_mutex_unlock(&hists->lock);
179 return he; 252 return he;
180} 253}
181 254
@@ -222,7 +295,7 @@ void hist_entry__free(struct hist_entry *he)
222 * collapse the histogram 295 * collapse the histogram
223 */ 296 */
224 297
225static bool hists__collapse_insert_entry(struct hists *self, 298static bool hists__collapse_insert_entry(struct hists *hists,
226 struct rb_root *root, 299 struct rb_root *root,
227 struct hist_entry *he) 300 struct hist_entry *he)
228{ 301{
@@ -233,15 +306,16 @@ static bool hists__collapse_insert_entry(struct hists *self,
233 306
234 while (*p != NULL) { 307 while (*p != NULL) {
235 parent = *p; 308 parent = *p;
236 iter = rb_entry(parent, struct hist_entry, rb_node); 309 iter = rb_entry(parent, struct hist_entry, rb_node_in);
237 310
238 cmp = hist_entry__collapse(iter, he); 311 cmp = hist_entry__collapse(iter, he);
239 312
240 if (!cmp) { 313 if (!cmp) {
241 iter->period += he->period; 314 iter->period += he->period;
315 iter->nr_events += he->nr_events;
242 if (symbol_conf.use_callchain) { 316 if (symbol_conf.use_callchain) {
243 callchain_cursor_reset(&self->callchain_cursor); 317 callchain_cursor_reset(&hists->callchain_cursor);
244 callchain_merge(&self->callchain_cursor, iter->callchain, 318 callchain_merge(&hists->callchain_cursor, iter->callchain,
245 he->callchain); 319 he->callchain);
246 } 320 }
247 hist_entry__free(he); 321 hist_entry__free(he);
@@ -254,35 +328,68 @@ static bool hists__collapse_insert_entry(struct hists *self,
254 p = &(*p)->rb_right; 328 p = &(*p)->rb_right;
255 } 329 }
256 330
257 rb_link_node(&he->rb_node, parent, p); 331 rb_link_node(&he->rb_node_in, parent, p);
258 rb_insert_color(&he->rb_node, root); 332 rb_insert_color(&he->rb_node_in, root);
259 return true; 333 return true;
260} 334}
261 335
262void hists__collapse_resort(struct hists *self) 336static struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
337{
338 struct rb_root *root;
339
340 pthread_mutex_lock(&hists->lock);
341
342 root = hists->entries_in;
343 if (++hists->entries_in > &hists->entries_in_array[1])
344 hists->entries_in = &hists->entries_in_array[0];
345
346 pthread_mutex_unlock(&hists->lock);
347
348 return root;
349}
350
351static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
352{
353 hists__filter_entry_by_dso(hists, he);
354 hists__filter_entry_by_thread(hists, he);
355}
356
357static void __hists__collapse_resort(struct hists *hists, bool threaded)
263{ 358{
264 struct rb_root tmp; 359 struct rb_root *root;
265 struct rb_node *next; 360 struct rb_node *next;
266 struct hist_entry *n; 361 struct hist_entry *n;
267 362
268 if (!sort__need_collapse) 363 if (!sort__need_collapse && !threaded)
269 return; 364 return;
270 365
271 tmp = RB_ROOT; 366 root = hists__get_rotate_entries_in(hists);
272 next = rb_first(&self->entries); 367 next = rb_first(root);
273 self->nr_entries = 0;
274 hists__reset_col_len(self);
275 368
276 while (next) { 369 while (next) {
277 n = rb_entry(next, struct hist_entry, rb_node); 370 n = rb_entry(next, struct hist_entry, rb_node_in);
278 next = rb_next(&n->rb_node); 371 next = rb_next(&n->rb_node_in);
279 372
280 rb_erase(&n->rb_node, &self->entries); 373 rb_erase(&n->rb_node_in, root);
281 if (hists__collapse_insert_entry(self, &tmp, n)) 374 if (hists__collapse_insert_entry(hists, &hists->entries_collapsed, n)) {
282 hists__inc_nr_entries(self, n); 375 /*
376 * If it wasn't combined with one of the entries already
377 * collapsed, we need to apply the filters that may have
378 * been set by, say, the hist_browser.
379 */
380 hists__apply_filters(hists, n);
381 }
283 } 382 }
383}
284 384
285 self->entries = tmp; 385void hists__collapse_resort(struct hists *hists)
386{
387 return __hists__collapse_resort(hists, false);
388}
389
390void hists__collapse_resort_threaded(struct hists *hists)
391{
392 return __hists__collapse_resort(hists, true);
286} 393}
287 394
288/* 395/*
@@ -315,31 +422,44 @@ static void __hists__insert_output_entry(struct rb_root *entries,
315 rb_insert_color(&he->rb_node, entries); 422 rb_insert_color(&he->rb_node, entries);
316} 423}
317 424
318void hists__output_resort(struct hists *self) 425static void __hists__output_resort(struct hists *hists, bool threaded)
319{ 426{
320 struct rb_root tmp; 427 struct rb_root *root;
321 struct rb_node *next; 428 struct rb_node *next;
322 struct hist_entry *n; 429 struct hist_entry *n;
323 u64 min_callchain_hits; 430 u64 min_callchain_hits;
324 431
325 min_callchain_hits = self->stats.total_period * (callchain_param.min_percent / 100); 432 min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
433
434 if (sort__need_collapse || threaded)
435 root = &hists->entries_collapsed;
436 else
437 root = hists->entries_in;
326 438
327 tmp = RB_ROOT; 439 next = rb_first(root);
328 next = rb_first(&self->entries); 440 hists->entries = RB_ROOT;
329 441
330 self->nr_entries = 0; 442 hists->nr_entries = 0;
331 hists__reset_col_len(self); 443 hists->stats.total_period = 0;
444 hists__reset_col_len(hists);
332 445
333 while (next) { 446 while (next) {
334 n = rb_entry(next, struct hist_entry, rb_node); 447 n = rb_entry(next, struct hist_entry, rb_node_in);
335 next = rb_next(&n->rb_node); 448 next = rb_next(&n->rb_node_in);
336 449
337 rb_erase(&n->rb_node, &self->entries); 450 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits);
338 __hists__insert_output_entry(&tmp, n, min_callchain_hits); 451 hists__inc_nr_entries(hists, n);
339 hists__inc_nr_entries(self, n);
340 } 452 }
453}
341 454
342 self->entries = tmp; 455void hists__output_resort(struct hists *hists)
456{
457 return __hists__output_resort(hists, false);
458}
459
460void hists__output_resort_threaded(struct hists *hists)
461{
462 return __hists__output_resort(hists, true);
343} 463}
344 464
345static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) 465static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
@@ -594,12 +714,27 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
594 return ret; 714 return ret;
595} 715}
596 716
597int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, 717void hists__output_recalc_col_len(struct hists *hists, int max_rows)
598 struct hists *hists, struct hists *pair_hists, 718{
599 bool show_displacement, long displacement, 719 struct rb_node *next = rb_first(&hists->entries);
600 bool color, u64 session_total) 720 struct hist_entry *n;
721 int row = 0;
722
723 hists__reset_col_len(hists);
724
725 while (next && row++ < max_rows) {
726 n = rb_entry(next, struct hist_entry, rb_node);
727 if (!n->filtered)
728 hists__calc_col_len(hists, n);
729 next = rb_next(&n->rb_node);
730 }
731}
732
733static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s,
734 size_t size, struct hists *pair_hists,
735 bool show_displacement, long displacement,
736 bool color, u64 session_total)
601{ 737{
602 struct sort_entry *se;
603 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; 738 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
604 u64 nr_events; 739 u64 nr_events;
605 const char *sep = symbol_conf.field_sep; 740 const char *sep = symbol_conf.field_sep;
@@ -664,6 +799,13 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
664 ret += snprintf(s + ret, size - ret, "%11" PRIu64, nr_events); 799 ret += snprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
665 } 800 }
666 801
802 if (symbol_conf.show_total_period) {
803 if (sep)
804 ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
805 else
806 ret += snprintf(s + ret, size - ret, " %12" PRIu64, period);
807 }
808
667 if (pair_hists) { 809 if (pair_hists) {
668 char bf[32]; 810 char bf[32];
669 double old_percent = 0, new_percent = 0, diff; 811 double old_percent = 0, new_percent = 0, diff;
@@ -698,26 +840,42 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
698 } 840 }
699 } 841 }
700 842
843 return ret;
844}
845
846int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
847 struct hists *hists)
848{
849 const char *sep = symbol_conf.field_sep;
850 struct sort_entry *se;
851 int ret = 0;
852
701 list_for_each_entry(se, &hist_entry__sort_list, list) { 853 list_for_each_entry(se, &hist_entry__sort_list, list) {
702 if (se->elide) 854 if (se->elide)
703 continue; 855 continue;
704 856
705 ret += snprintf(s + ret, size - ret, "%s", sep ?: " "); 857 ret += snprintf(s + ret, size - ret, "%s", sep ?: " ");
706 ret += se->se_snprintf(self, s + ret, size - ret, 858 ret += se->se_snprintf(he, s + ret, size - ret,
707 hists__col_len(hists, se->se_width_idx)); 859 hists__col_len(hists, se->se_width_idx));
708 } 860 }
709 861
710 return ret; 862 return ret;
711} 863}
712 864
713int hist_entry__fprintf(struct hist_entry *self, struct hists *hists, 865int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists,
714 struct hists *pair_hists, bool show_displacement, 866 struct hists *pair_hists, bool show_displacement,
715 long displacement, FILE *fp, u64 session_total) 867 long displacement, FILE *fp, u64 session_total)
716{ 868{
717 char bf[512]; 869 char bf[512];
718 hist_entry__snprintf(self, bf, sizeof(bf), hists, pair_hists, 870 int ret;
719 show_displacement, displacement, 871
720 true, session_total); 872 if (size == 0 || size > sizeof(bf))
873 size = sizeof(bf);
874
875 ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists,
876 show_displacement, displacement,
877 true, session_total);
878 hist_entry__snprintf(he, bf + ret, size - ret, hists);
721 return fprintf(fp, "%s\n", bf); 879 return fprintf(fp, "%s\n", bf);
722} 880}
723 881
@@ -738,8 +896,9 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self,
738 left_margin); 896 left_margin);
739} 897}
740 898
741size_t hists__fprintf(struct hists *self, struct hists *pair, 899size_t hists__fprintf(struct hists *hists, struct hists *pair,
742 bool show_displacement, FILE *fp) 900 bool show_displacement, bool show_header, int max_rows,
901 int max_cols, FILE *fp)
743{ 902{
744 struct sort_entry *se; 903 struct sort_entry *se;
745 struct rb_node *nd; 904 struct rb_node *nd;
@@ -749,9 +908,13 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
749 unsigned int width; 908 unsigned int width;
750 const char *sep = symbol_conf.field_sep; 909 const char *sep = symbol_conf.field_sep;
751 const char *col_width = symbol_conf.col_width_list_str; 910 const char *col_width = symbol_conf.col_width_list_str;
911 int nr_rows = 0;
752 912
753 init_rem_hits(); 913 init_rem_hits();
754 914
915 if (!show_header)
916 goto print_entries;
917
755 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead"); 918 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
756 919
757 if (symbol_conf.show_nr_samples) { 920 if (symbol_conf.show_nr_samples) {
@@ -761,6 +924,13 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
761 fputs(" Samples ", fp); 924 fputs(" Samples ", fp);
762 } 925 }
763 926
927 if (symbol_conf.show_total_period) {
928 if (sep)
929 ret += fprintf(fp, "%cPeriod", *sep);
930 else
931 ret += fprintf(fp, " Period ");
932 }
933
764 if (symbol_conf.show_cpu_utilization) { 934 if (symbol_conf.show_cpu_utilization) {
765 if (sep) { 935 if (sep) {
766 ret += fprintf(fp, "%csys", *sep); 936 ret += fprintf(fp, "%csys", *sep);
@@ -803,18 +973,21 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
803 width = strlen(se->se_header); 973 width = strlen(se->se_header);
804 if (symbol_conf.col_width_list_str) { 974 if (symbol_conf.col_width_list_str) {
805 if (col_width) { 975 if (col_width) {
806 hists__set_col_len(self, se->se_width_idx, 976 hists__set_col_len(hists, se->se_width_idx,
807 atoi(col_width)); 977 atoi(col_width));
808 col_width = strchr(col_width, ','); 978 col_width = strchr(col_width, ',');
809 if (col_width) 979 if (col_width)
810 ++col_width; 980 ++col_width;
811 } 981 }
812 } 982 }
813 if (!hists__new_col_len(self, se->se_width_idx, width)) 983 if (!hists__new_col_len(hists, se->se_width_idx, width))
814 width = hists__col_len(self, se->se_width_idx); 984 width = hists__col_len(hists, se->se_width_idx);
815 fprintf(fp, " %*s", width, se->se_header); 985 fprintf(fp, " %*s", width, se->se_header);
816 } 986 }
987
817 fprintf(fp, "\n"); 988 fprintf(fp, "\n");
989 if (max_rows && ++nr_rows >= max_rows)
990 goto out;
818 991
819 if (sep) 992 if (sep)
820 goto print_entries; 993 goto print_entries;
@@ -822,6 +995,8 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
822 fprintf(fp, "# ........"); 995 fprintf(fp, "# ........");
823 if (symbol_conf.show_nr_samples) 996 if (symbol_conf.show_nr_samples)
824 fprintf(fp, " .........."); 997 fprintf(fp, " ..........");
998 if (symbol_conf.show_total_period)
999 fprintf(fp, " ............");
825 if (pair) { 1000 if (pair) {
826 fprintf(fp, " .........."); 1001 fprintf(fp, " ..........");
827 if (show_displacement) 1002 if (show_displacement)
@@ -834,17 +1009,23 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
834 continue; 1009 continue;
835 1010
836 fprintf(fp, " "); 1011 fprintf(fp, " ");
837 width = hists__col_len(self, se->se_width_idx); 1012 width = hists__col_len(hists, se->se_width_idx);
838 if (width == 0) 1013 if (width == 0)
839 width = strlen(se->se_header); 1014 width = strlen(se->se_header);
840 for (i = 0; i < width; i++) 1015 for (i = 0; i < width; i++)
841 fprintf(fp, "."); 1016 fprintf(fp, ".");
842 } 1017 }
843 1018
844 fprintf(fp, "\n#\n"); 1019 fprintf(fp, "\n");
1020 if (max_rows && ++nr_rows >= max_rows)
1021 goto out;
1022
1023 fprintf(fp, "#\n");
1024 if (max_rows && ++nr_rows >= max_rows)
1025 goto out;
845 1026
846print_entries: 1027print_entries:
847 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { 1028 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
848 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 1029 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
849 1030
850 if (h->filtered) 1031 if (h->filtered)
@@ -858,19 +1039,22 @@ print_entries:
858 displacement = 0; 1039 displacement = 0;
859 ++position; 1040 ++position;
860 } 1041 }
861 ret += hist_entry__fprintf(h, self, pair, show_displacement, 1042 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement,
862 displacement, fp, self->stats.total_period); 1043 displacement, fp, hists->stats.total_period);
863 1044
864 if (symbol_conf.use_callchain) 1045 if (symbol_conf.use_callchain)
865 ret += hist_entry__fprintf_callchain(h, self, fp, 1046 ret += hist_entry__fprintf_callchain(h, hists, fp,
866 self->stats.total_period); 1047 hists->stats.total_period);
1048 if (max_rows && ++nr_rows >= max_rows)
1049 goto out;
1050
867 if (h->ms.map == NULL && verbose > 1) { 1051 if (h->ms.map == NULL && verbose > 1) {
868 __map_groups__fprintf_maps(&h->thread->mg, 1052 __map_groups__fprintf_maps(&h->thread->mg,
869 MAP__FUNCTION, verbose, fp); 1053 MAP__FUNCTION, verbose, fp);
870 fprintf(fp, "%.10s end\n", graph_dotted_line); 1054 fprintf(fp, "%.10s end\n", graph_dotted_line);
871 } 1055 }
872 } 1056 }
873 1057out:
874 free(rem_sq_bracket); 1058 free(rem_sq_bracket);
875 1059
876 return ret; 1060 return ret;
@@ -879,7 +1063,7 @@ print_entries:
879/* 1063/*
880 * See hists__fprintf to match the column widths 1064 * See hists__fprintf to match the column widths
881 */ 1065 */
882unsigned int hists__sort_list_width(struct hists *self) 1066unsigned int hists__sort_list_width(struct hists *hists)
883{ 1067{
884 struct sort_entry *se; 1068 struct sort_entry *se;
885 int ret = 9; /* total % */ 1069 int ret = 9; /* total % */
@@ -896,9 +1080,12 @@ unsigned int hists__sort_list_width(struct hists *self)
896 if (symbol_conf.show_nr_samples) 1080 if (symbol_conf.show_nr_samples)
897 ret += 11; 1081 ret += 11;
898 1082
1083 if (symbol_conf.show_total_period)
1084 ret += 13;
1085
899 list_for_each_entry(se, &hist_entry__sort_list, list) 1086 list_for_each_entry(se, &hist_entry__sort_list, list)
900 if (!se->elide) 1087 if (!se->elide)
901 ret += 2 + hists__col_len(self, se->se_width_idx); 1088 ret += 2 + hists__col_len(hists, se->se_width_idx);
902 1089
903 if (verbose) /* Addr + origin */ 1090 if (verbose) /* Addr + origin */
904 ret += 3 + BITS_PER_LONG / 4; 1091 ret += 3 + BITS_PER_LONG / 4;
@@ -906,63 +1093,84 @@ unsigned int hists__sort_list_width(struct hists *self)
906 return ret; 1093 return ret;
907} 1094}
908 1095
909static void hists__remove_entry_filter(struct hists *self, struct hist_entry *h, 1096static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h,
910 enum hist_filter filter) 1097 enum hist_filter filter)
911{ 1098{
912 h->filtered &= ~(1 << filter); 1099 h->filtered &= ~(1 << filter);
913 if (h->filtered) 1100 if (h->filtered)
914 return; 1101 return;
915 1102
916 ++self->nr_entries; 1103 ++hists->nr_entries;
917 if (h->ms.unfolded) 1104 if (h->ms.unfolded)
918 self->nr_entries += h->nr_rows; 1105 hists->nr_entries += h->nr_rows;
919 h->row_offset = 0; 1106 h->row_offset = 0;
920 self->stats.total_period += h->period; 1107 hists->stats.total_period += h->period;
921 self->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events; 1108 hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events;
922 1109
923 hists__calc_col_len(self, h); 1110 hists__calc_col_len(hists, h);
924} 1111}
925 1112
926void hists__filter_by_dso(struct hists *self, const struct dso *dso) 1113
1114static bool hists__filter_entry_by_dso(struct hists *hists,
1115 struct hist_entry *he)
1116{
1117 if (hists->dso_filter != NULL &&
1118 (he->ms.map == NULL || he->ms.map->dso != hists->dso_filter)) {
1119 he->filtered |= (1 << HIST_FILTER__DSO);
1120 return true;
1121 }
1122
1123 return false;
1124}
1125
1126void hists__filter_by_dso(struct hists *hists)
927{ 1127{
928 struct rb_node *nd; 1128 struct rb_node *nd;
929 1129
930 self->nr_entries = self->stats.total_period = 0; 1130 hists->nr_entries = hists->stats.total_period = 0;
931 self->stats.nr_events[PERF_RECORD_SAMPLE] = 0; 1131 hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
932 hists__reset_col_len(self); 1132 hists__reset_col_len(hists);
933 1133
934 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { 1134 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
935 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 1135 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
936 1136
937 if (symbol_conf.exclude_other && !h->parent) 1137 if (symbol_conf.exclude_other && !h->parent)
938 continue; 1138 continue;
939 1139
940 if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) { 1140 if (hists__filter_entry_by_dso(hists, h))
941 h->filtered |= (1 << HIST_FILTER__DSO);
942 continue; 1141 continue;
943 }
944 1142
945 hists__remove_entry_filter(self, h, HIST_FILTER__DSO); 1143 hists__remove_entry_filter(hists, h, HIST_FILTER__DSO);
946 } 1144 }
947} 1145}
948 1146
949void hists__filter_by_thread(struct hists *self, const struct thread *thread) 1147static bool hists__filter_entry_by_thread(struct hists *hists,
1148 struct hist_entry *he)
1149{
1150 if (hists->thread_filter != NULL &&
1151 he->thread != hists->thread_filter) {
1152 he->filtered |= (1 << HIST_FILTER__THREAD);
1153 return true;
1154 }
1155
1156 return false;
1157}
1158
1159void hists__filter_by_thread(struct hists *hists)
950{ 1160{
951 struct rb_node *nd; 1161 struct rb_node *nd;
952 1162
953 self->nr_entries = self->stats.total_period = 0; 1163 hists->nr_entries = hists->stats.total_period = 0;
954 self->stats.nr_events[PERF_RECORD_SAMPLE] = 0; 1164 hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
955 hists__reset_col_len(self); 1165 hists__reset_col_len(hists);
956 1166
957 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { 1167 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
958 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 1168 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
959 1169
960 if (thread != NULL && h->thread != thread) { 1170 if (hists__filter_entry_by_thread(hists, h))
961 h->filtered |= (1 << HIST_FILTER__THREAD);
962 continue; 1171 continue;
963 }
964 1172
965 hists__remove_entry_filter(self, h, HIST_FILTER__THREAD); 1173 hists__remove_entry_filter(hists, h, HIST_FILTER__THREAD);
966 } 1174 }
967} 1175}
968 1176
@@ -976,13 +1184,13 @@ int hist_entry__annotate(struct hist_entry *he, size_t privsize)
976 return symbol__annotate(he->ms.sym, he->ms.map, privsize); 1184 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
977} 1185}
978 1186
979void hists__inc_nr_events(struct hists *self, u32 type) 1187void hists__inc_nr_events(struct hists *hists, u32 type)
980{ 1188{
981 ++self->stats.nr_events[0]; 1189 ++hists->stats.nr_events[0];
982 ++self->stats.nr_events[type]; 1190 ++hists->stats.nr_events[type];
983} 1191}
984 1192
985size_t hists__fprintf_nr_events(struct hists *self, FILE *fp) 1193size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
986{ 1194{
987 int i; 1195 int i;
988 size_t ret = 0; 1196 size_t ret = 0;
@@ -990,7 +1198,7 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
990 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 1198 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
991 const char *name; 1199 const char *name;
992 1200
993 if (self->stats.nr_events[i] == 0) 1201 if (hists->stats.nr_events[i] == 0)
994 continue; 1202 continue;
995 1203
996 name = perf_event__name(i); 1204 name = perf_event__name(i);
@@ -998,8 +1206,18 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
998 continue; 1206 continue;
999 1207
1000 ret += fprintf(fp, "%16s events: %10d\n", name, 1208 ret += fprintf(fp, "%16s events: %10d\n", name,
1001 self->stats.nr_events[i]); 1209 hists->stats.nr_events[i]);
1002 } 1210 }
1003 1211
1004 return ret; 1212 return ret;
1005} 1213}
1214
1215void hists__init(struct hists *hists)
1216{
1217 memset(hists, 0, sizeof(*hists));
1218 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
1219 hists->entries_in = &hists->entries_in_array[0];
1220 hists->entries_collapsed = RB_ROOT;
1221 hists->entries = RB_ROOT;
1222 pthread_mutex_init(&hists->lock, NULL);
1223}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 3beb97c4d822..c86c1d27bd1e 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -2,6 +2,7 @@
2#define __PERF_HIST_H 2#define __PERF_HIST_H
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <pthread.h>
5#include "callchain.h" 6#include "callchain.h"
6 7
7extern struct callchain_param callchain_param; 8extern struct callchain_param callchain_param;
@@ -27,6 +28,7 @@ struct events_stats {
27 u64 total_lost; 28 u64 total_lost;
28 u64 total_invalid_chains; 29 u64 total_invalid_chains;
29 u32 nr_events[PERF_RECORD_HEADER_MAX]; 30 u32 nr_events[PERF_RECORD_HEADER_MAX];
31 u32 nr_lost_warned;
30 u32 nr_unknown_events; 32 u32 nr_unknown_events;
31 u32 nr_invalid_chains; 33 u32 nr_invalid_chains;
32 u32 nr_unknown_id; 34 u32 nr_unknown_id;
@@ -42,9 +44,18 @@ enum hist_column {
42 HISTC_NR_COLS, /* Last entry */ 44 HISTC_NR_COLS, /* Last entry */
43}; 45};
44 46
47struct thread;
48struct dso;
49
45struct hists { 50struct hists {
51 struct rb_root entries_in_array[2];
52 struct rb_root *entries_in;
46 struct rb_root entries; 53 struct rb_root entries;
54 struct rb_root entries_collapsed;
47 u64 nr_entries; 55 u64 nr_entries;
56 const struct thread *thread_filter;
57 const struct dso *dso_filter;
58 pthread_mutex_t lock;
48 struct events_stats stats; 59 struct events_stats stats;
49 u64 event_stream; 60 u64 event_stream;
50 u16 col_len[HISTC_NR_COLS]; 61 u16 col_len[HISTC_NR_COLS];
@@ -52,34 +63,42 @@ struct hists {
52 struct callchain_cursor callchain_cursor; 63 struct callchain_cursor callchain_cursor;
53}; 64};
54 65
66void hists__init(struct hists *hists);
67
55struct hist_entry *__hists__add_entry(struct hists *self, 68struct hist_entry *__hists__add_entry(struct hists *self,
56 struct addr_location *al, 69 struct addr_location *al,
57 struct symbol *parent, u64 period); 70 struct symbol *parent, u64 period);
58extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); 71extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
59extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); 72extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
60int hist_entry__fprintf(struct hist_entry *self, struct hists *hists, 73int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists,
61 struct hists *pair_hists, bool show_displacement, 74 struct hists *pair_hists, bool show_displacement,
62 long displacement, FILE *fp, u64 total); 75 long displacement, FILE *fp, u64 session_total);
63int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, 76int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size,
64 struct hists *hists, struct hists *pair_hists, 77 struct hists *hists);
65 bool show_displacement, long displacement,
66 bool color, u64 total);
67void hist_entry__free(struct hist_entry *); 78void hist_entry__free(struct hist_entry *);
68 79
69void hists__output_resort(struct hists *self); 80void hists__output_resort(struct hists *self);
81void hists__output_resort_threaded(struct hists *hists);
70void hists__collapse_resort(struct hists *self); 82void hists__collapse_resort(struct hists *self);
83void hists__collapse_resort_threaded(struct hists *hists);
84
85void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
86void hists__decay_entries_threaded(struct hists *hists, bool zap_user,
87 bool zap_kernel);
88void hists__output_recalc_col_len(struct hists *hists, int max_rows);
71 89
72void hists__inc_nr_events(struct hists *self, u32 type); 90void hists__inc_nr_events(struct hists *self, u32 type);
73size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); 91size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
74 92
75size_t hists__fprintf(struct hists *self, struct hists *pair, 93size_t hists__fprintf(struct hists *self, struct hists *pair,
76 bool show_displacement, FILE *fp); 94 bool show_displacement, bool show_header,
95 int max_rows, int max_cols, FILE *fp);
77 96
78int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); 97int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
79int hist_entry__annotate(struct hist_entry *self, size_t privsize); 98int hist_entry__annotate(struct hist_entry *self, size_t privsize);
80 99
81void hists__filter_by_dso(struct hists *self, const struct dso *dso); 100void hists__filter_by_dso(struct hists *hists);
82void hists__filter_by_thread(struct hists *self, const struct thread *thread); 101void hists__filter_by_thread(struct hists *hists);
83 102
84u16 hists__col_len(struct hists *self, enum hist_column col); 103u16 hists__col_len(struct hists *self, enum hist_column col);
85void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); 104void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
@@ -90,26 +109,33 @@ struct perf_evlist;
90#ifdef NO_NEWT_SUPPORT 109#ifdef NO_NEWT_SUPPORT
91static inline 110static inline
92int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used, 111int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
93 const char *help __used) 112 const char *help __used,
113 void(*timer)(void *arg) __used,
114 void *arg __used,
115 int refresh __used)
94{ 116{
95 return 0; 117 return 0;
96} 118}
97 119
98static inline int hist_entry__tui_annotate(struct hist_entry *self __used, 120static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
99 int evidx __used) 121 int evidx __used,
122 int nr_events __used,
123 void(*timer)(void *arg) __used,
124 void *arg __used,
125 int delay_secs __used)
100{ 126{
101 return 0; 127 return 0;
102} 128}
103#define KEY_LEFT -1 129#define K_LEFT -1
104#define KEY_RIGHT -2 130#define K_RIGHT -2
105#else 131#else
106#include <newt.h> 132#include "ui/keysyms.h"
107int hist_entry__tui_annotate(struct hist_entry *self, int evidx); 133int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events,
108 134 void(*timer)(void *arg), void *arg, int delay_secs);
109#define KEY_LEFT NEWT_KEY_LEFT
110#define KEY_RIGHT NEWT_KEY_RIGHT
111 135
112int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help); 136int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
137 void(*timer)(void *arg), void *arg,
138 int refresh);
113#endif 139#endif
114 140
115unsigned int hists__sort_list_width(struct hists *self); 141unsigned int hists__sort_list_width(struct hists *self);
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
index 791f9dd27ebf..547628e97f3d 100644
--- a/tools/perf/util/include/linux/compiler.h
+++ b/tools/perf/util/include/linux/compiler.h
@@ -5,7 +5,9 @@
5#define __always_inline inline 5#define __always_inline inline
6#endif 6#endif
7#define __user 7#define __user
8#ifndef __attribute_const__
8#define __attribute_const__ 9#define __attribute_const__
10#endif
9 11
10#define __used __attribute__((__unused__)) 12#define __used __attribute__((__unused__))
11 13
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index a16ecab5229d..78284b13e808 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -18,6 +18,13 @@ static inline int is_anon_memory(const char *filename)
18 return strcmp(filename, "//anon") == 0; 18 return strcmp(filename, "//anon") == 0;
19} 19}
20 20
21static inline int is_no_dso_memory(const char *filename)
22{
23 return !strcmp(filename, "[stack]") ||
24 !strcmp(filename, "[vdso]") ||
25 !strcmp(filename, "[heap]");
26}
27
21void map__init(struct map *self, enum map_type type, 28void map__init(struct map *self, enum map_type type,
22 u64 start, u64 end, u64 pgoff, struct dso *dso) 29 u64 start, u64 end, u64 pgoff, struct dso *dso)
23{ 30{
@@ -42,9 +49,10 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
42 if (self != NULL) { 49 if (self != NULL) {
43 char newfilename[PATH_MAX]; 50 char newfilename[PATH_MAX];
44 struct dso *dso; 51 struct dso *dso;
45 int anon; 52 int anon, no_dso;
46 53
47 anon = is_anon_memory(filename); 54 anon = is_anon_memory(filename);
55 no_dso = is_no_dso_memory(filename);
48 56
49 if (anon) { 57 if (anon) {
50 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); 58 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
@@ -57,12 +65,16 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
57 65
58 map__init(self, type, start, start + len, pgoff, dso); 66 map__init(self, type, start, start + len, pgoff, dso);
59 67
60 if (anon) { 68 if (anon || no_dso) {
61set_identity:
62 self->map_ip = self->unmap_ip = identity__map_ip; 69 self->map_ip = self->unmap_ip = identity__map_ip;
63 } else if (strcmp(filename, "[vdso]") == 0) { 70
64 dso__set_loaded(dso, self->type); 71 /*
65 goto set_identity; 72 * Set memory without DSO as loaded. All map__find_*
73 * functions still return NULL, and we avoid the
74 * unnecessary map__load warning.
75 */
76 if (no_dso)
77 dso__set_loaded(dso, self->type);
66 } 78 }
67 } 79 }
68 return self; 80 return self;
@@ -127,8 +139,8 @@ int map__load(struct map *self, symbol_filter_t filter)
127 139
128 if (len > sizeof(DSO__DELETED) && 140 if (len > sizeof(DSO__DELETED) &&
129 strcmp(name + real_len + 1, DSO__DELETED) == 0) { 141 strcmp(name + real_len + 1, DSO__DELETED) == 0) {
130 pr_warning("%.*s was updated, restart the long " 142 pr_warning("%.*s was updated (is prelink enabled?). "
131 "running apps that use it!\n", 143 "Restart the long running apps that use it!\n",
132 (int)real_len, name); 144 (int)real_len, name);
133 } else { 145 } else {
134 pr_warning("no symbols found in %s, maybe install " 146 pr_warning("no symbols found in %s, maybe install "
@@ -220,55 +232,55 @@ u64 map__objdump_2ip(struct map *map, u64 addr)
220 return ip; 232 return ip;
221} 233}
222 234
223void map_groups__init(struct map_groups *self) 235void map_groups__init(struct map_groups *mg)
224{ 236{
225 int i; 237 int i;
226 for (i = 0; i < MAP__NR_TYPES; ++i) { 238 for (i = 0; i < MAP__NR_TYPES; ++i) {
227 self->maps[i] = RB_ROOT; 239 mg->maps[i] = RB_ROOT;
228 INIT_LIST_HEAD(&self->removed_maps[i]); 240 INIT_LIST_HEAD(&mg->removed_maps[i]);
229 } 241 }
230 self->machine = NULL; 242 mg->machine = NULL;
231} 243}
232 244
233static void maps__delete(struct rb_root *self) 245static void maps__delete(struct rb_root *maps)
234{ 246{
235 struct rb_node *next = rb_first(self); 247 struct rb_node *next = rb_first(maps);
236 248
237 while (next) { 249 while (next) {
238 struct map *pos = rb_entry(next, struct map, rb_node); 250 struct map *pos = rb_entry(next, struct map, rb_node);
239 251
240 next = rb_next(&pos->rb_node); 252 next = rb_next(&pos->rb_node);
241 rb_erase(&pos->rb_node, self); 253 rb_erase(&pos->rb_node, maps);
242 map__delete(pos); 254 map__delete(pos);
243 } 255 }
244} 256}
245 257
246static void maps__delete_removed(struct list_head *self) 258static void maps__delete_removed(struct list_head *maps)
247{ 259{
248 struct map *pos, *n; 260 struct map *pos, *n;
249 261
250 list_for_each_entry_safe(pos, n, self, node) { 262 list_for_each_entry_safe(pos, n, maps, node) {
251 list_del(&pos->node); 263 list_del(&pos->node);
252 map__delete(pos); 264 map__delete(pos);
253 } 265 }
254} 266}
255 267
256void map_groups__exit(struct map_groups *self) 268void map_groups__exit(struct map_groups *mg)
257{ 269{
258 int i; 270 int i;
259 271
260 for (i = 0; i < MAP__NR_TYPES; ++i) { 272 for (i = 0; i < MAP__NR_TYPES; ++i) {
261 maps__delete(&self->maps[i]); 273 maps__delete(&mg->maps[i]);
262 maps__delete_removed(&self->removed_maps[i]); 274 maps__delete_removed(&mg->removed_maps[i]);
263 } 275 }
264} 276}
265 277
266void map_groups__flush(struct map_groups *self) 278void map_groups__flush(struct map_groups *mg)
267{ 279{
268 int type; 280 int type;
269 281
270 for (type = 0; type < MAP__NR_TYPES; type++) { 282 for (type = 0; type < MAP__NR_TYPES; type++) {
271 struct rb_root *root = &self->maps[type]; 283 struct rb_root *root = &mg->maps[type];
272 struct rb_node *next = rb_first(root); 284 struct rb_node *next = rb_first(root);
273 285
274 while (next) { 286 while (next) {
@@ -280,17 +292,17 @@ void map_groups__flush(struct map_groups *self)
280 * instance in some hist_entry instances, so 292 * instance in some hist_entry instances, so
281 * just move them to a separate list. 293 * just move them to a separate list.
282 */ 294 */
283 list_add_tail(&pos->node, &self->removed_maps[pos->type]); 295 list_add_tail(&pos->node, &mg->removed_maps[pos->type]);
284 } 296 }
285 } 297 }
286} 298}
287 299
288struct symbol *map_groups__find_symbol(struct map_groups *self, 300struct symbol *map_groups__find_symbol(struct map_groups *mg,
289 enum map_type type, u64 addr, 301 enum map_type type, u64 addr,
290 struct map **mapp, 302 struct map **mapp,
291 symbol_filter_t filter) 303 symbol_filter_t filter)
292{ 304{
293 struct map *map = map_groups__find(self, type, addr); 305 struct map *map = map_groups__find(mg, type, addr);
294 306
295 if (map != NULL) { 307 if (map != NULL) {
296 if (mapp != NULL) 308 if (mapp != NULL)
@@ -301,7 +313,7 @@ struct symbol *map_groups__find_symbol(struct map_groups *self,
301 return NULL; 313 return NULL;
302} 314}
303 315
304struct symbol *map_groups__find_symbol_by_name(struct map_groups *self, 316struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
305 enum map_type type, 317 enum map_type type,
306 const char *name, 318 const char *name,
307 struct map **mapp, 319 struct map **mapp,
@@ -309,7 +321,7 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *self,
309{ 321{
310 struct rb_node *nd; 322 struct rb_node *nd;
311 323
312 for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { 324 for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
313 struct map *pos = rb_entry(nd, struct map, rb_node); 325 struct map *pos = rb_entry(nd, struct map, rb_node);
314 struct symbol *sym = map__find_symbol_by_name(pos, name, filter); 326 struct symbol *sym = map__find_symbol_by_name(pos, name, filter);
315 327
@@ -323,13 +335,13 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *self,
323 return NULL; 335 return NULL;
324} 336}
325 337
326size_t __map_groups__fprintf_maps(struct map_groups *self, 338size_t __map_groups__fprintf_maps(struct map_groups *mg,
327 enum map_type type, int verbose, FILE *fp) 339 enum map_type type, int verbose, FILE *fp)
328{ 340{
329 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); 341 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
330 struct rb_node *nd; 342 struct rb_node *nd;
331 343
332 for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { 344 for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
333 struct map *pos = rb_entry(nd, struct map, rb_node); 345 struct map *pos = rb_entry(nd, struct map, rb_node);
334 printed += fprintf(fp, "Map:"); 346 printed += fprintf(fp, "Map:");
335 printed += map__fprintf(pos, fp); 347 printed += map__fprintf(pos, fp);
@@ -342,22 +354,22 @@ size_t __map_groups__fprintf_maps(struct map_groups *self,
342 return printed; 354 return printed;
343} 355}
344 356
345size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp) 357size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp)
346{ 358{
347 size_t printed = 0, i; 359 size_t printed = 0, i;
348 for (i = 0; i < MAP__NR_TYPES; ++i) 360 for (i = 0; i < MAP__NR_TYPES; ++i)
349 printed += __map_groups__fprintf_maps(self, i, verbose, fp); 361 printed += __map_groups__fprintf_maps(mg, i, verbose, fp);
350 return printed; 362 return printed;
351} 363}
352 364
353static size_t __map_groups__fprintf_removed_maps(struct map_groups *self, 365static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg,
354 enum map_type type, 366 enum map_type type,
355 int verbose, FILE *fp) 367 int verbose, FILE *fp)
356{ 368{
357 struct map *pos; 369 struct map *pos;
358 size_t printed = 0; 370 size_t printed = 0;
359 371
360 list_for_each_entry(pos, &self->removed_maps[type], node) { 372 list_for_each_entry(pos, &mg->removed_maps[type], node) {
361 printed += fprintf(fp, "Map:"); 373 printed += fprintf(fp, "Map:");
362 printed += map__fprintf(pos, fp); 374 printed += map__fprintf(pos, fp);
363 if (verbose > 1) { 375 if (verbose > 1) {
@@ -368,26 +380,26 @@ static size_t __map_groups__fprintf_removed_maps(struct map_groups *self,
368 return printed; 380 return printed;
369} 381}
370 382
371static size_t map_groups__fprintf_removed_maps(struct map_groups *self, 383static size_t map_groups__fprintf_removed_maps(struct map_groups *mg,
372 int verbose, FILE *fp) 384 int verbose, FILE *fp)
373{ 385{
374 size_t printed = 0, i; 386 size_t printed = 0, i;
375 for (i = 0; i < MAP__NR_TYPES; ++i) 387 for (i = 0; i < MAP__NR_TYPES; ++i)
376 printed += __map_groups__fprintf_removed_maps(self, i, verbose, fp); 388 printed += __map_groups__fprintf_removed_maps(mg, i, verbose, fp);
377 return printed; 389 return printed;
378} 390}
379 391
380size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp) 392size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp)
381{ 393{
382 size_t printed = map_groups__fprintf_maps(self, verbose, fp); 394 size_t printed = map_groups__fprintf_maps(mg, verbose, fp);
383 printed += fprintf(fp, "Removed maps:\n"); 395 printed += fprintf(fp, "Removed maps:\n");
384 return printed + map_groups__fprintf_removed_maps(self, verbose, fp); 396 return printed + map_groups__fprintf_removed_maps(mg, verbose, fp);
385} 397}
386 398
387int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, 399int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
388 int verbose, FILE *fp) 400 int verbose, FILE *fp)
389{ 401{
390 struct rb_root *root = &self->maps[map->type]; 402 struct rb_root *root = &mg->maps[map->type];
391 struct rb_node *next = rb_first(root); 403 struct rb_node *next = rb_first(root);
392 int err = 0; 404 int err = 0;
393 405
@@ -418,7 +430,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
418 } 430 }
419 431
420 before->end = map->start - 1; 432 before->end = map->start - 1;
421 map_groups__insert(self, before); 433 map_groups__insert(mg, before);
422 if (verbose >= 2) 434 if (verbose >= 2)
423 map__fprintf(before, fp); 435 map__fprintf(before, fp);
424 } 436 }
@@ -432,7 +444,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
432 } 444 }
433 445
434 after->start = map->end + 1; 446 after->start = map->end + 1;
435 map_groups__insert(self, after); 447 map_groups__insert(mg, after);
436 if (verbose >= 2) 448 if (verbose >= 2)
437 map__fprintf(after, fp); 449 map__fprintf(after, fp);
438 } 450 }
@@ -441,7 +453,7 @@ move_map:
441 * If we have references, just move them to a separate list. 453 * If we have references, just move them to a separate list.
442 */ 454 */
443 if (pos->referenced) 455 if (pos->referenced)
444 list_add_tail(&pos->node, &self->removed_maps[map->type]); 456 list_add_tail(&pos->node, &mg->removed_maps[map->type]);
445 else 457 else
446 map__delete(pos); 458 map__delete(pos);
447 459
@@ -455,7 +467,7 @@ move_map:
455/* 467/*
456 * XXX This should not really _copy_ te maps, but refcount them. 468 * XXX This should not really _copy_ te maps, but refcount them.
457 */ 469 */
458int map_groups__clone(struct map_groups *self, 470int map_groups__clone(struct map_groups *mg,
459 struct map_groups *parent, enum map_type type) 471 struct map_groups *parent, enum map_type type)
460{ 472{
461 struct rb_node *nd; 473 struct rb_node *nd;
@@ -464,7 +476,7 @@ int map_groups__clone(struct map_groups *self,
464 struct map *new = map__clone(map); 476 struct map *new = map__clone(map);
465 if (new == NULL) 477 if (new == NULL)
466 return -ENOMEM; 478 return -ENOMEM;
467 map_groups__insert(self, new); 479 map_groups__insert(mg, new);
468 } 480 }
469 return 0; 481 return 0;
470} 482}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index b397c0383728..890d85545d0f 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -123,17 +123,17 @@ void map__fixup_end(struct map *self);
123 123
124void map__reloc_vmlinux(struct map *self); 124void map__reloc_vmlinux(struct map *self);
125 125
126size_t __map_groups__fprintf_maps(struct map_groups *self, 126size_t __map_groups__fprintf_maps(struct map_groups *mg,
127 enum map_type type, int verbose, FILE *fp); 127 enum map_type type, int verbose, FILE *fp);
128void maps__insert(struct rb_root *maps, struct map *map); 128void maps__insert(struct rb_root *maps, struct map *map);
129void maps__remove(struct rb_root *self, struct map *map); 129void maps__remove(struct rb_root *maps, struct map *map);
130struct map *maps__find(struct rb_root *maps, u64 addr); 130struct map *maps__find(struct rb_root *maps, u64 addr);
131void map_groups__init(struct map_groups *self); 131void map_groups__init(struct map_groups *mg);
132void map_groups__exit(struct map_groups *self); 132void map_groups__exit(struct map_groups *mg);
133int map_groups__clone(struct map_groups *self, 133int map_groups__clone(struct map_groups *mg,
134 struct map_groups *parent, enum map_type type); 134 struct map_groups *parent, enum map_type type);
135size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp); 135size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp);
136size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp); 136size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp);
137 137
138typedef void (*machine__process_t)(struct machine *self, void *data); 138typedef void (*machine__process_t)(struct machine *self, void *data);
139 139
@@ -162,29 +162,29 @@ static inline bool machine__is_host(struct machine *self)
162 return self ? self->pid == HOST_KERNEL_ID : false; 162 return self ? self->pid == HOST_KERNEL_ID : false;
163} 163}
164 164
165static inline void map_groups__insert(struct map_groups *self, struct map *map) 165static inline void map_groups__insert(struct map_groups *mg, struct map *map)
166{ 166{
167 maps__insert(&self->maps[map->type], map); 167 maps__insert(&mg->maps[map->type], map);
168 map->groups = self; 168 map->groups = mg;
169} 169}
170 170
171static inline void map_groups__remove(struct map_groups *self, struct map *map) 171static inline void map_groups__remove(struct map_groups *mg, struct map *map)
172{ 172{
173 maps__remove(&self->maps[map->type], map); 173 maps__remove(&mg->maps[map->type], map);
174} 174}
175 175
176static inline struct map *map_groups__find(struct map_groups *self, 176static inline struct map *map_groups__find(struct map_groups *mg,
177 enum map_type type, u64 addr) 177 enum map_type type, u64 addr)
178{ 178{
179 return maps__find(&self->maps[type], addr); 179 return maps__find(&mg->maps[type], addr);
180} 180}
181 181
182struct symbol *map_groups__find_symbol(struct map_groups *self, 182struct symbol *map_groups__find_symbol(struct map_groups *mg,
183 enum map_type type, u64 addr, 183 enum map_type type, u64 addr,
184 struct map **mapp, 184 struct map **mapp,
185 symbol_filter_t filter); 185 symbol_filter_t filter);
186 186
187struct symbol *map_groups__find_symbol_by_name(struct map_groups *self, 187struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
188 enum map_type type, 188 enum map_type type,
189 const char *name, 189 const char *name,
190 struct map **mapp, 190 struct map **mapp,
@@ -208,11 +208,11 @@ struct symbol *machine__find_kernel_function(struct machine *self, u64 addr,
208} 208}
209 209
210static inline 210static inline
211struct symbol *map_groups__find_function_by_name(struct map_groups *self, 211struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
212 const char *name, struct map **mapp, 212 const char *name, struct map **mapp,
213 symbol_filter_t filter) 213 symbol_filter_t filter)
214{ 214{
215 return map_groups__find_symbol_by_name(self, MAP__FUNCTION, name, mapp, filter); 215 return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp, filter);
216} 216}
217 217
218static inline 218static inline
@@ -225,13 +225,13 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *self,
225 filter); 225 filter);
226} 226}
227 227
228int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, 228int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
229 int verbose, FILE *fp); 229 int verbose, FILE *fp);
230 230
231struct map *map_groups__find_by_name(struct map_groups *self, 231struct map *map_groups__find_by_name(struct map_groups *mg,
232 enum map_type type, const char *name); 232 enum map_type type, const char *name);
233struct map *machine__new_module(struct machine *self, u64 start, const char *filename); 233struct map *machine__new_module(struct machine *self, u64 start, const char *filename);
234 234
235void map_groups__flush(struct map_groups *self); 235void map_groups__flush(struct map_groups *mg);
236 236
237#endif /* __PERF_MAP_H */ 237#endif /* __PERF_MAP_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4ea7e19f5251..928918b796b2 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -697,7 +697,11 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr)
697 return EVT_FAILED; 697 return EVT_FAILED;
698 n = hex2u64(str + 1, &config); 698 n = hex2u64(str + 1, &config);
699 if (n > 0) { 699 if (n > 0) {
700 *strp = str + n + 1; 700 const char *end = str + n + 1;
701 if (*end != '\0' && *end != ',' && *end != ':')
702 return EVT_FAILED;
703
704 *strp = end;
701 attr->type = PERF_TYPE_RAW; 705 attr->type = PERF_TYPE_RAW;
702 attr->config = config; 706 attr->config = config;
703 return EVT_HANDLED; 707 return EVT_HANDLED;
@@ -1097,6 +1101,4 @@ void print_events(const char *event_glob)
1097 printf("\n"); 1101 printf("\n");
1098 1102
1099 print_tracepoint_events(NULL, NULL); 1103 print_tracepoint_events(NULL, NULL);
1100
1101 exit(129);
1102} 1104}
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index b82d54fa2c56..eb25900e2211 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1820,11 +1820,15 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1820 ret = -ENOMEM; 1820 ret = -ENOMEM;
1821 goto error; 1821 goto error;
1822 } 1822 }
1823 tev->point.module = strdup(module); 1823
1824 if (tev->point.module == NULL) { 1824 if (module) {
1825 ret = -ENOMEM; 1825 tev->point.module = strdup(module);
1826 goto error; 1826 if (tev->point.module == NULL) {
1827 ret = -ENOMEM;
1828 goto error;
1829 }
1827 } 1830 }
1831
1828 tev->point.offset = pev->point.offset; 1832 tev->point.offset = pev->point.offset;
1829 tev->point.retprobe = pev->point.retprobe; 1833 tev->point.retprobe = pev->point.retprobe;
1830 tev->nargs = pev->nargs; 1834 tev->nargs = pev->nargs;
@@ -1952,8 +1956,10 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
1952 1956
1953 pr_debug("Writing event: %s\n", buf); 1957 pr_debug("Writing event: %s\n", buf);
1954 ret = write(fd, buf, strlen(buf)); 1958 ret = write(fd, buf, strlen(buf));
1955 if (ret < 0) 1959 if (ret < 0) {
1960 ret = -errno;
1956 goto error; 1961 goto error;
1962 }
1957 1963
1958 printf("Remove event: %s\n", ent->s); 1964 printf("Remove event: %s\n", ent->s);
1959 return 0; 1965 return 0;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 3e44a3e36519..5d732621a462 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -612,12 +612,12 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
612 return ret; 612 return ret;
613} 613}
614 614
615/* Find a variable in a subprogram die */ 615/* Find a variable in a scope DIE */
616static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) 616static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
617{ 617{
618 Dwarf_Die vr_die, *scopes; 618 Dwarf_Die vr_die;
619 char buf[32], *ptr; 619 char buf[32], *ptr;
620 int ret, nscopes; 620 int ret = 0;
621 621
622 if (!is_c_varname(pf->pvar->var)) { 622 if (!is_c_varname(pf->pvar->var)) {
623 /* Copy raw parameters */ 623 /* Copy raw parameters */
@@ -652,30 +652,16 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
652 if (pf->tvar->name == NULL) 652 if (pf->tvar->name == NULL)
653 return -ENOMEM; 653 return -ENOMEM;
654 654
655 pr_debug("Searching '%s' variable in context.\n", 655 pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
656 pf->pvar->var);
657 /* Search child die for local variables and parameters. */ 656 /* Search child die for local variables and parameters. */
658 if (die_find_variable_at(sp_die, pf->pvar->var, pf->addr, &vr_die)) 657 if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
659 ret = convert_variable(&vr_die, pf); 658 /* Search again in global variables */
660 else { 659 if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
661 /* Search upper class */ 660 ret = -ENOENT;
662 nscopes = dwarf_getscopes_die(sp_die, &scopes);
663 while (nscopes-- > 1) {
664 pr_debug("Searching variables in %s\n",
665 dwarf_diename(&scopes[nscopes]));
666 /* We should check this scope, so give dummy address */
667 if (die_find_variable_at(&scopes[nscopes],
668 pf->pvar->var, 0,
669 &vr_die)) {
670 ret = convert_variable(&vr_die, pf);
671 goto found;
672 }
673 }
674 if (scopes)
675 free(scopes);
676 ret = -ENOENT;
677 } 661 }
678found: 662 if (ret >= 0)
663 ret = convert_variable(&vr_die, pf);
664
679 if (ret < 0) 665 if (ret < 0)
680 pr_warning("Failed to find '%s' in this function.\n", 666 pr_warning("Failed to find '%s' in this function.\n",
681 pf->pvar->var); 667 pf->pvar->var);
@@ -718,26 +704,30 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
718 return 0; 704 return 0;
719} 705}
720 706
721/* Call probe_finder callback with real subprogram DIE */ 707/* Call probe_finder callback with scope DIE */
722static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf) 708static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
723{ 709{
724 Dwarf_Die die_mem;
725 Dwarf_Attribute fb_attr; 710 Dwarf_Attribute fb_attr;
726 size_t nops; 711 size_t nops;
727 int ret; 712 int ret;
728 713
729 /* If no real subprogram, find a real one */ 714 if (!sc_die) {
730 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { 715 pr_err("Caller must pass a scope DIE. Program error.\n");
731 sp_die = die_find_realfunc(&pf->cu_die, pf->addr, &die_mem); 716 return -EINVAL;
732 if (!sp_die) { 717 }
718
719 /* If not a real subprogram, find a real one */
720 if (dwarf_tag(sc_die) != DW_TAG_subprogram) {
721 if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
733 pr_warning("Failed to find probe point in any " 722 pr_warning("Failed to find probe point in any "
734 "functions.\n"); 723 "functions.\n");
735 return -ENOENT; 724 return -ENOENT;
736 } 725 }
737 } 726 } else
727 memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
738 728
739 /* Get the frame base attribute/ops */ 729 /* Get the frame base attribute/ops from subprogram */
740 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); 730 dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
741 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); 731 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
742 if (ret <= 0 || nops == 0) { 732 if (ret <= 0 || nops == 0) {
743 pf->fb_ops = NULL; 733 pf->fb_ops = NULL;
@@ -755,7 +745,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
755 } 745 }
756 746
757 /* Call finder's callback handler */ 747 /* Call finder's callback handler */
758 ret = pf->callback(sp_die, pf); 748 ret = pf->callback(sc_die, pf);
759 749
760 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 750 /* *pf->fb_ops will be cached in libdw. Don't free it. */
761 pf->fb_ops = NULL; 751 pf->fb_ops = NULL;
@@ -763,17 +753,82 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
763 return ret; 753 return ret;
764} 754}
765 755
756struct find_scope_param {
757 const char *function;
758 const char *file;
759 int line;
760 int diff;
761 Dwarf_Die *die_mem;
762 bool found;
763};
764
765static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
766{
767 struct find_scope_param *fsp = data;
768 const char *file;
769 int lno;
770
771 /* Skip if declared file name does not match */
772 if (fsp->file) {
773 file = dwarf_decl_file(fn_die);
774 if (!file || strcmp(fsp->file, file) != 0)
775 return 0;
776 }
777 /* If the function name is given, that's what user expects */
778 if (fsp->function) {
779 if (die_compare_name(fn_die, fsp->function)) {
780 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
781 fsp->found = true;
782 return 1;
783 }
784 } else {
785 /* With the line number, find the nearest declared DIE */
786 dwarf_decl_line(fn_die, &lno);
787 if (lno < fsp->line && fsp->diff > fsp->line - lno) {
788 /* Keep a candidate and continue */
789 fsp->diff = fsp->line - lno;
790 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
791 fsp->found = true;
792 }
793 }
794 return 0;
795}
796
797/* Find an appropriate scope fits to given conditions */
798static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
799{
800 struct find_scope_param fsp = {
801 .function = pf->pev->point.function,
802 .file = pf->fname,
803 .line = pf->lno,
804 .diff = INT_MAX,
805 .die_mem = die_mem,
806 .found = false,
807 };
808
809 cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp);
810
811 return fsp.found ? die_mem : NULL;
812}
813
766static int probe_point_line_walker(const char *fname, int lineno, 814static int probe_point_line_walker(const char *fname, int lineno,
767 Dwarf_Addr addr, void *data) 815 Dwarf_Addr addr, void *data)
768{ 816{
769 struct probe_finder *pf = data; 817 struct probe_finder *pf = data;
818 Dwarf_Die *sc_die, die_mem;
770 int ret; 819 int ret;
771 820
772 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0) 821 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
773 return 0; 822 return 0;
774 823
775 pf->addr = addr; 824 pf->addr = addr;
776 ret = call_probe_finder(NULL, pf); 825 sc_die = find_best_scope(pf, &die_mem);
826 if (!sc_die) {
827 pr_warning("Failed to find scope of probe point.\n");
828 return -ENOENT;
829 }
830
831 ret = call_probe_finder(sc_die, pf);
777 832
778 /* Continue if no error, because the line will be in inline function */ 833 /* Continue if no error, because the line will be in inline function */
779 return ret < 0 ? ret : 0; 834 return ret < 0 ? ret : 0;
@@ -827,6 +882,7 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
827 Dwarf_Addr addr, void *data) 882 Dwarf_Addr addr, void *data)
828{ 883{
829 struct probe_finder *pf = data; 884 struct probe_finder *pf = data;
885 Dwarf_Die *sc_die, die_mem;
830 int ret; 886 int ret;
831 887
832 if (!line_list__has_line(&pf->lcache, lineno) || 888 if (!line_list__has_line(&pf->lcache, lineno) ||
@@ -836,7 +892,14 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
836 pr_debug("Probe line found: line:%d addr:0x%llx\n", 892 pr_debug("Probe line found: line:%d addr:0x%llx\n",
837 lineno, (unsigned long long)addr); 893 lineno, (unsigned long long)addr);
838 pf->addr = addr; 894 pf->addr = addr;
839 ret = call_probe_finder(NULL, pf); 895 pf->lno = lineno;
896 sc_die = find_best_scope(pf, &die_mem);
897 if (!sc_die) {
898 pr_warning("Failed to find scope of probe point.\n");
899 return -ENOENT;
900 }
901
902 ret = call_probe_finder(sc_die, pf);
840 903
841 /* 904 /*
842 * Continue if no error, because the lazy pattern will match 905 * Continue if no error, because the lazy pattern will match
@@ -861,42 +924,39 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
861 return die_walk_lines(sp_die, probe_point_lazy_walker, pf); 924 return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
862} 925}
863 926
864/* Callback parameter with return value */
865struct dwarf_callback_param {
866 void *data;
867 int retval;
868};
869
870static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 927static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
871{ 928{
872 struct dwarf_callback_param *param = data; 929 struct probe_finder *pf = data;
873 struct probe_finder *pf = param->data;
874 struct perf_probe_point *pp = &pf->pev->point; 930 struct perf_probe_point *pp = &pf->pev->point;
875 Dwarf_Addr addr; 931 Dwarf_Addr addr;
932 int ret;
876 933
877 if (pp->lazy_line) 934 if (pp->lazy_line)
878 param->retval = find_probe_point_lazy(in_die, pf); 935 ret = find_probe_point_lazy(in_die, pf);
879 else { 936 else {
880 /* Get probe address */ 937 /* Get probe address */
881 if (dwarf_entrypc(in_die, &addr) != 0) { 938 if (dwarf_entrypc(in_die, &addr) != 0) {
882 pr_warning("Failed to get entry address of %s.\n", 939 pr_warning("Failed to get entry address of %s.\n",
883 dwarf_diename(in_die)); 940 dwarf_diename(in_die));
884 param->retval = -ENOENT; 941 return -ENOENT;
885 return DWARF_CB_ABORT;
886 } 942 }
887 pf->addr = addr; 943 pf->addr = addr;
888 pf->addr += pp->offset; 944 pf->addr += pp->offset;
889 pr_debug("found inline addr: 0x%jx\n", 945 pr_debug("found inline addr: 0x%jx\n",
890 (uintmax_t)pf->addr); 946 (uintmax_t)pf->addr);
891 947
892 param->retval = call_probe_finder(in_die, pf); 948 ret = call_probe_finder(in_die, pf);
893 if (param->retval < 0)
894 return DWARF_CB_ABORT;
895 } 949 }
896 950
897 return DWARF_CB_OK; 951 return ret;
898} 952}
899 953
954/* Callback parameter with return value for libdw */
955struct dwarf_callback_param {
956 void *data;
957 int retval;
958};
959
900/* Search function from function name */ 960/* Search function from function name */
901static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) 961static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
902{ 962{
@@ -933,14 +993,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
933 /* TODO: Check the address in this function */ 993 /* TODO: Check the address in this function */
934 param->retval = call_probe_finder(sp_die, pf); 994 param->retval = call_probe_finder(sp_die, pf);
935 } 995 }
936 } else { 996 } else
937 struct dwarf_callback_param _param = {.data = (void *)pf,
938 .retval = 0};
939 /* Inlined function: search instances */ 997 /* Inlined function: search instances */
940 dwarf_func_inline_instances(sp_die, probe_point_inline_cb, 998 param->retval = die_walk_instances(sp_die,
941 &_param); 999 probe_point_inline_cb, (void *)pf);
942 param->retval = _param.retval;
943 }
944 1000
945 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */ 1001 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
946} 1002}
@@ -1060,7 +1116,7 @@ found:
1060} 1116}
1061 1117
1062/* Add a found probe point into trace event list */ 1118/* Add a found probe point into trace event list */
1063static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf) 1119static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1064{ 1120{
1065 struct trace_event_finder *tf = 1121 struct trace_event_finder *tf =
1066 container_of(pf, struct trace_event_finder, pf); 1122 container_of(pf, struct trace_event_finder, pf);
@@ -1075,8 +1131,9 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1075 } 1131 }
1076 tev = &tf->tevs[tf->ntevs++]; 1132 tev = &tf->tevs[tf->ntevs++];
1077 1133
1078 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe, 1134 /* Trace point should be converted from subprogram DIE */
1079 &tev->point); 1135 ret = convert_to_trace_point(&pf->sp_die, pf->addr,
1136 pf->pev->point.retprobe, &tev->point);
1080 if (ret < 0) 1137 if (ret < 0)
1081 return ret; 1138 return ret;
1082 1139
@@ -1091,7 +1148,8 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1091 for (i = 0; i < pf->pev->nargs; i++) { 1148 for (i = 0; i < pf->pev->nargs; i++) {
1092 pf->pvar = &pf->pev->args[i]; 1149 pf->pvar = &pf->pev->args[i];
1093 pf->tvar = &tev->args[i]; 1150 pf->tvar = &tev->args[i];
1094 ret = find_variable(sp_die, pf); 1151 /* Variable should be found from scope DIE */
1152 ret = find_variable(sc_die, pf);
1095 if (ret != 0) 1153 if (ret != 0)
1096 return ret; 1154 return ret;
1097 } 1155 }
@@ -1159,13 +1217,13 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1159} 1217}
1160 1218
1161/* Add a found vars into available variables list */ 1219/* Add a found vars into available variables list */
1162static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf) 1220static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1163{ 1221{
1164 struct available_var_finder *af = 1222 struct available_var_finder *af =
1165 container_of(pf, struct available_var_finder, pf); 1223 container_of(pf, struct available_var_finder, pf);
1166 struct variable_list *vl; 1224 struct variable_list *vl;
1167 Dwarf_Die die_mem, *scopes = NULL; 1225 Dwarf_Die die_mem;
1168 int ret, nscopes; 1226 int ret;
1169 1227
1170 /* Check number of tevs */ 1228 /* Check number of tevs */
1171 if (af->nvls == af->max_vls) { 1229 if (af->nvls == af->max_vls) {
@@ -1174,8 +1232,9 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1174 } 1232 }
1175 vl = &af->vls[af->nvls++]; 1233 vl = &af->vls[af->nvls++];
1176 1234
1177 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe, 1235 /* Trace point should be converted from subprogram DIE */
1178 &vl->point); 1236 ret = convert_to_trace_point(&pf->sp_die, pf->addr,
1237 pf->pev->point.retprobe, &vl->point);
1179 if (ret < 0) 1238 if (ret < 0)
1180 return ret; 1239 return ret;
1181 1240
@@ -1187,19 +1246,14 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1187 if (vl->vars == NULL) 1246 if (vl->vars == NULL)
1188 return -ENOMEM; 1247 return -ENOMEM;
1189 af->child = true; 1248 af->child = true;
1190 die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem); 1249 die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
1191 1250
1192 /* Find external variables */ 1251 /* Find external variables */
1193 if (!af->externs) 1252 if (!af->externs)
1194 goto out; 1253 goto out;
1195 /* Don't need to search child DIE for externs. */ 1254 /* Don't need to search child DIE for externs. */
1196 af->child = false; 1255 af->child = false;
1197 nscopes = dwarf_getscopes_die(sp_die, &scopes); 1256 die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
1198 while (nscopes-- > 1)
1199 die_find_child(&scopes[nscopes], collect_variables_cb,
1200 (void *)af, &die_mem);
1201 if (scopes)
1202 free(scopes);
1203 1257
1204out: 1258out:
1205 if (strlist__empty(vl->vars)) { 1259 if (strlist__empty(vl->vars)) {
@@ -1391,10 +1445,14 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1391 1445
1392static int line_range_inline_cb(Dwarf_Die *in_die, void *data) 1446static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1393{ 1447{
1394 struct dwarf_callback_param *param = data; 1448 find_line_range_by_line(in_die, data);
1395 1449
1396 param->retval = find_line_range_by_line(in_die, param->data); 1450 /*
1397 return DWARF_CB_ABORT; /* No need to find other instances */ 1451 * We have to check all instances of inlined function, because
1452 * some execution paths can be optimized out depends on the
1453 * function argument of instances
1454 */
1455 return 0;
1398} 1456}
1399 1457
1400/* Search function from function name */ 1458/* Search function from function name */
@@ -1422,15 +1480,10 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1422 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); 1480 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1423 lr->start = lf->lno_s; 1481 lr->start = lf->lno_s;
1424 lr->end = lf->lno_e; 1482 lr->end = lf->lno_e;
1425 if (dwarf_func_inline(sp_die)) { 1483 if (dwarf_func_inline(sp_die))
1426 struct dwarf_callback_param _param; 1484 param->retval = die_walk_instances(sp_die,
1427 _param.data = (void *)lf; 1485 line_range_inline_cb, lf);
1428 _param.retval = 0; 1486 else
1429 dwarf_func_inline_instances(sp_die,
1430 line_range_inline_cb,
1431 &_param);
1432 param->retval = _param.retval;
1433 } else
1434 param->retval = find_line_range_by_line(sp_die, lf); 1487 param->retval = find_line_range_by_line(sp_die, lf);
1435 return DWARF_CB_ABORT; 1488 return DWARF_CB_ABORT;
1436 } 1489 }
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index c478b42a2473..1132c8f0ce89 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -57,7 +57,7 @@ struct probe_finder {
57 struct perf_probe_event *pev; /* Target probe event */ 57 struct perf_probe_event *pev; /* Target probe event */
58 58
59 /* Callback when a probe point is found */ 59 /* Callback when a probe point is found */
60 int (*callback)(Dwarf_Die *sp_die, struct probe_finder *pf); 60 int (*callback)(Dwarf_Die *sc_die, struct probe_finder *pf);
61 61
62 /* For function searching */ 62 /* For function searching */
63 int lno; /* Line number */ 63 int lno; /* Line number */
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 8e0b5a39d8a7..9dd47a4f2596 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -187,16 +187,119 @@ static PyTypeObject pyrf_throttle_event__type = {
187 .tp_repr = (reprfunc)pyrf_throttle_event__repr, 187 .tp_repr = (reprfunc)pyrf_throttle_event__repr,
188}; 188};
189 189
190static char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
191
192static PyMemberDef pyrf_lost_event__members[] = {
193 sample_members
194 member_def(lost_event, id, T_ULONGLONG, "event id"),
195 member_def(lost_event, lost, T_ULONGLONG, "number of lost events"),
196 { .name = NULL, },
197};
198
199static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
200{
201 PyObject *ret;
202 char *s;
203
204 if (asprintf(&s, "{ type: lost, id: %#" PRIx64 ", "
205 "lost: %#" PRIx64 " }",
206 pevent->event.lost.id, pevent->event.lost.lost) < 0) {
207 ret = PyErr_NoMemory();
208 } else {
209 ret = PyString_FromString(s);
210 free(s);
211 }
212 return ret;
213}
214
215static PyTypeObject pyrf_lost_event__type = {
216 PyVarObject_HEAD_INIT(NULL, 0)
217 .tp_name = "perf.lost_event",
218 .tp_basicsize = sizeof(struct pyrf_event),
219 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
220 .tp_doc = pyrf_lost_event__doc,
221 .tp_members = pyrf_lost_event__members,
222 .tp_repr = (reprfunc)pyrf_lost_event__repr,
223};
224
225static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
226
227static PyMemberDef pyrf_read_event__members[] = {
228 sample_members
229 member_def(read_event, pid, T_UINT, "event pid"),
230 member_def(read_event, tid, T_UINT, "event tid"),
231 { .name = NULL, },
232};
233
234static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent)
235{
236 return PyString_FromFormat("{ type: read, pid: %u, tid: %u }",
237 pevent->event.read.pid,
238 pevent->event.read.tid);
239 /*
240 * FIXME: return the array of read values,
241 * making this method useful ;-)
242 */
243}
244
245static PyTypeObject pyrf_read_event__type = {
246 PyVarObject_HEAD_INIT(NULL, 0)
247 .tp_name = "perf.read_event",
248 .tp_basicsize = sizeof(struct pyrf_event),
249 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
250 .tp_doc = pyrf_read_event__doc,
251 .tp_members = pyrf_read_event__members,
252 .tp_repr = (reprfunc)pyrf_read_event__repr,
253};
254
255static char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object.");
256
257static PyMemberDef pyrf_sample_event__members[] = {
258 sample_members
259 member_def(perf_event_header, type, T_UINT, "event type"),
260 { .name = NULL, },
261};
262
263static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
264{
265 PyObject *ret;
266 char *s;
267
268 if (asprintf(&s, "{ type: sample }") < 0) {
269 ret = PyErr_NoMemory();
270 } else {
271 ret = PyString_FromString(s);
272 free(s);
273 }
274 return ret;
275}
276
277static PyTypeObject pyrf_sample_event__type = {
278 PyVarObject_HEAD_INIT(NULL, 0)
279 .tp_name = "perf.sample_event",
280 .tp_basicsize = sizeof(struct pyrf_event),
281 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
282 .tp_doc = pyrf_sample_event__doc,
283 .tp_members = pyrf_sample_event__members,
284 .tp_repr = (reprfunc)pyrf_sample_event__repr,
285};
286
190static int pyrf_event__setup_types(void) 287static int pyrf_event__setup_types(void)
191{ 288{
192 int err; 289 int err;
193 pyrf_mmap_event__type.tp_new = 290 pyrf_mmap_event__type.tp_new =
194 pyrf_task_event__type.tp_new = 291 pyrf_task_event__type.tp_new =
195 pyrf_comm_event__type.tp_new = 292 pyrf_comm_event__type.tp_new =
293 pyrf_lost_event__type.tp_new =
294 pyrf_read_event__type.tp_new =
295 pyrf_sample_event__type.tp_new =
196 pyrf_throttle_event__type.tp_new = PyType_GenericNew; 296 pyrf_throttle_event__type.tp_new = PyType_GenericNew;
197 err = PyType_Ready(&pyrf_mmap_event__type); 297 err = PyType_Ready(&pyrf_mmap_event__type);
198 if (err < 0) 298 if (err < 0)
199 goto out; 299 goto out;
300 err = PyType_Ready(&pyrf_lost_event__type);
301 if (err < 0)
302 goto out;
200 err = PyType_Ready(&pyrf_task_event__type); 303 err = PyType_Ready(&pyrf_task_event__type);
201 if (err < 0) 304 if (err < 0)
202 goto out; 305 goto out;
@@ -206,20 +309,26 @@ static int pyrf_event__setup_types(void)
206 err = PyType_Ready(&pyrf_throttle_event__type); 309 err = PyType_Ready(&pyrf_throttle_event__type);
207 if (err < 0) 310 if (err < 0)
208 goto out; 311 goto out;
312 err = PyType_Ready(&pyrf_read_event__type);
313 if (err < 0)
314 goto out;
315 err = PyType_Ready(&pyrf_sample_event__type);
316 if (err < 0)
317 goto out;
209out: 318out:
210 return err; 319 return err;
211} 320}
212 321
213static PyTypeObject *pyrf_event__type[] = { 322static PyTypeObject *pyrf_event__type[] = {
214 [PERF_RECORD_MMAP] = &pyrf_mmap_event__type, 323 [PERF_RECORD_MMAP] = &pyrf_mmap_event__type,
215 [PERF_RECORD_LOST] = &pyrf_mmap_event__type, 324 [PERF_RECORD_LOST] = &pyrf_lost_event__type,
216 [PERF_RECORD_COMM] = &pyrf_comm_event__type, 325 [PERF_RECORD_COMM] = &pyrf_comm_event__type,
217 [PERF_RECORD_EXIT] = &pyrf_task_event__type, 326 [PERF_RECORD_EXIT] = &pyrf_task_event__type,
218 [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type, 327 [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type,
219 [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type, 328 [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
220 [PERF_RECORD_FORK] = &pyrf_task_event__type, 329 [PERF_RECORD_FORK] = &pyrf_task_event__type,
221 [PERF_RECORD_READ] = &pyrf_mmap_event__type, 330 [PERF_RECORD_READ] = &pyrf_read_event__type,
222 [PERF_RECORD_SAMPLE] = &pyrf_mmap_event__type, 331 [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type,
223}; 332};
224 333
225static PyObject *pyrf_event__new(union perf_event *event) 334static PyObject *pyrf_event__new(union perf_event *event)
@@ -514,7 +623,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
514 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; 623 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
515 624
516 evsel->attr.inherit = inherit; 625 evsel->attr.inherit = inherit;
517 if (perf_evsel__open(evsel, cpus, threads, group) < 0) { 626 /*
627 * This will group just the fds for this single evsel, to group
628 * multiple events, use evlist.open().
629 */
630 if (perf_evsel__open(evsel, cpus, threads, group, NULL) < 0) {
518 PyErr_SetFromErrno(PyExc_OSError); 631 PyErr_SetFromErrno(PyExc_OSError);
519 return NULL; 632 return NULL;
520 } 633 }
@@ -694,7 +807,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
694 first = list_entry(evlist->entries.next, struct perf_evsel, node); 807 first = list_entry(evlist->entries.next, struct perf_evsel, node);
695 err = perf_event__parse_sample(event, first->attr.sample_type, 808 err = perf_event__parse_sample(event, first->attr.sample_type,
696 perf_evsel__sample_size(first), 809 perf_evsel__sample_size(first),
697 sample_id_all, &pevent->sample); 810 sample_id_all, &pevent->sample, false);
698 if (err) 811 if (err)
699 return PyErr_Format(PyExc_OSError, 812 return PyErr_Format(PyExc_OSError,
700 "perf: can't parse sample, err=%d", err); 813 "perf: can't parse sample, err=%d", err);
@@ -705,6 +818,25 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
705 return Py_None; 818 return Py_None;
706} 819}
707 820
821static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
822 PyObject *args, PyObject *kwargs)
823{
824 struct perf_evlist *evlist = &pevlist->evlist;
825 int group = 0;
826 static char *kwlist[] = { "group", NULL };
827
828 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group))
829 return NULL;
830
831 if (perf_evlist__open(evlist, group) < 0) {
832 PyErr_SetFromErrno(PyExc_OSError);
833 return NULL;
834 }
835
836 Py_INCREF(Py_None);
837 return Py_None;
838}
839
708static PyMethodDef pyrf_evlist__methods[] = { 840static PyMethodDef pyrf_evlist__methods[] = {
709 { 841 {
710 .ml_name = "mmap", 842 .ml_name = "mmap",
@@ -713,6 +845,12 @@ static PyMethodDef pyrf_evlist__methods[] = {
713 .ml_doc = PyDoc_STR("mmap the file descriptor table.") 845 .ml_doc = PyDoc_STR("mmap the file descriptor table.")
714 }, 846 },
715 { 847 {
848 .ml_name = "open",
849 .ml_meth = (PyCFunction)pyrf_evlist__open,
850 .ml_flags = METH_VARARGS | METH_KEYWORDS,
851 .ml_doc = PyDoc_STR("open the file descriptors.")
852 },
853 {
716 .ml_name = "poll", 854 .ml_name = "poll",
717 .ml_meth = (PyCFunction)pyrf_evlist__poll, 855 .ml_meth = (PyCFunction)pyrf_evlist__poll,
718 .ml_flags = METH_VARARGS | METH_KEYWORDS, 856 .ml_flags = METH_VARARGS | METH_KEYWORDS,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 72458d9da5b1..85c1e6b76f0a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -502,6 +502,7 @@ static void flush_sample_queue(struct perf_session *s,
502 struct perf_sample sample; 502 struct perf_sample sample;
503 u64 limit = os->next_flush; 503 u64 limit = os->next_flush;
504 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; 504 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
505 unsigned idx = 0, progress_next = os->nr_samples / 16;
505 int ret; 506 int ret;
506 507
507 if (!ops->ordered_samples || !limit) 508 if (!ops->ordered_samples || !limit)
@@ -521,6 +522,11 @@ static void flush_sample_queue(struct perf_session *s,
521 os->last_flush = iter->timestamp; 522 os->last_flush = iter->timestamp;
522 list_del(&iter->list); 523 list_del(&iter->list);
523 list_add(&iter->list, &os->sample_cache); 524 list_add(&iter->list, &os->sample_cache);
525 if (++idx >= progress_next) {
526 progress_next += os->nr_samples / 16;
527 ui_progress__update(idx, os->nr_samples,
528 "Processing time ordered events...");
529 }
524 } 530 }
525 531
526 if (list_empty(head)) { 532 if (list_empty(head)) {
@@ -529,6 +535,8 @@ static void flush_sample_queue(struct perf_session *s,
529 os->last_sample = 535 os->last_sample =
530 list_entry(head->prev, struct sample_queue, list); 536 list_entry(head->prev, struct sample_queue, list);
531 } 537 }
538
539 os->nr_samples = 0;
532} 540}
533 541
534/* 542/*
@@ -588,6 +596,7 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
588 u64 timestamp = new->timestamp; 596 u64 timestamp = new->timestamp;
589 struct list_head *p; 597 struct list_head *p;
590 598
599 ++os->nr_samples;
591 os->last_sample = new; 600 os->last_sample = new;
592 601
593 if (!sample) { 602 if (!sample) {
@@ -738,10 +747,27 @@ static int perf_session_deliver_event(struct perf_session *session,
738 747
739 dump_event(session, event, file_offset, sample); 748 dump_event(session, event, file_offset, sample);
740 749
750 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
751 if (evsel != NULL && event->header.type != PERF_RECORD_SAMPLE) {
752 /*
753 * XXX We're leaving PERF_RECORD_SAMPLE unnacounted here
754 * because the tools right now may apply filters, discarding
755 * some of the samples. For consistency, in the future we
756 * should have something like nr_filtered_samples and remove
757 * the sample->period from total_sample_period, etc, KISS for
758 * now tho.
759 *
760 * Also testing against NULL allows us to handle files without
761 * attr.sample_id_all and/or without PERF_SAMPLE_ID. In the
762 * future probably it'll be a good idea to restrict event
763 * processing via perf_session to files with both set.
764 */
765 hists__inc_nr_events(&evsel->hists, event->header.type);
766 }
767
741 switch (event->header.type) { 768 switch (event->header.type) {
742 case PERF_RECORD_SAMPLE: 769 case PERF_RECORD_SAMPLE:
743 dump_sample(session, event, sample); 770 dump_sample(session, event, sample);
744 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
745 if (evsel == NULL) { 771 if (evsel == NULL) {
746 ++session->hists.stats.nr_unknown_id; 772 ++session->hists.stats.nr_unknown_id;
747 return -1; 773 return -1;
@@ -874,11 +900,11 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
874 const struct perf_event_ops *ops) 900 const struct perf_event_ops *ops)
875{ 901{
876 if (ops->lost == perf_event__process_lost && 902 if (ops->lost == perf_event__process_lost &&
877 session->hists.stats.total_lost != 0) { 903 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
878 ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64 904 ui__warning("Processed %d events and lost %d chunks!\n\n"
879 "!\n\nCheck IO/CPU overload!\n\n", 905 "Check IO/CPU overload!\n\n",
880 session->hists.stats.total_period, 906 session->hists.stats.nr_events[0],
881 session->hists.stats.total_lost); 907 session->hists.stats.nr_events[PERF_RECORD_LOST]);
882 } 908 }
883 909
884 if (session->hists.stats.nr_unknown_events != 0) { 910 if (session->hists.stats.nr_unknown_events != 0) {
@@ -1012,7 +1038,6 @@ int __perf_session__process_events(struct perf_session *session,
1012{ 1038{
1013 u64 head, page_offset, file_offset, file_pos, progress_next; 1039 u64 head, page_offset, file_offset, file_pos, progress_next;
1014 int err, mmap_prot, mmap_flags, map_idx = 0; 1040 int err, mmap_prot, mmap_flags, map_idx = 0;
1015 struct ui_progress *progress;
1016 size_t page_size, mmap_size; 1041 size_t page_size, mmap_size;
1017 char *buf, *mmaps[8]; 1042 char *buf, *mmaps[8];
1018 union perf_event *event; 1043 union perf_event *event;
@@ -1030,9 +1055,6 @@ int __perf_session__process_events(struct perf_session *session,
1030 file_size = data_offset + data_size; 1055 file_size = data_offset + data_size;
1031 1056
1032 progress_next = file_size / 16; 1057 progress_next = file_size / 16;
1033 progress = ui_progress__new("Processing events...", file_size);
1034 if (progress == NULL)
1035 return -1;
1036 1058
1037 mmap_size = session->mmap_window; 1059 mmap_size = session->mmap_window;
1038 if (mmap_size > file_size) 1060 if (mmap_size > file_size)
@@ -1095,7 +1117,8 @@ more:
1095 1117
1096 if (file_pos >= progress_next) { 1118 if (file_pos >= progress_next) {
1097 progress_next += file_size / 16; 1119 progress_next += file_size / 16;
1098 ui_progress__update(progress, file_pos); 1120 ui_progress__update(file_pos, file_size,
1121 "Processing events...");
1099 } 1122 }
1100 1123
1101 if (file_pos < file_size) 1124 if (file_pos < file_size)
@@ -1106,7 +1129,6 @@ more:
1106 session->ordered_samples.next_flush = ULLONG_MAX; 1129 session->ordered_samples.next_flush = ULLONG_MAX;
1107 flush_sample_queue(session, ops); 1130 flush_sample_queue(session, ops);
1108out_err: 1131out_err:
1109 ui_progress__delete(progress);
1110 perf_session__warn_about_errors(session, ops); 1132 perf_session__warn_about_errors(session, ops);
1111 perf_session_free_sample_buffers(session); 1133 perf_session_free_sample_buffers(session);
1112 return err; 1134 return err;
@@ -1326,3 +1348,22 @@ int perf_session__cpu_bitmap(struct perf_session *session,
1326 1348
1327 return 0; 1349 return 0;
1328} 1350}
1351
1352void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
1353 bool full)
1354{
1355 struct stat st;
1356 int ret;
1357
1358 if (session == NULL || fp == NULL)
1359 return;
1360
1361 ret = fstat(session->fd, &st);
1362 if (ret == -1)
1363 return;
1364
1365 fprintf(fp, "# ========\n");
1366 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime));
1367 perf_header__fprintf_info(session, fp, full);
1368 fprintf(fp, "# ========\n#\n");
1369}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 170601e67d6b..6e393c98eb34 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -23,6 +23,7 @@ struct ordered_samples {
23 struct sample_queue *sample_buffer; 23 struct sample_queue *sample_buffer;
24 struct sample_queue *last_sample; 24 struct sample_queue *last_sample;
25 int sample_buffer_idx; 25 int sample_buffer_idx;
26 unsigned int nr_samples;
26}; 27};
27 28
28struct perf_session { 29struct perf_session {
@@ -162,7 +163,8 @@ static inline int perf_session__parse_sample(struct perf_session *session,
162{ 163{
163 return perf_event__parse_sample(event, session->sample_type, 164 return perf_event__parse_sample(event, session->sample_type,
164 session->sample_size, 165 session->sample_size,
165 session->sample_id_all, sample); 166 session->sample_id_all, sample,
167 session->header.needs_swap);
166} 168}
167 169
168struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 170struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
@@ -176,4 +178,5 @@ void perf_session__print_ip(union perf_event *event,
176int perf_session__cpu_bitmap(struct perf_session *session, 178int perf_session__cpu_bitmap(struct perf_session *session,
177 const char *cpu_list, unsigned long *cpu_bitmap); 179 const char *cpu_list, unsigned long *cpu_bitmap);
178 180
181void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full);
179#endif /* __PERF_SESSION_H */ 182#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index bbc982f5dd8b..95d370074928 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -3,9 +3,27 @@
3from distutils.core import setup, Extension 3from distutils.core import setup, Extension
4from os import getenv 4from os import getenv
5 5
6from distutils.command.build_ext import build_ext as _build_ext
7from distutils.command.install_lib import install_lib as _install_lib
8
9class build_ext(_build_ext):
10 def finalize_options(self):
11 _build_ext.finalize_options(self)
12 self.build_lib = build_lib
13 self.build_temp = build_tmp
14
15class install_lib(_install_lib):
16 def finalize_options(self):
17 _install_lib.finalize_options(self)
18 self.build_dir = build_lib
19
20
6cflags = ['-fno-strict-aliasing', '-Wno-write-strings'] 21cflags = ['-fno-strict-aliasing', '-Wno-write-strings']
7cflags += getenv('CFLAGS', '').split() 22cflags += getenv('CFLAGS', '').split()
8 23
24build_lib = getenv('PYTHON_EXTBUILD_LIB')
25build_tmp = getenv('PYTHON_EXTBUILD_TMP')
26
9perf = Extension('perf', 27perf = Extension('perf',
10 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
11 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', 29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
@@ -21,4 +39,5 @@ setup(name='perf',
21 author_email='acme@redhat.com', 39 author_email='acme@redhat.com',
22 license='GPLv2', 40 license='GPLv2',
23 url='http://perf.wiki.kernel.org', 41 url='http://perf.wiki.kernel.org',
24 ext_modules=[perf]) 42 ext_modules=[perf],
43 cmdclass={'build_ext': build_ext, 'install_lib': install_lib})
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 401e220566fd..16da30d8d765 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -151,11 +151,17 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
151{ 151{
152 u64 ip_l, ip_r; 152 u64 ip_l, ip_r;
153 153
154 if (!left->ms.sym && !right->ms.sym)
155 return right->level - left->level;
156
157 if (!left->ms.sym || !right->ms.sym)
158 return cmp_null(left->ms.sym, right->ms.sym);
159
154 if (left->ms.sym == right->ms.sym) 160 if (left->ms.sym == right->ms.sym)
155 return 0; 161 return 0;
156 162
157 ip_l = left->ms.sym ? left->ms.sym->start : left->ip; 163 ip_l = left->ms.sym->start;
158 ip_r = right->ms.sym ? right->ms.sym->start : right->ip; 164 ip_r = right->ms.sym->start;
159 165
160 return (int64_t)(ip_r - ip_l); 166 return (int64_t)(ip_r - ip_l);
161} 167}
@@ -171,7 +177,9 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
171 BITS_PER_LONG / 4, self->ip, o); 177 BITS_PER_LONG / 4, self->ip, o);
172 } 178 }
173 179
174 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level); 180 if (!sort_dso.elide)
181 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level);
182
175 if (self->ms.sym) 183 if (self->ms.sym)
176 ret += repsep_snprintf(bf + ret, size - ret, "%s", 184 ret += repsep_snprintf(bf + ret, size - ret, "%s",
177 self->ms.sym->name); 185 self->ms.sym->name);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 77d0388ad415..3f67ae395752 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -45,6 +45,7 @@ extern enum sort_type sort__first_dimension;
45 * @nr_rows - rows expanded in callchain, recalculated on folding/unfolding 45 * @nr_rows - rows expanded in callchain, recalculated on folding/unfolding
46 */ 46 */
47struct hist_entry { 47struct hist_entry {
48 struct rb_node rb_node_in;
48 struct rb_node rb_node; 49 struct rb_node rb_node;
49 u64 period; 50 u64 period;
50 u64 period_sys; 51 u64 period_sys;
@@ -63,6 +64,7 @@ struct hist_entry {
63 64
64 bool init_have_children; 65 bool init_have_children;
65 char level; 66 char level;
67 bool used;
66 u8 filtered; 68 u8 filtered;
67 struct symbol *parent; 69 struct symbol *parent;
68 union { 70 union {
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index eec196329fd9..632b50c7bc26 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -24,7 +24,7 @@
24#include <sys/utsname.h> 24#include <sys/utsname.h>
25 25
26#ifndef KSYM_NAME_LEN 26#ifndef KSYM_NAME_LEN
27#define KSYM_NAME_LEN 128 27#define KSYM_NAME_LEN 256
28#endif 28#endif
29 29
30#ifndef NT_GNU_BUILD_ID 30#ifndef NT_GNU_BUILD_ID
@@ -46,6 +46,7 @@ struct symbol_conf symbol_conf = {
46 .exclude_other = true, 46 .exclude_other = true,
47 .use_modules = true, 47 .use_modules = true,
48 .try_vmlinux_path = true, 48 .try_vmlinux_path = true,
49 .annotate_src = true,
49 .symfs = "", 50 .symfs = "",
50}; 51};
51 52
@@ -74,16 +75,104 @@ static void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
74 75
75bool symbol_type__is_a(char symbol_type, enum map_type map_type) 76bool symbol_type__is_a(char symbol_type, enum map_type map_type)
76{ 77{
78 symbol_type = toupper(symbol_type);
79
77 switch (map_type) { 80 switch (map_type) {
78 case MAP__FUNCTION: 81 case MAP__FUNCTION:
79 return symbol_type == 'T' || symbol_type == 'W'; 82 return symbol_type == 'T' || symbol_type == 'W';
80 case MAP__VARIABLE: 83 case MAP__VARIABLE:
81 return symbol_type == 'D' || symbol_type == 'd'; 84 return symbol_type == 'D';
82 default: 85 default:
83 return false; 86 return false;
84 } 87 }
85} 88}
86 89
90static int prefix_underscores_count(const char *str)
91{
92 const char *tail = str;
93
94 while (*tail == '_')
95 tail++;
96
97 return tail - str;
98}
99
100#define SYMBOL_A 0
101#define SYMBOL_B 1
102
103static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
104{
105 s64 a;
106 s64 b;
107
108 /* Prefer a symbol with non zero length */
109 a = syma->end - syma->start;
110 b = symb->end - symb->start;
111 if ((b == 0) && (a > 0))
112 return SYMBOL_A;
113 else if ((a == 0) && (b > 0))
114 return SYMBOL_B;
115
116 /* Prefer a non weak symbol over a weak one */
117 a = syma->binding == STB_WEAK;
118 b = symb->binding == STB_WEAK;
119 if (b && !a)
120 return SYMBOL_A;
121 if (a && !b)
122 return SYMBOL_B;
123
124 /* Prefer a global symbol over a non global one */
125 a = syma->binding == STB_GLOBAL;
126 b = symb->binding == STB_GLOBAL;
127 if (a && !b)
128 return SYMBOL_A;
129 if (b && !a)
130 return SYMBOL_B;
131
132 /* Prefer a symbol with less underscores */
133 a = prefix_underscores_count(syma->name);
134 b = prefix_underscores_count(symb->name);
135 if (b > a)
136 return SYMBOL_A;
137 else if (a > b)
138 return SYMBOL_B;
139
140 /* If all else fails, choose the symbol with the longest name */
141 if (strlen(syma->name) >= strlen(symb->name))
142 return SYMBOL_A;
143 else
144 return SYMBOL_B;
145}
146
147static void symbols__fixup_duplicate(struct rb_root *symbols)
148{
149 struct rb_node *nd;
150 struct symbol *curr, *next;
151
152 nd = rb_first(symbols);
153
154 while (nd) {
155 curr = rb_entry(nd, struct symbol, rb_node);
156again:
157 nd = rb_next(&curr->rb_node);
158 next = rb_entry(nd, struct symbol, rb_node);
159
160 if (!nd)
161 break;
162
163 if (curr->start != next->start)
164 continue;
165
166 if (choose_best_symbol(curr, next) == SYMBOL_A) {
167 rb_erase(&next->rb_node, symbols);
168 goto again;
169 } else {
170 nd = rb_next(&curr->rb_node);
171 rb_erase(&curr->rb_node, symbols);
172 }
173 }
174}
175
87static void symbols__fixup_end(struct rb_root *symbols) 176static void symbols__fixup_end(struct rb_root *symbols)
88{ 177{
89 struct rb_node *nd, *prevnd = rb_first(symbols); 178 struct rb_node *nd, *prevnd = rb_first(symbols);
@@ -438,18 +527,11 @@ int kallsyms__parse(const char *filename, void *arg,
438 char *line = NULL; 527 char *line = NULL;
439 size_t n; 528 size_t n;
440 int err = -1; 529 int err = -1;
441 u64 prev_start = 0;
442 char prev_symbol_type = 0;
443 char *prev_symbol_name;
444 FILE *file = fopen(filename, "r"); 530 FILE *file = fopen(filename, "r");
445 531
446 if (file == NULL) 532 if (file == NULL)
447 goto out_failure; 533 goto out_failure;
448 534
449 prev_symbol_name = malloc(KSYM_NAME_LEN);
450 if (prev_symbol_name == NULL)
451 goto out_close;
452
453 err = 0; 535 err = 0;
454 536
455 while (!feof(file)) { 537 while (!feof(file)) {
@@ -470,7 +552,7 @@ int kallsyms__parse(const char *filename, void *arg,
470 if (len + 2 >= line_len) 552 if (len + 2 >= line_len)
471 continue; 553 continue;
472 554
473 symbol_type = toupper(line[len]); 555 symbol_type = line[len];
474 len += 2; 556 len += 2;
475 symbol_name = line + len; 557 symbol_name = line + len;
476 len = line_len - len; 558 len = line_len - len;
@@ -480,24 +562,18 @@ int kallsyms__parse(const char *filename, void *arg,
480 break; 562 break;
481 } 563 }
482 564
483 if (prev_symbol_type) { 565 /*
484 u64 end = start; 566 * module symbols are not sorted so we add all
485 if (end != prev_start) 567 * symbols with zero length and rely on
486 --end; 568 * symbols__fixup_end() to fix it up.
487 err = process_symbol(arg, prev_symbol_name, 569 */
488 prev_symbol_type, prev_start, end); 570 err = process_symbol(arg, symbol_name,
489 if (err) 571 symbol_type, start, start);
490 break; 572 if (err)
491 } 573 break;
492
493 memcpy(prev_symbol_name, symbol_name, len + 1);
494 prev_symbol_type = symbol_type;
495 prev_start = start;
496 } 574 }
497 575
498 free(prev_symbol_name);
499 free(line); 576 free(line);
500out_close:
501 fclose(file); 577 fclose(file);
502 return err; 578 return err;
503 579
@@ -703,6 +779,9 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
703 if (dso__load_all_kallsyms(dso, filename, map) < 0) 779 if (dso__load_all_kallsyms(dso, filename, map) < 0)
704 return -1; 780 return -1;
705 781
782 symbols__fixup_duplicate(&dso->symbols[map->type]);
783 symbols__fixup_end(&dso->symbols[map->type]);
784
706 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 785 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
707 dso->symtab_type = SYMTAB__GUEST_KALLSYMS; 786 dso->symtab_type = SYMTAB__GUEST_KALLSYMS;
708 else 787 else
@@ -1092,8 +1171,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1092 if (dso->has_build_id) { 1171 if (dso->has_build_id) {
1093 u8 build_id[BUILD_ID_SIZE]; 1172 u8 build_id[BUILD_ID_SIZE];
1094 1173
1095 if (elf_read_build_id(elf, build_id, 1174 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
1096 BUILD_ID_SIZE) != BUILD_ID_SIZE)
1097 goto out_elf_end; 1175 goto out_elf_end;
1098 1176
1099 if (!dso__build_id_equal(dso, build_id)) 1177 if (!dso__build_id_equal(dso, build_id))
@@ -1111,6 +1189,8 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1111 } 1189 }
1112 1190
1113 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx); 1191 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx);
1192 if (opdshdr.sh_type != SHT_PROGBITS)
1193 opdsec = NULL;
1114 if (opdsec) 1194 if (opdsec)
1115 opddata = elf_rawdata(opdsec, NULL); 1195 opddata = elf_rawdata(opdsec, NULL);
1116 1196
@@ -1276,6 +1356,7 @@ new_symbol:
1276 * For misannotated, zeroed, ASM function sizes. 1356 * For misannotated, zeroed, ASM function sizes.
1277 */ 1357 */
1278 if (nr > 0) { 1358 if (nr > 0) {
1359 symbols__fixup_duplicate(&dso->symbols[map->type]);
1279 symbols__fixup_end(&dso->symbols[map->type]); 1360 symbols__fixup_end(&dso->symbols[map->type]);
1280 if (kmap) { 1361 if (kmap) {
1281 /* 1362 /*
@@ -1362,8 +1443,8 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1362 ptr = data->d_buf; 1443 ptr = data->d_buf;
1363 while (ptr < (data->d_buf + data->d_size)) { 1444 while (ptr < (data->d_buf + data->d_size)) {
1364 GElf_Nhdr *nhdr = ptr; 1445 GElf_Nhdr *nhdr = ptr;
1365 int namesz = NOTE_ALIGN(nhdr->n_namesz), 1446 size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
1366 descsz = NOTE_ALIGN(nhdr->n_descsz); 1447 descsz = NOTE_ALIGN(nhdr->n_descsz);
1367 const char *name; 1448 const char *name;
1368 1449
1369 ptr += sizeof(*nhdr); 1450 ptr += sizeof(*nhdr);
@@ -1372,8 +1453,10 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1372 if (nhdr->n_type == NT_GNU_BUILD_ID && 1453 if (nhdr->n_type == NT_GNU_BUILD_ID &&
1373 nhdr->n_namesz == sizeof("GNU")) { 1454 nhdr->n_namesz == sizeof("GNU")) {
1374 if (memcmp(name, "GNU", sizeof("GNU")) == 0) { 1455 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
1375 memcpy(bf, ptr, BUILD_ID_SIZE); 1456 size_t sz = min(size, descsz);
1376 err = BUILD_ID_SIZE; 1457 memcpy(bf, ptr, sz);
1458 memset(bf + sz, 0, size - sz);
1459 err = descsz;
1377 break; 1460 break;
1378 } 1461 }
1379 } 1462 }
@@ -1425,7 +1508,7 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
1425 while (1) { 1508 while (1) {
1426 char bf[BUFSIZ]; 1509 char bf[BUFSIZ];
1427 GElf_Nhdr nhdr; 1510 GElf_Nhdr nhdr;
1428 int namesz, descsz; 1511 size_t namesz, descsz;
1429 1512
1430 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr)) 1513 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
1431 break; 1514 break;
@@ -1434,15 +1517,16 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
1434 descsz = NOTE_ALIGN(nhdr.n_descsz); 1517 descsz = NOTE_ALIGN(nhdr.n_descsz);
1435 if (nhdr.n_type == NT_GNU_BUILD_ID && 1518 if (nhdr.n_type == NT_GNU_BUILD_ID &&
1436 nhdr.n_namesz == sizeof("GNU")) { 1519 nhdr.n_namesz == sizeof("GNU")) {
1437 if (read(fd, bf, namesz) != namesz) 1520 if (read(fd, bf, namesz) != (ssize_t)namesz)
1438 break; 1521 break;
1439 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) { 1522 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
1440 if (read(fd, build_id, 1523 size_t sz = min(descsz, size);
1441 BUILD_ID_SIZE) == BUILD_ID_SIZE) { 1524 if (read(fd, build_id, sz) == (ssize_t)sz) {
1525 memset(build_id + sz, 0, size - sz);
1442 err = 0; 1526 err = 0;
1443 break; 1527 break;
1444 } 1528 }
1445 } else if (read(fd, bf, descsz) != descsz) 1529 } else if (read(fd, bf, descsz) != (ssize_t)descsz)
1446 break; 1530 break;
1447 } else { 1531 } else {
1448 int n = namesz + descsz; 1532 int n = namesz + descsz;
@@ -1504,6 +1588,17 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1504 dso->adjust_symbols = 0; 1588 dso->adjust_symbols = 0;
1505 1589
1506 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { 1590 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
1591 struct stat st;
1592
1593 if (lstat(dso->name, &st) < 0)
1594 return -1;
1595
1596 if (st.st_uid && (st.st_uid != geteuid())) {
1597 pr_warning("File %s not owned by current user or root, "
1598 "ignoring it.\n", dso->name);
1599 return -1;
1600 }
1601
1507 ret = dso__load_perf_map(dso, map, filter); 1602 ret = dso__load_perf_map(dso, map, filter);
1508 dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : 1603 dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT :
1509 SYMTAB__NOT_FOUND; 1604 SYMTAB__NOT_FOUND;
@@ -2170,27 +2265,22 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
2170 return ret; 2265 return ret;
2171} 2266}
2172 2267
2173struct dso *dso__new_kernel(const char *name) 2268static struct dso*
2269dso__kernel_findnew(struct machine *machine, const char *name,
2270 const char *short_name, int dso_type)
2174{ 2271{
2175 struct dso *dso = dso__new(name ?: "[kernel.kallsyms]"); 2272 /*
2176 2273 * The kernel dso could be created by build_id processing.
2177 if (dso != NULL) { 2274 */
2178 dso__set_short_name(dso, "[kernel]"); 2275 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
2179 dso->kernel = DSO_TYPE_KERNEL;
2180 }
2181
2182 return dso;
2183}
2184 2276
2185static struct dso *dso__new_guest_kernel(struct machine *machine, 2277 /*
2186 const char *name) 2278 * We need to run this in all cases, since during the build_id
2187{ 2279 * processing we had no idea this was the kernel dso.
2188 char bf[PATH_MAX]; 2280 */
2189 struct dso *dso = dso__new(name ?: machine__mmap_name(machine, bf,
2190 sizeof(bf)));
2191 if (dso != NULL) { 2281 if (dso != NULL) {
2192 dso__set_short_name(dso, "[guest.kernel]"); 2282 dso__set_short_name(dso, short_name);
2193 dso->kernel = DSO_TYPE_GUEST_KERNEL; 2283 dso->kernel = dso_type;
2194 } 2284 }
2195 2285
2196 return dso; 2286 return dso;
@@ -2208,24 +2298,36 @@ void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
2208 dso->has_build_id = true; 2298 dso->has_build_id = true;
2209} 2299}
2210 2300
2211static struct dso *machine__create_kernel(struct machine *machine) 2301static struct dso *machine__get_kernel(struct machine *machine)
2212{ 2302{
2213 const char *vmlinux_name = NULL; 2303 const char *vmlinux_name = NULL;
2214 struct dso *kernel; 2304 struct dso *kernel;
2215 2305
2216 if (machine__is_host(machine)) { 2306 if (machine__is_host(machine)) {
2217 vmlinux_name = symbol_conf.vmlinux_name; 2307 vmlinux_name = symbol_conf.vmlinux_name;
2218 kernel = dso__new_kernel(vmlinux_name); 2308 if (!vmlinux_name)
2309 vmlinux_name = "[kernel.kallsyms]";
2310
2311 kernel = dso__kernel_findnew(machine, vmlinux_name,
2312 "[kernel]",
2313 DSO_TYPE_KERNEL);
2219 } else { 2314 } else {
2315 char bf[PATH_MAX];
2316
2220 if (machine__is_default_guest(machine)) 2317 if (machine__is_default_guest(machine))
2221 vmlinux_name = symbol_conf.default_guest_vmlinux_name; 2318 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
2222 kernel = dso__new_guest_kernel(machine, vmlinux_name); 2319 if (!vmlinux_name)
2320 vmlinux_name = machine__mmap_name(machine, bf,
2321 sizeof(bf));
2322
2323 kernel = dso__kernel_findnew(machine, vmlinux_name,
2324 "[guest.kernel]",
2325 DSO_TYPE_GUEST_KERNEL);
2223 } 2326 }
2224 2327
2225 if (kernel != NULL) { 2328 if (kernel != NULL && (!kernel->has_build_id))
2226 dso__read_running_kernel_build_id(kernel, machine); 2329 dso__read_running_kernel_build_id(kernel, machine);
2227 dsos__add(&machine->kernel_dsos, kernel); 2330
2228 }
2229 return kernel; 2331 return kernel;
2230} 2332}
2231 2333
@@ -2329,7 +2431,7 @@ void machine__destroy_kernel_maps(struct machine *machine)
2329 2431
2330int machine__create_kernel_maps(struct machine *machine) 2432int machine__create_kernel_maps(struct machine *machine)
2331{ 2433{
2332 struct dso *kernel = machine__create_kernel(machine); 2434 struct dso *kernel = machine__get_kernel(machine);
2333 2435
2334 if (kernel == NULL || 2436 if (kernel == NULL ||
2335 __machine__create_kernel_maps(machine, kernel) < 0) 2437 __machine__create_kernel_maps(machine, kernel) < 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 325ee36a9d29..29f8d742e92f 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -72,11 +72,14 @@ struct symbol_conf {
72 use_modules, 72 use_modules,
73 sort_by_name, 73 sort_by_name,
74 show_nr_samples, 74 show_nr_samples,
75 show_total_period,
75 use_callchain, 76 use_callchain,
76 exclude_other, 77 exclude_other,
77 show_cpu_utilization, 78 show_cpu_utilization,
78 initialized, 79 initialized,
79 kptr_restrict; 80 kptr_restrict,
81 annotate_asm_raw,
82 annotate_src;
80 const char *vmlinux_name, 83 const char *vmlinux_name,
81 *kallsyms_name, 84 *kallsyms_name,
82 *source_prefix, 85 *source_prefix,
@@ -155,7 +158,6 @@ struct dso {
155}; 158};
156 159
157struct dso *dso__new(const char *name); 160struct dso *dso__new(const char *name);
158struct dso *dso__new_kernel(const char *name);
159void dso__delete(struct dso *dso); 161void dso__delete(struct dso *dso);
160 162
161int dso__name_len(const struct dso *dso); 163int dso__name_len(const struct dso *dso);
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index a11f60735a18..500471dffa4f 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -15,52 +15,6 @@
15#include "top.h" 15#include "top.h"
16#include <inttypes.h> 16#include <inttypes.h>
17 17
18/*
19 * Ordering weight: count-1 * count-2 * ... / count-n
20 */
21static double sym_weight(const struct sym_entry *sym, struct perf_top *top)
22{
23 double weight = sym->snap_count;
24 int counter;
25
26 if (!top->display_weighted)
27 return weight;
28
29 for (counter = 1; counter < top->evlist->nr_entries - 1; counter++)
30 weight *= sym->count[counter];
31
32 weight /= (sym->count[counter] + 1);
33
34 return weight;
35}
36
37static void perf_top__remove_active_sym(struct perf_top *top, struct sym_entry *syme)
38{
39 pthread_mutex_lock(&top->active_symbols_lock);
40 list_del_init(&syme->node);
41 pthread_mutex_unlock(&top->active_symbols_lock);
42}
43
44static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
45{
46 struct rb_node **p = &tree->rb_node;
47 struct rb_node *parent = NULL;
48 struct sym_entry *iter;
49
50 while (*p != NULL) {
51 parent = *p;
52 iter = rb_entry(parent, struct sym_entry, rb_node);
53
54 if (se->weight > iter->weight)
55 p = &(*p)->rb_left;
56 else
57 p = &(*p)->rb_right;
58 }
59
60 rb_link_node(&se->rb_node, parent, p);
61 rb_insert_color(&se->rb_node, tree);
62}
63
64#define SNPRINTF(buf, size, fmt, args...) \ 18#define SNPRINTF(buf, size, fmt, args...) \
65({ \ 19({ \
66 size_t r = snprintf(buf, size, fmt, ## args); \ 20 size_t r = snprintf(buf, size, fmt, ## args); \
@@ -69,7 +23,6 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
69 23
70size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) 24size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
71{ 25{
72 struct perf_evsel *counter;
73 float samples_per_sec = top->samples / top->delay_secs; 26 float samples_per_sec = top->samples / top->delay_secs;
74 float ksamples_per_sec = top->kernel_samples / top->delay_secs; 27 float ksamples_per_sec = top->kernel_samples / top->delay_secs;
75 float esamples_percent = (100.0 * top->exact_samples) / top->samples; 28 float esamples_percent = (100.0 * top->exact_samples) / top->samples;
@@ -104,7 +57,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
104 esamples_percent); 57 esamples_percent);
105 } 58 }
106 59
107 if (top->evlist->nr_entries == 1 || !top->display_weighted) { 60 if (top->evlist->nr_entries == 1) {
108 struct perf_evsel *first; 61 struct perf_evsel *first;
109 first = list_entry(top->evlist->entries.next, struct perf_evsel, node); 62 first = list_entry(top->evlist->entries.next, struct perf_evsel, node);
110 ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ", 63 ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ",
@@ -112,27 +65,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
112 top->freq ? "Hz" : ""); 65 top->freq ? "Hz" : "");
113 } 66 }
114 67
115 if (!top->display_weighted) { 68 ret += SNPRINTF(bf + ret, size - ret, "%s", event_name(top->sym_evsel));
116 ret += SNPRINTF(bf + ret, size - ret, "%s",
117 event_name(top->sym_evsel));
118 } else {
119 /*
120 * Don't let events eat all the space. Leaving 30 bytes
121 * for the rest should be enough.
122 */
123 size_t last_pos = size - 30;
124
125 list_for_each_entry(counter, &top->evlist->entries, node) {
126 ret += SNPRINTF(bf + ret, size - ret, "%s%s",
127 counter->idx ? "/" : "",
128 event_name(counter));
129 if (ret > last_pos) {
130 sprintf(bf + last_pos - 3, "..");
131 ret = last_pos - 1;
132 break;
133 }
134 }
135 }
136 69
137 ret += SNPRINTF(bf + ret, size - ret, "], "); 70 ret += SNPRINTF(bf + ret, size - ret, "], ");
138 71
@@ -166,73 +99,3 @@ void perf_top__reset_sample_counters(struct perf_top *top)
166 top->exact_samples = top->guest_kernel_samples = 99 top->exact_samples = top->guest_kernel_samples =
167 top->guest_us_samples = 0; 100 top->guest_us_samples = 0;
168} 101}
169
170float perf_top__decay_samples(struct perf_top *top, struct rb_root *root)
171{
172 struct sym_entry *syme, *n;
173 float sum_ksamples = 0.0;
174 int snap = !top->display_weighted ? top->sym_evsel->idx : 0, j;
175
176 /* Sort the active symbols */
177 pthread_mutex_lock(&top->active_symbols_lock);
178 syme = list_entry(top->active_symbols.next, struct sym_entry, node);
179 pthread_mutex_unlock(&top->active_symbols_lock);
180
181 top->rb_entries = 0;
182 list_for_each_entry_safe_from(syme, n, &top->active_symbols, node) {
183 syme->snap_count = syme->count[snap];
184 if (syme->snap_count != 0) {
185
186 if ((top->hide_user_symbols &&
187 syme->map->dso->kernel == DSO_TYPE_USER) ||
188 (top->hide_kernel_symbols &&
189 syme->map->dso->kernel == DSO_TYPE_KERNEL)) {
190 perf_top__remove_active_sym(top, syme);
191 continue;
192 }
193 syme->weight = sym_weight(syme, top);
194
195 if ((int)syme->snap_count >= top->count_filter) {
196 rb_insert_active_sym(root, syme);
197 ++top->rb_entries;
198 }
199 sum_ksamples += syme->snap_count;
200
201 for (j = 0; j < top->evlist->nr_entries; j++)
202 syme->count[j] = top->zero ? 0 : syme->count[j] * 7 / 8;
203 } else
204 perf_top__remove_active_sym(top, syme);
205 }
206
207 return sum_ksamples;
208}
209
210/*
211 * Find the longest symbol name that will be displayed
212 */
213void perf_top__find_widths(struct perf_top *top, struct rb_root *root,
214 int *dso_width, int *dso_short_width, int *sym_width)
215{
216 struct rb_node *nd;
217 int printed = 0;
218
219 *sym_width = *dso_width = *dso_short_width = 0;
220
221 for (nd = rb_first(root); nd; nd = rb_next(nd)) {
222 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
223 struct symbol *sym = sym_entry__symbol(syme);
224
225 if (++printed > top->print_entries ||
226 (int)syme->snap_count < top->count_filter)
227 continue;
228
229 if (syme->map->dso->long_name_len > *dso_width)
230 *dso_width = syme->map->dso->long_name_len;
231
232 if (syme->map->dso->short_name_len > *dso_short_width)
233 *dso_short_width = syme->map->dso->short_name_len;
234
235 if (sym->namelen > *sym_width)
236 *sym_width = sym->namelen;
237 }
238}
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index bfbf95bcc603..399650967958 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -4,26 +4,10 @@
4#include "types.h" 4#include "types.h"
5#include "../perf.h" 5#include "../perf.h"
6#include <stddef.h> 6#include <stddef.h>
7#include <pthread.h>
8#include <linux/list.h>
9#include <linux/rbtree.h>
10 7
11struct perf_evlist; 8struct perf_evlist;
12struct perf_evsel; 9struct perf_evsel;
13 10struct perf_session;
14struct sym_entry {
15 struct rb_node rb_node;
16 struct list_head node;
17 unsigned long snap_count;
18 double weight;
19 struct map *map;
20 unsigned long count[0];
21};
22
23static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
24{
25 return ((void *)self) + symbol_conf.priv_size;
26}
27 11
28struct perf_top { 12struct perf_top {
29 struct perf_evlist *evlist; 13 struct perf_evlist *evlist;
@@ -31,34 +15,20 @@ struct perf_top {
31 * Symbols will be added here in perf_event__process_sample and will 15 * Symbols will be added here in perf_event__process_sample and will
32 * get out after decayed. 16 * get out after decayed.
33 */ 17 */
34 struct list_head active_symbols;
35 pthread_mutex_t active_symbols_lock;
36 pthread_cond_t active_symbols_cond;
37 u64 samples; 18 u64 samples;
38 u64 kernel_samples, us_samples; 19 u64 kernel_samples, us_samples;
39 u64 exact_samples; 20 u64 exact_samples;
40 u64 guest_us_samples, guest_kernel_samples; 21 u64 guest_us_samples, guest_kernel_samples;
41 int print_entries, count_filter, delay_secs; 22 int print_entries, count_filter, delay_secs;
42 int display_weighted, freq, rb_entries; 23 int freq;
43 pid_t target_pid, target_tid; 24 pid_t target_pid, target_tid;
44 bool hide_kernel_symbols, hide_user_symbols, zero; 25 bool hide_kernel_symbols, hide_user_symbols, zero;
45 const char *cpu_list; 26 const char *cpu_list;
46 struct sym_entry *sym_filter_entry; 27 struct hist_entry *sym_filter_entry;
47 struct perf_evsel *sym_evsel; 28 struct perf_evsel *sym_evsel;
29 struct perf_session *session;
48}; 30};
49 31
50size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 32size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
51void perf_top__reset_sample_counters(struct perf_top *top); 33void perf_top__reset_sample_counters(struct perf_top *top);
52float perf_top__decay_samples(struct perf_top *top, struct rb_root *root);
53void perf_top__find_widths(struct perf_top *top, struct rb_root *root,
54 int *dso_width, int *dso_short_width, int *sym_width);
55
56#ifdef NO_NEWT_SUPPORT
57static inline int perf_top__tui_browser(struct perf_top *top __used)
58{
59 return 0;
60}
61#else
62int perf_top__tui_browser(struct perf_top *top);
63#endif
64#endif /* __PERF_TOP_H */ 34#endif /* __PERF_TOP_H */
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 3403f814ad72..d2655f08bcc0 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -80,7 +80,7 @@ static void die(const char *fmt, ...)
80 int ret = errno; 80 int ret = errno;
81 81
82 if (errno) 82 if (errno)
83 perror("trace-cmd"); 83 perror("perf");
84 else 84 else
85 ret = -1; 85 ret = -1;
86 86
@@ -196,7 +196,8 @@ static void record_file(const char *file, size_t hdr_sz)
196 die("Can't read '%s'", file); 196 die("Can't read '%s'", file);
197 197
198 /* put in zeros for file size, then fill true size later */ 198 /* put in zeros for file size, then fill true size later */
199 write_or_die(&size, hdr_sz); 199 if (hdr_sz)
200 write_or_die(&size, hdr_sz);
200 201
201 do { 202 do {
202 r = read(fd, buf, BUFSIZ); 203 r = read(fd, buf, BUFSIZ);
@@ -212,7 +213,7 @@ static void record_file(const char *file, size_t hdr_sz)
212 if (bigendian()) 213 if (bigendian())
213 sizep += sizeof(u64) - hdr_sz; 214 sizep += sizeof(u64) - hdr_sz;
214 215
215 if (pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) 216 if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0)
216 die("writing to %s", output_file); 217 die("writing to %s", output_file);
217} 218}
218 219
@@ -428,6 +429,19 @@ get_tracepoints_path(struct list_head *pattrs)
428 return nr_tracepoints > 0 ? path.next : NULL; 429 return nr_tracepoints > 0 ? path.next : NULL;
429} 430}
430 431
432static void
433put_tracepoints_path(struct tracepoint_path *tps)
434{
435 while (tps) {
436 struct tracepoint_path *t = tps;
437
438 tps = tps->next;
439 free(t->name);
440 free(t->system);
441 free(t);
442 }
443}
444
431bool have_tracepoints(struct list_head *pattrs) 445bool have_tracepoints(struct list_head *pattrs)
432{ 446{
433 struct perf_evsel *pos; 447 struct perf_evsel *pos;
@@ -439,19 +453,11 @@ bool have_tracepoints(struct list_head *pattrs)
439 return false; 453 return false;
440} 454}
441 455
442int read_tracing_data(int fd, struct list_head *pattrs) 456static void tracing_data_header(void)
443{ 457{
444 char buf[BUFSIZ]; 458 char buf[20];
445 struct tracepoint_path *tps = get_tracepoints_path(pattrs);
446
447 /*
448 * What? No tracepoints? No sense writing anything here, bail out.
449 */
450 if (tps == NULL)
451 return -1;
452
453 output_fd = fd;
454 459
460 /* just guessing this is someone's birthday.. ;) */
455 buf[0] = 23; 461 buf[0] = 23;
456 buf[1] = 8; 462 buf[1] = 8;
457 buf[2] = 68; 463 buf[2] = 68;
@@ -476,28 +482,86 @@ int read_tracing_data(int fd, struct list_head *pattrs)
476 /* save page_size */ 482 /* save page_size */
477 page_size = sysconf(_SC_PAGESIZE); 483 page_size = sysconf(_SC_PAGESIZE);
478 write_or_die(&page_size, 4); 484 write_or_die(&page_size, 4);
485}
486
487struct tracing_data *tracing_data_get(struct list_head *pattrs,
488 int fd, bool temp)
489{
490 struct tracepoint_path *tps;
491 struct tracing_data *tdata;
492
493 output_fd = fd;
494
495 tps = get_tracepoints_path(pattrs);
496 if (!tps)
497 return NULL;
479 498
499 tdata = malloc_or_die(sizeof(*tdata));
500 tdata->temp = temp;
501 tdata->size = 0;
502
503 if (temp) {
504 int temp_fd;
505
506 snprintf(tdata->temp_file, sizeof(tdata->temp_file),
507 "/tmp/perf-XXXXXX");
508 if (!mkstemp(tdata->temp_file))
509 die("Can't make temp file");
510
511 temp_fd = open(tdata->temp_file, O_RDWR);
512 if (temp_fd < 0)
513 die("Can't read '%s'", tdata->temp_file);
514
515 /*
516 * Set the temp file the default output, so all the
517 * tracing data are stored into it.
518 */
519 output_fd = temp_fd;
520 }
521
522 tracing_data_header();
480 read_header_files(); 523 read_header_files();
481 read_ftrace_files(tps); 524 read_ftrace_files(tps);
482 read_event_files(tps); 525 read_event_files(tps);
483 read_proc_kallsyms(); 526 read_proc_kallsyms();
484 read_ftrace_printk(); 527 read_ftrace_printk();
485 528
486 return 0; 529 /*
530 * All tracing data are stored by now, we can restore
531 * the default output file in case we used temp file.
532 */
533 if (temp) {
534 tdata->size = lseek(output_fd, 0, SEEK_CUR);
535 close(output_fd);
536 output_fd = fd;
537 }
538
539 put_tracepoints_path(tps);
540 return tdata;
487} 541}
488 542
489ssize_t read_tracing_data_size(int fd, struct list_head *pattrs) 543void tracing_data_put(struct tracing_data *tdata)
490{ 544{
491 ssize_t size; 545 if (tdata->temp) {
492 int err = 0; 546 record_file(tdata->temp_file, 0);
547 unlink(tdata->temp_file);
548 }
493 549
494 calc_data_size = 1; 550 free(tdata);
495 err = read_tracing_data(fd, pattrs); 551}
496 size = calc_data_size - 1;
497 calc_data_size = 0;
498 552
499 if (err < 0) 553int read_tracing_data(int fd, struct list_head *pattrs)
500 return err; 554{
555 struct tracing_data *tdata;
501 556
502 return size; 557 /*
558 * We work over the real file, so we can write data
559 * directly, no temp file is needed.
560 */
561 tdata = tracing_data_get(pattrs, fd, false);
562 if (!tdata)
563 return -ENOMEM;
564
565 tracing_data_put(tdata);
566 return 0;
503} 567}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index f674dda3363b..a84100817649 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -263,7 +263,18 @@ void *raw_field_ptr(struct event *event, const char *name, void *data);
263unsigned long long eval_flag(const char *flag); 263unsigned long long eval_flag(const char *flag);
264 264
265int read_tracing_data(int fd, struct list_head *pattrs); 265int read_tracing_data(int fd, struct list_head *pattrs);
266ssize_t read_tracing_data_size(int fd, struct list_head *pattrs); 266
267struct tracing_data {
268 /* size is only valid if temp is 'true' */
269 ssize_t size;
270 bool temp;
271 char temp_file[50];
272};
273
274struct tracing_data *tracing_data_get(struct list_head *pattrs,
275 int fd, bool temp);
276void tracing_data_put(struct tracing_data *tdata);
277
267 278
268/* taken from kernel/trace/trace.h */ 279/* taken from kernel/trace/trace.h */
269enum trace_flag_type { 280enum trace_flag_type {
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
index 611219f80680..556829124b02 100644
--- a/tools/perf/util/ui/browser.c
+++ b/tools/perf/util/ui/browser.c
@@ -1,5 +1,10 @@
1#include "../util.h"
2#include "../cache.h"
3#include "../../perf.h"
1#include "libslang.h" 4#include "libslang.h"
5#include <newt.h>
2#include "ui.h" 6#include "ui.h"
7#include "util.h"
3#include <linux/compiler.h> 8#include <linux/compiler.h>
4#include <linux/list.h> 9#include <linux/list.h>
5#include <linux/rbtree.h> 10#include <linux/rbtree.h>
@@ -7,13 +12,13 @@
7#include <sys/ttydefaults.h> 12#include <sys/ttydefaults.h>
8#include "browser.h" 13#include "browser.h"
9#include "helpline.h" 14#include "helpline.h"
15#include "keysyms.h"
10#include "../color.h" 16#include "../color.h"
11#include "../util.h"
12#include <stdio.h>
13 17
14static int ui_browser__percent_color(double percent, bool current) 18static int ui_browser__percent_color(struct ui_browser *browser,
19 double percent, bool current)
15{ 20{
16 if (current) 21 if (current && (!browser->use_navkeypressed || browser->navkeypressed))
17 return HE_COLORSET_SELECTED; 22 return HE_COLORSET_SELECTED;
18 if (percent >= MIN_RED) 23 if (percent >= MIN_RED)
19 return HE_COLORSET_TOP; 24 return HE_COLORSET_TOP;
@@ -30,7 +35,7 @@ void ui_browser__set_color(struct ui_browser *self __used, int color)
30void ui_browser__set_percent_color(struct ui_browser *self, 35void ui_browser__set_percent_color(struct ui_browser *self,
31 double percent, bool current) 36 double percent, bool current)
32{ 37{
33 int color = ui_browser__percent_color(percent, current); 38 int color = ui_browser__percent_color(self, percent, current);
34 ui_browser__set_color(self, color); 39 ui_browser__set_color(self, color);
35} 40}
36 41
@@ -39,31 +44,62 @@ void ui_browser__gotorc(struct ui_browser *self, int y, int x)
39 SLsmg_gotorc(self->y + y, self->x + x); 44 SLsmg_gotorc(self->y + y, self->x + x);
40} 45}
41 46
47static struct list_head *
48ui_browser__list_head_filter_entries(struct ui_browser *browser,
49 struct list_head *pos)
50{
51 do {
52 if (!browser->filter || !browser->filter(browser, pos))
53 return pos;
54 pos = pos->next;
55 } while (pos != browser->entries);
56
57 return NULL;
58}
59
60static struct list_head *
61ui_browser__list_head_filter_prev_entries(struct ui_browser *browser,
62 struct list_head *pos)
63{
64 do {
65 if (!browser->filter || !browser->filter(browser, pos))
66 return pos;
67 pos = pos->prev;
68 } while (pos != browser->entries);
69
70 return NULL;
71}
72
42void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence) 73void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
43{ 74{
44 struct list_head *head = self->entries; 75 struct list_head *head = self->entries;
45 struct list_head *pos; 76 struct list_head *pos;
46 77
78 if (self->nr_entries == 0)
79 return;
80
47 switch (whence) { 81 switch (whence) {
48 case SEEK_SET: 82 case SEEK_SET:
49 pos = head->next; 83 pos = ui_browser__list_head_filter_entries(self, head->next);
50 break; 84 break;
51 case SEEK_CUR: 85 case SEEK_CUR:
52 pos = self->top; 86 pos = self->top;
53 break; 87 break;
54 case SEEK_END: 88 case SEEK_END:
55 pos = head->prev; 89 pos = ui_browser__list_head_filter_prev_entries(self, head->prev);
56 break; 90 break;
57 default: 91 default:
58 return; 92 return;
59 } 93 }
60 94
95 assert(pos != NULL);
96
61 if (offset > 0) { 97 if (offset > 0) {
62 while (offset-- != 0) 98 while (offset-- != 0)
63 pos = pos->next; 99 pos = ui_browser__list_head_filter_entries(self, pos->next);
64 } else { 100 } else {
65 while (offset++ != 0) 101 while (offset++ != 0)
66 pos = pos->prev; 102 pos = ui_browser__list_head_filter_prev_entries(self, pos->prev);
67 } 103 }
68 104
69 self->top = pos; 105 self->top = pos;
@@ -127,41 +163,76 @@ bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
127 163
128void ui_browser__refresh_dimensions(struct ui_browser *self) 164void ui_browser__refresh_dimensions(struct ui_browser *self)
129{ 165{
130 int cols, rows; 166 self->width = SLtt_Screen_Cols - 1;
131 newtGetScreenSize(&cols, &rows); 167 self->height = SLtt_Screen_Rows - 2;
132
133 self->width = cols - 1;
134 self->height = rows - 2;
135 self->y = 1; 168 self->y = 1;
136 self->x = 0; 169 self->x = 0;
137} 170}
138 171
139void ui_browser__reset_index(struct ui_browser *self) 172void ui_browser__handle_resize(struct ui_browser *browser)
140{ 173{
141 self->index = self->top_idx = 0; 174 ui__refresh_dimensions(false);
142 self->seek(self, 0, SEEK_SET); 175 ui_browser__show(browser, browser->title, ui_helpline__current);
176 ui_browser__refresh(browser);
143} 177}
144 178
145void ui_browser__add_exit_key(struct ui_browser *self, int key) 179int ui_browser__warning(struct ui_browser *browser, int timeout,
180 const char *format, ...)
146{ 181{
147 newtFormAddHotKey(self->form, key); 182 va_list args;
183 char *text;
184 int key = 0, err;
185
186 va_start(args, format);
187 err = vasprintf(&text, format, args);
188 va_end(args);
189
190 if (err < 0) {
191 va_start(args, format);
192 ui_helpline__vpush(format, args);
193 va_end(args);
194 } else {
195 while ((key == ui__question_window("Warning!", text,
196 "Press any key...",
197 timeout)) == K_RESIZE)
198 ui_browser__handle_resize(browser);
199 free(text);
200 }
201
202 return key;
148} 203}
149 204
150void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]) 205int ui_browser__help_window(struct ui_browser *browser, const char *text)
151{ 206{
152 int i = 0; 207 int key;
153 208
154 while (keys[i] && i < 64) { 209 while ((key = ui__help_window(text)) == K_RESIZE)
155 ui_browser__add_exit_key(self, keys[i]); 210 ui_browser__handle_resize(browser);
156 ++i; 211
157 } 212 return key;
213}
214
215bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text)
216{
217 int key;
218
219 while ((key = ui__dialog_yesno(text)) == K_RESIZE)
220 ui_browser__handle_resize(browser);
221
222 return key == K_ENTER || toupper(key) == 'Y';
223}
224
225void ui_browser__reset_index(struct ui_browser *self)
226{
227 self->index = self->top_idx = 0;
228 self->seek(self, 0, SEEK_SET);
158} 229}
159 230
160void __ui_browser__show_title(struct ui_browser *browser, const char *title) 231void __ui_browser__show_title(struct ui_browser *browser, const char *title)
161{ 232{
162 SLsmg_gotorc(0, 0); 233 SLsmg_gotorc(0, 0);
163 ui_browser__set_color(browser, NEWT_COLORSET_ROOT); 234 ui_browser__set_color(browser, NEWT_COLORSET_ROOT);
164 slsmg_write_nstring(title, browser->width); 235 slsmg_write_nstring(title, browser->width + 1);
165} 236}
166 237
167void ui_browser__show_title(struct ui_browser *browser, const char *title) 238void ui_browser__show_title(struct ui_browser *browser, const char *title)
@@ -174,78 +245,145 @@ void ui_browser__show_title(struct ui_browser *browser, const char *title)
174int ui_browser__show(struct ui_browser *self, const char *title, 245int ui_browser__show(struct ui_browser *self, const char *title,
175 const char *helpline, ...) 246 const char *helpline, ...)
176{ 247{
248 int err;
177 va_list ap; 249 va_list ap;
178 int keys[] = { NEWT_KEY_UP, NEWT_KEY_DOWN, NEWT_KEY_PGUP,
179 NEWT_KEY_PGDN, NEWT_KEY_HOME, NEWT_KEY_END, ' ',
180 NEWT_KEY_LEFT, NEWT_KEY_ESCAPE, 'q', CTRL('c'), 0 };
181
182 if (self->form != NULL)
183 newtFormDestroy(self->form);
184 250
185 ui_browser__refresh_dimensions(self); 251 ui_browser__refresh_dimensions(self);
186 self->form = newtForm(NULL, NULL, 0);
187 if (self->form == NULL)
188 return -1;
189
190 self->sb = newtVerticalScrollbar(self->width, 1, self->height,
191 HE_COLORSET_NORMAL,
192 HE_COLORSET_SELECTED);
193 if (self->sb == NULL)
194 return -1;
195 252
196 pthread_mutex_lock(&ui__lock); 253 pthread_mutex_lock(&ui__lock);
197 __ui_browser__show_title(self, title); 254 __ui_browser__show_title(self, title);
198 255
199 ui_browser__add_exit_keys(self, keys); 256 self->title = title;
200 newtFormAddComponent(self->form, self->sb); 257 free(self->helpline);
258 self->helpline = NULL;
201 259
202 va_start(ap, helpline); 260 va_start(ap, helpline);
203 ui_helpline__vpush(helpline, ap); 261 err = vasprintf(&self->helpline, helpline, ap);
204 va_end(ap); 262 va_end(ap);
263 if (err > 0)
264 ui_helpline__push(self->helpline);
205 pthread_mutex_unlock(&ui__lock); 265 pthread_mutex_unlock(&ui__lock);
206 return 0; 266 return err ? 0 : -1;
207} 267}
208 268
209void ui_browser__hide(struct ui_browser *self) 269void ui_browser__hide(struct ui_browser *browser __used)
210{ 270{
211 pthread_mutex_lock(&ui__lock); 271 pthread_mutex_lock(&ui__lock);
212 newtFormDestroy(self->form);
213 self->form = NULL;
214 ui_helpline__pop(); 272 ui_helpline__pop();
215 pthread_mutex_unlock(&ui__lock); 273 pthread_mutex_unlock(&ui__lock);
216} 274}
217 275
218int ui_browser__refresh(struct ui_browser *self) 276static void ui_browser__scrollbar_set(struct ui_browser *browser)
277{
278 int height = browser->height, h = 0, pct = 0,
279 col = browser->width,
280 row = browser->y - 1;
281
282 if (browser->nr_entries > 1) {
283 pct = ((browser->index * (browser->height - 1)) /
284 (browser->nr_entries - 1));
285 }
286
287 SLsmg_set_char_set(1);
288
289 while (h < height) {
290 ui_browser__gotorc(browser, row++, col);
291 SLsmg_write_char(h == pct ? SLSMG_DIAMOND_CHAR : SLSMG_CKBRD_CHAR);
292 ++h;
293 }
294
295 SLsmg_set_char_set(0);
296}
297
298static int __ui_browser__refresh(struct ui_browser *browser)
219{ 299{
220 int row; 300 int row;
301 int width = browser->width;
302
303 row = browser->refresh(browser);
304 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
305
306 if (!browser->use_navkeypressed || browser->navkeypressed)
307 ui_browser__scrollbar_set(browser);
308 else
309 width += 1;
310
311 SLsmg_fill_region(browser->y + row, browser->x,
312 browser->height - row, width, ' ');
313
314 return 0;
315}
221 316
317int ui_browser__refresh(struct ui_browser *browser)
318{
222 pthread_mutex_lock(&ui__lock); 319 pthread_mutex_lock(&ui__lock);
223 newtScrollbarSet(self->sb, self->index, self->nr_entries - 1); 320 __ui_browser__refresh(browser);
224 row = self->refresh(self);
225 ui_browser__set_color(self, HE_COLORSET_NORMAL);
226 SLsmg_fill_region(self->y + row, self->x,
227 self->height - row, self->width, ' ');
228 pthread_mutex_unlock(&ui__lock); 321 pthread_mutex_unlock(&ui__lock);
229 322
230 return 0; 323 return 0;
231} 324}
232 325
233int ui_browser__run(struct ui_browser *self) 326/*
327 * Here we're updating nr_entries _after_ we started browsing, i.e. we have to
328 * forget about any reference to any entry in the underlying data structure,
329 * that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
330 * after an output_resort and hist decay.
331 */
332void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries)
234{ 333{
235 struct newtExitStruct es; 334 off_t offset = nr_entries - browser->nr_entries;
335
336 browser->nr_entries = nr_entries;
236 337
237 if (ui_browser__refresh(self) < 0) 338 if (offset < 0) {
238 return -1; 339 if (browser->top_idx < (u64)-offset)
340 offset = -browser->top_idx;
341
342 browser->index += offset;
343 browser->top_idx += offset;
344 }
345
346 browser->top = NULL;
347 browser->seek(browser, browser->top_idx, SEEK_SET);
348}
349
350int ui_browser__run(struct ui_browser *self, int delay_secs)
351{
352 int err, key;
239 353
240 while (1) { 354 while (1) {
241 off_t offset; 355 off_t offset;
242 356
243 newtFormRun(self->form, &es); 357 pthread_mutex_lock(&ui__lock);
244 358 err = __ui_browser__refresh(self);
245 if (es.reason != NEWT_EXIT_HOTKEY) 359 SLsmg_refresh();
360 pthread_mutex_unlock(&ui__lock);
361 if (err < 0)
246 break; 362 break;
247 switch (es.u.key) { 363
248 case NEWT_KEY_DOWN: 364 key = ui__getch(delay_secs);
365
366 if (key == K_RESIZE) {
367 ui__refresh_dimensions(false);
368 ui_browser__refresh_dimensions(self);
369 __ui_browser__show_title(self, self->title);
370 ui_helpline__puts(self->helpline);
371 continue;
372 }
373
374 if (self->use_navkeypressed && !self->navkeypressed) {
375 if (key == K_DOWN || key == K_UP ||
376 key == K_PGDN || key == K_PGUP ||
377 key == K_HOME || key == K_END ||
378 key == ' ') {
379 self->navkeypressed = true;
380 continue;
381 } else
382 return key;
383 }
384
385 switch (key) {
386 case K_DOWN:
249 if (self->index == self->nr_entries - 1) 387 if (self->index == self->nr_entries - 1)
250 break; 388 break;
251 ++self->index; 389 ++self->index;
@@ -254,7 +392,7 @@ int ui_browser__run(struct ui_browser *self)
254 self->seek(self, +1, SEEK_CUR); 392 self->seek(self, +1, SEEK_CUR);
255 } 393 }
256 break; 394 break;
257 case NEWT_KEY_UP: 395 case K_UP:
258 if (self->index == 0) 396 if (self->index == 0)
259 break; 397 break;
260 --self->index; 398 --self->index;
@@ -263,7 +401,7 @@ int ui_browser__run(struct ui_browser *self)
263 self->seek(self, -1, SEEK_CUR); 401 self->seek(self, -1, SEEK_CUR);
264 } 402 }
265 break; 403 break;
266 case NEWT_KEY_PGDN: 404 case K_PGDN:
267 case ' ': 405 case ' ':
268 if (self->top_idx + self->height > self->nr_entries - 1) 406 if (self->top_idx + self->height > self->nr_entries - 1)
269 break; 407 break;
@@ -275,7 +413,7 @@ int ui_browser__run(struct ui_browser *self)
275 self->top_idx += offset; 413 self->top_idx += offset;
276 self->seek(self, +offset, SEEK_CUR); 414 self->seek(self, +offset, SEEK_CUR);
277 break; 415 break;
278 case NEWT_KEY_PGUP: 416 case K_PGUP:
279 if (self->top_idx == 0) 417 if (self->top_idx == 0)
280 break; 418 break;
281 419
@@ -288,10 +426,10 @@ int ui_browser__run(struct ui_browser *self)
288 self->top_idx -= offset; 426 self->top_idx -= offset;
289 self->seek(self, -offset, SEEK_CUR); 427 self->seek(self, -offset, SEEK_CUR);
290 break; 428 break;
291 case NEWT_KEY_HOME: 429 case K_HOME:
292 ui_browser__reset_index(self); 430 ui_browser__reset_index(self);
293 break; 431 break;
294 case NEWT_KEY_END: 432 case K_END:
295 offset = self->height - 1; 433 offset = self->height - 1;
296 if (offset >= self->nr_entries) 434 if (offset >= self->nr_entries)
297 offset = self->nr_entries - 1; 435 offset = self->nr_entries - 1;
@@ -301,10 +439,8 @@ int ui_browser__run(struct ui_browser *self)
301 self->seek(self, -offset, SEEK_END); 439 self->seek(self, -offset, SEEK_END);
302 break; 440 break;
303 default: 441 default:
304 return es.u.key; 442 return key;
305 } 443 }
306 if (ui_browser__refresh(self) < 0)
307 return -1;
308 } 444 }
309 return -1; 445 return -1;
310} 446}
@@ -316,41 +452,146 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
316 int row = 0; 452 int row = 0;
317 453
318 if (self->top == NULL || self->top == self->entries) 454 if (self->top == NULL || self->top == self->entries)
319 self->top = head->next; 455 self->top = ui_browser__list_head_filter_entries(self, head->next);
320 456
321 pos = self->top; 457 pos = self->top;
322 458
323 list_for_each_from(pos, head) { 459 list_for_each_from(pos, head) {
324 ui_browser__gotorc(self, row, 0); 460 if (!self->filter || !self->filter(self, pos)) {
325 self->write(self, pos, row); 461 ui_browser__gotorc(self, row, 0);
326 if (++row == self->height) 462 self->write(self, pos, row);
327 break; 463 if (++row == self->height)
464 break;
465 }
328 } 466 }
329 467
330 return row; 468 return row;
331} 469}
332 470
333static struct newtPercentTreeColors { 471static struct ui_browser__colorset {
334 const char *topColorFg, *topColorBg; 472 const char *name, *fg, *bg;
335 const char *mediumColorFg, *mediumColorBg; 473 int colorset;
336 const char *normalColorFg, *normalColorBg; 474} ui_browser__colorsets[] = {
337 const char *selColorFg, *selColorBg; 475 {
338 const char *codeColorFg, *codeColorBg; 476 .colorset = HE_COLORSET_TOP,
339} defaultPercentTreeColors = { 477 .name = "top",
340 "red", "lightgray", 478 .fg = "red",
341 "green", "lightgray", 479 .bg = "default",
342 "black", "lightgray", 480 },
343 "lightgray", "magenta", 481 {
344 "blue", "lightgray", 482 .colorset = HE_COLORSET_MEDIUM,
483 .name = "medium",
484 .fg = "green",
485 .bg = "default",
486 },
487 {
488 .colorset = HE_COLORSET_NORMAL,
489 .name = "normal",
490 .fg = "default",
491 .bg = "default",
492 },
493 {
494 .colorset = HE_COLORSET_SELECTED,
495 .name = "selected",
496 .fg = "black",
497 .bg = "lightgray",
498 },
499 {
500 .colorset = HE_COLORSET_CODE,
501 .name = "code",
502 .fg = "blue",
503 .bg = "default",
504 },
505 {
506 .name = NULL,
507 }
345}; 508};
346 509
510
511static int ui_browser__color_config(const char *var, const char *value,
512 void *data __used)
513{
514 char *fg = NULL, *bg;
515 int i;
516
517 /* same dir for all commands */
518 if (prefixcmp(var, "colors.") != 0)
519 return 0;
520
521 for (i = 0; ui_browser__colorsets[i].name != NULL; ++i) {
522 const char *name = var + 7;
523
524 if (strcmp(ui_browser__colorsets[i].name, name) != 0)
525 continue;
526
527 fg = strdup(value);
528 if (fg == NULL)
529 break;
530
531 bg = strchr(fg, ',');
532 if (bg == NULL)
533 break;
534
535 *bg = '\0';
536 while (isspace(*++bg));
537 ui_browser__colorsets[i].bg = bg;
538 ui_browser__colorsets[i].fg = fg;
539 return 0;
540 }
541
542 free(fg);
543 return -1;
544}
545
546void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence)
547{
548 switch (whence) {
549 case SEEK_SET:
550 browser->top = browser->entries;
551 break;
552 case SEEK_CUR:
553 browser->top = browser->top + browser->top_idx + offset;
554 break;
555 case SEEK_END:
556 browser->top = browser->top + browser->nr_entries + offset;
557 break;
558 default:
559 return;
560 }
561}
562
563unsigned int ui_browser__argv_refresh(struct ui_browser *browser)
564{
565 unsigned int row = 0, idx = browser->top_idx;
566 char **pos;
567
568 if (browser->top == NULL)
569 browser->top = browser->entries;
570
571 pos = (char **)browser->top;
572 while (idx < browser->nr_entries) {
573 if (!browser->filter || !browser->filter(browser, *pos)) {
574 ui_browser__gotorc(browser, row, 0);
575 browser->write(browser, pos, row);
576 if (++row == browser->height)
577 break;
578 }
579
580 ++idx;
581 ++pos;
582 }
583
584 return row;
585}
586
347void ui_browser__init(void) 587void ui_browser__init(void)
348{ 588{
349 struct newtPercentTreeColors *c = &defaultPercentTreeColors; 589 int i = 0;
590
591 perf_config(ui_browser__color_config, NULL);
350 592
351 sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); 593 while (ui_browser__colorsets[i].name) {
352 sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg); 594 struct ui_browser__colorset *c = &ui_browser__colorsets[i++];
353 sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg); 595 sltt_set_color(c->colorset, c->name, c->fg, c->bg);
354 sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg); 596 }
355 sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);
356} 597}
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h
index fc63dda10910..84d761b730c1 100644
--- a/tools/perf/util/ui/browser.h
+++ b/tools/perf/util/ui/browser.h
@@ -2,7 +2,6 @@
2#define _PERF_UI_BROWSER_H_ 1 2#define _PERF_UI_BROWSER_H_ 1
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include <newt.h>
6#include <sys/types.h> 5#include <sys/types.h>
7#include "../types.h" 6#include "../types.h"
8 7
@@ -13,15 +12,19 @@
13#define HE_COLORSET_CODE 54 12#define HE_COLORSET_CODE 54
14 13
15struct ui_browser { 14struct ui_browser {
16 newtComponent form, sb;
17 u64 index, top_idx; 15 u64 index, top_idx;
18 void *top, *entries; 16 void *top, *entries;
19 u16 y, x, width, height; 17 u16 y, x, width, height;
20 void *priv; 18 void *priv;
19 const char *title;
20 char *helpline;
21 unsigned int (*refresh)(struct ui_browser *self); 21 unsigned int (*refresh)(struct ui_browser *self);
22 void (*write)(struct ui_browser *self, void *entry, int row); 22 void (*write)(struct ui_browser *self, void *entry, int row);
23 void (*seek)(struct ui_browser *self, off_t offset, int whence); 23 void (*seek)(struct ui_browser *self, off_t offset, int whence);
24 bool (*filter)(struct ui_browser *self, void *entry);
24 u32 nr_entries; 25 u32 nr_entries;
26 bool navkeypressed;
27 bool use_navkeypressed;
25}; 28};
26 29
27void ui_browser__set_color(struct ui_browser *self, int color); 30void ui_browser__set_color(struct ui_browser *self, int color);
@@ -32,15 +35,23 @@ void ui_browser__refresh_dimensions(struct ui_browser *self);
32void ui_browser__reset_index(struct ui_browser *self); 35void ui_browser__reset_index(struct ui_browser *self);
33 36
34void ui_browser__gotorc(struct ui_browser *self, int y, int x); 37void ui_browser__gotorc(struct ui_browser *self, int y, int x);
35void ui_browser__add_exit_key(struct ui_browser *self, int key);
36void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]);
37void __ui_browser__show_title(struct ui_browser *browser, const char *title); 38void __ui_browser__show_title(struct ui_browser *browser, const char *title);
38void ui_browser__show_title(struct ui_browser *browser, const char *title); 39void ui_browser__show_title(struct ui_browser *browser, const char *title);
39int ui_browser__show(struct ui_browser *self, const char *title, 40int ui_browser__show(struct ui_browser *self, const char *title,
40 const char *helpline, ...); 41 const char *helpline, ...);
41void ui_browser__hide(struct ui_browser *self); 42void ui_browser__hide(struct ui_browser *self);
42int ui_browser__refresh(struct ui_browser *self); 43int ui_browser__refresh(struct ui_browser *self);
43int ui_browser__run(struct ui_browser *self); 44int ui_browser__run(struct ui_browser *browser, int delay_secs);
45void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries);
46void ui_browser__handle_resize(struct ui_browser *browser);
47
48int ui_browser__warning(struct ui_browser *browser, int timeout,
49 const char *format, ...);
50int ui_browser__help_window(struct ui_browser *browser, const char *text);
51bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
52
53void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
54unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
44 55
45void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence); 56void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence);
46unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self); 57unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 0229723aceb3..0575905d1205 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -1,31 +1,31 @@
1#include "../../util.h"
1#include "../browser.h" 2#include "../browser.h"
2#include "../helpline.h" 3#include "../helpline.h"
3#include "../libslang.h" 4#include "../libslang.h"
5#include "../ui.h"
6#include "../util.h"
4#include "../../annotate.h" 7#include "../../annotate.h"
5#include "../../hist.h" 8#include "../../hist.h"
6#include "../../sort.h" 9#include "../../sort.h"
7#include "../../symbol.h" 10#include "../../symbol.h"
8#include <pthread.h> 11#include <pthread.h>
9 12#include <newt.h>
10static void ui__error_window(const char *fmt, ...)
11{
12 va_list ap;
13
14 va_start(ap, fmt);
15 newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap);
16 va_end(ap);
17}
18 13
19struct annotate_browser { 14struct annotate_browser {
20 struct ui_browser b; 15 struct ui_browser b;
21 struct rb_root entries; 16 struct rb_root entries;
22 struct rb_node *curr_hot; 17 struct rb_node *curr_hot;
18 struct objdump_line *selection;
19 int nr_asm_entries;
20 int nr_entries;
21 bool hide_src_code;
23}; 22};
24 23
25struct objdump_line_rb_node { 24struct objdump_line_rb_node {
26 struct rb_node rb_node; 25 struct rb_node rb_node;
27 double percent; 26 double percent;
28 u32 idx; 27 u32 idx;
28 int idx_asm;
29}; 29};
30 30
31static inline 31static inline
@@ -34,9 +34,22 @@ struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self)
34 return (struct objdump_line_rb_node *)(self + 1); 34 return (struct objdump_line_rb_node *)(self + 1);
35} 35}
36 36
37static bool objdump_line__filter(struct ui_browser *browser, void *entry)
38{
39 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
40
41 if (ab->hide_src_code) {
42 struct objdump_line *ol = list_entry(entry, struct objdump_line, node);
43 return ol->offset == -1;
44 }
45
46 return false;
47}
48
37static void annotate_browser__write(struct ui_browser *self, void *entry, int row) 49static void annotate_browser__write(struct ui_browser *self, void *entry, int row)
38{ 50{
39 struct objdump_line *ol = rb_entry(entry, struct objdump_line, node); 51 struct annotate_browser *ab = container_of(self, struct annotate_browser, b);
52 struct objdump_line *ol = list_entry(entry, struct objdump_line, node);
40 bool current_entry = ui_browser__is_current_entry(self, row); 53 bool current_entry = ui_browser__is_current_entry(self, row);
41 int width = self->width; 54 int width = self->width;
42 55
@@ -51,6 +64,11 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
51 64
52 SLsmg_write_char(':'); 65 SLsmg_write_char(':');
53 slsmg_write_nstring(" ", 8); 66 slsmg_write_nstring(" ", 8);
67
68 /* The scroll bar isn't being used */
69 if (!self->navkeypressed)
70 width += 1;
71
54 if (!*ol->line) 72 if (!*ol->line)
55 slsmg_write_nstring(" ", width - 18); 73 slsmg_write_nstring(" ", width - 18);
56 else 74 else
@@ -58,6 +76,8 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
58 76
59 if (!current_entry) 77 if (!current_entry)
60 ui_browser__set_color(self, HE_COLORSET_CODE); 78 ui_browser__set_color(self, HE_COLORSET_CODE);
79 else
80 ab->selection = ol;
61} 81}
62 82
63static double objdump_line__calc_percent(struct objdump_line *self, 83static double objdump_line__calc_percent(struct objdump_line *self,
@@ -141,7 +161,8 @@ static void annotate_browser__set_top(struct annotate_browser *self,
141static void annotate_browser__calc_percent(struct annotate_browser *browser, 161static void annotate_browser__calc_percent(struct annotate_browser *browser,
142 int evidx) 162 int evidx)
143{ 163{
144 struct symbol *sym = browser->b.priv; 164 struct map_symbol *ms = browser->b.priv;
165 struct symbol *sym = ms->sym;
145 struct annotation *notes = symbol__annotation(sym); 166 struct annotation *notes = symbol__annotation(sym);
146 struct objdump_line *pos; 167 struct objdump_line *pos;
147 168
@@ -163,25 +184,60 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
163 browser->curr_hot = rb_last(&browser->entries); 184 browser->curr_hot = rb_last(&browser->entries);
164} 185}
165 186
187static bool annotate_browser__toggle_source(struct annotate_browser *browser)
188{
189 struct objdump_line *ol;
190 struct objdump_line_rb_node *olrb;
191 off_t offset = browser->b.index - browser->b.top_idx;
192
193 browser->b.seek(&browser->b, offset, SEEK_CUR);
194 ol = list_entry(browser->b.top, struct objdump_line, node);
195 olrb = objdump_line__rb(ol);
196
197 if (browser->hide_src_code) {
198 if (olrb->idx_asm < offset)
199 offset = olrb->idx;
200
201 browser->b.nr_entries = browser->nr_entries;
202 browser->hide_src_code = false;
203 browser->b.seek(&browser->b, -offset, SEEK_CUR);
204 browser->b.top_idx = olrb->idx - offset;
205 browser->b.index = olrb->idx;
206 } else {
207 if (olrb->idx_asm < 0) {
208 ui_helpline__puts("Only available for assembly lines.");
209 browser->b.seek(&browser->b, -offset, SEEK_CUR);
210 return false;
211 }
212
213 if (olrb->idx_asm < offset)
214 offset = olrb->idx_asm;
215
216 browser->b.nr_entries = browser->nr_asm_entries;
217 browser->hide_src_code = true;
218 browser->b.seek(&browser->b, -offset, SEEK_CUR);
219 browser->b.top_idx = olrb->idx_asm - offset;
220 browser->b.index = olrb->idx_asm;
221 }
222
223 return true;
224}
225
166static int annotate_browser__run(struct annotate_browser *self, int evidx, 226static int annotate_browser__run(struct annotate_browser *self, int evidx,
167 int refresh) 227 int nr_events, void(*timer)(void *arg),
228 void *arg, int delay_secs)
168{ 229{
169 struct rb_node *nd = NULL; 230 struct rb_node *nd = NULL;
170 struct symbol *sym = self->b.priv; 231 struct map_symbol *ms = self->b.priv;
171 /* 232 struct symbol *sym = ms->sym;
172 * RIGHT To allow builtin-annotate to cycle thru multiple symbols by 233 const char *help = "<-, ESC: exit, TAB/shift+TAB: cycle hottest lines, "
173 * examining the exit key for this function. 234 "H: Hottest, -> Line action, S -> Toggle source "
174 */ 235 "code view";
175 int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB,
176 NEWT_KEY_RIGHT, 0 };
177 int key; 236 int key;
178 237
179 if (ui_browser__show(&self->b, sym->name, 238 if (ui_browser__show(&self->b, sym->name, help) < 0)
180 "<-, -> or ESC: exit, TAB/shift+TAB: "
181 "cycle hottest lines, H: Hottest") < 0)
182 return -1; 239 return -1;
183 240
184 ui_browser__add_exit_keys(&self->b, exit_keys);
185 annotate_browser__calc_percent(self, evidx); 241 annotate_browser__calc_percent(self, evidx);
186 242
187 if (self->curr_hot) 243 if (self->curr_hot)
@@ -189,13 +245,10 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
189 245
190 nd = self->curr_hot; 246 nd = self->curr_hot;
191 247
192 if (refresh != 0)
193 newtFormSetTimer(self->b.form, refresh);
194
195 while (1) { 248 while (1) {
196 key = ui_browser__run(&self->b); 249 key = ui_browser__run(&self->b, delay_secs);
197 250
198 if (refresh != 0) { 251 if (delay_secs != 0) {
199 annotate_browser__calc_percent(self, evidx); 252 annotate_browser__calc_percent(self, evidx);
200 /* 253 /*
201 * Current line focus got out of the list of most active 254 * Current line focus got out of the list of most active
@@ -207,15 +260,14 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
207 } 260 }
208 261
209 switch (key) { 262 switch (key) {
210 case -1: 263 case K_TIMER:
211 /* 264 if (timer != NULL)
212 * FIXME we need to check if it was 265 timer(arg);
213 * es.reason == NEWT_EXIT_TIMER 266
214 */ 267 if (delay_secs != 0)
215 if (refresh != 0)
216 symbol__annotate_decay_histogram(sym, evidx); 268 symbol__annotate_decay_histogram(sym, evidx);
217 continue; 269 continue;
218 case NEWT_KEY_TAB: 270 case K_TAB:
219 if (nd != NULL) { 271 if (nd != NULL) {
220 nd = rb_prev(nd); 272 nd = rb_prev(nd);
221 if (nd == NULL) 273 if (nd == NULL)
@@ -223,7 +275,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
223 } else 275 } else
224 nd = self->curr_hot; 276 nd = self->curr_hot;
225 break; 277 break;
226 case NEWT_KEY_UNTAB: 278 case K_UNTAB:
227 if (nd != NULL) 279 if (nd != NULL)
228 nd = rb_next(nd); 280 nd = rb_next(nd);
229 if (nd == NULL) 281 if (nd == NULL)
@@ -234,8 +286,68 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
234 case 'H': 286 case 'H':
235 nd = self->curr_hot; 287 nd = self->curr_hot;
236 break; 288 break;
237 default: 289 case 'S':
290 if (annotate_browser__toggle_source(self))
291 ui_helpline__puts(help);
292 continue;
293 case K_ENTER:
294 case K_RIGHT:
295 if (self->selection == NULL) {
296 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
297 continue;
298 }
299
300 if (self->selection->offset == -1) {
301 ui_helpline__puts("Actions are only available for assembly lines.");
302 continue;
303 } else {
304 char *s = strstr(self->selection->line, "callq ");
305 struct annotation *notes;
306 struct symbol *target;
307 u64 ip;
308
309 if (s == NULL) {
310 ui_helpline__puts("Actions are only available for the 'callq' instruction.");
311 continue;
312 }
313
314 s = strchr(s, ' ');
315 if (s++ == NULL) {
316 ui_helpline__puts("Invallid callq instruction.");
317 continue;
318 }
319
320 ip = strtoull(s, NULL, 16);
321 ip = ms->map->map_ip(ms->map, ip);
322 target = map__find_symbol(ms->map, ip, NULL);
323 if (target == NULL) {
324 ui_helpline__puts("The called function was not found.");
325 continue;
326 }
327
328 notes = symbol__annotation(target);
329 pthread_mutex_lock(&notes->lock);
330
331 if (notes->src == NULL &&
332 symbol__alloc_hist(target, nr_events) < 0) {
333 pthread_mutex_unlock(&notes->lock);
334 ui__warning("Not enough memory for annotating '%s' symbol!\n",
335 target->name);
336 continue;
337 }
338
339 pthread_mutex_unlock(&notes->lock);
340 symbol__tui_annotate(target, ms->map, evidx, nr_events,
341 timer, arg, delay_secs);
342 }
343 continue;
344 case K_LEFT:
345 case K_ESC:
346 case 'q':
347 case CTRL('c'):
238 goto out; 348 goto out;
349 default:
350 continue;
239 } 351 }
240 352
241 if (nd != NULL) 353 if (nd != NULL)
@@ -246,22 +358,31 @@ out:
246 return key; 358 return key;
247} 359}
248 360
249int hist_entry__tui_annotate(struct hist_entry *he, int evidx) 361int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events,
362 void(*timer)(void *arg), void *arg, int delay_secs)
250{ 363{
251 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, 0); 364 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, nr_events,
365 timer, arg, delay_secs);
252} 366}
253 367
254int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 368int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
255 int refresh) 369 int nr_events, void(*timer)(void *arg), void *arg,
370 int delay_secs)
256{ 371{
257 struct objdump_line *pos, *n; 372 struct objdump_line *pos, *n;
258 struct annotation *notes; 373 struct annotation *notes;
374 struct map_symbol ms = {
375 .map = map,
376 .sym = sym,
377 };
259 struct annotate_browser browser = { 378 struct annotate_browser browser = {
260 .b = { 379 .b = {
261 .refresh = ui_browser__list_head_refresh, 380 .refresh = ui_browser__list_head_refresh,
262 .seek = ui_browser__list_head_seek, 381 .seek = ui_browser__list_head_seek,
263 .write = annotate_browser__write, 382 .write = annotate_browser__write,
264 .priv = sym, 383 .filter = objdump_line__filter,
384 .priv = &ms,
385 .use_navkeypressed = true,
265 }, 386 },
266 }; 387 };
267 int ret; 388 int ret;
@@ -273,7 +394,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
273 return -1; 394 return -1;
274 395
275 if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) { 396 if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) {
276 ui__error_window(ui_helpline__last_msg); 397 ui__error("%s", ui_helpline__last_msg);
277 return -1; 398 return -1;
278 } 399 }
279 400
@@ -288,12 +409,18 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
288 if (browser.b.width < line_len) 409 if (browser.b.width < line_len)
289 browser.b.width = line_len; 410 browser.b.width = line_len;
290 rbpos = objdump_line__rb(pos); 411 rbpos = objdump_line__rb(pos);
291 rbpos->idx = browser.b.nr_entries++; 412 rbpos->idx = browser.nr_entries++;
413 if (pos->offset != -1)
414 rbpos->idx_asm = browser.nr_asm_entries++;
415 else
416 rbpos->idx_asm = -1;
292 } 417 }
293 418
419 browser.b.nr_entries = browser.nr_entries;
294 browser.b.entries = &notes->src->source, 420 browser.b.entries = &notes->src->source,
295 browser.b.width += 18; /* Percentage */ 421 browser.b.width += 18; /* Percentage */
296 ret = annotate_browser__run(&browser, evidx, refresh); 422 ret = annotate_browser__run(&browser, evidx, nr_events,
423 timer, arg, delay_secs);
297 list_for_each_entry_safe(pos, n, &notes->src->source, node) { 424 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
298 list_del(&pos->node); 425 list_del(&pos->node);
299 objdump_line__free(pos); 426 objdump_line__free(pos);
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index 5d767c622dfc..d0c94b459685 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -17,6 +17,7 @@
17#include "../browser.h" 17#include "../browser.h"
18#include "../helpline.h" 18#include "../helpline.h"
19#include "../util.h" 19#include "../util.h"
20#include "../ui.h"
20#include "map.h" 21#include "map.h"
21 22
22struct hist_browser { 23struct hist_browser {
@@ -24,8 +25,12 @@ struct hist_browser {
24 struct hists *hists; 25 struct hists *hists;
25 struct hist_entry *he_selection; 26 struct hist_entry *he_selection;
26 struct map_symbol *selection; 27 struct map_symbol *selection;
28 bool has_symbols;
27}; 29};
28 30
31static int hists__browser_title(struct hists *self, char *bf, size_t size,
32 const char *ev_name);
33
29static void hist_browser__refresh_dimensions(struct hist_browser *self) 34static void hist_browser__refresh_dimensions(struct hist_browser *self)
30{ 35{
31 /* 3 == +/- toggle symbol before actual hist_entry rendering */ 36 /* 3 == +/- toggle symbol before actual hist_entry rendering */
@@ -290,28 +295,49 @@ static void hist_browser__set_folding(struct hist_browser *self, bool unfold)
290 ui_browser__reset_index(&self->b); 295 ui_browser__reset_index(&self->b);
291} 296}
292 297
293static int hist_browser__run(struct hist_browser *self, const char *title) 298static void ui_browser__warn_lost_events(struct ui_browser *browser)
299{
300 ui_browser__warning(browser, 4,
301 "Events are being lost, check IO/CPU overload!\n\n"
302 "You may want to run 'perf' using a RT scheduler policy:\n\n"
303 " perf top -r 80\n\n"
304 "Or reduce the sampling frequency.");
305}
306
307static int hist_browser__run(struct hist_browser *self, const char *ev_name,
308 void(*timer)(void *arg), void *arg, int delay_secs)
294{ 309{
295 int key; 310 int key;
296 int exit_keys[] = { 'a', '?', 'h', 'C', 'd', 'D', 'E', 't', 311 char title[160];
297 NEWT_KEY_ENTER, NEWT_KEY_RIGHT, NEWT_KEY_LEFT,
298 NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0, };
299 312
300 self->b.entries = &self->hists->entries; 313 self->b.entries = &self->hists->entries;
301 self->b.nr_entries = self->hists->nr_entries; 314 self->b.nr_entries = self->hists->nr_entries;
302 315
303 hist_browser__refresh_dimensions(self); 316 hist_browser__refresh_dimensions(self);
317 hists__browser_title(self->hists, title, sizeof(title), ev_name);
304 318
305 if (ui_browser__show(&self->b, title, 319 if (ui_browser__show(&self->b, title,
306 "Press '?' for help on key bindings") < 0) 320 "Press '?' for help on key bindings") < 0)
307 return -1; 321 return -1;
308 322
309 ui_browser__add_exit_keys(&self->b, exit_keys);
310
311 while (1) { 323 while (1) {
312 key = ui_browser__run(&self->b); 324 key = ui_browser__run(&self->b, delay_secs);
313 325
314 switch (key) { 326 switch (key) {
327 case K_TIMER:
328 timer(arg);
329 ui_browser__update_nr_entries(&self->b, self->hists->nr_entries);
330
331 if (self->hists->stats.nr_lost_warned !=
332 self->hists->stats.nr_events[PERF_RECORD_LOST]) {
333 self->hists->stats.nr_lost_warned =
334 self->hists->stats.nr_events[PERF_RECORD_LOST];
335 ui_browser__warn_lost_events(&self->b);
336 }
337
338 hists__browser_title(self->hists, title, sizeof(title), ev_name);
339 ui_browser__show_title(&self->b, title);
340 continue;
315 case 'D': { /* Debug */ 341 case 'D': { /* Debug */
316 static int seq; 342 static int seq;
317 struct hist_entry *h = rb_entry(self->b.top, 343 struct hist_entry *h = rb_entry(self->b.top,
@@ -334,7 +360,7 @@ static int hist_browser__run(struct hist_browser *self, const char *title)
334 /* Expand the whole world. */ 360 /* Expand the whole world. */
335 hist_browser__set_folding(self, true); 361 hist_browser__set_folding(self, true);
336 break; 362 break;
337 case NEWT_KEY_ENTER: 363 case K_ENTER:
338 if (hist_browser__toggle_fold(self)) 364 if (hist_browser__toggle_fold(self))
339 break; 365 break;
340 /* fall thru */ 366 /* fall thru */
@@ -532,7 +558,7 @@ static int hist_browser__show_entry(struct hist_browser *self,
532 char s[256]; 558 char s[256];
533 double percent; 559 double percent;
534 int printed = 0; 560 int printed = 0;
535 int color, width = self->b.width; 561 int width = self->b.width - 6; /* The percentage */
536 char folded_sign = ' '; 562 char folded_sign = ' ';
537 bool current_entry = ui_browser__is_current_entry(&self->b, row); 563 bool current_entry = ui_browser__is_current_entry(&self->b, row);
538 off_t row_offset = entry->row_offset; 564 off_t row_offset = entry->row_offset;
@@ -548,26 +574,35 @@ static int hist_browser__show_entry(struct hist_browser *self,
548 } 574 }
549 575
550 if (row_offset == 0) { 576 if (row_offset == 0) {
551 hist_entry__snprintf(entry, s, sizeof(s), self->hists, NULL, false, 577 hist_entry__snprintf(entry, s, sizeof(s), self->hists);
552 0, false, self->hists->stats.total_period);
553 percent = (entry->period * 100.0) / self->hists->stats.total_period; 578 percent = (entry->period * 100.0) / self->hists->stats.total_period;
554 579
555 color = HE_COLORSET_SELECTED; 580 ui_browser__set_percent_color(&self->b, percent, current_entry);
556 if (!current_entry) {
557 if (percent >= MIN_RED)
558 color = HE_COLORSET_TOP;
559 else if (percent >= MIN_GREEN)
560 color = HE_COLORSET_MEDIUM;
561 else
562 color = HE_COLORSET_NORMAL;
563 }
564
565 ui_browser__set_color(&self->b, color);
566 ui_browser__gotorc(&self->b, row, 0); 581 ui_browser__gotorc(&self->b, row, 0);
567 if (symbol_conf.use_callchain) { 582 if (symbol_conf.use_callchain) {
568 slsmg_printf("%c ", folded_sign); 583 slsmg_printf("%c ", folded_sign);
569 width -= 2; 584 width -= 2;
570 } 585 }
586
587 slsmg_printf(" %5.2f%%", percent);
588
589 /* The scroll bar isn't being used */
590 if (!self->b.navkeypressed)
591 width += 1;
592
593 if (!current_entry || !self->b.navkeypressed)
594 ui_browser__set_color(&self->b, HE_COLORSET_NORMAL);
595
596 if (symbol_conf.show_nr_samples) {
597 slsmg_printf(" %11u", entry->nr_events);
598 width -= 12;
599 }
600
601 if (symbol_conf.show_total_period) {
602 slsmg_printf(" %12" PRIu64, entry->period);
603 width -= 13;
604 }
605
571 slsmg_write_nstring(s, width); 606 slsmg_write_nstring(s, width);
572 ++row; 607 ++row;
573 ++printed; 608 ++printed;
@@ -585,14 +620,23 @@ static int hist_browser__show_entry(struct hist_browser *self,
585 return printed; 620 return printed;
586} 621}
587 622
623static void ui_browser__hists_init_top(struct ui_browser *browser)
624{
625 if (browser->top == NULL) {
626 struct hist_browser *hb;
627
628 hb = container_of(browser, struct hist_browser, b);
629 browser->top = rb_first(&hb->hists->entries);
630 }
631}
632
588static unsigned int hist_browser__refresh(struct ui_browser *self) 633static unsigned int hist_browser__refresh(struct ui_browser *self)
589{ 634{
590 unsigned row = 0; 635 unsigned row = 0;
591 struct rb_node *nd; 636 struct rb_node *nd;
592 struct hist_browser *hb = container_of(self, struct hist_browser, b); 637 struct hist_browser *hb = container_of(self, struct hist_browser, b);
593 638
594 if (self->top == NULL) 639 ui_browser__hists_init_top(self);
595 self->top = rb_first(&hb->hists->entries);
596 640
597 for (nd = self->top; nd; nd = rb_next(nd)) { 641 for (nd = self->top; nd; nd = rb_next(nd)) {
598 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 642 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
@@ -644,6 +688,8 @@ static void ui_browser__hists_seek(struct ui_browser *self,
644 if (self->nr_entries == 0) 688 if (self->nr_entries == 0)
645 return; 689 return;
646 690
691 ui_browser__hists_init_top(self);
692
647 switch (whence) { 693 switch (whence) {
648 case SEEK_SET: 694 case SEEK_SET:
649 nd = hists__filter_entries(rb_first(self->entries)); 695 nd = hists__filter_entries(rb_first(self->entries));
@@ -761,6 +807,8 @@ static struct hist_browser *hist_browser__new(struct hists *hists)
761 self->hists = hists; 807 self->hists = hists;
762 self->b.refresh = hist_browser__refresh; 808 self->b.refresh = hist_browser__refresh;
763 self->b.seek = ui_browser__hists_seek; 809 self->b.seek = ui_browser__hists_seek;
810 self->b.use_navkeypressed = true,
811 self->has_symbols = sort_sym.list.next != NULL;
764 } 812 }
765 813
766 return self; 814 return self;
@@ -782,11 +830,12 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *self)
782} 830}
783 831
784static int hists__browser_title(struct hists *self, char *bf, size_t size, 832static int hists__browser_title(struct hists *self, char *bf, size_t size,
785 const char *ev_name, const struct dso *dso, 833 const char *ev_name)
786 const struct thread *thread)
787{ 834{
788 char unit; 835 char unit;
789 int printed; 836 int printed;
837 const struct dso *dso = self->dso_filter;
838 const struct thread *thread = self->thread_filter;
790 unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE]; 839 unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];
791 840
792 nr_events = convert_unit(nr_events, &unit); 841 nr_events = convert_unit(nr_events, &unit);
@@ -803,16 +852,15 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
803 return printed; 852 return printed;
804} 853}
805 854
806static int perf_evsel__hists_browse(struct perf_evsel *evsel, 855static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
807 const char *helpline, const char *ev_name, 856 const char *helpline, const char *ev_name,
808 bool left_exits) 857 bool left_exits,
858 void(*timer)(void *arg), void *arg,
859 int delay_secs)
809{ 860{
810 struct hists *self = &evsel->hists; 861 struct hists *self = &evsel->hists;
811 struct hist_browser *browser = hist_browser__new(self); 862 struct hist_browser *browser = hist_browser__new(self);
812 struct pstack *fstack; 863 struct pstack *fstack;
813 const struct thread *thread_filter = NULL;
814 const struct dso *dso_filter = NULL;
815 char msg[160];
816 int key = -1; 864 int key = -1;
817 865
818 if (browser == NULL) 866 if (browser == NULL)
@@ -824,8 +872,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
824 872
825 ui_helpline__push(helpline); 873 ui_helpline__push(helpline);
826 874
827 hists__browser_title(self, msg, sizeof(msg), ev_name,
828 dso_filter, thread_filter);
829 while (1) { 875 while (1) {
830 const struct thread *thread = NULL; 876 const struct thread *thread = NULL;
831 const struct dso *dso = NULL; 877 const struct dso *dso = NULL;
@@ -834,7 +880,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
834 annotate = -2, zoom_dso = -2, zoom_thread = -2, 880 annotate = -2, zoom_dso = -2, zoom_thread = -2,
835 browse_map = -2; 881 browse_map = -2;
836 882
837 key = hist_browser__run(browser, msg); 883 key = hist_browser__run(browser, ev_name, timer, arg, delay_secs);
838 884
839 if (browser->he_selection != NULL) { 885 if (browser->he_selection != NULL) {
840 thread = hist_browser__selected_thread(browser); 886 thread = hist_browser__selected_thread(browser);
@@ -842,14 +888,23 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
842 } 888 }
843 889
844 switch (key) { 890 switch (key) {
845 case NEWT_KEY_TAB: 891 case K_TAB:
846 case NEWT_KEY_UNTAB: 892 case K_UNTAB:
893 if (nr_events == 1)
894 continue;
847 /* 895 /*
848 * Exit the browser, let hists__browser_tree 896 * Exit the browser, let hists__browser_tree
849 * go to the next or previous 897 * go to the next or previous
850 */ 898 */
851 goto out_free_stack; 899 goto out_free_stack;
852 case 'a': 900 case 'a':
901 if (!browser->has_symbols) {
902 ui_browser__warning(&browser->b, delay_secs * 2,
903 "Annotation is only available for symbolic views, "
904 "include \"sym\" in --sort to use it.");
905 continue;
906 }
907
853 if (browser->selection == NULL || 908 if (browser->selection == NULL ||
854 browser->selection->sym == NULL || 909 browser->selection->sym == NULL ||
855 browser->selection->map->dso->annotate_warned) 910 browser->selection->map->dso->annotate_warned)
@@ -859,25 +914,30 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
859 goto zoom_dso; 914 goto zoom_dso;
860 case 't': 915 case 't':
861 goto zoom_thread; 916 goto zoom_thread;
862 case NEWT_KEY_F1: 917 case K_F1:
863 case 'h': 918 case 'h':
864 case '?': 919 case '?':
865 ui__help_window("-> Zoom into DSO/Threads & Annotate current symbol\n" 920 ui_browser__help_window(&browser->b,
866 "<- Zoom out\n" 921 "h/?/F1 Show this window\n"
867 "a Annotate current symbol\n" 922 "UP/DOWN/PGUP\n"
868 "h/?/F1 Show this window\n" 923 "PGDN/SPACE Navigate\n"
869 "C Collapse all callchains\n" 924 "q/ESC/CTRL+C Exit browser\n\n"
870 "E Expand all callchains\n" 925 "For multiple event sessions:\n\n"
871 "d Zoom into current DSO\n" 926 "TAB/UNTAB Switch events\n\n"
872 "t Zoom into current Thread\n" 927 "For symbolic views (--sort has sym):\n\n"
873 "TAB/UNTAB Switch events\n" 928 "-> Zoom into DSO/Threads & Annotate current symbol\n"
874 "q/CTRL+C Exit browser"); 929 "<- Zoom out\n"
930 "a Annotate current symbol\n"
931 "C Collapse all callchains\n"
932 "E Expand all callchains\n"
933 "d Zoom into current DSO\n"
934 "t Zoom into current Thread");
875 continue; 935 continue;
876 case NEWT_KEY_ENTER: 936 case K_ENTER:
877 case NEWT_KEY_RIGHT: 937 case K_RIGHT:
878 /* menu */ 938 /* menu */
879 break; 939 break;
880 case NEWT_KEY_LEFT: { 940 case K_LEFT: {
881 const void *top; 941 const void *top;
882 942
883 if (pstack__empty(fstack)) { 943 if (pstack__empty(fstack)) {
@@ -889,21 +949,28 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
889 continue; 949 continue;
890 } 950 }
891 top = pstack__pop(fstack); 951 top = pstack__pop(fstack);
892 if (top == &dso_filter) 952 if (top == &browser->hists->dso_filter)
893 goto zoom_out_dso; 953 goto zoom_out_dso;
894 if (top == &thread_filter) 954 if (top == &browser->hists->thread_filter)
895 goto zoom_out_thread; 955 goto zoom_out_thread;
896 continue; 956 continue;
897 } 957 }
898 case NEWT_KEY_ESCAPE: 958 case K_ESC:
899 if (!left_exits && 959 if (!left_exits &&
900 !ui__dialog_yesno("Do you really want to exit?")) 960 !ui_browser__dialog_yesno(&browser->b,
961 "Do you really want to exit?"))
901 continue; 962 continue;
902 /* Fall thru */ 963 /* Fall thru */
903 default: 964 case 'q':
965 case CTRL('c'):
904 goto out_free_stack; 966 goto out_free_stack;
967 default:
968 continue;
905 } 969 }
906 970
971 if (!browser->has_symbols)
972 goto add_exit_option;
973
907 if (browser->selection != NULL && 974 if (browser->selection != NULL &&
908 browser->selection->sym != NULL && 975 browser->selection->sym != NULL &&
909 !browser->selection->map->dso->annotate_warned && 976 !browser->selection->map->dso->annotate_warned &&
@@ -913,14 +980,14 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
913 980
914 if (thread != NULL && 981 if (thread != NULL &&
915 asprintf(&options[nr_options], "Zoom %s %s(%d) thread", 982 asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
916 (thread_filter ? "out of" : "into"), 983 (browser->hists->thread_filter ? "out of" : "into"),
917 (thread->comm_set ? thread->comm : ""), 984 (thread->comm_set ? thread->comm : ""),
918 thread->pid) > 0) 985 thread->pid) > 0)
919 zoom_thread = nr_options++; 986 zoom_thread = nr_options++;
920 987
921 if (dso != NULL && 988 if (dso != NULL &&
922 asprintf(&options[nr_options], "Zoom %s %s DSO", 989 asprintf(&options[nr_options], "Zoom %s %s DSO",
923 (dso_filter ? "out of" : "into"), 990 (browser->hists->dso_filter ? "out of" : "into"),
924 (dso->kernel ? "the Kernel" : dso->short_name)) > 0) 991 (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
925 zoom_dso = nr_options++; 992 zoom_dso = nr_options++;
926 993
@@ -928,7 +995,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
928 browser->selection->map != NULL && 995 browser->selection->map != NULL &&
929 asprintf(&options[nr_options], "Browse map details") > 0) 996 asprintf(&options[nr_options], "Browse map details") > 0)
930 browse_map = nr_options++; 997 browse_map = nr_options++;
931 998add_exit_option:
932 options[nr_options++] = (char *)"Exit"; 999 options[nr_options++] = (char *)"Exit";
933 1000
934 choice = ui__popup_menu(nr_options, options); 1001 choice = ui__popup_menu(nr_options, options);
@@ -944,50 +1011,59 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
944 1011
945 if (choice == annotate) { 1012 if (choice == annotate) {
946 struct hist_entry *he; 1013 struct hist_entry *he;
1014 int err;
947do_annotate: 1015do_annotate:
948 he = hist_browser__selected_entry(browser); 1016 he = hist_browser__selected_entry(browser);
949 if (he == NULL) 1017 if (he == NULL)
950 continue; 1018 continue;
951 1019 /*
952 hist_entry__tui_annotate(he, evsel->idx); 1020 * Don't let this be freed, say, by hists__decay_entry.
1021 */
1022 he->used = true;
1023 err = hist_entry__tui_annotate(he, evsel->idx, nr_events,
1024 timer, arg, delay_secs);
1025 he->used = false;
1026 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
1027 if (err)
1028 ui_browser__handle_resize(&browser->b);
953 } else if (choice == browse_map) 1029 } else if (choice == browse_map)
954 map__browse(browser->selection->map); 1030 map__browse(browser->selection->map);
955 else if (choice == zoom_dso) { 1031 else if (choice == zoom_dso) {
956zoom_dso: 1032zoom_dso:
957 if (dso_filter) { 1033 if (browser->hists->dso_filter) {
958 pstack__remove(fstack, &dso_filter); 1034 pstack__remove(fstack, &browser->hists->dso_filter);
959zoom_out_dso: 1035zoom_out_dso:
960 ui_helpline__pop(); 1036 ui_helpline__pop();
961 dso_filter = NULL; 1037 browser->hists->dso_filter = NULL;
1038 sort_dso.elide = false;
962 } else { 1039 } else {
963 if (dso == NULL) 1040 if (dso == NULL)
964 continue; 1041 continue;
965 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", 1042 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
966 dso->kernel ? "the Kernel" : dso->short_name); 1043 dso->kernel ? "the Kernel" : dso->short_name);
967 dso_filter = dso; 1044 browser->hists->dso_filter = dso;
968 pstack__push(fstack, &dso_filter); 1045 sort_dso.elide = true;
1046 pstack__push(fstack, &browser->hists->dso_filter);
969 } 1047 }
970 hists__filter_by_dso(self, dso_filter); 1048 hists__filter_by_dso(self);
971 hists__browser_title(self, msg, sizeof(msg), ev_name,
972 dso_filter, thread_filter);
973 hist_browser__reset(browser); 1049 hist_browser__reset(browser);
974 } else if (choice == zoom_thread) { 1050 } else if (choice == zoom_thread) {
975zoom_thread: 1051zoom_thread:
976 if (thread_filter) { 1052 if (browser->hists->thread_filter) {
977 pstack__remove(fstack, &thread_filter); 1053 pstack__remove(fstack, &browser->hists->thread_filter);
978zoom_out_thread: 1054zoom_out_thread:
979 ui_helpline__pop(); 1055 ui_helpline__pop();
980 thread_filter = NULL; 1056 browser->hists->thread_filter = NULL;
1057 sort_thread.elide = false;
981 } else { 1058 } else {
982 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", 1059 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
983 thread->comm_set ? thread->comm : "", 1060 thread->comm_set ? thread->comm : "",
984 thread->pid); 1061 thread->pid);
985 thread_filter = thread; 1062 browser->hists->thread_filter = thread;
986 pstack__push(fstack, &thread_filter); 1063 sort_thread.elide = true;
1064 pstack__push(fstack, &browser->hists->thread_filter);
987 } 1065 }
988 hists__filter_by_thread(self, thread_filter); 1066 hists__filter_by_thread(self);
989 hists__browser_title(self, msg, sizeof(msg), ev_name,
990 dso_filter, thread_filter);
991 hist_browser__reset(browser); 1067 hist_browser__reset(browser);
992 } 1068 }
993 } 1069 }
@@ -1001,6 +1077,7 @@ out:
1001struct perf_evsel_menu { 1077struct perf_evsel_menu {
1002 struct ui_browser b; 1078 struct ui_browser b;
1003 struct perf_evsel *selection; 1079 struct perf_evsel *selection;
1080 bool lost_events, lost_events_warned;
1004}; 1081};
1005 1082
1006static void perf_evsel_menu__write(struct ui_browser *browser, 1083static void perf_evsel_menu__write(struct ui_browser *browser,
@@ -1013,22 +1090,38 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1013 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1090 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
1014 const char *ev_name = event_name(evsel); 1091 const char *ev_name = event_name(evsel);
1015 char bf[256], unit; 1092 char bf[256], unit;
1093 const char *warn = " ";
1094 size_t printed;
1016 1095
1017 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : 1096 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
1018 HE_COLORSET_NORMAL); 1097 HE_COLORSET_NORMAL);
1019 1098
1020 nr_events = convert_unit(nr_events, &unit); 1099 nr_events = convert_unit(nr_events, &unit);
1021 snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events, 1100 printed = snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
1022 unit, unit == ' ' ? "" : " ", ev_name); 1101 unit, unit == ' ' ? "" : " ", ev_name);
1023 slsmg_write_nstring(bf, browser->width); 1102 slsmg_printf("%s", bf);
1103
1104 nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST];
1105 if (nr_events != 0) {
1106 menu->lost_events = true;
1107 if (!current_entry)
1108 ui_browser__set_color(browser, HE_COLORSET_TOP);
1109 nr_events = convert_unit(nr_events, &unit);
1110 snprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!", nr_events,
1111 unit, unit == ' ' ? "" : " ");
1112 warn = bf;
1113 }
1114
1115 slsmg_write_nstring(warn, browser->width - printed);
1024 1116
1025 if (current_entry) 1117 if (current_entry)
1026 menu->selection = evsel; 1118 menu->selection = evsel;
1027} 1119}
1028 1120
1029static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help) 1121static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
1122 int nr_events, const char *help,
1123 void(*timer)(void *arg), void *arg, int delay_secs)
1030{ 1124{
1031 int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, };
1032 struct perf_evlist *evlist = menu->b.priv; 1125 struct perf_evlist *evlist = menu->b.priv;
1033 struct perf_evsel *pos; 1126 struct perf_evsel *pos;
1034 const char *ev_name, *title = "Available samples"; 1127 const char *ev_name, *title = "Available samples";
@@ -1038,50 +1131,72 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help)
1038 "ESC: exit, ENTER|->: Browse histograms") < 0) 1131 "ESC: exit, ENTER|->: Browse histograms") < 0)
1039 return -1; 1132 return -1;
1040 1133
1041 ui_browser__add_exit_keys(&menu->b, exit_keys);
1042
1043 while (1) { 1134 while (1) {
1044 key = ui_browser__run(&menu->b); 1135 key = ui_browser__run(&menu->b, delay_secs);
1045 1136
1046 switch (key) { 1137 switch (key) {
1047 case NEWT_KEY_RIGHT: 1138 case K_TIMER:
1048 case NEWT_KEY_ENTER: 1139 timer(arg);
1140
1141 if (!menu->lost_events_warned && menu->lost_events) {
1142 ui_browser__warn_lost_events(&menu->b);
1143 menu->lost_events_warned = true;
1144 }
1145 continue;
1146 case K_RIGHT:
1147 case K_ENTER:
1049 if (!menu->selection) 1148 if (!menu->selection)
1050 continue; 1149 continue;
1051 pos = menu->selection; 1150 pos = menu->selection;
1052browse_hists: 1151browse_hists:
1152 perf_evlist__set_selected(evlist, pos);
1153 /*
1154 * Give the calling tool a chance to populate the non
1155 * default evsel resorted hists tree.
1156 */
1157 if (timer)
1158 timer(arg);
1053 ev_name = event_name(pos); 1159 ev_name = event_name(pos);
1054 key = perf_evsel__hists_browse(pos, help, ev_name, true); 1160 key = perf_evsel__hists_browse(pos, nr_events, help,
1161 ev_name, true, timer,
1162 arg, delay_secs);
1055 ui_browser__show_title(&menu->b, title); 1163 ui_browser__show_title(&menu->b, title);
1056 break; 1164 switch (key) {
1057 case NEWT_KEY_LEFT: 1165 case K_TAB:
1166 if (pos->node.next == &evlist->entries)
1167 pos = list_entry(evlist->entries.next, struct perf_evsel, node);
1168 else
1169 pos = list_entry(pos->node.next, struct perf_evsel, node);
1170 goto browse_hists;
1171 case K_UNTAB:
1172 if (pos->node.prev == &evlist->entries)
1173 pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
1174 else
1175 pos = list_entry(pos->node.prev, struct perf_evsel, node);
1176 goto browse_hists;
1177 case K_ESC:
1178 if (!ui_browser__dialog_yesno(&menu->b,
1179 "Do you really want to exit?"))
1180 continue;
1181 /* Fall thru */
1182 case 'q':
1183 case CTRL('c'):
1184 goto out;
1185 default:
1186 continue;
1187 }
1188 case K_LEFT:
1058 continue; 1189 continue;
1059 case NEWT_KEY_ESCAPE: 1190 case K_ESC:
1060 if (!ui__dialog_yesno("Do you really want to exit?")) 1191 if (!ui_browser__dialog_yesno(&menu->b,
1192 "Do you really want to exit?"))
1061 continue; 1193 continue;
1062 /* Fall thru */ 1194 /* Fall thru */
1063 default:
1064 goto out;
1065 }
1066
1067 switch (key) {
1068 case NEWT_KEY_TAB:
1069 if (pos->node.next == &evlist->entries)
1070 pos = list_entry(evlist->entries.next, struct perf_evsel, node);
1071 else
1072 pos = list_entry(pos->node.next, struct perf_evsel, node);
1073 goto browse_hists;
1074 case NEWT_KEY_UNTAB:
1075 if (pos->node.prev == &evlist->entries)
1076 pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
1077 else
1078 pos = list_entry(pos->node.prev, struct perf_evsel, node);
1079 goto browse_hists;
1080 case 'q': 1195 case 'q':
1081 case CTRL('c'): 1196 case CTRL('c'):
1082 goto out; 1197 goto out;
1083 default: 1198 default:
1084 break; 1199 continue;
1085 } 1200 }
1086 } 1201 }
1087 1202
@@ -1091,7 +1206,9 @@ out:
1091} 1206}
1092 1207
1093static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, 1208static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1094 const char *help) 1209 const char *help,
1210 void(*timer)(void *arg), void *arg,
1211 int delay_secs)
1095{ 1212{
1096 struct perf_evsel *pos; 1213 struct perf_evsel *pos;
1097 struct perf_evsel_menu menu = { 1214 struct perf_evsel_menu menu = {
@@ -1121,18 +1238,24 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1121 pos->name = strdup(ev_name); 1238 pos->name = strdup(ev_name);
1122 } 1239 }
1123 1240
1124 return perf_evsel_menu__run(&menu, help); 1241 return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer,
1242 arg, delay_secs);
1125} 1243}
1126 1244
1127int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help) 1245int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
1246 void(*timer)(void *arg), void *arg,
1247 int delay_secs)
1128{ 1248{
1129 1249
1130 if (evlist->nr_entries == 1) { 1250 if (evlist->nr_entries == 1) {
1131 struct perf_evsel *first = list_entry(evlist->entries.next, 1251 struct perf_evsel *first = list_entry(evlist->entries.next,
1132 struct perf_evsel, node); 1252 struct perf_evsel, node);
1133 const char *ev_name = event_name(first); 1253 const char *ev_name = event_name(first);
1134 return perf_evsel__hists_browse(first, help, ev_name, false); 1254 return perf_evsel__hists_browse(first, evlist->nr_entries, help,
1255 ev_name, false, timer, arg,
1256 delay_secs);
1135 } 1257 }
1136 1258
1137 return __perf_evlist__tui_browse_hists(evlist, help); 1259 return __perf_evlist__tui_browse_hists(evlist, help,
1260 timer, arg, delay_secs);
1138} 1261}
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index 8462bffe20bc..6905bcc8be2d 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -1,5 +1,6 @@
1#include "../libslang.h" 1#include "../libslang.h"
2#include <elf.h> 2#include <elf.h>
3#include <newt.h>
3#include <inttypes.h> 4#include <inttypes.h>
4#include <sys/ttydefaults.h> 5#include <sys/ttydefaults.h>
5#include <ctype.h> 6#include <ctype.h>
@@ -108,11 +109,8 @@ static int map_browser__run(struct map_browser *self)
108 verbose ? "" : "restart with -v to use") < 0) 109 verbose ? "" : "restart with -v to use") < 0)
109 return -1; 110 return -1;
110 111
111 if (verbose)
112 ui_browser__add_exit_key(&self->b, '/');
113
114 while (1) { 112 while (1) {
115 key = ui_browser__run(&self->b); 113 key = ui_browser__run(&self->b, 0);
116 114
117 if (verbose && key == '/') 115 if (verbose && key == '/')
118 map_browser__search(self); 116 map_browser__search(self);
diff --git a/tools/perf/util/ui/browsers/top.c b/tools/perf/util/ui/browsers/top.c
deleted file mode 100644
index 5a06538532af..000000000000
--- a/tools/perf/util/ui/browsers/top.c
+++ /dev/null
@@ -1,213 +0,0 @@
1/*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Parts came from builtin-{top,stat,record}.c, see those files for further
5 * copyright notes.
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9#include "../browser.h"
10#include "../../annotate.h"
11#include "../helpline.h"
12#include "../libslang.h"
13#include "../util.h"
14#include "../../evlist.h"
15#include "../../hist.h"
16#include "../../sort.h"
17#include "../../symbol.h"
18#include "../../top.h"
19
20struct perf_top_browser {
21 struct ui_browser b;
22 struct rb_root root;
23 struct sym_entry *selection;
24 float sum_ksamples;
25 int dso_width;
26 int dso_short_width;
27 int sym_width;
28};
29
30static void perf_top_browser__write(struct ui_browser *browser, void *entry, int row)
31{
32 struct perf_top_browser *top_browser = container_of(browser, struct perf_top_browser, b);
33 struct sym_entry *syme = rb_entry(entry, struct sym_entry, rb_node);
34 bool current_entry = ui_browser__is_current_entry(browser, row);
35 struct symbol *symbol = sym_entry__symbol(syme);
36 struct perf_top *top = browser->priv;
37 int width = browser->width;
38 double pcnt;
39
40 pcnt = 100.0 - (100.0 * ((top_browser->sum_ksamples - syme->snap_count) /
41 top_browser->sum_ksamples));
42 ui_browser__set_percent_color(browser, pcnt, current_entry);
43
44 if (top->evlist->nr_entries == 1 || !top->display_weighted) {
45 slsmg_printf("%20.2f ", syme->weight);
46 width -= 24;
47 } else {
48 slsmg_printf("%9.1f %10ld ", syme->weight, syme->snap_count);
49 width -= 23;
50 }
51
52 slsmg_printf("%4.1f%%", pcnt);
53 width -= 7;
54
55 if (verbose) {
56 slsmg_printf(" %016" PRIx64, symbol->start);
57 width -= 17;
58 }
59
60 slsmg_printf(" %-*.*s ", top_browser->sym_width, top_browser->sym_width,
61 symbol->name);
62 width -= top_browser->sym_width;
63 slsmg_write_nstring(width >= syme->map->dso->long_name_len ?
64 syme->map->dso->long_name :
65 syme->map->dso->short_name, width);
66
67 if (current_entry)
68 top_browser->selection = syme;
69}
70
71static void perf_top_browser__update_rb_tree(struct perf_top_browser *browser)
72{
73 struct perf_top *top = browser->b.priv;
74 u64 top_idx = browser->b.top_idx;
75
76 browser->root = RB_ROOT;
77 browser->b.top = NULL;
78 browser->sum_ksamples = perf_top__decay_samples(top, &browser->root);
79 /*
80 * No active symbols
81 */
82 if (top->rb_entries == 0)
83 return;
84
85 perf_top__find_widths(top, &browser->root, &browser->dso_width,
86 &browser->dso_short_width,
87 &browser->sym_width);
88 if (browser->sym_width + browser->dso_width > browser->b.width - 29) {
89 browser->dso_width = browser->dso_short_width;
90 if (browser->sym_width + browser->dso_width > browser->b.width - 29)
91 browser->sym_width = browser->b.width - browser->dso_width - 29;
92 }
93
94 /*
95 * Adjust the ui_browser indexes since the entries in the browser->root
96 * rb_tree may have changed, then seek it from start, so that we get a
97 * possible new top of the screen.
98 */
99 browser->b.nr_entries = top->rb_entries;
100
101 if (top_idx >= browser->b.nr_entries) {
102 if (browser->b.height >= browser->b.nr_entries)
103 top_idx = browser->b.nr_entries - browser->b.height;
104 else
105 top_idx = 0;
106 }
107
108 if (browser->b.index >= top_idx + browser->b.height)
109 browser->b.index = top_idx + browser->b.index - browser->b.top_idx;
110
111 if (browser->b.index >= browser->b.nr_entries)
112 browser->b.index = browser->b.nr_entries - 1;
113
114 browser->b.top_idx = top_idx;
115 browser->b.seek(&browser->b, top_idx, SEEK_SET);
116}
117
118static void perf_top_browser__annotate(struct perf_top_browser *browser)
119{
120 struct sym_entry *syme = browser->selection;
121 struct symbol *sym = sym_entry__symbol(syme);
122 struct annotation *notes = symbol__annotation(sym);
123 struct perf_top *top = browser->b.priv;
124
125 if (notes->src != NULL)
126 goto do_annotation;
127
128 pthread_mutex_lock(&notes->lock);
129
130 top->sym_filter_entry = NULL;
131
132 if (symbol__alloc_hist(sym, top->evlist->nr_entries) < 0) {
133 pr_err("Not enough memory for annotating '%s' symbol!\n",
134 sym->name);
135 pthread_mutex_unlock(&notes->lock);
136 return;
137 }
138
139 top->sym_filter_entry = syme;
140
141 pthread_mutex_unlock(&notes->lock);
142do_annotation:
143 symbol__tui_annotate(sym, syme->map, 0, top->delay_secs * 1000);
144}
145
146static int perf_top_browser__run(struct perf_top_browser *browser)
147{
148 int key;
149 char title[160];
150 struct perf_top *top = browser->b.priv;
151 int delay_msecs = top->delay_secs * 1000;
152 int exit_keys[] = { 'a', NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, };
153
154 perf_top_browser__update_rb_tree(browser);
155 perf_top__header_snprintf(top, title, sizeof(title));
156 perf_top__reset_sample_counters(top);
157
158 if (ui_browser__show(&browser->b, title,
159 "ESC: exit, ENTER|->|a: Live Annotate") < 0)
160 return -1;
161
162 newtFormSetTimer(browser->b.form, delay_msecs);
163 ui_browser__add_exit_keys(&browser->b, exit_keys);
164
165 while (1) {
166 key = ui_browser__run(&browser->b);
167
168 switch (key) {
169 case -1:
170 /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
171 perf_top_browser__update_rb_tree(browser);
172 perf_top__header_snprintf(top, title, sizeof(title));
173 perf_top__reset_sample_counters(top);
174 ui_browser__set_color(&browser->b, NEWT_COLORSET_ROOT);
175 SLsmg_gotorc(0, 0);
176 slsmg_write_nstring(title, browser->b.width);
177 break;
178 case 'a':
179 case NEWT_KEY_RIGHT:
180 case NEWT_KEY_ENTER:
181 if (browser->selection)
182 perf_top_browser__annotate(browser);
183 break;
184 case NEWT_KEY_LEFT:
185 continue;
186 case NEWT_KEY_ESCAPE:
187 if (!ui__dialog_yesno("Do you really want to exit?"))
188 continue;
189 /* Fall thru */
190 default:
191 goto out;
192 }
193 }
194out:
195 ui_browser__hide(&browser->b);
196 return key;
197}
198
199int perf_top__tui_browser(struct perf_top *top)
200{
201 struct perf_top_browser browser = {
202 .b = {
203 .entries = &browser.root,
204 .refresh = ui_browser__rb_tree_refresh,
205 .seek = ui_browser__rb_tree_seek,
206 .write = perf_top_browser__write,
207 .priv = top,
208 },
209 };
210
211 ui_helpline__push("Press <- or ESC to exit");
212 return perf_top_browser__run(&browser);
213}
diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c
index f36d2ff509ed..6ef3c5691762 100644
--- a/tools/perf/util/ui/helpline.c
+++ b/tools/perf/util/ui/helpline.c
@@ -1,20 +1,28 @@
1#define _GNU_SOURCE 1#define _GNU_SOURCE
2#include <stdio.h> 2#include <stdio.h>
3#include <stdlib.h> 3#include <stdlib.h>
4#include <newt.h> 4#include <string.h>
5 5
6#include "../debug.h" 6#include "../debug.h"
7#include "helpline.h" 7#include "helpline.h"
8#include "ui.h" 8#include "ui.h"
9#include "libslang.h"
9 10
10void ui_helpline__pop(void) 11void ui_helpline__pop(void)
11{ 12{
12 newtPopHelpLine();
13} 13}
14 14
15char ui_helpline__current[512];
16
15void ui_helpline__push(const char *msg) 17void ui_helpline__push(const char *msg)
16{ 18{
17 newtPushHelpLine(msg); 19 const size_t sz = sizeof(ui_helpline__current);
20
21 SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
22 SLsmg_set_color(0);
23 SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols);
24 SLsmg_refresh();
25 strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0';
18} 26}
19 27
20void ui_helpline__vpush(const char *fmt, va_list ap) 28void ui_helpline__vpush(const char *fmt, va_list ap)
@@ -63,7 +71,7 @@ int ui_helpline__show_help(const char *format, va_list ap)
63 71
64 if (ui_helpline__last_msg[backlog - 1] == '\n') { 72 if (ui_helpline__last_msg[backlog - 1] == '\n') {
65 ui_helpline__puts(ui_helpline__last_msg); 73 ui_helpline__puts(ui_helpline__last_msg);
66 newtRefresh(); 74 SLsmg_refresh();
67 backlog = 0; 75 backlog = 0;
68 } 76 }
69 pthread_mutex_unlock(&ui__lock); 77 pthread_mutex_unlock(&ui__lock);
diff --git a/tools/perf/util/ui/helpline.h b/tools/perf/util/ui/helpline.h
index ab6028d0c401..7bab6b34e35e 100644
--- a/tools/perf/util/ui/helpline.h
+++ b/tools/perf/util/ui/helpline.h
@@ -1,6 +1,9 @@
1#ifndef _PERF_UI_HELPLINE_H_ 1#ifndef _PERF_UI_HELPLINE_H_
2#define _PERF_UI_HELPLINE_H_ 1 2#define _PERF_UI_HELPLINE_H_ 1
3 3
4#include <stdio.h>
5#include <stdarg.h>
6
4void ui_helpline__init(void); 7void ui_helpline__init(void);
5void ui_helpline__pop(void); 8void ui_helpline__pop(void);
6void ui_helpline__push(const char *msg); 9void ui_helpline__push(const char *msg);
@@ -8,4 +11,6 @@ void ui_helpline__vpush(const char *fmt, va_list ap);
8void ui_helpline__fpush(const char *fmt, ...); 11void ui_helpline__fpush(const char *fmt, ...);
9void ui_helpline__puts(const char *msg); 12void ui_helpline__puts(const char *msg);
10 13
14extern char ui_helpline__current[];
15
11#endif /* _PERF_UI_HELPLINE_H_ */ 16#endif /* _PERF_UI_HELPLINE_H_ */
diff --git a/tools/perf/util/ui/keysyms.h b/tools/perf/util/ui/keysyms.h
new file mode 100644
index 000000000000..3458b1985761
--- /dev/null
+++ b/tools/perf/util/ui/keysyms.h
@@ -0,0 +1,25 @@
1#ifndef _PERF_KEYSYMS_H_
2#define _PERF_KEYSYMS_H_ 1
3
4#include "libslang.h"
5
6#define K_DOWN SL_KEY_DOWN
7#define K_END SL_KEY_END
8#define K_ENTER '\r'
9#define K_ESC 033
10#define K_F1 SL_KEY_F(1)
11#define K_HOME SL_KEY_HOME
12#define K_LEFT SL_KEY_LEFT
13#define K_PGDN SL_KEY_NPAGE
14#define K_PGUP SL_KEY_PPAGE
15#define K_RIGHT SL_KEY_RIGHT
16#define K_TAB '\t'
17#define K_UNTAB SL_KEY_UNTAB
18#define K_UP SL_KEY_UP
19
20/* Not really keys */
21#define K_TIMER -1
22#define K_ERROR -2
23#define K_RESIZE -3
24
25#endif /* _PERF_KEYSYMS_H_ */
diff --git a/tools/perf/util/ui/libslang.h b/tools/perf/util/ui/libslang.h
index 2b63e1c9b181..4d54b6450f5b 100644
--- a/tools/perf/util/ui/libslang.h
+++ b/tools/perf/util/ui/libslang.h
@@ -24,4 +24,6 @@
24#define sltt_set_color SLtt_set_color 24#define sltt_set_color SLtt_set_color
25#endif 25#endif
26 26
27#define SL_KEY_UNTAB 0x1000
28
27#endif /* _PERF_UI_SLANG_H_ */ 29#endif /* _PERF_UI_SLANG_H_ */
diff --git a/tools/perf/util/ui/progress.c b/tools/perf/util/ui/progress.c
index d7fc399d36b3..295e366b6311 100644
--- a/tools/perf/util/ui/progress.c
+++ b/tools/perf/util/ui/progress.c
@@ -1,60 +1,29 @@
1#include <stdlib.h>
2#include <newt.h>
3#include "../cache.h" 1#include "../cache.h"
4#include "progress.h" 2#include "progress.h"
3#include "libslang.h"
4#include "ui.h"
5#include "browser.h"
5 6
6struct ui_progress { 7void ui_progress__update(u64 curr, u64 total, const char *title)
7 newtComponent form, scale;
8};
9
10struct ui_progress *ui_progress__new(const char *title, u64 total)
11{
12 struct ui_progress *self = malloc(sizeof(*self));
13
14 if (self != NULL) {
15 int cols;
16
17 if (use_browser <= 0)
18 return self;
19 newtGetScreenSize(&cols, NULL);
20 cols -= 4;
21 newtCenteredWindow(cols, 1, title);
22 self->form = newtForm(NULL, NULL, 0);
23 if (self->form == NULL)
24 goto out_free_self;
25 self->scale = newtScale(0, 0, cols, total);
26 if (self->scale == NULL)
27 goto out_free_form;
28 newtFormAddComponent(self->form, self->scale);
29 newtRefresh();
30 }
31
32 return self;
33
34out_free_form:
35 newtFormDestroy(self->form);
36out_free_self:
37 free(self);
38 return NULL;
39}
40
41void ui_progress__update(struct ui_progress *self, u64 curr)
42{ 8{
9 int bar, y;
43 /* 10 /*
44 * FIXME: We should have a per UI backend way of showing progress, 11 * FIXME: We should have a per UI backend way of showing progress,
45 * stdio will just show a percentage as NN%, etc. 12 * stdio will just show a percentage as NN%, etc.
46 */ 13 */
47 if (use_browser <= 0) 14 if (use_browser <= 0)
48 return; 15 return;
49 newtScaleSet(self->scale, curr);
50 newtRefresh();
51}
52 16
53void ui_progress__delete(struct ui_progress *self) 17 ui__refresh_dimensions(true);
54{ 18 pthread_mutex_lock(&ui__lock);
55 if (use_browser > 0) { 19 y = SLtt_Screen_Rows / 2 - 2;
56 newtFormDestroy(self->form); 20 SLsmg_set_color(0);
57 newtPopWindow(); 21 SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
58 } 22 SLsmg_gotorc(y++, 1);
59 free(self); 23 SLsmg_write_string((char *)title);
24 SLsmg_set_color(HE_COLORSET_SELECTED);
25 bar = ((SLtt_Screen_Cols - 2) * curr) / total;
26 SLsmg_fill_region(y, 1, 1, bar, ' ');
27 SLsmg_refresh();
28 pthread_mutex_unlock(&ui__lock);
60} 29}
diff --git a/tools/perf/util/ui/progress.h b/tools/perf/util/ui/progress.h
index a3820a0beb5b..d9c205b59aa1 100644
--- a/tools/perf/util/ui/progress.h
+++ b/tools/perf/util/ui/progress.h
@@ -1,11 +1,8 @@
1#ifndef _PERF_UI_PROGRESS_H_ 1#ifndef _PERF_UI_PROGRESS_H_
2#define _PERF_UI_PROGRESS_H_ 1 2#define _PERF_UI_PROGRESS_H_ 1
3 3
4struct ui_progress; 4#include <../types.h>
5 5
6struct ui_progress *ui_progress__new(const char *title, u64 total); 6void ui_progress__update(u64 curr, u64 total, const char *title);
7void ui_progress__delete(struct ui_progress *self);
8
9void ui_progress__update(struct ui_progress *self, u64 curr);
10 7
11#endif 8#endif
diff --git a/tools/perf/util/ui/setup.c b/tools/perf/util/ui/setup.c
index ee46d671db59..85a69faa09aa 100644
--- a/tools/perf/util/ui/setup.c
+++ b/tools/perf/util/ui/setup.c
@@ -7,9 +7,85 @@
7#include "browser.h" 7#include "browser.h"
8#include "helpline.h" 8#include "helpline.h"
9#include "ui.h" 9#include "ui.h"
10#include "util.h"
11#include "libslang.h"
12#include "keysyms.h"
10 13
11pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; 14pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
12 15
16static volatile int ui__need_resize;
17
18void ui__refresh_dimensions(bool force)
19{
20 if (force || ui__need_resize) {
21 ui__need_resize = 0;
22 pthread_mutex_lock(&ui__lock);
23 SLtt_get_screen_size();
24 SLsmg_reinit_smg();
25 pthread_mutex_unlock(&ui__lock);
26 }
27}
28
29static void ui__sigwinch(int sig __used)
30{
31 ui__need_resize = 1;
32}
33
34static void ui__setup_sigwinch(void)
35{
36 static bool done;
37
38 if (done)
39 return;
40
41 done = true;
42 pthread__unblock_sigwinch();
43 signal(SIGWINCH, ui__sigwinch);
44}
45
46int ui__getch(int delay_secs)
47{
48 struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
49 fd_set read_set;
50 int err, key;
51
52 ui__setup_sigwinch();
53
54 FD_ZERO(&read_set);
55 FD_SET(0, &read_set);
56
57 if (delay_secs) {
58 timeout.tv_sec = delay_secs;
59 timeout.tv_usec = 0;
60 }
61
62 err = select(1, &read_set, NULL, NULL, ptimeout);
63
64 if (err == 0)
65 return K_TIMER;
66
67 if (err == -1) {
68 if (errno == EINTR)
69 return K_RESIZE;
70 return K_ERROR;
71 }
72
73 key = SLang_getkey();
74 if (key != K_ESC)
75 return key;
76
77 FD_ZERO(&read_set);
78 FD_SET(0, &read_set);
79 timeout.tv_sec = 0;
80 timeout.tv_usec = 20;
81 err = select(1, &read_set, NULL, NULL, &timeout);
82 if (err == 0)
83 return K_ESC;
84
85 SLang_ungetkey(key);
86 return SLkp_getkey();
87}
88
13static void newt_suspend(void *d __used) 89static void newt_suspend(void *d __used)
14{ 90{
15 newtSuspend(); 91 newtSuspend();
@@ -17,6 +93,33 @@ static void newt_suspend(void *d __used)
17 newtResume(); 93 newtResume();
18} 94}
19 95
96static int ui__init(void)
97{
98 int err = SLkp_init();
99
100 if (err < 0)
101 goto out;
102
103 SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB);
104out:
105 return err;
106}
107
108static void ui__exit(void)
109{
110 SLtt_set_cursor_visibility(1);
111 SLsmg_refresh();
112 SLsmg_reset_smg();
113 SLang_reset_tty();
114}
115
116static void ui__signal(int sig)
117{
118 ui__exit();
119 psignal(sig, "perf");
120 exit(0);
121}
122
20void setup_browser(bool fallback_to_pager) 123void setup_browser(bool fallback_to_pager)
21{ 124{
22 if (!isatty(1) || !use_browser || dump_trace) { 125 if (!isatty(1) || !use_browser || dump_trace) {
@@ -28,19 +131,25 @@ void setup_browser(bool fallback_to_pager)
28 131
29 use_browser = 1; 132 use_browser = 1;
30 newtInit(); 133 newtInit();
31 newtCls(); 134 ui__init();
32 newtSetSuspendCallback(newt_suspend, NULL); 135 newtSetSuspendCallback(newt_suspend, NULL);
33 ui_helpline__init(); 136 ui_helpline__init();
34 ui_browser__init(); 137 ui_browser__init();
138
139 signal(SIGSEGV, ui__signal);
140 signal(SIGFPE, ui__signal);
141 signal(SIGINT, ui__signal);
142 signal(SIGQUIT, ui__signal);
143 signal(SIGTERM, ui__signal);
35} 144}
36 145
37void exit_browser(bool wait_for_ok) 146void exit_browser(bool wait_for_ok)
38{ 147{
39 if (use_browser > 0) { 148 if (use_browser > 0) {
40 if (wait_for_ok) { 149 if (wait_for_ok)
41 char title[] = "Fatal Error", ok[] = "Ok"; 150 ui__question_window("Fatal Error",
42 newtWinMessage(title, ok, ui_helpline__last_msg); 151 ui_helpline__last_msg,
43 } 152 "Press any key...", 0);
44 newtFinished(); 153 ui__exit();
45 } 154 }
46} 155}
diff --git a/tools/perf/util/ui/ui.h b/tools/perf/util/ui/ui.h
index d264e059c829..7b67045479f6 100644
--- a/tools/perf/util/ui/ui.h
+++ b/tools/perf/util/ui/ui.h
@@ -2,7 +2,10 @@
2#define _PERF_UI_H_ 1 2#define _PERF_UI_H_ 1
3 3
4#include <pthread.h> 4#include <pthread.h>
5#include <stdbool.h>
5 6
6extern pthread_mutex_t ui__lock; 7extern pthread_mutex_t ui__lock;
7 8
9void ui__refresh_dimensions(bool force);
10
8#endif /* _PERF_UI_H_ */ 11#endif /* _PERF_UI_H_ */
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
index fdf1fc8f08bc..45daa7c41dad 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -1,6 +1,5 @@
1#include <newt.h> 1#include "../util.h"
2#include <signal.h> 2#include <signal.h>
3#include <stdio.h>
4#include <stdbool.h> 3#include <stdbool.h>
5#include <string.h> 4#include <string.h>
6#include <sys/ttydefaults.h> 5#include <sys/ttydefaults.h>
@@ -8,72 +7,75 @@
8#include "../cache.h" 7#include "../cache.h"
9#include "../debug.h" 8#include "../debug.h"
10#include "browser.h" 9#include "browser.h"
10#include "keysyms.h"
11#include "helpline.h" 11#include "helpline.h"
12#include "ui.h" 12#include "ui.h"
13#include "util.h" 13#include "util.h"
14#include "libslang.h"
14 15
15static void newt_form__set_exit_keys(newtComponent self) 16static void ui_browser__argv_write(struct ui_browser *browser,
17 void *entry, int row)
16{ 18{
17 newtFormAddHotKey(self, NEWT_KEY_LEFT); 19 char **arg = entry;
18 newtFormAddHotKey(self, NEWT_KEY_ESCAPE); 20 bool current_entry = ui_browser__is_current_entry(browser, row);
19 newtFormAddHotKey(self, 'Q');
20 newtFormAddHotKey(self, 'q');
21 newtFormAddHotKey(self, CTRL('c'));
22}
23 21
24static newtComponent newt_form__new(void) 22 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
25{ 23 HE_COLORSET_NORMAL);
26 newtComponent self = newtForm(NULL, NULL, 0); 24 slsmg_write_nstring(*arg, browser->width);
27 if (self)
28 newt_form__set_exit_keys(self);
29 return self;
30} 25}
31 26
32int ui__popup_menu(int argc, char * const argv[]) 27static int popup_menu__run(struct ui_browser *menu)
33{ 28{
34 struct newtExitStruct es; 29 int key;
35 int i, rc = -1, max_len = 5;
36 newtComponent listbox, form = newt_form__new();
37 30
38 if (form == NULL) 31 if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
39 return -1; 32 return -1;
40 33
41 listbox = newtListbox(0, 0, argc, NEWT_FLAG_RETURNEXIT); 34 while (1) {
42 if (listbox == NULL) 35 key = ui_browser__run(menu, 0);
43 goto out_destroy_form;
44 36
45 newtFormAddComponent(form, listbox); 37 switch (key) {
38 case K_RIGHT:
39 case K_ENTER:
40 key = menu->index;
41 break;
42 case K_LEFT:
43 case K_ESC:
44 case 'q':
45 case CTRL('c'):
46 key = -1;
47 break;
48 default:
49 continue;
50 }
46 51
47 for (i = 0; i < argc; ++i) { 52 break;
48 int len = strlen(argv[i]);
49 if (len > max_len)
50 max_len = len;
51 if (newtListboxAddEntry(listbox, argv[i], (void *)(long)i))
52 goto out_destroy_form;
53 } 53 }
54 54
55 newtCenteredWindow(max_len, argc, NULL); 55 ui_browser__hide(menu);
56 newtFormRun(form, &es); 56 return key;
57 rc = newtListboxGetCurrent(listbox) - NULL;
58 if (es.reason == NEWT_EXIT_HOTKEY)
59 rc = -1;
60 newtPopWindow();
61out_destroy_form:
62 newtFormDestroy(form);
63 return rc;
64} 57}
65 58
66int ui__help_window(const char *text) 59int ui__popup_menu(int argc, char * const argv[])
67{ 60{
68 struct newtExitStruct es; 61 struct ui_browser menu = {
69 newtComponent tb, form = newt_form__new(); 62 .entries = (void *)argv,
70 int rc = -1; 63 .refresh = ui_browser__argv_refresh,
64 .seek = ui_browser__argv_seek,
65 .write = ui_browser__argv_write,
66 .nr_entries = argc,
67 };
68
69 return popup_menu__run(&menu);
70}
71
72int ui__question_window(const char *title, const char *text,
73 const char *exit_msg, int delay_secs)
74{
75 int x, y;
71 int max_len = 0, nr_lines = 0; 76 int max_len = 0, nr_lines = 0;
72 const char *t; 77 const char *t;
73 78
74 if (form == NULL)
75 return -1;
76
77 t = text; 79 t = text;
78 while (1) { 80 while (1) {
79 const char *sep = strchr(t, '\n'); 81 const char *sep = strchr(t, '\n');
@@ -90,41 +92,77 @@ int ui__help_window(const char *text)
90 t = sep + 1; 92 t = sep + 1;
91 } 93 }
92 94
93 tb = newtTextbox(0, 0, max_len, nr_lines, 0); 95 max_len += 2;
94 if (tb == NULL) 96 nr_lines += 4;
95 goto out_destroy_form; 97 y = SLtt_Screen_Rows / 2 - nr_lines / 2,
96 98 x = SLtt_Screen_Cols / 2 - max_len / 2;
97 newtTextboxSetText(tb, text); 99
98 newtFormAddComponent(form, tb); 100 SLsmg_set_color(0);
99 newtCenteredWindow(max_len, nr_lines, NULL); 101 SLsmg_draw_box(y, x++, nr_lines, max_len);
100 newtFormRun(form, &es); 102 if (title) {
101 newtPopWindow(); 103 SLsmg_gotorc(y, x + 1);
102 rc = 0; 104 SLsmg_write_string((char *)title);
103out_destroy_form: 105 }
104 newtFormDestroy(form); 106 SLsmg_gotorc(++y, x);
105 return rc; 107 nr_lines -= 2;
108 max_len -= 2;
109 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
110 nr_lines, max_len, 1);
111 SLsmg_gotorc(y + nr_lines - 2, x);
112 SLsmg_write_nstring((char *)" ", max_len);
113 SLsmg_gotorc(y + nr_lines - 1, x);
114 SLsmg_write_nstring((char *)exit_msg, max_len);
115 SLsmg_refresh();
116 return ui__getch(delay_secs);
106} 117}
107 118
108static const char yes[] = "Yes", no[] = "No", 119int ui__help_window(const char *text)
109 warning_str[] = "Warning!", ok[] = "Ok"; 120{
121 return ui__question_window("Help", text, "Press any key...", 0);
122}
110 123
111bool ui__dialog_yesno(const char *msg) 124int ui__dialog_yesno(const char *msg)
112{ 125{
113 /* newtWinChoice should really be accepting const char pointers... */ 126 return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
114 return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1;
115} 127}
116 128
117void ui__warning(const char *format, ...) 129int __ui__warning(const char *title, const char *format, va_list args)
118{ 130{
119 va_list args; 131 char *s;
132
133 if (use_browser > 0 && vasprintf(&s, format, args) > 0) {
134 int key;
120 135
121 va_start(args, format);
122 if (use_browser > 0) {
123 pthread_mutex_lock(&ui__lock); 136 pthread_mutex_lock(&ui__lock);
124 newtWinMessagev((char *)warning_str, (char *)ok, 137 key = ui__question_window(title, s, "Press any key...", 0);
125 (char *)format, args);
126 pthread_mutex_unlock(&ui__lock); 138 pthread_mutex_unlock(&ui__lock);
127 } else 139 free(s);
128 vfprintf(stderr, format, args); 140 return key;
141 }
142
143 fprintf(stderr, "%s:\n", title);
144 vfprintf(stderr, format, args);
145 return K_ESC;
146}
147
148int ui__warning(const char *format, ...)
149{
150 int key;
151 va_list args;
152
153 va_start(args, format);
154 key = __ui__warning("Warning", format, args);
155 va_end(args);
156 return key;
157}
158
159int ui__error(const char *format, ...)
160{
161 int key;
162 va_list args;
163
164 va_start(args, format);
165 key = __ui__warning("Error", format, args);
129 va_end(args); 166 va_end(args);
167 return key;
130} 168}
diff --git a/tools/perf/util/ui/util.h b/tools/perf/util/ui/util.h
index afcbc1d99531..2d1738bd71c8 100644
--- a/tools/perf/util/ui/util.h
+++ b/tools/perf/util/ui/util.h
@@ -1,10 +1,14 @@
1#ifndef _PERF_UI_UTIL_H_ 1#ifndef _PERF_UI_UTIL_H_
2#define _PERF_UI_UTIL_H_ 1 2#define _PERF_UI_UTIL_H_ 1
3 3
4#include <stdbool.h> 4#include <stdarg.h>
5 5
6int ui__getch(int delay_secs);
6int ui__popup_menu(int argc, char * const argv[]); 7int ui__popup_menu(int argc, char * const argv[]);
7int ui__help_window(const char *text); 8int ui__help_window(const char *text);
8bool ui__dialog_yesno(const char *msg); 9int ui__dialog_yesno(const char *msg);
10int ui__question_window(const char *title, const char *text,
11 const char *exit_msg, int delay_secs);
12int __ui__warning(const char *title, const char *format, va_list args);
9 13
10#endif /* _PERF_UI_UTIL_H_ */ 14#endif /* _PERF_UI_UTIL_H_ */
diff --git a/tools/power/cpupower/.gitignore b/tools/power/cpupower/.gitignore
new file mode 100644
index 000000000000..8a83dd2ffc11
--- /dev/null
+++ b/tools/power/cpupower/.gitignore
@@ -0,0 +1,22 @@
1.libs
2libcpupower.so
3libcpupower.so.0
4libcpupower.so.0.0.0
5build/ccdv
6cpufreq-info
7cpufreq-set
8cpufreq-aperf
9lib/.libs
10lib/cpufreq.lo
11lib/cpufreq.o
12lib/proc.lo
13lib/proc.o
14lib/sysfs.lo
15lib/sysfs.o
16po/cpupowerutils.pot
17po/*.gmo
18utils/cpufreq-info.o
19utils/cpufreq-set.o
20utils/cpufreq-aperf.o
21cpupower
22bench/cpufreq-bench
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
new file mode 100644
index 000000000000..e8a03aceceb1
--- /dev/null
+++ b/tools/power/cpupower/Makefile
@@ -0,0 +1,280 @@
1# Makefile for cpupower
2#
3# Copyright (C) 2005,2006 Dominik Brodowski <linux@dominikbrodowski.net>
4#
5# Based largely on the Makefile for udev by:
6#
7# Copyright (C) 2003,2004 Greg Kroah-Hartman <greg@kroah.com>
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; version 2 of the License.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16# General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21#
22
23# --- CONFIGURATION BEGIN ---
24
25# Set the following to `true' to make a unstripped, unoptimized
26# binary. Leave this set to `false' for production use.
27DEBUG ?= true
28
29# make the build silent. Set this to something else to make it noisy again.
30V ?= false
31
32# Internationalization support (output in different languages).
33# Requires gettext.
34NLS ?= true
35
36# Set the following to 'true' to build/install the
37# cpufreq-bench benchmarking tool
38CPUFREQ_BENCH ?= true
39
40# Prefix to the directories we're installing to
41DESTDIR ?=
42
43# --- CONFIGURATION END ---
44
45
46
47# Package-related definitions. Distributions can modify the version
48# and _should_ modify the PACKAGE_BUGREPORT definition
49
50VERSION= $(shell ./utils/version-gen.sh)
51LIB_MAJ= 0.0.0
52LIB_MIN= 0
53
54PACKAGE = cpupower
55PACKAGE_BUGREPORT = cpufreq@vger.kernel.org
56LANGUAGES = de fr it cs pt
57
58
59# Directory definitions. These are default and most probably
60# do not need to be changed. Please note that DESTDIR is
61# added in front of any of them
62
63bindir ?= /usr/bin
64sbindir ?= /usr/sbin
65mandir ?= /usr/man
66includedir ?= /usr/include
67libdir ?= /usr/lib
68localedir ?= /usr/share/locale
69docdir ?= /usr/share/doc/packages/cpupower
70confdir ?= /etc/
71
72# Toolchain: what tools do we use, and what options do they need:
73
74CP = cp -fpR
75INSTALL = /usr/bin/install -c
76INSTALL_PROGRAM = ${INSTALL}
77INSTALL_DATA = ${INSTALL} -m 644
78INSTALL_SCRIPT = ${INSTALL_PROGRAM}
79
80# If you are running a cross compiler, you may want to set this
81# to something more interesting, like "arm-linux-". If you want
82# to compile vs uClibc, that can be done here as well.
83CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
84CC = $(CROSS)gcc
85LD = $(CROSS)gcc
86AR = $(CROSS)ar
87STRIP = $(CROSS)strip
88RANLIB = $(CROSS)ranlib
89HOSTCC = gcc
90
91
92# Now we set up the build system
93#
94
95# set up PWD so that older versions of make will work with our build.
96PWD = $(shell pwd)
97
98GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo po/$$HLANG.gmo; done;}
99
100export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS
101
102# check if compiler option is supported
103cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;}
104
105# use '-Os' optimization if available, else use -O2
106OPTIMIZATION := $(call cc-supports,-Os,-O2)
107
108WARNINGS := -Wall -Wchar-subscripts -Wpointer-arith -Wsign-compare
109WARNINGS += $(call cc-supports,-Wno-pointer-sign)
110WARNINGS += $(call cc-supports,-Wdeclaration-after-statement)
111WARNINGS += -Wshadow
112
113CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
114 -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE
115
116UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \
117 utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \
118 utils/helpers/pci.o utils/helpers/bitmask.o \
119 utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \
120 utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \
121 utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \
122 utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
123 utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o
124
125UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
126 utils/helpers/bitmask.h \
127 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
128
129UTIL_SRC := $(UTIL_OBJS:.o=.c)
130
131LIB_HEADERS = lib/cpufreq.h lib/sysfs.h
132LIB_SRC = lib/cpufreq.c lib/sysfs.c
133LIB_OBJS = lib/cpufreq.o lib/sysfs.o
134
135CFLAGS += -pipe
136
137ifeq ($(strip $(NLS)),true)
138 INSTALL_NLS += install-gmo
139 COMPILE_NLS += create-gmo
140 CFLAGS += -DNLS
141endif
142
143ifeq ($(strip $(CPUFREQ_BENCH)),true)
144 INSTALL_BENCH += install-bench
145 COMPILE_BENCH += compile-bench
146endif
147
148CFLAGS += $(WARNINGS)
149
150ifeq ($(strip $(V)),false)
151 QUIET=@
152 ECHO=@echo
153else
154 QUIET=
155 ECHO=@\#
156endif
157export QUIET ECHO
158
159# if DEBUG is enabled, then we do not strip or optimize
160ifeq ($(strip $(DEBUG)),true)
161 CFLAGS += -O1 -g -DDEBUG
162 STRIPCMD = /bin/true -Since_we_are_debugging
163else
164 CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer
165 STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
166endif
167
168
169# the actual make rules
170
171all: libcpupower cpupower $(COMPILE_NLS) $(COMPILE_BENCH)
172
173lib/%.o: $(LIB_SRC) $(LIB_HEADERS)
174 $(ECHO) " CC " $@
175 $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c
176
177libcpupower.so.$(LIB_MAJ): $(LIB_OBJS)
178 $(ECHO) " LD " $@
179 $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \
180 -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS)
181 @ln -sf $@ libcpupower.so
182 @ln -sf $@ libcpupower.so.$(LIB_MIN)
183
184libcpupower: libcpupower.so.$(LIB_MAJ)
185
186# Let all .o files depend on its .c file and all headers
187# Might be worth to put this into utils/Makefile at some point of time
188$(UTIL_OBJS): $(UTIL_HEADERS)
189
190.c.o:
191 $(ECHO) " CC " $@
192 $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c
193
194cpupower: $(UTIL_OBJS) libcpupower.so.$(LIB_MAJ)
195 $(ECHO) " CC " $@
196 $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpupower -lrt -lpci -L. -o $@ $(UTIL_OBJS)
197 $(QUIET) $(STRIPCMD) $@
198
199po/$(PACKAGE).pot: $(UTIL_SRC)
200 $(ECHO) " GETTEXT " $@
201 $(QUIET) xgettext --default-domain=$(PACKAGE) --add-comments \
202 --keyword=_ --keyword=N_ $(UTIL_SRC) && \
203 test -f $(PACKAGE).po && \
204 mv -f $(PACKAGE).po po/$(PACKAGE).pot
205
206po/%.gmo: po/%.po
207 $(ECHO) " MSGFMT " $@
208 $(QUIET) msgfmt -o $@ po/$*.po
209
210create-gmo: ${GMO_FILES}
211
212update-po: po/$(PACKAGE).pot
213 $(ECHO) " MSGMRG " $@
214 $(QUIET) @for HLANG in $(LANGUAGES); do \
215 echo -n "Updating $$HLANG "; \
216 if msgmerge po/$$HLANG.po po/$(PACKAGE).pot -o \
217 po/$$HLANG.new.po; then \
218 mv -f po/$$HLANG.new.po po/$$HLANG.po; \
219 else \
220 echo "msgmerge for $$HLANG failed!"; \
221 rm -f po/$$HLANG.new.po; \
222 fi; \
223 done;
224
225compile-bench: libcpupower.so.$(LIB_MAJ)
226 @V=$(V) confdir=$(confdir) $(MAKE) -C bench
227
228clean:
229 -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
230 | xargs rm -f
231 -rm -f $(UTIL_BINS)
232 -rm -f $(IDLE_OBJS)
233 -rm -f cpupower
234 -rm -f libcpupower.so*
235 -rm -rf po/*.gmo po/*.pot
236 $(MAKE) -C bench clean
237
238
239install-lib:
240 $(INSTALL) -d $(DESTDIR)${libdir}
241 $(CP) libcpupower.so* $(DESTDIR)${libdir}/
242 $(INSTALL) -d $(DESTDIR)${includedir}
243 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
244
245install-tools:
246 $(INSTALL) -d $(DESTDIR)${bindir}
247 $(INSTALL_PROGRAM) cpupower $(DESTDIR)${bindir}
248
249install-man:
250 $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1
251 $(INSTALL_DATA) -D man/cpupower-frequency-set.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1
252 $(INSTALL_DATA) -D man/cpupower-frequency-info.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1
253 $(INSTALL_DATA) -D man/cpupower-set.1 $(DESTDIR)${mandir}/man1/cpupower-set.1
254 $(INSTALL_DATA) -D man/cpupower-info.1 $(DESTDIR)${mandir}/man1/cpupower-info.1
255 $(INSTALL_DATA) -D man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1
256
257install-gmo:
258 $(INSTALL) -d $(DESTDIR)${localedir}
259 for HLANG in $(LANGUAGES); do \
260 echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \
261 $(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
262 done;
263
264install-bench:
265 @#DESTDIR must be set from outside to survive
266 @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench install
267
268install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
269
270uninstall:
271 - rm -f $(DESTDIR)${libdir}/libcpupower.*
272 - rm -f $(DESTDIR)${includedir}/cpufreq.h
273 - rm -f $(DESTDIR)${bindir}/utils/cpupower
274 - rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1
275 - rm -f $(DESTDIR)${mandir}/man1/cpufreq-info.1
276 - for HLANG in $(LANGUAGES); do \
277 rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
278 done;
279
280.PHONY: all utils libcpupower update-po create-gmo install-lib install-tools install-man install-gmo install uninstall clean
diff --git a/tools/power/cpupower/README b/tools/power/cpupower/README
new file mode 100644
index 000000000000..fd9d4c0d6688
--- /dev/null
+++ b/tools/power/cpupower/README
@@ -0,0 +1,49 @@
1The cpufrequtils package (homepage:
2http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils.html )
3consists of the following elements:
4
5requirements
6------------
7
8On x86 pciutils is needed at runtime (-lpci).
9For compilation pciutils-devel (pci/pci.h) and a gcc version
10providing cpuid.h is needed.
11For both it's not explicitly checked for (yet).
12
13
14libcpufreq
15----------
16
17"libcpufreq" is a library which offers a unified access method for userspace
18tools and programs to the cpufreq core and drivers in the Linux kernel. This
19allows for code reduction in userspace tools, a clean implementation of
20the interaction to the cpufreq core, and support for both the sysfs and proc
21interfaces [depending on configuration, see below].
22
23
24compilation and installation
25----------------------------
26
27make
28su
29make install
30
31should suffice on most systems. It builds default libcpufreq,
32cpufreq-set and cpufreq-info files and installs them in /usr/lib and
33/usr/bin, respectively. If you want to set up the paths differently and/or
34want to configure the package to your specific needs, you need to open
35"Makefile" with an editor of your choice and edit the block marked
36CONFIGURATION.
37
38
39THANKS
40------
41Many thanks to Mattia Dongili who wrote the autotoolization and
42libtoolization, the manpages and the italian language file for cpufrequtils;
43to Dave Jones for his feedback and his dump_psb tool; to Bruno Ducrot for his
44powernow-k8-decode and intel_gsic tools as well as the french language file;
45and to various others commenting on the previous (pre-)releases of
46cpufrequtils.
47
48
49 Dominik Brodowski
diff --git a/tools/power/cpupower/ToDo b/tools/power/cpupower/ToDo
new file mode 100644
index 000000000000..874b78b586ee
--- /dev/null
+++ b/tools/power/cpupower/ToDo
@@ -0,0 +1,11 @@
1ToDos sorted by priority:
2
3- Use bitmask functions to parse CPU topology more robust
4 (current implementation has issues on AMD)
5- Try to read out boost states and frequencies on Intel
6- Adjust README
7- Somewhere saw the ability to read power consumption of
8 RAM from HW on Intel SandyBridge -> another monitor?
9- Add another c1e debug idle monitor
10 -> Is by design racy with BIOS, but could be added
11 with a --force option and some "be careful" messages
diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile
new file mode 100644
index 000000000000..2b67606fc3e3
--- /dev/null
+++ b/tools/power/cpupower/bench/Makefile
@@ -0,0 +1,29 @@
1LIBS = -L../ -lm -lcpupower
2
3OBJS = main.o parse.o system.o benchmark.o
4CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
5
6%.o : %.c
7 $(ECHO) " CC " $@
8 $(QUIET) $(CC) -c $(CFLAGS) $< -o $@
9
10cpufreq-bench: $(OBJS)
11 $(ECHO) " CC " $@
12 $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS)
13
14all: cpufreq-bench
15
16install:
17 mkdir -p $(DESTDIR)/$(sbindir)
18 mkdir -p $(DESTDIR)/$(bindir)
19 mkdir -p $(DESTDIR)/$(docdir)
20 mkdir -p $(DESTDIR)/$(confdir)
21 install -m 755 cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench
22 install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh
23 install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH
24 install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh
25 install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf
26
27clean:
28 rm -f *.o
29 rm -f cpufreq-bench
diff --git a/tools/power/cpupower/bench/README-BENCH b/tools/power/cpupower/bench/README-BENCH
new file mode 100644
index 000000000000..8093ec738170
--- /dev/null
+++ b/tools/power/cpupower/bench/README-BENCH
@@ -0,0 +1,124 @@
1This is cpufreq-bench, a microbenchmark for the cpufreq framework.
2
3Purpose
4=======
5
6What is this benchmark for:
7 - Identify worst case performance loss when doing dynamic frequency
8 scaling using Linux kernel governors
9 - Identify average reaction time of a governor to CPU load changes
10 - (Stress) Testing whether a cpufreq low level driver or governor works
11 as expected
12 - Identify cpufreq related performance regressions between kernels
13 - Possibly Real time priority testing? -> what happens if there are
14 processes with a higher prio than the governor's kernel thread
15 - ...
16
17What this benchmark does *not* cover:
18 - Power saving related regressions (In fact as better the performance
19 throughput is, the worse the power savings will be, but the first should
20 mostly count more...)
21 - Real world (workloads)
22
23
24Description
25===========
26
27cpufreq-bench helps to test the condition of a given cpufreq governor.
28For that purpose, it compares the performance governor to a configured
29powersave module.
30
31
32How it works
33============
34You can specify load (100% CPU load) and sleep (0% CPU load) times in us which
35will be run X time in a row (cycles):
36
37 sleep=25000
38 load=25000
39 cycles=20
40
41This part of the configuration file will create 25ms load/sleep turns,
42repeated 20 times.
43
44Adding this:
45 sleep_step=25000
46 load_step=25000
47 rounds=5
48Will increase load and sleep time by 25ms 5 times.
49Together you get following test:
5025ms load/sleep time repeated 20 times (cycles).
5150ms load/sleep time repeated 20 times (cycles).
52..
53100ms load/sleep time repeated 20 times (cycles).
54
55First it is calibrated how long a specific CPU intensive calculation
56takes on this machine and needs to be run in a loop using the performance
57governor.
58Then the above test runs are processed using the performance governor
59and the governor to test. The time the calculation really needed
60with the dynamic freq scaling governor is compared with the time needed
61on full performance and you get the overall performance loss.
62
63
64Example of expected results with ondemand governor:
65
66This shows expected results of the first two test run rounds from
67above config, you there have:
68
69100% CPU load (load) | 0 % CPU load (sleep) | round
70 25 ms | 25 ms | 1
71 50 ms | 50 ms | 2
72
73For example if ondemand governor is configured to have a 50ms
74sampling rate you get:
75
76In round 1, ondemand should have rather static 50% load and probably
77won't ever switch up (as long as up_threshold is above).
78
79In round 2, if the ondemand sampling times exactly match the load/sleep
80trigger of the cpufreq-bench, you will see no performance loss (compare with
81below possible ondemand sample kick ins (1)):
82
83But if ondemand always kicks in in the middle of the load sleep cycles, it
84will always see 50% loads and you get worst performance impact never
85switching up (compare with below possible ondemand sample kick ins (2))::
86
87 50 50 50 50ms ->time
88load -----| |-----| |-----| |-----|
89 | | | | | | |
90sleep |-----| |-----| |-----| |----
91 |-----|-----|-----|-----|-----|-----|-----|---- ondemand sampling (1)
92 100 0 100 0 100 0 100 load seen by ondemand(%)
93 |-----|-----|-----|-----|-----|-----|-----|-- ondemand sampling (2)
94 50 50 50 50 50 50 50 load seen by ondemand(%)
95
96You can easily test all kind of load/sleep times and check whether your
97governor in average behaves as expected.
98
99
100ToDo
101====
102
103Provide a gnuplot utility script for easy generation of plots to present
104the outcome nicely.
105
106
107cpufreq-bench Command Usage
108===========================
109-l, --load=<long int> initial load time in us
110-s, --sleep=<long int> initial sleep time in us
111-x, --load-step=<long int> time to be added to load time, in us
112-y, --sleep-step=<long int> time to be added to sleep time, in us
113-c, --cpu=<unsigned int> CPU Number to use, starting at 0
114-p, --prio=<priority> scheduler priority, HIGH, LOW or DEFAULT
115-g, --governor=<governor> cpufreq governor to test
116-n, --cycles=<int> load/sleep cycles to get an avarage value to compare
117-r, --rounds<int> load/sleep rounds
118-f, --file=<configfile> config file to use
119-o, --output=<dir> output dir, must exist
120-v, --verbose verbose output on/off
121
122Due to the high priority, the application may not be responsible for some time.
123After the benchmark, the logfile is saved in OUTPUTDIR/benchmark_TIMESTAMP.log
124
diff --git a/tools/power/cpupower/bench/benchmark.c b/tools/power/cpupower/bench/benchmark.c
new file mode 100644
index 000000000000..81b1c48607d9
--- /dev/null
+++ b/tools/power/cpupower/bench/benchmark.c
@@ -0,0 +1,194 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <stdio.h>
21#include <unistd.h>
22#include <math.h>
23
24#include "config.h"
25#include "system.h"
26#include "benchmark.h"
27
28/* Print out progress if we log into a file */
29#define show_progress(total_time, progress_time) \
30if (config->output != stdout) { \
31 fprintf(stdout, "Progress: %02lu %%\r", \
32 (progress_time * 100) / total_time); \
33 fflush(stdout); \
34}
35
36/**
37 * compute how many rounds of calculation we should do
38 * to get the given load time
39 *
40 * @param load aimed load time in µs
41 *
42 * @retval rounds of calculation
43 **/
44
45unsigned int calculate_timespace(long load, struct config *config)
46{
47 int i;
48 long long now, then;
49 unsigned int estimated = GAUGECOUNT;
50 unsigned int rounds = 0;
51 unsigned int timed = 0;
52
53 if (config->verbose)
54 printf("calibrating load of %lius, please wait...\n", load);
55
56 /* get the initial calculation time for a specific number of rounds */
57 now = get_time();
58 ROUNDS(estimated);
59 then = get_time();
60
61 timed = (unsigned int)(then - now);
62
63 /* approximation of the wanted load time by comparing with the
64 * initial calculation time */
65 for (i = 0; i < 4; i++) {
66 rounds = (unsigned int)(load * estimated / timed);
67 dprintf("calibrating with %u rounds\n", rounds);
68 now = get_time();
69 ROUNDS(rounds);
70 then = get_time();
71
72 timed = (unsigned int)(then - now);
73 estimated = rounds;
74 }
75 if (config->verbose)
76 printf("calibration done\n");
77
78 return estimated;
79}
80
81/**
82 * benchmark
83 * generates a specific sleep an load time with the performance
84 * governor and compares the used time for same calculations done
85 * with the configured powersave governor
86 *
87 * @param config config values for the benchmark
88 *
89 **/
90
91void start_benchmark(struct config *config)
92{
93 unsigned int _round, cycle;
94 long long now, then;
95 long sleep_time = 0, load_time = 0;
96 long performance_time = 0, powersave_time = 0;
97 unsigned int calculations;
98 unsigned long total_time = 0, progress_time = 0;
99
100 sleep_time = config->sleep;
101 load_time = config->load;
102
103 /* For the progress bar */
104 for (_round = 1; _round <= config->rounds; _round++)
105 total_time += _round * (config->sleep + config->load);
106 total_time *= 2; /* powersave and performance cycles */
107
108 for (_round = 0; _round < config->rounds; _round++) {
109 performance_time = 0LL;
110 powersave_time = 0LL;
111
112 show_progress(total_time, progress_time);
113
114 /* set the cpufreq governor to "performance" which disables
115 * P-State switching. */
116 if (set_cpufreq_governor("performance", config->cpu) != 0)
117 return;
118
119 /* calibrate the calculation time. the resulting calculation
120 * _rounds should produce a load which matches the configured
121 * load time */
122 calculations = calculate_timespace(load_time, config);
123
124 if (config->verbose)
125 printf("_round %i: doing %u cycles with %u calculations"
126 " for %lius\n", _round + 1, config->cycles,
127 calculations, load_time);
128
129 fprintf(config->output, "%u %li %li ",
130 _round, load_time, sleep_time);
131
132 if (config->verbose)
133 printf("avarage: %lius, rps:%li\n",
134 load_time / calculations,
135 1000000 * calculations / load_time);
136
137 /* do some sleep/load cycles with the performance governor */
138 for (cycle = 0; cycle < config->cycles; cycle++) {
139 now = get_time();
140 usleep(sleep_time);
141 ROUNDS(calculations);
142 then = get_time();
143 performance_time += then - now - sleep_time;
144 if (config->verbose)
145 printf("performance cycle took %lius, "
146 "sleep: %lius, "
147 "load: %lius, rounds: %u\n",
148 (long)(then - now), sleep_time,
149 load_time, calculations);
150 }
151 fprintf(config->output, "%li ",
152 performance_time / config->cycles);
153
154 progress_time += sleep_time + load_time;
155 show_progress(total_time, progress_time);
156
157 /* set the powersave governor which activates P-State switching
158 * again */
159 if (set_cpufreq_governor(config->governor, config->cpu) != 0)
160 return;
161
162 /* again, do some sleep/load cycles with the
163 * powersave governor */
164 for (cycle = 0; cycle < config->cycles; cycle++) {
165 now = get_time();
166 usleep(sleep_time);
167 ROUNDS(calculations);
168 then = get_time();
169 powersave_time += then - now - sleep_time;
170 if (config->verbose)
171 printf("powersave cycle took %lius, "
172 "sleep: %lius, "
173 "load: %lius, rounds: %u\n",
174 (long)(then - now), sleep_time,
175 load_time, calculations);
176 }
177
178 progress_time += sleep_time + load_time;
179
180 /* compare the avarage sleep/load cycles */
181 fprintf(config->output, "%li ",
182 powersave_time / config->cycles);
183 fprintf(config->output, "%.3f\n",
184 performance_time * 100.0 / powersave_time);
185 fflush(config->output);
186
187 if (config->verbose)
188 printf("performance is at %.2f%%\n",
189 performance_time * 100.0 / powersave_time);
190
191 sleep_time += config->sleep_step;
192 load_time += config->load_step;
193 }
194}
diff --git a/tools/power/cpupower/bench/benchmark.h b/tools/power/cpupower/bench/benchmark.h
new file mode 100644
index 000000000000..51d7f50ac2bb
--- /dev/null
+++ b/tools/power/cpupower/bench/benchmark.h
@@ -0,0 +1,29 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20/* load loop, this schould take about 1 to 2ms to complete */
21#define ROUNDS(x) {unsigned int rcnt; \
22 for (rcnt = 0; rcnt < x*1000; rcnt++) { \
23 (void)(((int)(pow(rcnt, rcnt) * \
24 sqrt(rcnt*7230970)) ^ 7230716) ^ \
25 (int)atan2(rcnt, rcnt)); \
26 } } \
27
28
29void start_benchmark(struct config *config);
diff --git a/tools/power/cpupower/bench/config.h b/tools/power/cpupower/bench/config.h
new file mode 100644
index 000000000000..ee6f258e5336
--- /dev/null
+++ b/tools/power/cpupower/bench/config.h
@@ -0,0 +1,36 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20/* initial loop count for the load calibration */
21#define GAUGECOUNT 1500
22
23/* default scheduling policy SCHED_OTHER */
24#define SCHEDULER SCHED_OTHER
25
26#define PRIORITY_DEFAULT 0
27#define PRIORITY_HIGH sched_get_priority_max(SCHEDULER)
28#define PRIORITY_LOW sched_get_priority_min(SCHEDULER)
29
30/* enable further debug messages */
31#ifdef DEBUG
32#define dprintf printf
33#else
34#define dprintf(...) do { } while (0)
35#endif
36
diff --git a/tools/power/cpupower/bench/cpufreq-bench_plot.sh b/tools/power/cpupower/bench/cpufreq-bench_plot.sh
new file mode 100644
index 000000000000..410021a12f40
--- /dev/null
+++ b/tools/power/cpupower/bench/cpufreq-bench_plot.sh
@@ -0,0 +1,104 @@
1#!/bin/bash
2
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2, or (at your option)
6# any later version.
7
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16# 02110-1301, USA.
17
18# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
19
20# Helper script to easily create nice plots of your cpufreq-bench results
21
22dir=`mktemp -d`
23output_file="cpufreq-bench.png"
24global_title="cpufreq-bench plot"
25picture_type="jpeg"
26file[0]=""
27
28function usage()
29{
30 echo "cpufreq-bench_plot.sh [OPTIONS] logfile [measure_title] [logfile [measure_title]] ...]"
31 echo
32 echo "Options"
33 echo " -o output_file"
34 echo " -t global_title"
35 echo " -p picture_type [jpeg|gif|png|postscript|...]"
36 exit 1
37}
38
39if [ $# -eq 0 ];then
40 echo "No benchmark results file provided"
41 echo
42 usage
43fi
44
45while getopts o:t:p: name ; do
46 case $name in
47 o)
48 output_file="$OPTARG".$picture_type
49 ;;
50 t)
51 global_title="$OPTARG"
52 ;;
53 p)
54 picture_type="$OPTARG"
55 ;;
56 ?)
57 usage
58 ;;
59 esac
60done
61shift $(($OPTIND -1))
62
63plots=0
64while [ "$1" ];do
65 if [ ! -f "$1" ];then
66 echo "File $1 does not exist"
67 usage
68 fi
69 file[$plots]="$1"
70 title[$plots]="$2"
71 # echo "File: ${file[$plots]} - ${title[plots]}"
72 shift;shift
73 plots=$((plots + 1))
74done
75
76echo "set terminal $picture_type" >> $dir/plot_script.gpl
77echo "set output \"$output_file\"" >> $dir/plot_script.gpl
78echo "set title \"$global_title\"" >> $dir/plot_script.gpl
79echo "set xlabel \"sleep/load time\"" >> $dir/plot_script.gpl
80echo "set ylabel \"Performance (%)\"" >> $dir/plot_script.gpl
81
82for((plot=0;plot<$plots;plot++));do
83
84 # Sanity check
85 ###### I am to dump to get this redirected to stderr/stdout in one awk call... #####
86 cat ${file[$plot]} |grep -v "^#" |awk '{if ($2 != $3) printf("Error in measure %d:Load time %s does not equal sleep time %s, plot will not be correct\n", $1, $2, $3); ERR=1}'
87 ###### I am to dump to get this redirected in one awk call... #####
88
89 # Parse out load time (which must be equal to sleep time for a plot), divide it by 1000
90 # to get ms and parse out the performance in percentage and write it to a temp file for plotting
91 cat ${file[$plot]} |grep -v "^#" |awk '{printf "%lu %.1f\n",$2/1000, $6}' >$dir/data_$plot
92
93 if [ $plot -eq 0 ];then
94 echo -n "plot " >> $dir/plot_script.gpl
95 fi
96 echo -n "\"$dir/data_$plot\" title \"${title[$plot]}\" with lines" >> $dir/plot_script.gpl
97 if [ $(($plot + 1)) -ne $plots ];then
98 echo -n ", " >> $dir/plot_script.gpl
99 fi
100done
101echo >> $dir/plot_script.gpl
102
103gnuplot $dir/plot_script.gpl
104rm -r $dir \ No newline at end of file
diff --git a/tools/power/cpupower/bench/cpufreq-bench_script.sh b/tools/power/cpupower/bench/cpufreq-bench_script.sh
new file mode 100644
index 000000000000..de20d2a06879
--- /dev/null
+++ b/tools/power/cpupower/bench/cpufreq-bench_script.sh
@@ -0,0 +1,101 @@
1#!/bin/bash
2
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2, or (at your option)
6# any later version.
7
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16# 02110-1301, USA.
17
18# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
19
20# Ondemand up_threshold and sampling rate test script for cpufreq-bench
21# mircobenchmark.
22# Modify the general variables at the top or extend or copy out parts
23# if you want to test other things
24#
25
26# Default with latest kernels is 95, before micro account patches
27# it was 80, cmp. with git commit 808009131046b62ac434dbc796
28UP_THRESHOLD="60 80 95"
29# Depending on the kernel and the HW sampling rate could be restricted
30# and cannot be set that low...
31# E.g. before git commit cef9615a853ebc4972084f7 one could only set
32# min sampling rate of 80000 if CONFIG_HZ=250
33SAMPLING_RATE="20000 80000"
34
35function measure()
36{
37 local -i up_threshold_set
38 local -i sampling_rate_set
39
40 for up_threshold in $UP_THRESHOLD;do
41 for sampling_rate in $SAMPLING_RATE;do
42 # Set values in sysfs
43 echo $up_threshold >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold
44 echo $sampling_rate >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate
45 up_threshold_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold)
46 sampling_rate_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate)
47
48 # Verify set values in sysfs
49 if [ ${up_threshold_set} -eq ${up_threshold} ];then
50 echo "up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}"
51 else
52 echo "WARNING: Tried to set up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}"
53 fi
54 if [ ${sampling_rate_set} -eq ${sampling_rate} ];then
55 echo "sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}"
56 else
57 echo "WARNING: Tried to set sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}"
58 fi
59
60 # Benchmark
61 cpufreq-bench -o /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}
62 done
63 done
64}
65
66function create_plots()
67{
68 local command
69
70 for up_threshold in $UP_THRESHOLD;do
71 command="cpufreq-bench_plot.sh -o \"sampling_rate_${SAMPLING_RATE}_up_threshold_${up_threshold}\" -t \"Ondemand sampling_rate: ${SAMPLING_RATE} comparison - Up_threshold: $up_threshold %\""
72 for sampling_rate in $SAMPLING_RATE;do
73 command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"sampling_rate = $sampling_rate\""
74 done
75 echo $command
76 eval "$command"
77 echo
78 done
79
80 for sampling_rate in $SAMPLING_RATE;do
81 command="cpufreq-bench_plot.sh -o \"up_threshold_${UP_THRESHOLD}_sampling_rate_${sampling_rate}\" -t \"Ondemand up_threshold: ${UP_THRESHOLD} % comparison - sampling_rate: $sampling_rate\""
82 for up_threshold in $UP_THRESHOLD;do
83 command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold\""
84 done
85 echo $command
86 eval "$command"
87 echo
88 done
89
90 command="cpufreq-bench_plot.sh -o \"up_threshold_${UP_THRESHOLD}_sampling_rate_${SAMPLING_RATE}\" -t \"Ondemand up_threshold: ${UP_THRESHOLD} and sampling_rate ${SAMPLING_RATE} comparison\""
91 for sampling_rate in $SAMPLING_RATE;do
92 for up_threshold in $UP_THRESHOLD;do
93 command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold - sampling_rate = $sampling_rate\""
94 done
95 done
96 echo "$command"
97 eval "$command"
98}
99
100measure
101create_plots \ No newline at end of file
diff --git a/tools/power/cpupower/bench/example.cfg b/tools/power/cpupower/bench/example.cfg
new file mode 100644
index 000000000000..f91f64360688
--- /dev/null
+++ b/tools/power/cpupower/bench/example.cfg
@@ -0,0 +1,11 @@
1sleep = 50000
2load = 50000
3cpu = 0
4priority = LOW
5output = /var/log/cpufreq-bench
6sleep_step = 50000
7load_step = 50000
8cycles = 20
9rounds = 40
10verbose = 0
11governor = ondemand
diff --git a/tools/power/cpupower/bench/main.c b/tools/power/cpupower/bench/main.c
new file mode 100644
index 000000000000..24910313a521
--- /dev/null
+++ b/tools/power/cpupower/bench/main.c
@@ -0,0 +1,202 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24#include <getopt.h>
25#include <errno.h>
26
27#include "config.h"
28#include "system.h"
29#include "benchmark.h"
30
31static struct option long_options[] = {
32 {"output", 1, 0, 'o'},
33 {"sleep", 1, 0, 's'},
34 {"load", 1, 0, 'l'},
35 {"verbose", 0, 0, 'v'},
36 {"cpu", 1, 0, 'c'},
37 {"governor", 1, 0, 'g'},
38 {"prio", 1, 0, 'p'},
39 {"file", 1, 0, 'f'},
40 {"cycles", 1, 0, 'n'},
41 {"rounds", 1, 0, 'r'},
42 {"load-step", 1, 0, 'x'},
43 {"sleep-step", 1, 0, 'y'},
44 {"help", 0, 0, 'h'},
45 {0, 0, 0, 0}
46};
47
48/*******************************************************************
49 usage
50*******************************************************************/
51
52void usage()
53{
54 printf("usage: ./bench\n");
55 printf("Options:\n");
56 printf(" -l, --load=<long int>\t\tinitial load time in us\n");
57 printf(" -s, --sleep=<long int>\t\tinitial sleep time in us\n");
58 printf(" -x, --load-step=<long int>\ttime to be added to load time, in us\n");
59 printf(" -y, --sleep-step=<long int>\ttime to be added to sleep time, in us\n");
60 printf(" -c, --cpu=<cpu #>\t\t\tCPU Nr. to use, starting at 0\n");
61 printf(" -p, --prio=<priority>\t\t\tscheduler priority, HIGH, LOW or DEFAULT\n");
62 printf(" -g, --governor=<governor>\t\tcpufreq governor to test\n");
63 printf(" -n, --cycles=<int>\t\t\tload/sleep cycles\n");
64 printf(" -r, --rounds<int>\t\t\tload/sleep rounds\n");
65 printf(" -f, --file=<configfile>\t\tconfig file to use\n");
66 printf(" -o, --output=<dir>\t\t\toutput path. Filename will be OUTPUTPATH/benchmark_TIMESTAMP.log\n");
67 printf(" -v, --verbose\t\t\t\tverbose output on/off\n");
68 printf(" -h, --help\t\t\t\tPrint this help screen\n");
69 exit(1);
70}
71
72/*******************************************************************
73 main
74*******************************************************************/
75
76int main(int argc, char **argv)
77{
78 int c;
79 int option_index = 0;
80 struct config *config = NULL;
81
82 config = prepare_default_config();
83
84 if (config == NULL)
85 return EXIT_FAILURE;
86
87 while (1) {
88 c = getopt_long (argc, argv, "hg:o:s:l:vc:p:f:n:r:x:y:",
89 long_options, &option_index);
90 if (c == -1)
91 break;
92
93 switch (c) {
94 case 'o':
95 if (config->output != NULL)
96 fclose(config->output);
97
98 config->output = prepare_output(optarg);
99
100 if (config->output == NULL)
101 return EXIT_FAILURE;
102
103 dprintf("user output path -> %s\n", optarg);
104 break;
105 case 's':
106 sscanf(optarg, "%li", &config->sleep);
107 dprintf("user sleep time -> %s\n", optarg);
108 break;
109 case 'l':
110 sscanf(optarg, "%li", &config->load);
111 dprintf("user load time -> %s\n", optarg);
112 break;
113 case 'c':
114 sscanf(optarg, "%u", &config->cpu);
115 dprintf("user cpu -> %s\n", optarg);
116 break;
117 case 'g':
118 strncpy(config->governor, optarg, 14);
119 dprintf("user governor -> %s\n", optarg);
120 break;
121 case 'p':
122 if (string_to_prio(optarg) != SCHED_ERR) {
123 config->prio = string_to_prio(optarg);
124 dprintf("user prio -> %s\n", optarg);
125 } else {
126 if (config != NULL) {
127 if (config->output != NULL)
128 fclose(config->output);
129 free(config);
130 }
131 usage();
132 }
133 break;
134 case 'n':
135 sscanf(optarg, "%u", &config->cycles);
136 dprintf("user cycles -> %s\n", optarg);
137 break;
138 case 'r':
139 sscanf(optarg, "%u", &config->rounds);
140 dprintf("user rounds -> %s\n", optarg);
141 break;
142 case 'x':
143 sscanf(optarg, "%li", &config->load_step);
144 dprintf("user load_step -> %s\n", optarg);
145 break;
146 case 'y':
147 sscanf(optarg, "%li", &config->sleep_step);
148 dprintf("user sleep_step -> %s\n", optarg);
149 break;
150 case 'f':
151 if (prepare_config(optarg, config))
152 return EXIT_FAILURE;
153 break;
154 case 'v':
155 config->verbose = 1;
156 dprintf("verbose output enabled\n");
157 break;
158 case 'h':
159 case '?':
160 default:
161 if (config != NULL) {
162 if (config->output != NULL)
163 fclose(config->output);
164 free(config);
165 }
166 usage();
167 }
168 }
169
170 if (config->verbose) {
171 printf("starting benchmark with parameters:\n");
172 printf("config:\n\t"
173 "sleep=%li\n\t"
174 "load=%li\n\t"
175 "sleep_step=%li\n\t"
176 "load_step=%li\n\t"
177 "cpu=%u\n\t"
178 "cycles=%u\n\t"
179 "rounds=%u\n\t"
180 "governor=%s\n\n",
181 config->sleep,
182 config->load,
183 config->sleep_step,
184 config->load_step,
185 config->cpu,
186 config->cycles,
187 config->rounds,
188 config->governor);
189 }
190
191 prepare_user(config);
192 prepare_system(config);
193 start_benchmark(config);
194
195 if (config->output != stdout)
196 fclose(config->output);
197
198 free(config);
199
200 return EXIT_SUCCESS;
201}
202
diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c
new file mode 100644
index 000000000000..543bba14ae2c
--- /dev/null
+++ b/tools/power/cpupower/bench/parse.c
@@ -0,0 +1,225 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <stdarg.h>
23#include <string.h>
24#include <time.h>
25#include <dirent.h>
26
27#include <sys/utsname.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30
31#include "parse.h"
32#include "config.h"
33
34/**
35 * converts priority string to priority
36 *
37 * @param str string that represents a scheduler priority
38 *
39 * @retval priority
40 * @retval SCHED_ERR when the priority doesn't exit
41 **/
42
43enum sched_prio string_to_prio(const char *str)
44{
45 if (strncasecmp("high", str, strlen(str)) == 0)
46 return SCHED_HIGH;
47 else if (strncasecmp("default", str, strlen(str)) == 0)
48 return SCHED_DEFAULT;
49 else if (strncasecmp("low", str, strlen(str)) == 0)
50 return SCHED_LOW;
51 else
52 return SCHED_ERR;
53}
54
55/**
56 * create and open logfile
57 *
58 * @param dir directory in which the logfile should be created
59 *
60 * @retval logfile on success
61 * @retval NULL when the file can't be created
62 **/
63
64FILE *prepare_output(const char *dirname)
65{
66 FILE *output = NULL;
67 int len;
68 char *filename;
69 struct utsname sysdata;
70 DIR *dir;
71
72 dir = opendir(dirname);
73 if (dir == NULL) {
74 if (mkdir(dirname, 0755)) {
75 perror("mkdir");
76 fprintf(stderr, "error: Cannot create dir %s\n",
77 dirname);
78 return NULL;
79 }
80 }
81
82 len = strlen(dirname) + 30;
83 filename = malloc(sizeof(char) * len);
84
85 if (uname(&sysdata) == 0) {
86 len += strlen(sysdata.nodename) + strlen(sysdata.release);
87 filename = realloc(filename, sizeof(char) * len);
88
89 if (filename == NULL) {
90 perror("realloc");
91 return NULL;
92 }
93
94 snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log",
95 dirname, sysdata.nodename, sysdata.release, time(NULL));
96 } else {
97 snprintf(filename, len - 1, "%s/benchmark_%li.log",
98 dirname, time(NULL));
99 }
100
101 dprintf("logilename: %s\n", filename);
102
103 output = fopen(filename, "w+");
104 if (output == NULL) {
105 perror("fopen");
106 fprintf(stderr, "error: unable to open logfile\n");
107 }
108
109 fprintf(stdout, "Logfile: %s\n", filename);
110
111 free(filename);
112 fprintf(output, "#round load sleep performance powersave percentage\n");
113 return output;
114}
115
116/**
117 * returns the default config
118 *
119 * @retval default config on success
120 * @retval NULL when the output file can't be created
121 **/
122
123struct config *prepare_default_config()
124{
125 struct config *config = malloc(sizeof(struct config));
126
127 dprintf("loading defaults\n");
128
129 config->sleep = 500000;
130 config->load = 500000;
131 config->sleep_step = 500000;
132 config->load_step = 500000;
133 config->cycles = 5;
134 config->rounds = 50;
135 config->cpu = 0;
136 config->prio = SCHED_HIGH;
137 config->verbose = 0;
138 strncpy(config->governor, "ondemand", 8);
139
140 config->output = stdout;
141
142#ifdef DEFAULT_CONFIG_FILE
143 if (prepare_config(DEFAULT_CONFIG_FILE, config))
144 return NULL;
145#endif
146 return config;
147}
148
149/**
150 * parses config file and returns the config to the caller
151 *
152 * @param path config file name
153 *
154 * @retval 1 on error
155 * @retval 0 on success
156 **/
157
158int prepare_config(const char *path, struct config *config)
159{
160 size_t len = 0;
161 char *opt, *val, *line = NULL;
162 FILE *configfile = fopen(path, "r");
163
164 if (config == NULL) {
165 fprintf(stderr, "error: config is NULL\n");
166 return 1;
167 }
168
169 if (configfile == NULL) {
170 perror("fopen");
171 fprintf(stderr, "error: unable to read configfile\n");
172 free(config);
173 return 1;
174 }
175
176 while (getline(&line, &len, configfile) != -1) {
177 if (line[0] == '#' || line[0] == ' ')
178 continue;
179
180 sscanf(line, "%as = %as", &opt, &val);
181
182 dprintf("parsing: %s -> %s\n", opt, val);
183
184 if (strncmp("sleep", opt, strlen(opt)) == 0)
185 sscanf(val, "%li", &config->sleep);
186
187 else if (strncmp("load", opt, strlen(opt)) == 0)
188 sscanf(val, "%li", &config->load);
189
190 else if (strncmp("load_step", opt, strlen(opt)) == 0)
191 sscanf(val, "%li", &config->load_step);
192
193 else if (strncmp("sleep_step", opt, strlen(opt)) == 0)
194 sscanf(val, "%li", &config->sleep_step);
195
196 else if (strncmp("cycles", opt, strlen(opt)) == 0)
197 sscanf(val, "%u", &config->cycles);
198
199 else if (strncmp("rounds", opt, strlen(opt)) == 0)
200 sscanf(val, "%u", &config->rounds);
201
202 else if (strncmp("verbose", opt, strlen(opt)) == 0)
203 sscanf(val, "%u", &config->verbose);
204
205 else if (strncmp("output", opt, strlen(opt)) == 0)
206 config->output = prepare_output(val);
207
208 else if (strncmp("cpu", opt, strlen(opt)) == 0)
209 sscanf(val, "%u", &config->cpu);
210
211 else if (strncmp("governor", opt, 14) == 0)
212 strncpy(config->governor, val, 14);
213
214 else if (strncmp("priority", opt, strlen(opt)) == 0) {
215 if (string_to_prio(val) != SCHED_ERR)
216 config->prio = string_to_prio(val);
217 }
218 }
219
220 free(line);
221 free(opt);
222 free(val);
223
224 return 0;
225}
diff --git a/tools/power/cpupower/bench/parse.h b/tools/power/cpupower/bench/parse.h
new file mode 100644
index 000000000000..a8dc632d9eee
--- /dev/null
+++ b/tools/power/cpupower/bench/parse.h
@@ -0,0 +1,53 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20/* struct that holds the required config parameters */
21struct config
22{
23 long sleep; /* sleep time in µs */
24 long load; /* load time in µs */
25 long sleep_step; /* time value which changes the
26 * sleep time after every round in µs */
27 long load_step; /* time value which changes the
28 * load time after every round in µs */
29 unsigned int cycles; /* calculation cycles with the same sleep/load time */
30 unsigned int rounds; /* calculation rounds with iterated sleep/load time */
31 unsigned int cpu; /* cpu for which the affinity is set */
32 char governor[15]; /* cpufreq governor */
33 enum sched_prio /* possible scheduler priorities */
34 {
35 SCHED_ERR = -1,
36 SCHED_HIGH,
37 SCHED_DEFAULT,
38 SCHED_LOW
39 } prio;
40
41 unsigned int verbose; /* verbose output */
42 FILE *output; /* logfile */
43 char *output_filename; /* logfile name, must be freed at the end
44 if output != NULL and output != stdout*/
45};
46
47enum sched_prio string_to_prio(const char *str);
48
49FILE *prepare_output(const char *dir);
50
51int prepare_config(const char *path, struct config *config);
52struct config *prepare_default_config();
53
diff --git a/tools/power/cpupower/bench/system.c b/tools/power/cpupower/bench/system.c
new file mode 100644
index 000000000000..f01e3f4be84c
--- /dev/null
+++ b/tools/power/cpupower/bench/system.c
@@ -0,0 +1,191 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <stdio.h>
21#include <time.h>
22#include <sys/time.h>
23#include <sys/types.h>
24#include <unistd.h>
25
26#include <sched.h>
27
28#include <cpufreq.h>
29
30#include "config.h"
31#include "system.h"
32
33/**
34 * returns time since epoch in µs
35 *
36 * @retval time
37 **/
38
39long long int get_time()
40{
41 struct timeval now;
42
43 gettimeofday(&now, NULL);
44
45 return (long long int)(now.tv_sec * 1000000LL + now.tv_usec);
46}
47
48/**
49 * sets the cpufreq governor
50 *
51 * @param governor cpufreq governor name
52 * @param cpu cpu for which the governor should be set
53 *
54 * @retval 0 on success
55 * @retval -1 when failed
56 **/
57
58int set_cpufreq_governor(char *governor, unsigned int cpu)
59{
60
61 dprintf("set %s as cpufreq governor\n", governor);
62
63 if (cpufreq_cpu_exists(cpu) != 0) {
64 perror("cpufreq_cpu_exists");
65 fprintf(stderr, "error: cpu %u does not exist\n", cpu);
66 return -1;
67 }
68
69 if (cpufreq_modify_policy_governor(cpu, governor) != 0) {
70 perror("cpufreq_modify_policy_governor");
71 fprintf(stderr, "error: unable to set %s governor\n", governor);
72 return -1;
73 }
74
75 return 0;
76}
77
78/**
79 * sets cpu affinity for the process
80 *
81 * @param cpu cpu# to which the affinity should be set
82 *
83 * @retval 0 on success
84 * @retval -1 when setting the affinity failed
85 **/
86
87int set_cpu_affinity(unsigned int cpu)
88{
89 cpu_set_t cpuset;
90
91 CPU_ZERO(&cpuset);
92 CPU_SET(cpu, &cpuset);
93
94 dprintf("set affinity to cpu #%u\n", cpu);
95
96 if (sched_setaffinity(getpid(), sizeof(cpu_set_t), &cpuset) < 0) {
97 perror("sched_setaffinity");
98 fprintf(stderr, "warning: unable to set cpu affinity\n");
99 return -1;
100 }
101
102 return 0;
103}
104
105/**
106 * sets the process priority parameter
107 *
108 * @param priority priority value
109 *
110 * @retval 0 on success
111 * @retval -1 when setting the priority failed
112 **/
113
114int set_process_priority(int priority)
115{
116 struct sched_param param;
117
118 dprintf("set scheduler priority to %i\n", priority);
119
120 param.sched_priority = priority;
121
122 if (sched_setscheduler(0, SCHEDULER, &param) < 0) {
123 perror("sched_setscheduler");
124 fprintf(stderr, "warning: unable to set scheduler priority\n");
125 return -1;
126 }
127
128 return 0;
129}
130
131/**
132 * notifies the user that the benchmark may run some time
133 *
134 * @param config benchmark config values
135 *
136 **/
137
138void prepare_user(const struct config *config)
139{
140 unsigned long sleep_time = 0;
141 unsigned long load_time = 0;
142 unsigned int round;
143
144 for (round = 0; round < config->rounds; round++) {
145 sleep_time += 2 * config->cycles *
146 (config->sleep + config->sleep_step * round);
147 load_time += 2 * config->cycles *
148 (config->load + config->load_step * round) +
149 (config->load + config->load_step * round * 4);
150 }
151
152 if (config->verbose || config->output != stdout)
153 printf("approx. test duration: %im\n",
154 (int)((sleep_time + load_time) / 60000000));
155}
156
157/**
158 * sets up the cpu affinity and scheduler priority
159 *
160 * @param config benchmark config values
161 *
162 **/
163
164void prepare_system(const struct config *config)
165{
166 if (config->verbose)
167 printf("set cpu affinity to cpu #%u\n", config->cpu);
168
169 set_cpu_affinity(config->cpu);
170
171 switch (config->prio) {
172 case SCHED_HIGH:
173 if (config->verbose)
174 printf("high priority condition requested\n");
175
176 set_process_priority(PRIORITY_HIGH);
177 break;
178 case SCHED_LOW:
179 if (config->verbose)
180 printf("low priority condition requested\n");
181
182 set_process_priority(PRIORITY_LOW);
183 break;
184 default:
185 if (config->verbose)
186 printf("default priority condition requested\n");
187
188 set_process_priority(PRIORITY_DEFAULT);
189 }
190}
191
diff --git a/tools/power/cpupower/bench/system.h b/tools/power/cpupower/bench/system.h
new file mode 100644
index 000000000000..3a8c858b78f0
--- /dev/null
+++ b/tools/power/cpupower/bench/system.h
@@ -0,0 +1,29 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include "parse.h"
21
22long long get_time();
23
24int set_cpufreq_governor(char *governor, unsigned int cpu);
25int set_cpu_affinity(unsigned int cpu);
26int set_process_priority(int priority);
27
28void prepare_user(const struct config *config);
29void prepare_system(const struct config *config);
diff --git a/tools/power/cpupower/debug/i386/Makefile b/tools/power/cpupower/debug/i386/Makefile
new file mode 100644
index 000000000000..d08cc1ead9bc
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/Makefile
@@ -0,0 +1,20 @@
1default: all
2
3centrino-decode: centrino-decode.c
4 $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c
5
6dump_psb: dump_psb.c
7 $(CC) $(CFLAGS) -o dump_psb dump_psb.c
8
9intel_gsic: intel_gsic.c
10 $(CC) $(CFLAGS) -o intel_gsic -llrmi intel_gsic.c
11
12powernow-k8-decode: powernow-k8-decode.c
13 $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c
14
15all: centrino-decode dump_psb intel_gsic powernow-k8-decode
16
17clean:
18 rm -rf centrino-decode dump_psb intel_gsic powernow-k8-decode
19
20.PHONY: all default clean
diff --git a/tools/power/cpupower/debug/i386/centrino-decode.c b/tools/power/cpupower/debug/i386/centrino-decode.c
new file mode 100644
index 000000000000..7ef24cce4926
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/centrino-decode.c
@@ -0,0 +1,113 @@
1/*
2 * (C) 2003 - 2004 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on code found in
7 * linux/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
8 * and originally developed by Jeremy Fitzhardinge.
9 *
10 * USAGE: simply run it to decode the current settings on CPU 0,
11 * or pass the CPU number as argument, or pass the MSR content
12 * as argument.
13 */
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <stdint.h>
18#include <unistd.h>
19#include <errno.h>
20#include <fcntl.h>
21
22#include <sys/types.h>
23#include <sys/stat.h>
24
25#define MCPU 32
26
27#define MSR_IA32_PERF_STATUS 0x198
28
29static int rdmsr(unsigned int cpu, unsigned int msr,
30 unsigned int *lo, unsigned int *hi)
31{
32 int fd;
33 char file[20];
34 unsigned long long val;
35 int retval = -1;
36
37 *lo = *hi = 0;
38
39 if (cpu > MCPU)
40 goto err1;
41
42 sprintf(file, "/dev/cpu/%d/msr", cpu);
43 fd = open(file, O_RDONLY);
44
45 if (fd < 0)
46 goto err1;
47
48 if (lseek(fd, msr, SEEK_CUR) == -1)
49 goto err2;
50
51 if (read(fd, &val, 8) != 8)
52 goto err2;
53
54 *lo = (uint32_t )(val & 0xffffffffull);
55 *hi = (uint32_t )(val>>32 & 0xffffffffull);
56
57 retval = 0;
58err2:
59 close(fd);
60err1:
61 return retval;
62}
63
64static void decode (unsigned int msr)
65{
66 unsigned int multiplier;
67 unsigned int mv;
68
69 multiplier = ((msr >> 8) & 0xFF);
70
71 mv = (((msr & 0xFF) * 16) + 700);
72
73 printf("0x%x means multiplier %d @ %d mV\n", msr, multiplier, mv);
74}
75
76static int decode_live(unsigned int cpu)
77{
78 unsigned int lo, hi;
79 int err;
80
81 err = rdmsr(cpu, MSR_IA32_PERF_STATUS, &lo, &hi);
82
83 if (err) {
84 printf("can't get MSR_IA32_PERF_STATUS for cpu %d\n", cpu);
85 printf("Possible trouble: you don't run an Enhanced SpeedStep capable cpu\n");
86 printf("or you are not root, or the msr driver is not present\n");
87 return 1;
88 }
89
90 decode(lo);
91
92 return 0;
93}
94
95int main (int argc, char **argv)
96{
97 unsigned int cpu, mode = 0;
98
99 if (argc < 2)
100 cpu = 0;
101 else {
102 cpu = strtoul(argv[1], NULL, 0);
103 if (cpu >= MCPU)
104 mode = 1;
105 }
106
107 if (mode)
108 decode(cpu);
109 else
110 decode_live(cpu);
111
112 return 0;
113}
diff --git a/tools/power/cpupower/debug/i386/dump_psb.c b/tools/power/cpupower/debug/i386/dump_psb.c
new file mode 100644
index 000000000000..8d6a47514253
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/dump_psb.c
@@ -0,0 +1,196 @@
1/*
2 * dump_psb. (c) 2004, Dave Jones, Red Hat Inc.
3 * Licensed under the GPL v2.
4 */
5
6#include <fcntl.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11
12#define _GNU_SOURCE
13#include <getopt.h>
14
15#include <sys/mman.h>
16
17#define LEN (0x100000 - 0xc0000)
18#define OFFSET (0xc0000)
19
20#ifndef __packed
21#define __packed __attribute((packed))
22#endif
23
24static long relevant;
25
26static const int fid_to_mult[32] = {
27 110, 115, 120, 125, 50, 55, 60, 65,
28 70, 75, 80, 85, 90, 95, 100, 105,
29 30, 190, 40, 200, 130, 135, 140, 210,
30 150, 225, 160, 165, 170, 180, -1, -1,
31};
32
33static const int vid_to_voltage[32] = {
34 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
35 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
36 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
37 1075, 1050, 1024, 1000, 975, 950, 925, 0,
38};
39
40struct psb_header {
41 char signature[10];
42 u_char version;
43 u_char flags;
44 u_short settlingtime;
45 u_char res1;
46 u_char numpst;
47} __packed;
48
49struct pst_header {
50 u_int32_t cpuid;
51 u_char fsb;
52 u_char maxfid;
53 u_char startvid;
54 u_char numpstates;
55} __packed;
56
57static u_int fsb;
58static u_int sgtc;
59
60static int
61decode_pst(char *p, int npstates)
62{
63 int i;
64 int freq, fid, vid;
65
66 for (i = 0; i < npstates; ++i) {
67 fid = *p++;
68 vid = *p++;
69 freq = 100 * fid_to_mult[fid] * fsb;
70
71 printf(" %2d %8dkHz FID %02x (%2d.%01d) VID %02x (%4dmV)\n",
72 i,
73 freq,
74 fid, fid_to_mult[fid]/10, fid_to_mult[fid]%10,
75 vid, vid_to_voltage[vid]);
76 }
77
78 return 0;
79}
80
81static
82void decode_psb(char *p, int numpst)
83{
84 int i;
85 struct psb_header *psb;
86 struct pst_header *pst;
87
88 psb = (struct psb_header*) p;
89
90 if (psb->version != 0x12)
91 return;
92
93 printf("PSB version: %hhx flags: %hhx settling time %hhuus res1 %hhx num pst %hhu\n",
94 psb->version,
95 psb->flags,
96 psb->settlingtime,
97 psb->res1,
98 psb->numpst);
99 sgtc = psb->settlingtime * 100;
100
101 if (sgtc < 10000)
102 sgtc = 10000;
103
104 p = ((char *) psb) + sizeof(struct psb_header);
105
106 if (numpst < 0)
107 numpst = psb->numpst;
108 else
109 printf("Overriding number of pst :%d\n", numpst);
110
111 for (i = 0; i < numpst; i++) {
112 pst = (struct pst_header*) p;
113
114 if (relevant != 0) {
115 if (relevant!= pst->cpuid)
116 goto next_one;
117 }
118
119 printf(" PST %d cpuid %.3x fsb %hhu mfid %hhx svid %hhx numberstates %hhu\n",
120 i+1,
121 pst->cpuid,
122 pst->fsb,
123 pst->maxfid,
124 pst->startvid,
125 pst->numpstates);
126
127 fsb = pst->fsb;
128 decode_pst(p + sizeof(struct pst_header), pst->numpstates);
129
130next_one:
131 p += sizeof(struct pst_header) + 2*pst->numpstates;
132 }
133
134}
135
136static struct option info_opts[] = {
137 {.name = "numpst", .has_arg=no_argument, .flag=NULL, .val='n'},
138};
139
140void print_help(void)
141{
142 printf ("Usage: dump_psb [options]\n");
143 printf ("Options:\n");
144 printf (" -n, --numpst Set number of PST tables to scan\n");
145 printf (" -r, --relevant Only display PSTs relevant to cpuid N\n");
146}
147
148int
149main(int argc, char *argv[])
150{
151 int fd;
152 int numpst=-1;
153 int ret=0, cont=1;
154 char *mem = NULL;
155 char *p;
156
157 do {
158 ret = getopt_long(argc, argv, "hr:n:", info_opts, NULL);
159 switch (ret){
160 case '?':
161 case 'h':
162 print_help();
163 cont = 0;
164 break;
165 case 'r':
166 relevant = strtol(optarg, NULL, 16);
167 break;
168 case 'n':
169 numpst = strtol(optarg, NULL, 10);
170 break;
171 case -1:
172 cont = 0;
173 break;
174 }
175
176 } while(cont);
177
178 fd = open("/dev/mem", O_RDONLY);
179 if (fd < 0) {
180 printf ("Couldn't open /dev/mem. Are you root?\n");
181 exit(1);
182 }
183
184 mem = mmap(mem, 0x100000 - 0xc0000, PROT_READ, MAP_SHARED, fd, 0xc0000);
185 close(fd);
186
187 for (p = mem; p - mem < LEN; p+=16) {
188 if (memcmp(p, "AMDK7PNOW!", 10) == 0) {
189 decode_psb(p, numpst);
190 break;
191 }
192 }
193
194 munmap(mem, LEN);
195 return 0;
196}
diff --git a/tools/power/cpupower/debug/i386/intel_gsic.c b/tools/power/cpupower/debug/i386/intel_gsic.c
new file mode 100644
index 000000000000..53f5293c9c9a
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/intel_gsic.c
@@ -0,0 +1,78 @@
1/*
2 * (C) 2003 Bruno Ducrot
3 * (C) 2004 Dominik Brodowski <linux@dominikbrodowski.de>
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 *
7 * Based on code found in
8 * linux/include/asm-i386/ist.h and linux/arch/i386/kernel/setup.c
9 * and originally developed by Andy Grover <andrew.grover@intel.com>
10 */
11
12#include <stdio.h>
13#include <string.h>
14#include <lrmi.h>
15
16int main (void)
17{
18 struct LRMI_regs r;
19 int retval;
20
21 if (!LRMI_init())
22 return 0;
23
24 memset(&r, 0, sizeof(r));
25
26 r.eax = 0x0000E980;
27 r.edx = 0x47534943;
28
29 retval = LRMI_int(0x15, &r);
30
31 if (!retval) {
32 printf("Failed!\n");
33 return 0;
34 }
35 if (r.eax == 0x47534943) {
36 printf("BIOS supports GSIC call:\n");
37 printf("\tsignature: %c%c%c%c\n",
38 (r.eax >> 24) & 0xff,
39 (r.eax >> 16) & 0xff,
40 (r.eax >> 8) & 0xff,
41 (r.eax) & 0xff);
42 printf("\tcommand port = 0x%.4x\n",
43 r.ebx & 0xffff);
44 printf("\tcommand = 0x%.4x\n",
45 (r.ebx >> 16) & 0xffff);
46 printf("\tevent port = 0x%.8x\n", r.ecx);
47 printf("\tflags = 0x%.8x\n", r.edx);
48 if (((r.ebx >> 16) & 0xffff) != 0x82) {
49 printf("non-default command value. If speedstep-smi "
50 "doesn't work out of the box,\nyou may want to "
51 "try out the default value by passing "
52 "smi_cmd=0x82 to the module\n ON YOUR OWN "
53 "RISK.\n");
54 }
55 if ((r.ebx & 0xffff) != 0xb2) {
56 printf("non-default command port. If speedstep-smi "
57 "doesn't work out of the box,\nyou may want to "
58 "try out the default value by passing "
59 "smi_port=0x82 to the module\n ON YOUR OWN "
60 "RISK.\n");
61 }
62 } else {
63 printf("BIOS DOES NOT support GSIC call. Dumping registers anyway:\n");
64 printf("eax = 0x%.8x\n", r.eax);
65 printf("ebx = 0x%.8x\n", r.ebx);
66 printf("ecx = 0x%.8x\n", r.ecx);
67 printf("edx = 0x%.8x\n", r.edx);
68 printf("Note also that some BIOS do not support the initial "
69 "GSIC call, but the newer\nspeeedstep-smi driver may "
70 "work.\nFor this, you need to pass some arguments to "
71 "the speedstep-smi driver:\n");
72 printf("\tsmi_cmd=0x?? smi_port=0x?? smi_sig=1\n");
73 printf("\nUnfortunately, you have to know what exactly are "
74 "smi_cmd and smi_port, and this\nis system "
75 "dependant.\n");
76 }
77 return 1;
78}
diff --git a/tools/power/cpupower/debug/i386/powernow-k8-decode.c b/tools/power/cpupower/debug/i386/powernow-k8-decode.c
new file mode 100644
index 000000000000..638a6b3bfd97
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/powernow-k8-decode.c
@@ -0,0 +1,96 @@
1/*
2 * (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on code found in
7 * linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
8 * and originally developed by Paul Devriendt
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <stdint.h>
14#include <unistd.h>
15#include <errno.h>
16#include <fcntl.h>
17
18#include <sys/types.h>
19#include <sys/stat.h>
20
21#define MCPU 32
22
23#define MSR_FIDVID_STATUS 0xc0010042
24
25#define MSR_S_HI_CURRENT_VID 0x0000001f
26#define MSR_S_LO_CURRENT_FID 0x0000003f
27
28static int get_fidvid(uint32_t cpu, uint32_t *fid, uint32_t *vid)
29{
30 int err = 1;
31 uint64_t msr = 0;
32 int fd;
33 char file[20];
34
35 if (cpu > MCPU)
36 goto out;
37
38 sprintf(file, "/dev/cpu/%d/msr", cpu);
39
40 fd = open(file, O_RDONLY);
41 if (fd < 0)
42 goto out;
43 lseek(fd, MSR_FIDVID_STATUS, SEEK_CUR);
44 if (read(fd, &msr, 8) != 8)
45 goto err1;
46
47 *fid = ((uint32_t )(msr & 0xffffffffull)) & MSR_S_LO_CURRENT_FID;
48 *vid = ((uint32_t )(msr>>32 & 0xffffffffull)) & MSR_S_HI_CURRENT_VID;
49 err = 0;
50err1:
51 close(fd);
52out:
53 return err;
54}
55
56
57/* Return a frequency in MHz, given an input fid */
58static uint32_t find_freq_from_fid(uint32_t fid)
59{
60 return 800 + (fid * 100);
61}
62
63/* Return a voltage in miliVolts, given an input vid */
64static uint32_t find_millivolts_from_vid(uint32_t vid)
65{
66 return 1550-vid*25;
67}
68
69int main (int argc, char *argv[])
70{
71 int err;
72 int cpu;
73 uint32_t fid, vid;
74
75 if (argc < 2)
76 cpu = 0;
77 else
78 cpu = strtoul(argv[1], NULL, 0);
79
80 err = get_fidvid(cpu, &fid, &vid);
81
82 if (err) {
83 printf("can't get fid, vid from MSR\n");
84 printf("Possible trouble: you don't run a powernow-k8 capable cpu\n");
85 printf("or you are not root, or the msr driver is not present\n");
86 exit(1);
87 }
88
89
90 printf("cpu %d currently at %d MHz and %d mV\n",
91 cpu,
92 find_freq_from_fid(fid),
93 find_millivolts_from_vid(vid));
94
95 return 0;
96}
diff --git a/tools/power/cpupower/debug/kernel/Makefile b/tools/power/cpupower/debug/kernel/Makefile
new file mode 100644
index 000000000000..96b146fe6f8d
--- /dev/null
+++ b/tools/power/cpupower/debug/kernel/Makefile
@@ -0,0 +1,23 @@
1obj-m :=
2
3KDIR := /lib/modules/$(shell uname -r)/build
4PWD := $(shell pwd)
5KMISC := /lib/modules/$(shell uname -r)/cpufrequtils/
6
7ifeq ("$(CONFIG_X86_TSC)", "y")
8 obj-m += cpufreq-test_tsc.o
9endif
10
11default:
12 $(MAKE) -C $(KDIR) M=$(PWD)
13
14clean:
15 - rm -rf *.o *.ko .tmp-versions .*.cmd .*.mod.* *.mod.c
16 - rm -rf .tmp_versions* Module.symvers modules.order
17
18install: default
19 install -d $(KMISC)
20 install -m 644 -c *.ko $(KMISC)
21 /sbin/depmod -a
22
23all: default
diff --git a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c
new file mode 100644
index 000000000000..66cace601e57
--- /dev/null
+++ b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c
@@ -0,0 +1,113 @@
1/*
2 * test module to check whether the TSC-based delay routine continues
3 * to work properly after cpufreq transitions. Needs ACPI to work
4 * properly.
5 *
6 * Based partly on the Power Management Timer (PMTMR) code to be found
7 * in arch/i386/kernel/timers/timer_pm.c on recent 2.6. kernels, especially
8 * code written by John Stultz. The read_pmtmr function was copied verbatim
9 * from that file.
10 *
11 * (C) 2004 Dominik Brodowski
12 *
13 * To use:
14 * 1.) pass clock=tsc to the kernel on your bootloader
15 * 2.) modprobe this module (it'll fail)
16 * 3.) change CPU frequency
17 * 4.) modprobe this module again
18 * 5.) if the third value, "diff_pmtmr", changes between 2. and 4., the
19 * TSC-based delay routine on the Linux kernel does not correctly
20 * handle the cpufreq transition. Please report this to
21 * cpufreq@vger.kernel.org
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28
29#include <asm/io.h>
30
31#include <acpi/acpi_bus.h>
32#include <acpi/acpi_drivers.h>
33
34static int pm_tmr_ioport = 0;
35
36/*helper function to safely read acpi pm timesource*/
37static u32 read_pmtmr(void)
38{
39 u32 v1=0,v2=0,v3=0;
40 /* It has been reported that because of various broken
41 * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
42 * source is not latched, so you must read it multiple
43 * times to insure a safe value is read.
44 */
45 do {
46 v1 = inl(pm_tmr_ioport);
47 v2 = inl(pm_tmr_ioport);
48 v3 = inl(pm_tmr_ioport);
49 } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
50 || (v3 > v1 && v3 < v2));
51
52 /* mask the output to 24 bits */
53 return (v2 & 0xFFFFFF);
54}
55
56static int __init cpufreq_test_tsc(void)
57{
58 u32 now, then, diff;
59 u64 now_tsc, then_tsc, diff_tsc;
60 int i;
61
62 /* the following code snipped is copied from arch/x86/kernel/acpi/boot.c
63 of Linux v2.6.25. */
64
65 /* detect the location of the ACPI PM Timer */
66 if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) {
67 /* FADT rev. 2 */
68 if (acpi_gbl_FADT.xpm_timer_block.space_id !=
69 ACPI_ADR_SPACE_SYSTEM_IO)
70 return 0;
71
72 pm_tmr_ioport = acpi_gbl_FADT.xpm_timer_block.address;
73 /*
74 * "X" fields are optional extensions to the original V1.0
75 * fields, so we must selectively expand V1.0 fields if the
76 * corresponding X field is zero.
77 */
78 if (!pm_tmr_ioport)
79 pm_tmr_ioport = acpi_gbl_FADT.pm_timer_block;
80 } else {
81 /* FADT rev. 1 */
82 pm_tmr_ioport = acpi_gbl_FADT.pm_timer_block;
83 }
84
85 printk(KERN_DEBUG "start--> \n");
86 then = read_pmtmr();
87 rdtscll(then_tsc);
88 for (i=0;i<20;i++) {
89 mdelay(100);
90 now = read_pmtmr();
91 rdtscll(now_tsc);
92 diff = (now - then) & 0xFFFFFF;
93 diff_tsc = now_tsc - then_tsc;
94 printk(KERN_DEBUG "t1: %08u t2: %08u diff_pmtmr: %08u diff_tsc: %016llu\n", then, now, diff, diff_tsc);
95 then = now;
96 then_tsc = now_tsc;
97 }
98 printk(KERN_DEBUG "<-- end \n");
99 return -ENODEV;
100}
101
102static void __exit cpufreq_none(void)
103{
104 return;
105}
106
107module_init(cpufreq_test_tsc)
108module_exit(cpufreq_none)
109
110
111MODULE_AUTHOR("Dominik Brodowski");
112MODULE_DESCRIPTION("Verify the TSC cpufreq notifier working correctly -- needs ACPI-enabled system");
113MODULE_LICENSE ("GPL");
diff --git a/tools/power/cpupower/debug/x86_64/Makefile b/tools/power/cpupower/debug/x86_64/Makefile
new file mode 100644
index 000000000000..3326217dd311
--- /dev/null
+++ b/tools/power/cpupower/debug/x86_64/Makefile
@@ -0,0 +1,14 @@
1default: all
2
3centrino-decode: ../i386/centrino-decode.c
4 $(CC) $(CFLAGS) -o $@ $<
5
6powernow-k8-decode: ../i386/powernow-k8-decode.c
7 $(CC) $(CFLAGS) -o $@ $<
8
9all: centrino-decode powernow-k8-decode
10
11clean:
12 rm -rf centrino-decode powernow-k8-decode
13
14.PHONY: all default clean
diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
new file mode 100644
index 000000000000..d961101d1cea
--- /dev/null
+++ b/tools/power/cpupower/lib/cpufreq.c
@@ -0,0 +1,208 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <stdio.h>
9#include <errno.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include "cpufreq.h"
14#include "sysfs.h"
15
16int cpufreq_cpu_exists(unsigned int cpu)
17{
18 return sysfs_cpu_exists(cpu);
19}
20
21unsigned long cpufreq_get_freq_kernel(unsigned int cpu)
22{
23 return sysfs_get_freq_kernel(cpu);
24}
25
26unsigned long cpufreq_get_freq_hardware(unsigned int cpu)
27{
28 return sysfs_get_freq_hardware(cpu);
29}
30
31unsigned long cpufreq_get_transition_latency(unsigned int cpu)
32{
33 return sysfs_get_freq_transition_latency(cpu);
34}
35
36int cpufreq_get_hardware_limits(unsigned int cpu,
37 unsigned long *min,
38 unsigned long *max)
39{
40 if ((!min) || (!max))
41 return -EINVAL;
42 return sysfs_get_freq_hardware_limits(cpu, min, max);
43}
44
45char *cpufreq_get_driver(unsigned int cpu)
46{
47 return sysfs_get_freq_driver(cpu);
48}
49
50void cpufreq_put_driver(char *ptr)
51{
52 if (!ptr)
53 return;
54 free(ptr);
55}
56
57struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu)
58{
59 return sysfs_get_freq_policy(cpu);
60}
61
62void cpufreq_put_policy(struct cpufreq_policy *policy)
63{
64 if ((!policy) || (!policy->governor))
65 return;
66
67 free(policy->governor);
68 policy->governor = NULL;
69 free(policy);
70}
71
72struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned
73 int cpu)
74{
75 return sysfs_get_freq_available_governors(cpu);
76}
77
78void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
79{
80 struct cpufreq_available_governors *tmp, *next;
81
82 if (!any)
83 return;
84
85 tmp = any->first;
86 while (tmp) {
87 next = tmp->next;
88 if (tmp->governor)
89 free(tmp->governor);
90 free(tmp);
91 tmp = next;
92 }
93}
94
95
96struct cpufreq_available_frequencies
97*cpufreq_get_available_frequencies(unsigned int cpu)
98{
99 return sysfs_get_available_frequencies(cpu);
100}
101
102void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies
103 *any) {
104 struct cpufreq_available_frequencies *tmp, *next;
105
106 if (!any)
107 return;
108
109 tmp = any->first;
110 while (tmp) {
111 next = tmp->next;
112 free(tmp);
113 tmp = next;
114 }
115}
116
117
118struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu)
119{
120 return sysfs_get_freq_affected_cpus(cpu);
121}
122
123void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
124{
125 struct cpufreq_affected_cpus *tmp, *next;
126
127 if (!any)
128 return;
129
130 tmp = any->first;
131 while (tmp) {
132 next = tmp->next;
133 free(tmp);
134 tmp = next;
135 }
136}
137
138
139struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu)
140{
141 return sysfs_get_freq_related_cpus(cpu);
142}
143
144void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
145{
146 cpufreq_put_affected_cpus(any);
147}
148
149
150int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
151{
152 if (!policy || !(policy->governor))
153 return -EINVAL;
154
155 return sysfs_set_freq_policy(cpu, policy);
156}
157
158
159int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq)
160{
161 return sysfs_modify_freq_policy_min(cpu, min_freq);
162}
163
164
165int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq)
166{
167 return sysfs_modify_freq_policy_max(cpu, max_freq);
168}
169
170
171int cpufreq_modify_policy_governor(unsigned int cpu, char *governor)
172{
173 if ((!governor) || (strlen(governor) > 19))
174 return -EINVAL;
175
176 return sysfs_modify_freq_policy_governor(cpu, governor);
177}
178
179int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency)
180{
181 return sysfs_set_frequency(cpu, target_frequency);
182}
183
184struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
185 unsigned long long *total_time)
186{
187 return sysfs_get_freq_stats(cpu, total_time);
188}
189
190void cpufreq_put_stats(struct cpufreq_stats *any)
191{
192 struct cpufreq_stats *tmp, *next;
193
194 if (!any)
195 return;
196
197 tmp = any->first;
198 while (tmp) {
199 next = tmp->next;
200 free(tmp);
201 tmp = next;
202 }
203}
204
205unsigned long cpufreq_get_transitions(unsigned int cpu)
206{
207 return sysfs_get_freq_transitions(cpu);
208}
diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
new file mode 100644
index 000000000000..3aae8e7a0839
--- /dev/null
+++ b/tools/power/cpupower/lib/cpufreq.h
@@ -0,0 +1,223 @@
1/*
2 * cpufreq.h - definitions for libcpufreq
3 *
4 * Copyright (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef _CPUFREQ_H
21#define _CPUFREQ_H 1
22
23struct cpufreq_policy {
24 unsigned long min;
25 unsigned long max;
26 char *governor;
27};
28
29struct cpufreq_available_governors {
30 char *governor;
31 struct cpufreq_available_governors *next;
32 struct cpufreq_available_governors *first;
33};
34
35struct cpufreq_available_frequencies {
36 unsigned long frequency;
37 struct cpufreq_available_frequencies *next;
38 struct cpufreq_available_frequencies *first;
39};
40
41
42struct cpufreq_affected_cpus {
43 unsigned int cpu;
44 struct cpufreq_affected_cpus *next;
45 struct cpufreq_affected_cpus *first;
46};
47
48struct cpufreq_stats {
49 unsigned long frequency;
50 unsigned long long time_in_state;
51 struct cpufreq_stats *next;
52 struct cpufreq_stats *first;
53};
54
55
56
57#ifdef __cplusplus
58extern "C" {
59#endif
60
61/*
62 * returns 0 if the specified CPU is present (it doesn't say
63 * whether it is online!), and an error value if not.
64 */
65
66extern int cpufreq_cpu_exists(unsigned int cpu);
67
68/* determine current CPU frequency
69 * - _kernel variant means kernel's opinion of CPU frequency
70 * - _hardware variant means actual hardware CPU frequency,
71 * which is only available to root.
72 *
73 * returns 0 on failure, else frequency in kHz.
74 */
75
76extern unsigned long cpufreq_get_freq_kernel(unsigned int cpu);
77
78extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
79
80#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu);
81
82
83/* determine CPU transition latency
84 *
85 * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds
86 */
87extern unsigned long cpufreq_get_transition_latency(unsigned int cpu);
88
89
90/* determine hardware CPU frequency limits
91 *
92 * These may be limited further by thermal, energy or other
93 * considerations by cpufreq policy notifiers in the kernel.
94 */
95
96extern int cpufreq_get_hardware_limits(unsigned int cpu,
97 unsigned long *min,
98 unsigned long *max);
99
100
101/* determine CPUfreq driver used
102 *
103 * Remember to call cpufreq_put_driver when no longer needed
104 * to avoid memory leakage, please.
105 */
106
107extern char *cpufreq_get_driver(unsigned int cpu);
108
109extern void cpufreq_put_driver(char *ptr);
110
111
112/* determine CPUfreq policy currently used
113 *
114 * Remember to call cpufreq_put_policy when no longer needed
115 * to avoid memory leakage, please.
116 */
117
118
119extern struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu);
120
121extern void cpufreq_put_policy(struct cpufreq_policy *policy);
122
123
124/* determine CPUfreq governors currently available
125 *
126 * may be modified by modprobe'ing or rmmod'ing other governors. Please
127 * free allocated memory by calling cpufreq_put_available_governors
128 * after use.
129 */
130
131
132extern struct cpufreq_available_governors
133*cpufreq_get_available_governors(unsigned int cpu);
134
135extern void cpufreq_put_available_governors(
136 struct cpufreq_available_governors *first);
137
138
139/* determine CPU frequency states available
140 *
141 * Only present on _some_ ->target() cpufreq drivers. For information purposes
142 * only. Please free allocated memory by calling
143 * cpufreq_put_available_frequencies after use.
144 */
145
146extern struct cpufreq_available_frequencies
147*cpufreq_get_available_frequencies(unsigned int cpu);
148
149extern void cpufreq_put_available_frequencies(
150 struct cpufreq_available_frequencies *first);
151
152
153/* determine affected CPUs
154 *
155 * Remember to call cpufreq_put_affected_cpus when no longer needed
156 * to avoid memory leakage, please.
157 */
158
159extern struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned
160 int cpu);
161
162extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first);
163
164
165/* determine related CPUs
166 *
167 * Remember to call cpufreq_put_related_cpus when no longer needed
168 * to avoid memory leakage, please.
169 */
170
171extern struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned
172 int cpu);
173
174extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first);
175
176
177/* determine stats for cpufreq subsystem
178 *
179 * This is not available in all kernel versions or configurations.
180 */
181
182extern struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
183 unsigned long long *total_time);
184
185extern void cpufreq_put_stats(struct cpufreq_stats *stats);
186
187extern unsigned long cpufreq_get_transitions(unsigned int cpu);
188
189
190/* set new cpufreq policy
191 *
192 * Tries to set the passed policy as new policy as close as possible,
193 * but results may differ depending e.g. on governors being available.
194 */
195
196extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
197
198
199/* modify a policy by only changing min/max freq or governor
200 *
201 * Does not check whether result is what was intended.
202 */
203
204extern int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq);
205extern int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq);
206extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
207
208
209/* set a specific frequency
210 *
211 * Does only work if userspace governor can be used and no external
212 * interference (other calls to this function or to set/modify_policy)
213 * occurs. Also does not work on ->range() cpufreq drivers.
214 */
215
216extern int cpufreq_set_frequency(unsigned int cpu,
217 unsigned long target_frequency);
218
219#ifdef __cplusplus
220}
221#endif
222
223#endif /* _CPUFREQ_H */
diff --git a/tools/power/cpupower/lib/sysfs.c b/tools/power/cpupower/lib/sysfs.c
new file mode 100644
index 000000000000..870713a75a81
--- /dev/null
+++ b/tools/power/cpupower/lib/sysfs.c
@@ -0,0 +1,672 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#include <stdio.h>
8#include <errno.h>
9#include <stdlib.h>
10#include <string.h>
11#include <limits.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include "cpufreq.h"
18
19#define PATH_TO_CPU "/sys/devices/system/cpu/"
20#define MAX_LINE_LEN 4096
21#define SYSFS_PATH_MAX 255
22
23
24static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
25{
26 int fd;
27 ssize_t numread;
28
29 fd = open(path, O_RDONLY);
30 if (fd == -1)
31 return 0;
32
33 numread = read(fd, buf, buflen - 1);
34 if (numread < 1) {
35 close(fd);
36 return 0;
37 }
38
39 buf[numread] = '\0';
40 close(fd);
41
42 return (unsigned int) numread;
43}
44
45
46/* CPUFREQ sysfs access **************************************************/
47
48/* helper function to read file from /sys into given buffer */
49/* fname is a relative path under "cpuX/cpufreq" dir */
50static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
51 char *buf, size_t buflen)
52{
53 char path[SYSFS_PATH_MAX];
54
55 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
56 cpu, fname);
57 return sysfs_read_file(path, buf, buflen);
58}
59
60/* helper function to write a new value to a /sys file */
61/* fname is a relative path under "cpuX/cpufreq" dir */
62static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
63 const char *fname,
64 const char *value, size_t len)
65{
66 char path[SYSFS_PATH_MAX];
67 int fd;
68 ssize_t numwrite;
69
70 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
71 cpu, fname);
72
73 fd = open(path, O_WRONLY);
74 if (fd == -1)
75 return 0;
76
77 numwrite = write(fd, value, len);
78 if (numwrite < 1) {
79 close(fd);
80 return 0;
81 }
82
83 close(fd);
84
85 return (unsigned int) numwrite;
86}
87
88/* read access to files which contain one numeric value */
89
90enum cpufreq_value {
91 CPUINFO_CUR_FREQ,
92 CPUINFO_MIN_FREQ,
93 CPUINFO_MAX_FREQ,
94 CPUINFO_LATENCY,
95 SCALING_CUR_FREQ,
96 SCALING_MIN_FREQ,
97 SCALING_MAX_FREQ,
98 STATS_NUM_TRANSITIONS,
99 MAX_CPUFREQ_VALUE_READ_FILES
100};
101
102static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
103 [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
104 [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
105 [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
106 [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
107 [SCALING_CUR_FREQ] = "scaling_cur_freq",
108 [SCALING_MIN_FREQ] = "scaling_min_freq",
109 [SCALING_MAX_FREQ] = "scaling_max_freq",
110 [STATS_NUM_TRANSITIONS] = "stats/total_trans"
111};
112
113
114static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
115 enum cpufreq_value which)
116{
117 unsigned long value;
118 unsigned int len;
119 char linebuf[MAX_LINE_LEN];
120 char *endp;
121
122 if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
123 return 0;
124
125 len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
126 linebuf, sizeof(linebuf));
127
128 if (len == 0)
129 return 0;
130
131 value = strtoul(linebuf, &endp, 0);
132
133 if (endp == linebuf || errno == ERANGE)
134 return 0;
135
136 return value;
137}
138
139/* read access to files which contain one string */
140
141enum cpufreq_string {
142 SCALING_DRIVER,
143 SCALING_GOVERNOR,
144 MAX_CPUFREQ_STRING_FILES
145};
146
147static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
148 [SCALING_DRIVER] = "scaling_driver",
149 [SCALING_GOVERNOR] = "scaling_governor",
150};
151
152
153static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
154 enum cpufreq_string which)
155{
156 char linebuf[MAX_LINE_LEN];
157 char *result;
158 unsigned int len;
159
160 if (which >= MAX_CPUFREQ_STRING_FILES)
161 return NULL;
162
163 len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
164 linebuf, sizeof(linebuf));
165 if (len == 0)
166 return NULL;
167
168 result = strdup(linebuf);
169 if (result == NULL)
170 return NULL;
171
172 if (result[strlen(result) - 1] == '\n')
173 result[strlen(result) - 1] = '\0';
174
175 return result;
176}
177
178/* write access */
179
180enum cpufreq_write {
181 WRITE_SCALING_MIN_FREQ,
182 WRITE_SCALING_MAX_FREQ,
183 WRITE_SCALING_GOVERNOR,
184 WRITE_SCALING_SET_SPEED,
185 MAX_CPUFREQ_WRITE_FILES
186};
187
188static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
189 [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
190 [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
191 [WRITE_SCALING_GOVERNOR] = "scaling_governor",
192 [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
193};
194
195static int sysfs_cpufreq_write_one_value(unsigned int cpu,
196 enum cpufreq_write which,
197 const char *new_value, size_t len)
198{
199 if (which >= MAX_CPUFREQ_WRITE_FILES)
200 return 0;
201
202 if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
203 new_value, len) != len)
204 return -ENODEV;
205
206 return 0;
207};
208
209unsigned long sysfs_get_freq_kernel(unsigned int cpu)
210{
211 return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
212}
213
214unsigned long sysfs_get_freq_hardware(unsigned int cpu)
215{
216 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
217}
218
219unsigned long sysfs_get_freq_transition_latency(unsigned int cpu)
220{
221 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
222}
223
224int sysfs_get_freq_hardware_limits(unsigned int cpu,
225 unsigned long *min,
226 unsigned long *max)
227{
228 if ((!min) || (!max))
229 return -EINVAL;
230
231 *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
232 if (!*min)
233 return -ENODEV;
234
235 *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
236 if (!*max)
237 return -ENODEV;
238
239 return 0;
240}
241
242char *sysfs_get_freq_driver(unsigned int cpu)
243{
244 return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
245}
246
247struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu)
248{
249 struct cpufreq_policy *policy;
250
251 policy = malloc(sizeof(struct cpufreq_policy));
252 if (!policy)
253 return NULL;
254
255 policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
256 if (!policy->governor) {
257 free(policy);
258 return NULL;
259 }
260 policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
261 policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
262 if ((!policy->min) || (!policy->max)) {
263 free(policy->governor);
264 free(policy);
265 return NULL;
266 }
267
268 return policy;
269}
270
271struct cpufreq_available_governors *
272sysfs_get_freq_available_governors(unsigned int cpu) {
273 struct cpufreq_available_governors *first = NULL;
274 struct cpufreq_available_governors *current = NULL;
275 char linebuf[MAX_LINE_LEN];
276 unsigned int pos, i;
277 unsigned int len;
278
279 len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
280 linebuf, sizeof(linebuf));
281 if (len == 0)
282 return NULL;
283
284 pos = 0;
285 for (i = 0; i < len; i++) {
286 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
287 if (i - pos < 2)
288 continue;
289 if (current) {
290 current->next = malloc(sizeof(*current));
291 if (!current->next)
292 goto error_out;
293 current = current->next;
294 } else {
295 first = malloc(sizeof(*first));
296 if (!first)
297 goto error_out;
298 current = first;
299 }
300 current->first = first;
301 current->next = NULL;
302
303 current->governor = malloc(i - pos + 1);
304 if (!current->governor)
305 goto error_out;
306
307 memcpy(current->governor, linebuf + pos, i - pos);
308 current->governor[i - pos] = '\0';
309 pos = i + 1;
310 }
311 }
312
313 return first;
314
315 error_out:
316 while (first) {
317 current = first->next;
318 if (first->governor)
319 free(first->governor);
320 free(first);
321 first = current;
322 }
323 return NULL;
324}
325
326
327struct cpufreq_available_frequencies *
328sysfs_get_available_frequencies(unsigned int cpu) {
329 struct cpufreq_available_frequencies *first = NULL;
330 struct cpufreq_available_frequencies *current = NULL;
331 char one_value[SYSFS_PATH_MAX];
332 char linebuf[MAX_LINE_LEN];
333 unsigned int pos, i;
334 unsigned int len;
335
336 len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
337 linebuf, sizeof(linebuf));
338 if (len == 0)
339 return NULL;
340
341 pos = 0;
342 for (i = 0; i < len; i++) {
343 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
344 if (i - pos < 2)
345 continue;
346 if (i - pos >= SYSFS_PATH_MAX)
347 goto error_out;
348 if (current) {
349 current->next = malloc(sizeof(*current));
350 if (!current->next)
351 goto error_out;
352 current = current->next;
353 } else {
354 first = malloc(sizeof(*first));
355 if (!first)
356 goto error_out;
357 current = first;
358 }
359 current->first = first;
360 current->next = NULL;
361
362 memcpy(one_value, linebuf + pos, i - pos);
363 one_value[i - pos] = '\0';
364 if (sscanf(one_value, "%lu", &current->frequency) != 1)
365 goto error_out;
366
367 pos = i + 1;
368 }
369 }
370
371 return first;
372
373 error_out:
374 while (first) {
375 current = first->next;
376 free(first);
377 first = current;
378 }
379 return NULL;
380}
381
382static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
383 const char *file)
384{
385 struct cpufreq_affected_cpus *first = NULL;
386 struct cpufreq_affected_cpus *current = NULL;
387 char one_value[SYSFS_PATH_MAX];
388 char linebuf[MAX_LINE_LEN];
389 unsigned int pos, i;
390 unsigned int len;
391
392 len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
393 if (len == 0)
394 return NULL;
395
396 pos = 0;
397 for (i = 0; i < len; i++) {
398 if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
399 if (i - pos < 1)
400 continue;
401 if (i - pos >= SYSFS_PATH_MAX)
402 goto error_out;
403 if (current) {
404 current->next = malloc(sizeof(*current));
405 if (!current->next)
406 goto error_out;
407 current = current->next;
408 } else {
409 first = malloc(sizeof(*first));
410 if (!first)
411 goto error_out;
412 current = first;
413 }
414 current->first = first;
415 current->next = NULL;
416
417 memcpy(one_value, linebuf + pos, i - pos);
418 one_value[i - pos] = '\0';
419
420 if (sscanf(one_value, "%u", &current->cpu) != 1)
421 goto error_out;
422
423 pos = i + 1;
424 }
425 }
426
427 return first;
428
429 error_out:
430 while (first) {
431 current = first->next;
432 free(first);
433 first = current;
434 }
435 return NULL;
436}
437
438struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(unsigned int cpu)
439{
440 return sysfs_get_cpu_list(cpu, "affected_cpus");
441}
442
443struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(unsigned int cpu)
444{
445 return sysfs_get_cpu_list(cpu, "related_cpus");
446}
447
448struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
449 unsigned long long *total_time) {
450 struct cpufreq_stats *first = NULL;
451 struct cpufreq_stats *current = NULL;
452 char one_value[SYSFS_PATH_MAX];
453 char linebuf[MAX_LINE_LEN];
454 unsigned int pos, i;
455 unsigned int len;
456
457 len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
458 linebuf, sizeof(linebuf));
459 if (len == 0)
460 return NULL;
461
462 *total_time = 0;
463 pos = 0;
464 for (i = 0; i < len; i++) {
465 if (i == strlen(linebuf) || linebuf[i] == '\n') {
466 if (i - pos < 2)
467 continue;
468 if ((i - pos) >= SYSFS_PATH_MAX)
469 goto error_out;
470 if (current) {
471 current->next = malloc(sizeof(*current));
472 if (!current->next)
473 goto error_out;
474 current = current->next;
475 } else {
476 first = malloc(sizeof(*first));
477 if (!first)
478 goto error_out;
479 current = first;
480 }
481 current->first = first;
482 current->next = NULL;
483
484 memcpy(one_value, linebuf + pos, i - pos);
485 one_value[i - pos] = '\0';
486 if (sscanf(one_value, "%lu %llu",
487 &current->frequency,
488 &current->time_in_state) != 2)
489 goto error_out;
490
491 *total_time = *total_time + current->time_in_state;
492 pos = i + 1;
493 }
494 }
495
496 return first;
497
498 error_out:
499 while (first) {
500 current = first->next;
501 free(first);
502 first = current;
503 }
504 return NULL;
505}
506
507unsigned long sysfs_get_freq_transitions(unsigned int cpu)
508{
509 return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
510}
511
512static int verify_gov(char *new_gov, char *passed_gov)
513{
514 unsigned int i, j = 0;
515
516 if (!passed_gov || (strlen(passed_gov) > 19))
517 return -EINVAL;
518
519 strncpy(new_gov, passed_gov, 20);
520 for (i = 0; i < 20; i++) {
521 if (j) {
522 new_gov[i] = '\0';
523 continue;
524 }
525 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
526 continue;
527
528 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
529 continue;
530
531 if (new_gov[i] == '-')
532 continue;
533
534 if (new_gov[i] == '_')
535 continue;
536
537 if (new_gov[i] == '\0') {
538 j = 1;
539 continue;
540 }
541 return -EINVAL;
542 }
543 new_gov[19] = '\0';
544 return 0;
545}
546
547int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor)
548{
549 char new_gov[SYSFS_PATH_MAX];
550
551 if (!governor)
552 return -EINVAL;
553
554 if (verify_gov(new_gov, governor))
555 return -EINVAL;
556
557 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
558 new_gov, strlen(new_gov));
559};
560
561int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq)
562{
563 char value[SYSFS_PATH_MAX];
564
565 snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
566
567 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
568 value, strlen(value));
569};
570
571
572int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq)
573{
574 char value[SYSFS_PATH_MAX];
575
576 snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
577
578 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
579 value, strlen(value));
580};
581
582
583int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy)
584{
585 char min[SYSFS_PATH_MAX];
586 char max[SYSFS_PATH_MAX];
587 char gov[SYSFS_PATH_MAX];
588 int ret;
589 unsigned long old_min;
590 int write_max_first;
591
592 if (!policy || !(policy->governor))
593 return -EINVAL;
594
595 if (policy->max < policy->min)
596 return -EINVAL;
597
598 if (verify_gov(gov, policy->governor))
599 return -EINVAL;
600
601 snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
602 snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
603
604 old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
605 write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
606
607 if (write_max_first) {
608 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
609 max, strlen(max));
610 if (ret)
611 return ret;
612 }
613
614 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
615 strlen(min));
616 if (ret)
617 return ret;
618
619 if (!write_max_first) {
620 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
621 max, strlen(max));
622 if (ret)
623 return ret;
624 }
625
626 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
627 gov, strlen(gov));
628}
629
630int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency)
631{
632 struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu);
633 char userspace_gov[] = "userspace";
634 char freq[SYSFS_PATH_MAX];
635 int ret;
636
637 if (!pol)
638 return -ENODEV;
639
640 if (strncmp(pol->governor, userspace_gov, 9) != 0) {
641 ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov);
642 if (ret) {
643 cpufreq_put_policy(pol);
644 return ret;
645 }
646 }
647
648 cpufreq_put_policy(pol);
649
650 snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
651
652 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
653 freq, strlen(freq));
654}
655
656/* CPUFREQ sysfs access **************************************************/
657
658/* General sysfs access **************************************************/
659int sysfs_cpu_exists(unsigned int cpu)
660{
661 char file[SYSFS_PATH_MAX];
662 struct stat statbuf;
663
664 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
665
666 if (stat(file, &statbuf) != 0)
667 return -ENOSYS;
668
669 return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
670}
671
672/* General sysfs access **************************************************/
diff --git a/tools/power/cpupower/lib/sysfs.h b/tools/power/cpupower/lib/sysfs.h
new file mode 100644
index 000000000000..c76a5e0af501
--- /dev/null
+++ b/tools/power/cpupower/lib/sysfs.h
@@ -0,0 +1,31 @@
1/* General */
2extern unsigned int sysfs_cpu_exists(unsigned int cpu);
3
4/* CPUfreq */
5extern unsigned long sysfs_get_freq_kernel(unsigned int cpu);
6extern unsigned long sysfs_get_freq_hardware(unsigned int cpu);
7extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu);
8extern int sysfs_get_freq_hardware_limits(unsigned int cpu,
9 unsigned long *min, unsigned long *max);
10extern char *sysfs_get_freq_driver(unsigned int cpu);
11extern struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu);
12extern struct cpufreq_available_governors *sysfs_get_freq_available_governors(
13 unsigned int cpu);
14extern struct cpufreq_available_frequencies *sysfs_get_available_frequencies(
15 unsigned int cpu);
16extern struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(
17 unsigned int cpu);
18extern struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(
19 unsigned int cpu);
20extern struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
21 unsigned long long *total_time);
22extern unsigned long sysfs_get_freq_transitions(unsigned int cpu);
23extern int sysfs_set_freq_policy(unsigned int cpu,
24 struct cpufreq_policy *policy);
25extern int sysfs_modify_freq_policy_min(unsigned int cpu,
26 unsigned long min_freq);
27extern int sysfs_modify_freq_policy_max(unsigned int cpu,
28 unsigned long max_freq);
29extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor);
30extern int sysfs_set_frequency(unsigned int cpu,
31 unsigned long target_frequency);
diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1
new file mode 100644
index 000000000000..bb60a8d1e45a
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-frequency-info.1
@@ -0,0 +1,76 @@
1.TH "cpupower-frequency-info" "1" "0.1" "Mattia Dongili" ""
2.SH "NAME"
3.LP
4cpupower frequency\-info \- Utility to retrieve cpufreq kernel information
5.SH "SYNTAX"
6.LP
7cpupower [ \-c cpulist ] frequency\-info [\fIoptions\fP]
8.SH "DESCRIPTION"
9.LP
10A small tool which prints out cpufreq information helpful to developers and interested users.
11.SH "OPTIONS"
12.LP
13.TP
14\fB\-e\fR \fB\-\-debug\fR
15Prints out debug information.
16.TP
17\fB\-f\fR \fB\-\-freq\fR
18Get frequency the CPU currently runs at, according to the cpufreq core.
19.TP
20\fB\-w\fR \fB\-\-hwfreq\fR
21Get frequency the CPU currently runs at, by reading it from hardware (only available to root).
22.TP
23\fB\-l\fR \fB\-\-hwlimits\fR
24Determine the minimum and maximum CPU frequency allowed.
25.TP
26\fB\-d\fR \fB\-\-driver\fR
27Determines the used cpufreq kernel driver.
28.TP
29\fB\-p\fR \fB\-\-policy\fR
30Gets the currently used cpufreq policy.
31.TP
32\fB\-g\fR \fB\-\-governors\fR
33Determines available cpufreq governors.
34.TP
35\fB\-a\fR \fB\-\-related\-cpus\fR
36Determines which CPUs run at the same hardware frequency.
37.TP
38\fB\-a\fR \fB\-\-affected\-cpus\fR
39Determines which CPUs need to have their frequency coordinated by software.
40.TP
41\fB\-s\fR \fB\-\-stats\fR
42Shows cpufreq statistics if available.
43.TP
44\fB\-y\fR \fB\-\-latency\fR
45Determines the maximum latency on CPU frequency changes.
46.TP
47\fB\-o\fR \fB\-\-proc\fR
48Prints out information like provided by the /proc/cpufreq interface in 2.4. and early 2.6. kernels.
49.TP
50\fB\-m\fR \fB\-\-human\fR
51human\-readable output for the \-f, \-w, \-s and \-y parameters.
52.TP
53\fB\-h\fR \fB\-\-help\fR
54Prints out the help screen.
55.SH "REMARKS"
56.LP
57By default only values of core zero are displayed. How to display settings of
58other cores is described in the cpupower(1) manpage in the \-\-cpu option section.
59.LP
60You can't specify more than one of the output specific options \-o \-e \-a \-g \-p \-d \-l \-w \-f \-y.
61.LP
62You also can't specify the \-o option combined with the \-c option.
63.SH "FILES"
64.nf
65\fI/sys/devices/system/cpu/cpu*/cpufreq/\fP
66\fI/proc/cpufreq\fP (deprecated)
67\fI/proc/sys/cpu/\fP (deprecated)
68.fi
69.SH "AUTHORS"
70.nf
71Dominik Brodowski <linux@brodo.de> \- author
72Mattia Dongili<malattia@gmail.com> \- first autolibtoolization
73.fi
74.SH "SEE ALSO"
75.LP
76cpupower\-frequency\-set(1), cpupower(1)
diff --git a/tools/power/cpupower/man/cpupower-frequency-set.1 b/tools/power/cpupower/man/cpupower-frequency-set.1
new file mode 100644
index 000000000000..685f469093ad
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-frequency-set.1
@@ -0,0 +1,54 @@
1.TH "cpupower-freqency-set" "1" "0.1" "Mattia Dongili" ""
2.SH "NAME"
3.LP
4cpupower frequency\-set \- A small tool which allows to modify cpufreq settings.
5.SH "SYNTAX"
6.LP
7cpupower [ \-c cpu ] frequency\-set [\fIoptions\fP]
8.SH "DESCRIPTION"
9.LP
10cpupower frequency\-set allows you to modify cpufreq settings without having to type e.g. "/sys/devices/system/cpu/cpu0/cpufreq/scaling_set_speed" all the time.
11.SH "OPTIONS"
12.LP
13.TP
14\fB\-d\fR \fB\-\-min\fR <FREQ>
15new minimum CPU frequency the governor may select.
16.TP
17\fB\-u\fR \fB\-\-max\fR <FREQ>
18new maximum CPU frequency the governor may select.
19.TP
20\fB\-g\fR \fB\-\-governor\fR <GOV>
21new cpufreq governor.
22.TP
23\fB\-f\fR \fB\-\-freq\fR <FREQ>
24specific frequency to be set. Requires userspace governor to be available and loaded.
25.TP
26\fB\-r\fR \fB\-\-related\fR
27modify all hardware-related CPUs at the same time
28.TP
29\fB\-h\fR \fB\-\-help\fR
30Prints out the help screen.
31.SH "REMARKS"
32.LP
33By default values are applied on all cores. How to modify single core
34configurations is described in the cpupower(1) manpage in the \-\-cpu option section.
35.LP
36The \-f FREQ, \-\-freq FREQ parameter cannot be combined with any other parameter.
37.LP
38FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz by postfixing the value with the wanted unit name, without any space (frequency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).
39.LP
40On Linux kernels up to 2.6.29, the \-r or \-\-related parameter is ignored.
41.SH "FILES"
42.nf
43\fI/sys/devices/system/cpu/cpu*/cpufreq/\fP
44\fI/proc/cpufreq\fP (deprecated)
45\fI/proc/sys/cpu/\fP (deprecated)
46.fi
47.SH "AUTHORS"
48.nf
49Dominik Brodowski <linux@brodo.de> \- author
50Mattia Dongili<malattia@gmail.com> \- first autolibtoolization
51.fi
52.SH "SEE ALSO"
53.LP
54cpupower\-frequency\-info(1), cpupower(1)
diff --git a/tools/power/cpupower/man/cpupower-info.1 b/tools/power/cpupower/man/cpupower-info.1
new file mode 100644
index 000000000000..58e21196f17f
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-info.1
@@ -0,0 +1,19 @@
1.TH CPUPOWER\-INFO "1" "22/02/2011" "" "cpupower Manual"
2.SH NAME
3cpupower\-info \- Shows processor power related kernel or hardware configurations
4.SH SYNOPSIS
5.ft B
6.B cpupower info [ \-b ] [ \-s ] [ \-m ]
7
8.SH DESCRIPTION
9\fBcpupower info \fP shows kernel configurations or processor hardware
10registers affecting processor power saving policies.
11
12Some options are platform wide, some affect single cores. By default values
13of core zero are displayed only. cpupower --cpu all cpuinfo will show the
14settings of all cores, see cpupower(1) how to choose specific cores.
15
16.SH "SEE ALSO"
17Options are described in detail in:
18
19cpupower(1), cpupower-set(1)
diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1
new file mode 100644
index 000000000000..d5cfa265c3d3
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-monitor.1
@@ -0,0 +1,179 @@
1.TH CPUPOWER\-MONITOR "1" "22/02/2011" "" "cpupower Manual"
2.SH NAME
3cpupower\-monitor \- Report processor frequency and idle statistics
4.SH SYNOPSIS
5.ft B
6.B cpupower monitor
7.RB "\-l"
8
9.B cpupower monitor
10.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
11.RB [ "\-i seconds" ]
12.br
13.B cpupower monitor
14.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
15.RB command
16.br
17.SH DESCRIPTION
18\fBcpupower-monitor \fP reports processor topology, frequency and idle power
19state statistics. Either \fBcommand\fP is forked and
20statistics are printed upon its completion, or statistics are printed periodically.
21
22\fBcpupower-monitor \fP implements independent processor sleep state and
23frequency counters. Some are retrieved from kernel statistics, some are
24directly reading out hardware registers. Use \-l to get an overview which are
25supported on your system.
26
27.SH Options
28.PP
29\-l
30.RS 4
31List available monitors on your system. Additional details about each monitor
32are shown:
33.RS 2
34.IP \(bu
35The name in quotation marks which can be passed to the \-m parameter.
36.IP \(bu
37The number of different counters the monitor supports in brackets.
38.IP \(bu
39The amount of time in seconds the counters might overflow, due to
40implementation constraints.
41.IP \(bu
42The name and a description of each counter and its processor hierarchy level
43coverage in square brackets:
44.RS 4
45.IP \(bu
46[T] \-> Thread
47.IP \(bu
48[C] \-> Core
49.IP \(bu
50[P] \-> Processor Package (Socket)
51.IP \(bu
52[M] \-> Machine/Platform wide counter
53.RE
54.RE
55.RE
56.PP
57\-m <mon1>,<mon2>,...
58.RS 4
59Only display specific monitors. Use the monitor string(s) provided by \-l option.
60.RE
61.PP
62\-i seconds
63.RS 4
64Measure intervall.
65.RE
66.PP
67command
68.RS 4
69Measure idle and frequency characteristics of an arbitrary command/workload.
70The executable \fBcommand\fP is forked and upon its exit, statistics gathered since it was
71forked are displayed.
72.RE
73.PP
74\-v
75.RS 4
76Increase verbosity if the binary was compiled with the DEBUG option set.
77.RE
78
79.SH MONITOR DESCRIPTIONS
80.SS "Idle_Stats"
81Shows statistics of the cpuidle kernel subsystem. Values are retrieved from
82/sys/devices/system/cpu/cpu*/cpuidle/state*/.
83The kernel updates these values every time an idle state is entered or
84left. Therefore there can be some inaccuracy when cores are in an idle
85state for some time when the measure starts or ends. In worst case it can happen
86that one core stayed in an idle state for the whole measure time and the idle
87state usage time as exported by the kernel did not get updated. In this case
88a state residency of 0 percent is shown while it was 100.
89
90.SS "Mperf"
91The name comes from the aperf/mperf (average and maximum) MSR registers used
92which are available on recent X86 processors. It shows the average frequency
93(including boost frequencies).
94The fact that on all recent hardware the mperf timer stops ticking in any idle
95state it is also used to show C0 (processor is active) and Cx (processor is in
96any sleep state) times. These counters do not have the inaccuracy restrictions
97the "Idle_Stats" counters may show.
98May work poorly on Linux-2.6.20 through 2.6.29, as the \fBacpi-cpufreq \fP
99kernel frequency driver periodically cleared aperf/mperf registers in those
100kernels.
101
102.SS "Nehalem" "SandyBridge"
103Intel Core and Package sleep state counters.
104Threads (hyperthreaded cores) may not be able to enter deeper core states if
105its sibling is utilized.
106Deepest package sleep states may in reality show up as machine/platform wide
107sleep states and can only be entered if all cores are idle. Look up Intel
108manuals (some are provided in the References section) for further details.
109
110.SS "Ontario" "Liano"
111AMD laptop and desktop processor (family 12h and 14h) sleep state counters.
112The registers are accessed via PCI and therefore can still be read out while
113cores have been offlined.
114
115There is one special counter: NBP1 (North Bridge P1).
116This one always returns 0 or 1, depending on whether the North Bridge P1
117power state got entered at least once during measure time.
118Being able to enter NBP1 state also depends on graphics power management.
119Therefore this counter can be used to verify whether the graphics' driver
120power management is working as expected.
121
122.SH EXAMPLES
123
124cpupower monitor -l" may show:
125.RS 4
126Monitor "Mperf" (3 states) \- Might overflow after 922000000 s
127
128 ...
129
130Monitor "Idle_Stats" (3 states) \- Might overflow after 4294967295 s
131
132 ...
133
134.RE
135cpupower monitor \-m "Idle_Stats,Mperf" scp /tmp/test /nfs/tmp
136
137Monitor the scp command, show both Mperf and Idle_Stats states counter
138statistics, but in exchanged order.
139
140
141
142.RE
143Be careful that the typical command to fully utilize one CPU by doing:
144
145cpupower monitor cat /dev/zero >/dev/null
146
147Does not work as expected, because the measured output is redirected to
148/dev/null. This could get workarounded by putting the line into an own, tiny
149shell script. Hit CTRL\-c to terminate the command and get the measure output
150displayed.
151
152.SH REFERENCES
153"BIOS and Kernel Developer’s Guide (BKDG) for AMD Family 14h Processors"
154http://support.amd.com/us/Processor_TechDocs/43170.pdf
155
156"Intel® Turbo Boost Technology
157in Intel® Core™ Microarchitecture (Nehalem) Based Processors"
158http://download.intel.com/design/processor/applnots/320354.pdf
159
160"Intel® 64 and IA-32 Architectures Software Developer's Manual
161Volume 3B: System Programming Guide"
162http://www.intel.com/products/processor/manuals
163
164.SH FILES
165.ta
166.nf
167/dev/cpu/*/msr
168/sys/devices/system/cpu/cpu*/cpuidle/state*/.
169.fi
170
171.SH "SEE ALSO"
172powertop(8), msr(4), vmstat(8)
173.PP
174.SH AUTHORS
175.nf
176Written by Thomas Renninger <trenn@suse.de>
177
178Nehalem, SandyBridge monitors and command passing
179based on turbostat.8 from Len Brown <len.brown@intel.com>
diff --git a/tools/power/cpupower/man/cpupower-set.1 b/tools/power/cpupower/man/cpupower-set.1
new file mode 100644
index 000000000000..c4954a9fe4e7
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-set.1
@@ -0,0 +1,103 @@
1.TH CPUPOWER\-SET "1" "22/02/2011" "" "cpupower Manual"
2.SH NAME
3cpupower\-set \- Set processor power related kernel or hardware configurations
4.SH SYNOPSIS
5.ft B
6.B cpupower set [ \-b VAL ] [ \-s VAL ] [ \-m VAL ]
7
8
9.SH DESCRIPTION
10\fBcpupower set \fP sets kernel configurations or directly accesses hardware
11registers affecting processor power saving policies.
12
13Some options are platform wide, some affect single cores. By default values
14are applied on all cores. How to modify single core configurations is
15described in the cpupower(1) manpage in the \-\-cpu option section. Whether an
16option affects the whole system or can be applied to individual cores is
17described in the Options sections.
18
19Use \fBcpupower info \fP to read out current settings and whether they are
20supported on the system at all.
21
22.SH Options
23.PP
24\-\-perf-bias, \-b
25.RS 4
26Sets a register on supported Intel processore which allows software to convey
27its policy for the relative importance of performance versus energy savings to
28the processor.
29
30The range of valid numbers is 0-15, where 0 is maximum
31performance and 15 is maximum energy efficiency.
32
33The processor uses this information in model-specific ways
34when it must select trade-offs between performance and
35energy efficiency.
36
37This policy hint does not supersede Processor Performance states
38(P-states) or CPU Idle power states (C-states), but allows
39software to have influence where it would otherwise be unable
40to express a preference.
41
42For example, this setting may tell the hardware how
43aggressively or conservatively to control frequency
44in the "turbo range" above the explicitly OS-controlled
45P-state frequency range. It may also tell the hardware
46how aggressively it should enter the OS requested C-states.
47
48This option can be applied to individual cores only via the \-\-cpu option,
49cpupower(1).
50
51Setting the performance bias value on one CPU can modify the setting on
52related CPUs as well (for example all CPUs on one socket), because of
53hardware restrictions.
54Use \fBcpupower -c all info -b\fP to verify.
55
56This options needs the msr kernel driver (CONFIG_X86_MSR) loaded.
57.RE
58.PP
59\-\-sched\-mc, \-m [ VAL ]
60.RE
61\-\-sched\-smt, \-s [ VAL ]
62.RS 4
63\-\-sched\-mc utilizes cores in one processor package/socket first before
64processes are scheduled to other processor packages/sockets.
65
66\-\-sched\-smt utilizes thread siblings of one processor core first before
67processes are scheduled to other cores.
68
69The impact on power consumption and performance (positiv or negativ) heavily
70depends on processor support for deep sleep states, frequency scaling and
71frequency boost modes and their dependencies between other thread siblings
72and processor cores.
73
74Taken over from kernel documentation:
75
76Adjust the kernel's multi-core scheduler support.
77
78Possible values are:
79.RS 2
800 - No power saving load balance (default value)
81
821 - Fill one thread/core/package first for long running threads
83
842 - Also bias task wakeups to semi-idle cpu package for power
85savings
86.RE
87
88sched_mc_power_savings is dependent upon SCHED_MC, which is
89itself architecture dependent.
90
91sched_smt_power_savings is dependent upon SCHED_SMT, which
92is itself architecture dependent.
93
94The two files are independent of each other. It is possible
95that one file may be present without the other.
96
97.SH "SEE ALSO"
98cpupower-info(1), cpupower-monitor(1), powertop(1)
99.PP
100.SH AUTHORS
101.nf
102\-\-perf\-bias parts written by Len Brown <len.brown@intel.com>
103Thomas Renninger <trenn@suse.de>
diff --git a/tools/power/cpupower/man/cpupower.1 b/tools/power/cpupower/man/cpupower.1
new file mode 100644
index 000000000000..baf741d06e82
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower.1
@@ -0,0 +1,72 @@
1.TH CPUPOWER "1" "07/03/2011" "" "cpupower Manual"
2.SH NAME
3cpupower \- Shows and sets processor power related values
4.SH SYNOPSIS
5.ft B
6.B cpupower [ \-c cpulist ] <command> [ARGS]
7
8.B cpupower \-v|\-\-version
9
10.B cpupower \-h|\-\-help
11
12.SH DESCRIPTION
13\fBcpupower \fP is a collection of tools to examine and tune power saving
14related features of your processor.
15
16The manpages of the commands (cpupower\-<command>(1)) provide detailed
17descriptions of supported features. Run \fBcpupower help\fP to get an overview
18of supported commands.
19
20.SH Options
21.PP
22\-\-help, \-h
23.RS 4
24Shows supported commands and general usage.
25.RE
26.PP
27\-\-cpu cpulist, \-c cpulist
28.RS 4
29Only show or set values for specific cores.
30This option is not supported by all commands, details can be found in the
31manpages of the commands.
32
33Some commands access all cores (typically the *\-set commands), some only
34the first core (typically the *\-info commands) by default.
35
36The syntax for <cpulist> is based on how the kernel exports CPU bitmasks via
37sysfs files. Some examples:
38.RS 4
39.TP 16
40Input
41Equivalent to
42.TP
43all
44all cores
45.TP
460\-3
470,1,2,3
48.TP
490\-7:2
500,2,4,6
51.TP
521,3,5-7
531,3,5,6,7
54.TP
550\-3:2,8\-15:4
560,2,8,12
57.RE
58.RE
59.PP
60\-\-version, \-v
61.RS 4
62Print the package name and version number.
63
64.SH "SEE ALSO"
65cpupower-set(1), cpupower-info(1), cpupower-idle(1),
66cpupower-frequency-set(1), cpupower-frequency-info(1), cpupower-monitor(1),
67powertop(1)
68.PP
69.SH AUTHORS
70.nf
71\-\-perf\-bias parts written by Len Brown <len.brown@intel.com>
72Thomas Renninger <trenn@suse.de>
diff --git a/tools/power/cpupower/po/cs.po b/tools/power/cpupower/po/cs.po
new file mode 100644
index 000000000000..cb22c45c5069
--- /dev/null
+++ b/tools/power/cpupower/po/cs.po
@@ -0,0 +1,944 @@
1# translation of cs.po to Czech
2# Czech translation for cpufrequtils package
3# Czech messages for cpufrequtils.
4# Copyright (C) 2007 kavol
5# This file is distributed under the same license as the cpufrequtils package.
6#
7# Karel Volný <kavol@seznam.cz>, 2007, 2008.
8msgid ""
9msgstr ""
10"Project-Id-Version: cs\n"
11"Report-Msgid-Bugs-To: \n"
12"POT-Creation-Date: 2011-03-08 17:03+0100\n"
13"PO-Revision-Date: 2008-06-11 16:26+0200\n"
14"Last-Translator: Karel Volný <kavol@seznam.cz>\n"
15"Language-Team: Czech <diskuze@lists.l10n.cz>\n"
16"Language: cs\n"
17"MIME-Version: 1.0\n"
18"Content-Type: text/plain; charset=UTF-8\n"
19"Content-Transfer-Encoding: 8bit\n"
20"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
21"X-Generator: KBabel 1.11.4\n"
22
23#: utils/idle_monitor/nhm_idle.c:36
24msgid "Processor Core C3"
25msgstr ""
26
27#: utils/idle_monitor/nhm_idle.c:43
28msgid "Processor Core C6"
29msgstr ""
30
31#: utils/idle_monitor/nhm_idle.c:51
32msgid "Processor Package C3"
33msgstr ""
34
35#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
36msgid "Processor Package C6"
37msgstr ""
38
39#: utils/idle_monitor/snb_idle.c:33
40msgid "Processor Core C7"
41msgstr ""
42
43#: utils/idle_monitor/snb_idle.c:40
44msgid "Processor Package C2"
45msgstr ""
46
47#: utils/idle_monitor/snb_idle.c:47
48msgid "Processor Package C7"
49msgstr ""
50
51#: utils/idle_monitor/amd_fam14h_idle.c:56
52msgid "Package in sleep state (PC1 or deeper)"
53msgstr ""
54
55#: utils/idle_monitor/amd_fam14h_idle.c:63
56msgid "Processor Package C1"
57msgstr ""
58
59#: utils/idle_monitor/amd_fam14h_idle.c:77
60msgid "North Bridge P1 boolean counter (returns 0 or 1)"
61msgstr ""
62
63#: utils/idle_monitor/mperf_monitor.c:35
64msgid "Processor Core not idle"
65msgstr ""
66
67#: utils/idle_monitor/mperf_monitor.c:42
68msgid "Processor Core in an idle state"
69msgstr ""
70
71#: utils/idle_monitor/mperf_monitor.c:50
72msgid "Average Frequency (including boost) in MHz"
73msgstr ""
74
75#: utils/idle_monitor/cpupower-monitor.c:66
76#, c-format
77msgid ""
78"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
79"interval_sec | -c command ...]\n"
80msgstr ""
81
82#: utils/idle_monitor/cpupower-monitor.c:69
83#, c-format
84msgid ""
85"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
86"interval_sec | -c command ...]\n"
87msgstr ""
88
89#: utils/idle_monitor/cpupower-monitor.c:71
90#, c-format
91msgid "\t -v: be more verbose\n"
92msgstr ""
93
94#: utils/idle_monitor/cpupower-monitor.c:73
95#, c-format
96msgid "\t -h: print this help\n"
97msgstr ""
98
99#: utils/idle_monitor/cpupower-monitor.c:74
100#, c-format
101msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
102msgstr ""
103
104#: utils/idle_monitor/cpupower-monitor.c:75
105#, c-format
106msgid "\t -t: show CPU topology/hierarchy\n"
107msgstr ""
108
109#: utils/idle_monitor/cpupower-monitor.c:76
110#, c-format
111msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
112msgstr ""
113
114#: utils/idle_monitor/cpupower-monitor.c:77
115#, c-format
116msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
117msgstr ""
118
119#: utils/idle_monitor/cpupower-monitor.c:79
120#, c-format
121msgid ""
122"only one of: -t, -l, -m are allowed\n"
123"If none of them is passed,"
124msgstr ""
125
126#: utils/idle_monitor/cpupower-monitor.c:80
127#, c-format
128msgid " all supported monitors are shown\n"
129msgstr ""
130
131#: utils/idle_monitor/cpupower-monitor.c:197
132#, c-format
133msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
134msgstr ""
135
136#: utils/idle_monitor/cpupower-monitor.c:207
137#, c-format
138msgid " *is offline\n"
139msgstr ""
140
141#: utils/idle_monitor/cpupower-monitor.c:236
142#, c-format
143msgid "%s: max monitor name length (%d) exceeded\n"
144msgstr ""
145
146#: utils/idle_monitor/cpupower-monitor.c:250
147#, c-format
148msgid "No matching monitor found in %s, try -l option\n"
149msgstr ""
150
151#: utils/idle_monitor/cpupower-monitor.c:266
152#, c-format
153msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
154msgstr ""
155
156#: utils/idle_monitor/cpupower-monitor.c:319
157#, c-format
158msgid "%s took %.5f seconds and exited with status %d\n"
159msgstr ""
160
161#: utils/idle_monitor/cpupower-monitor.c:406
162#, c-format
163msgid "Cannot read number of available processors\n"
164msgstr ""
165
166#: utils/idle_monitor/cpupower-monitor.c:417
167#, c-format
168msgid "Available monitor %s needs root access\n"
169msgstr ""
170
171#: utils/idle_monitor/cpupower-monitor.c:428
172#, c-format
173msgid "No HW Cstate monitors found\n"
174msgstr ""
175
176#: utils/cpupower.c:78
177#, c-format
178msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
179msgstr ""
180
181#: utils/cpupower.c:79
182#, c-format
183msgid "cpupower --version\n"
184msgstr ""
185
186#: utils/cpupower.c:80
187#, c-format
188msgid "Supported subcommands are:\n"
189msgstr ""
190
191#: utils/cpupower.c:83
192#, c-format
193msgid ""
194"\n"
195"Some subcommands can make use of the -c cpulist option.\n"
196msgstr ""
197
198#: utils/cpupower.c:84
199#, c-format
200msgid "Look at the general cpupower manpage how to use it\n"
201msgstr ""
202
203#: utils/cpupower.c:85
204#, c-format
205msgid "and read up the subcommand's manpage whether it is supported.\n"
206msgstr ""
207
208#: utils/cpupower.c:86
209#, c-format
210msgid ""
211"\n"
212"Use cpupower help subcommand for getting help for above subcommands.\n"
213msgstr ""
214
215#: utils/cpupower.c:91
216#, c-format
217msgid "Report errors and bugs to %s, please.\n"
218msgstr ""
219"Chyby v programu prosím hlaste na %s (anglicky).\n"
220"Chyby v pÅ™ekladu prosím hlaste na kavol@seznam.cz (Äesky ;-)\n"
221
222#: utils/cpupower.c:114
223#, c-format
224msgid "Error parsing cpu list\n"
225msgstr ""
226
227#: utils/cpupower.c:172
228#, c-format
229msgid "Subcommand %s needs root privileges\n"
230msgstr ""
231
232#: utils/cpufreq-info.c:31
233#, c-format
234msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
235msgstr "Nelze zjistit poÄet CPU (%s: %s), pÅ™edpokládá se 1.\n"
236
237#: utils/cpufreq-info.c:63
238#, c-format
239msgid ""
240" minimum CPU frequency - maximum CPU frequency - governor\n"
241msgstr ""
242" minimální frekvence CPU - maximální frekvence CPU - regulátor\n"
243
244#: utils/cpufreq-info.c:151
245#, c-format
246msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
247msgstr ""
248
249#. P state changes via MSR are identified via cpuid 80000007
250#. on Intel and AMD, but we assume boost capable machines can do that
251#. if (cpuid_eax(0x80000000) >= 0x80000007
252#. && (cpuid_edx(0x80000007) & (1 << 7)))
253#.
254#: utils/cpufreq-info.c:161
255#, c-format
256msgid " boost state support: \n"
257msgstr ""
258
259#: utils/cpufreq-info.c:163
260#, c-format
261msgid " Supported: %s\n"
262msgstr ""
263
264#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
265msgid "yes"
266msgstr ""
267
268#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
269msgid "no"
270msgstr ""
271
272#: utils/cpufreq-info.c:164
273#, fuzzy, c-format
274msgid " Active: %s\n"
275msgstr " ovladaÄ: %s\n"
276
277#: utils/cpufreq-info.c:177
278#, c-format
279msgid " Boost States: %d\n"
280msgstr ""
281
282#: utils/cpufreq-info.c:178
283#, c-format
284msgid " Total States: %d\n"
285msgstr ""
286
287#: utils/cpufreq-info.c:181
288#, c-format
289msgid " Pstate-Pb%d: %luMHz (boost state)\n"
290msgstr ""
291
292#: utils/cpufreq-info.c:184
293#, c-format
294msgid " Pstate-P%d: %luMHz\n"
295msgstr ""
296
297#: utils/cpufreq-info.c:211
298#, c-format
299msgid " no or unknown cpufreq driver is active on this CPU\n"
300msgstr " pro tento CPU není aktivní žádný známý ovladaÄ cpufreq\n"
301
302#: utils/cpufreq-info.c:213
303#, c-format
304msgid " driver: %s\n"
305msgstr " ovladaÄ: %s\n"
306
307#: utils/cpufreq-info.c:219
308#, fuzzy, c-format
309msgid " CPUs which run at the same hardware frequency: "
310msgstr " CPU, které musí měnit frekvenci zároveň: "
311
312#: utils/cpufreq-info.c:230
313#, fuzzy, c-format
314msgid " CPUs which need to have their frequency coordinated by software: "
315msgstr " CPU, které musí měnit frekvenci zároveň: "
316
317#: utils/cpufreq-info.c:241
318#, c-format
319msgid " maximum transition latency: "
320msgstr ""
321
322#: utils/cpufreq-info.c:247
323#, c-format
324msgid " hardware limits: "
325msgstr " hardwarové meze: "
326
327#: utils/cpufreq-info.c:256
328#, c-format
329msgid " available frequency steps: "
330msgstr " dostupné frekvence: "
331
332#: utils/cpufreq-info.c:269
333#, c-format
334msgid " available cpufreq governors: "
335msgstr " dostupné regulátory: "
336
337#: utils/cpufreq-info.c:280
338#, c-format
339msgid " current policy: frequency should be within "
340msgstr " souÄasná taktika: frekvence by mÄ›la být mezi "
341
342#: utils/cpufreq-info.c:282
343#, c-format
344msgid " and "
345msgstr " a "
346
347#: utils/cpufreq-info.c:286
348#, c-format
349msgid ""
350"The governor \"%s\" may decide which speed to use\n"
351" within this range.\n"
352msgstr ""
353" Regulátor \"%s\" může rozhodnout jakou frekvenci použít\n"
354" v těchto mezích.\n"
355
356#: utils/cpufreq-info.c:293
357#, c-format
358msgid " current CPU frequency is "
359msgstr " souÄasná frekvence CPU je "
360
361#: utils/cpufreq-info.c:296
362#, c-format
363msgid " (asserted by call to hardware)"
364msgstr " (zjištěno hardwarovým voláním)"
365
366#: utils/cpufreq-info.c:304
367#, c-format
368msgid " cpufreq stats: "
369msgstr " statistika cpufreq: "
370
371#: utils/cpufreq-info.c:472
372#, fuzzy, c-format
373msgid "Usage: cpupower freqinfo [options]\n"
374msgstr "Užití: cpufreq-info [pÅ™epínaÄe]\n"
375
376#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
377#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
378#, c-format
379msgid "Options:\n"
380msgstr "PÅ™epínaÄe:\n"
381
382#: utils/cpufreq-info.c:474
383#, fuzzy, c-format
384msgid " -e, --debug Prints out debug information [default]\n"
385msgstr " -e, --debug Vypíše ladicí informace\n"
386
387#: utils/cpufreq-info.c:475
388#, c-format
389msgid ""
390" -f, --freq Get frequency the CPU currently runs at, according\n"
391" to the cpufreq core *\n"
392msgstr ""
393" -f, --freq Zjistí aktuální frekvenci, na které CPU běží\n"
394" podle cpufreq *\n"
395
396#: utils/cpufreq-info.c:477
397#, c-format
398msgid ""
399" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
400" it from hardware (only available to root) *\n"
401msgstr ""
402" -w, --hwfreq Zjistí aktuální frekvenci, na které CPU běží\n"
403" z hardware (dostupné jen uživateli root) *\n"
404
405#: utils/cpufreq-info.c:479
406#, c-format
407msgid ""
408" -l, --hwlimits Determine the minimum and maximum CPU frequency "
409"allowed *\n"
410msgstr ""
411" -l, --hwlimits Zjistí minimální a maximální dostupnou frekvenci CPU "
412"*\n"
413
414#: utils/cpufreq-info.c:480
415#, c-format
416msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
417msgstr " -d, --driver Zjistí aktivní ovladaÄ cpufreq *\n"
418
419#: utils/cpufreq-info.c:481
420#, c-format
421msgid " -p, --policy Gets the currently used cpufreq policy *\n"
422msgstr " -p, --policy Zjistí aktuální taktiku cpufreq *\n"
423
424#: utils/cpufreq-info.c:482
425#, c-format
426msgid " -g, --governors Determines available cpufreq governors *\n"
427msgstr " -g, --governors Zjistí dostupné regulátory cpufreq *\n"
428
429#: utils/cpufreq-info.c:483
430#, fuzzy, c-format
431msgid ""
432" -r, --related-cpus Determines which CPUs run at the same hardware "
433"frequency *\n"
434msgstr ""
435" -a, --affected-cpus Zjistí, které CPU musí měnit frekvenci zároveň *\n"
436
437#: utils/cpufreq-info.c:484
438#, fuzzy, c-format
439msgid ""
440" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
441" coordinated by software *\n"
442msgstr ""
443" -a, --affected-cpus Zjistí, které CPU musí měnit frekvenci zároveň *\n"
444
445#: utils/cpufreq-info.c:486
446#, c-format
447msgid " -s, --stats Shows cpufreq statistics if available\n"
448msgstr " -s, --stats Zobrazí statistiku cpufreq, je-li dostupná\n"
449
450#: utils/cpufreq-info.c:487
451#, fuzzy, c-format
452msgid ""
453" -y, --latency Determines the maximum latency on CPU frequency "
454"changes *\n"
455msgstr ""
456" -l, --hwlimits Zjistí minimální a maximální dostupnou frekvenci CPU "
457"*\n"
458
459#: utils/cpufreq-info.c:488
460#, c-format
461msgid " -b, --boost Checks for turbo or boost modes *\n"
462msgstr ""
463
464#: utils/cpufreq-info.c:489
465#, c-format
466msgid ""
467" -o, --proc Prints out information like provided by the /proc/"
468"cpufreq\n"
469" interface in 2.4. and early 2.6. kernels\n"
470msgstr ""
471" -o, --proc Vypíše informace ve formátu, jaký používalo rozhraní\n"
472" /proc/cpufreq v kernelech Å™ady 2.4 a Äasné 2.6\n"
473
474#: utils/cpufreq-info.c:491
475#, fuzzy, c-format
476msgid ""
477" -m, --human human-readable output for the -f, -w, -s and -y "
478"parameters\n"
479msgstr ""
480" -m, --human Výstup parametrů -f, -w a -s v „lidmi Äitelném“ "
481"formátu\n"
482
483#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
484#, c-format
485msgid " -h, --help Prints out this screen\n"
486msgstr " -h, --help Vypíše tuto nápovědu\n"
487
488#: utils/cpufreq-info.c:495
489#, c-format
490msgid ""
491"If no argument or only the -c, --cpu parameter is given, debug output about\n"
492"cpufreq is printed which is useful e.g. for reporting bugs.\n"
493msgstr ""
494"Není-li zadán žádný parametr nebo je-li zadán pouze pÅ™epínaÄ -c, --cpu, "
495"jsou\n"
496"vypsány ladicí informace, což může být užiteÄné například pÅ™i hlášení chyb.\n"
497
498#: utils/cpufreq-info.c:497
499#, c-format
500msgid ""
501"For the arguments marked with *, omitting the -c or --cpu argument is\n"
502"equivalent to setting it to zero\n"
503msgstr ""
504"Není-li pÅ™i použití pÅ™epínaÄů oznaÄených * zadán parametr -c nebo --cpu,\n"
505"předpokládá se jeho hodnota 0.\n"
506
507#: utils/cpufreq-info.c:580
508#, c-format
509msgid ""
510"The argument passed to this tool can't be combined with passing a --cpu "
511"argument\n"
512msgstr "Zadaný parametr nemůže být použit zároveň s pÅ™epínaÄem -c nebo --cpu\n"
513
514#: utils/cpufreq-info.c:596
515#, c-format
516msgid ""
517"You can't specify more than one --cpu parameter and/or\n"
518"more than one output-specific argument\n"
519msgstr ""
520"Nelze zadat více než jeden parametr -c nebo --cpu\n"
521"anebo více než jeden parametr urÄující výstup\n"
522
523#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
524#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
525#, c-format
526msgid "invalid or unknown argument\n"
527msgstr "neplatný nebo neznámý parametr\n"
528
529#: utils/cpufreq-info.c:617
530#, c-format
531msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
532msgstr "nelze analyzovat CPU %d, vypadá to, že není přítomen\n"
533
534#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
535#, c-format
536msgid "analyzing CPU %d:\n"
537msgstr "analyzuji CPU %d:\n"
538
539#: utils/cpufreq-set.c:25
540#, fuzzy, c-format
541msgid "Usage: cpupower frequency-set [options]\n"
542msgstr "Užití: cpufreq-set [pÅ™epínaÄe]\n"
543
544#: utils/cpufreq-set.c:27
545#, c-format
546msgid ""
547" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
548"select\n"
549msgstr ""
550" -d FREQ, --min FREQ Nová nejnižší frekvence, kterou může regulátor "
551"vybrat\n"
552
553#: utils/cpufreq-set.c:28
554#, c-format
555msgid ""
556" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
557"select\n"
558msgstr ""
559" -u FREQ, --max FREQ Nová nejvyšší frekvence, kterou může regulátor "
560"zvolit\n"
561
562#: utils/cpufreq-set.c:29
563#, c-format
564msgid " -g GOV, --governor GOV new cpufreq governor\n"
565msgstr " -g GOV, --governors GOV Nový regulátor cpufreq\n"
566
567#: utils/cpufreq-set.c:30
568#, c-format
569msgid ""
570" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
571" governor to be available and loaded\n"
572msgstr ""
573" -f FREQ, --freq FREQ Frekvence, která má být nastavena. Vyžaduje, aby "
574"byl\n"
575" v jádře nahrán regulátor ‚userspace‘.\n"
576
577#: utils/cpufreq-set.c:32
578#, c-format
579msgid " -r, --related Switches all hardware-related CPUs\n"
580msgstr ""
581
582#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
583#, fuzzy, c-format
584msgid " -h, --help Prints out this screen\n"
585msgstr " -h, --help Vypíše tuto nápovědu\n"
586
587#: utils/cpufreq-set.c:35
588#, fuzzy, c-format
589msgid ""
590"Notes:\n"
591"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
592msgstr ""
593"Není-li pÅ™i použití pÅ™epínaÄů oznaÄených * zadán parametr -c nebo --cpu,\n"
594"předpokládá se jeho hodnota 0.\n"
595
596#: utils/cpufreq-set.c:37
597#, fuzzy, c-format
598msgid ""
599"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
600"parameter\n"
601" except the -c CPU, --cpu CPU parameter\n"
602"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
603" by postfixing the value with the wanted unit name, without any space\n"
604" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
605msgstr ""
606"Poznámky:\n"
607"1. Vynechání parametru -c nebo --cpu je ekvivalentní jeho nastavení na 0\n"
608"2. PÅ™epínaÄ -f nebo --freq nemůže být použit zároveň s žádným jiným vyjma -"
609"c\n"
610" nebo --cpu\n"
611"3. Frekvence (FREQ) mohou být zadány v Hz, kHz (výchozí), MHz, GHz nebo THz\n"
612" pÅ™ipojením názvu jednotky bez mezery mezi Äíslem a jednotkou\n"
613" (FREQ v kHz =^ Hz * 0,001 = ^ MHz * 1000 =^ GHz * 1000000)\n"
614
615#: utils/cpufreq-set.c:57
616#, c-format
617msgid ""
618"Error setting new values. Common errors:\n"
619"- Do you have proper administration rights? (super-user?)\n"
620"- Is the governor you requested available and modprobed?\n"
621"- Trying to set an invalid policy?\n"
622"- Trying to set a specific frequency, but userspace governor is not "
623"available,\n"
624" for example because of hardware which cannot be set to a specific "
625"frequency\n"
626" or because the userspace governor isn't loaded?\n"
627msgstr ""
628"Chyba při nastavování nových hodnot. Obvyklé problémy:\n"
629"- Máte patÅ™iÄná administrátorská práva? (root?)\n"
630"- Je požadovaný regulátor dostupný v jádře? (modprobe?)\n"
631"- Snažíte se nastavit neplatnou taktiku?\n"
632"- Snažíte se nastavit urÄitou frekvenci, ale není dostupný\n"
633" regulátor ‚userspace‘, například protože není nahrán v jádře,\n"
634" nebo nelze na tomto hardware nastavit urÄitou frekvenci?\n"
635
636#: utils/cpufreq-set.c:170
637#, c-format
638msgid "wrong, unknown or unhandled CPU?\n"
639msgstr "neznámý nebo nepodporovaný CPU?\n"
640
641#: utils/cpufreq-set.c:302
642#, c-format
643msgid ""
644"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
645"-g/--governor parameters\n"
646msgstr ""
647"pÅ™epínaÄ -f/--freq nemůže být použit zároveň\n"
648"s pÅ™epínaÄem -d/--min, -u/--max nebo -g/--governor\n"
649
650#: utils/cpufreq-set.c:308
651#, c-format
652msgid ""
653"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
654"-g/--governor must be passed\n"
655msgstr ""
656"Musí být zadán alespoň jeden pÅ™epínaÄ\n"
657"-f/--freq, -d/--min, -u/--max nebo -g/--governor\n"
658
659#: utils/cpufreq-set.c:347
660#, c-format
661msgid "Setting cpu: %d\n"
662msgstr ""
663
664#: utils/cpupower-set.c:22
665#, c-format
666msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
667msgstr ""
668
669#: utils/cpupower-set.c:24
670#, c-format
671msgid ""
672" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
673" Intel models [0-15], see manpage for details\n"
674msgstr ""
675
676#: utils/cpupower-set.c:26
677#, c-format
678msgid ""
679" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
680msgstr ""
681
682#: utils/cpupower-set.c:27
683#, c-format
684msgid ""
685" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
686"policy.\n"
687msgstr ""
688
689#: utils/cpupower-set.c:80
690#, c-format
691msgid "--perf-bias param out of range [0-%d]\n"
692msgstr ""
693
694#: utils/cpupower-set.c:91
695#, c-format
696msgid "--sched-mc param out of range [0-%d]\n"
697msgstr ""
698
699#: utils/cpupower-set.c:102
700#, c-format
701msgid "--sched-smt param out of range [0-%d]\n"
702msgstr ""
703
704#: utils/cpupower-set.c:121
705#, c-format
706msgid "Error setting sched-mc %s\n"
707msgstr ""
708
709#: utils/cpupower-set.c:127
710#, c-format
711msgid "Error setting sched-smt %s\n"
712msgstr ""
713
714#: utils/cpupower-set.c:146
715#, c-format
716msgid "Error setting perf-bias value on CPU %d\n"
717msgstr ""
718
719#: utils/cpupower-info.c:21
720#, c-format
721msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
722msgstr ""
723
724#: utils/cpupower-info.c:23
725#, c-format
726msgid ""
727" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
728" Intel models [0-15], see manpage for details\n"
729msgstr ""
730
731#: utils/cpupower-info.c:25
732#, fuzzy, c-format
733msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
734msgstr " -p, --policy Zjistí aktuální taktiku cpufreq *\n"
735
736#: utils/cpupower-info.c:26
737#, c-format
738msgid ""
739" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
740msgstr ""
741
742#: utils/cpupower-info.c:28
743#, c-format
744msgid ""
745"\n"
746"Passing no option will show all info, by default only on core 0\n"
747msgstr ""
748
749#: utils/cpupower-info.c:102
750#, c-format
751msgid "System's multi core scheduler setting: "
752msgstr ""
753
754#. if sysfs file is missing it's: errno == ENOENT
755#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
756#, c-format
757msgid "not supported\n"
758msgstr ""
759
760#: utils/cpupower-info.c:111
761#, c-format
762msgid "System's thread sibling scheduler setting: "
763msgstr ""
764
765#: utils/cpupower-info.c:126
766#, c-format
767msgid "Intel's performance bias setting needs root privileges\n"
768msgstr ""
769
770#: utils/cpupower-info.c:128
771#, c-format
772msgid "System does not support Intel's performance bias setting\n"
773msgstr ""
774
775#: utils/cpupower-info.c:147
776#, c-format
777msgid "Could not read perf-bias value\n"
778msgstr ""
779
780#: utils/cpupower-info.c:150
781#, c-format
782msgid "perf-bias: %d\n"
783msgstr ""
784
785#: utils/cpuidle-info.c:28
786#, fuzzy, c-format
787msgid "Analyzing CPU %d:\n"
788msgstr "analyzuji CPU %d:\n"
789
790#: utils/cpuidle-info.c:32
791#, c-format
792msgid "CPU %u: No idle states\n"
793msgstr ""
794
795#: utils/cpuidle-info.c:36
796#, c-format
797msgid "CPU %u: Can't read idle state info\n"
798msgstr ""
799
800#: utils/cpuidle-info.c:41
801#, c-format
802msgid "Could not determine max idle state %u\n"
803msgstr ""
804
805#: utils/cpuidle-info.c:46
806#, c-format
807msgid "Number of idle states: %d\n"
808msgstr ""
809
810#: utils/cpuidle-info.c:48
811#, fuzzy, c-format
812msgid "Available idle states:"
813msgstr " dostupné frekvence: "
814
815#: utils/cpuidle-info.c:71
816#, c-format
817msgid "Flags/Description: %s\n"
818msgstr ""
819
820#: utils/cpuidle-info.c:74
821#, c-format
822msgid "Latency: %lu\n"
823msgstr ""
824
825#: utils/cpuidle-info.c:76
826#, c-format
827msgid "Usage: %lu\n"
828msgstr ""
829
830#: utils/cpuidle-info.c:78
831#, c-format
832msgid "Duration: %llu\n"
833msgstr ""
834
835#: utils/cpuidle-info.c:90
836#, c-format
837msgid "Could not determine cpuidle driver\n"
838msgstr ""
839
840#: utils/cpuidle-info.c:94
841#, fuzzy, c-format
842msgid "CPUidle driver: %s\n"
843msgstr " ovladaÄ: %s\n"
844
845#: utils/cpuidle-info.c:99
846#, c-format
847msgid "Could not determine cpuidle governor\n"
848msgstr ""
849
850#: utils/cpuidle-info.c:103
851#, c-format
852msgid "CPUidle governor: %s\n"
853msgstr ""
854
855#: utils/cpuidle-info.c:122
856#, c-format
857msgid "CPU %u: Can't read C-state info\n"
858msgstr ""
859
860#. printf("Cstates: %d\n", cstates);
861#: utils/cpuidle-info.c:127
862#, c-format
863msgid "active state: C0\n"
864msgstr ""
865
866#: utils/cpuidle-info.c:128
867#, c-format
868msgid "max_cstate: C%u\n"
869msgstr ""
870
871#: utils/cpuidle-info.c:129
872#, c-format
873msgid "maximum allowed latency: %lu usec\n"
874msgstr ""
875
876#: utils/cpuidle-info.c:130
877#, c-format
878msgid "states:\t\n"
879msgstr ""
880
881#: utils/cpuidle-info.c:132
882#, c-format
883msgid " C%d: type[C%d] "
884msgstr ""
885
886#: utils/cpuidle-info.c:134
887#, c-format
888msgid "promotion[--] demotion[--] "
889msgstr ""
890
891#: utils/cpuidle-info.c:135
892#, c-format
893msgid "latency[%03lu] "
894msgstr ""
895
896#: utils/cpuidle-info.c:137
897#, c-format
898msgid "usage[%08lu] "
899msgstr ""
900
901#: utils/cpuidle-info.c:139
902#, c-format
903msgid "duration[%020Lu] \n"
904msgstr ""
905
906#: utils/cpuidle-info.c:147
907#, fuzzy, c-format
908msgid "Usage: cpupower idleinfo [options]\n"
909msgstr "Užití: cpufreq-info [pÅ™epínaÄe]\n"
910
911#: utils/cpuidle-info.c:149
912#, fuzzy, c-format
913msgid " -s, --silent Only show general C-state information\n"
914msgstr " -e, --debug Vypíše ladicí informace\n"
915
916#: utils/cpuidle-info.c:150
917#, fuzzy, c-format
918msgid ""
919" -o, --proc Prints out information like provided by the /proc/"
920"acpi/processor/*/power\n"
921" interface in older kernels\n"
922msgstr ""
923" -o, --proc Vypíše informace ve formátu, jaký používalo rozhraní\n"
924" /proc/cpufreq v kernelech Å™ady 2.4 a Äasné 2.6\n"
925
926#: utils/cpuidle-info.c:209
927#, fuzzy, c-format
928msgid "You can't specify more than one output-specific argument\n"
929msgstr ""
930"Nelze zadat více než jeden parametr -c nebo --cpu\n"
931"anebo více než jeden parametr urÄující výstup\n"
932
933#~ msgid ""
934#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
935#~ "about\n"
936#~ msgstr ""
937#~ " -c CPU, --cpu CPU Číslo CPU, o kterém se mají zjistit informace\n"
938
939#~ msgid ""
940#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
941#~ "modified\n"
942#~ msgstr ""
943#~ " -c CPU, --cpu CPU Číslo CPU pro který se má provést nastavení "
944#~ "cpufreq\n"
diff --git a/tools/power/cpupower/po/de.po b/tools/power/cpupower/po/de.po
new file mode 100644
index 000000000000..78c09e51663a
--- /dev/null
+++ b/tools/power/cpupower/po/de.po
@@ -0,0 +1,961 @@
1# German translations for cpufrequtils package
2# German messages for cpufrequtils.
3# Copyright (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.net>
4# This file is distributed under the same license as the cpufrequtils package.
5#
6msgid ""
7msgstr ""
8"Project-Id-Version: cpufrequtils 006\n"
9"Report-Msgid-Bugs-To: \n"
10"POT-Creation-Date: 2011-03-08 17:03+0100\n"
11"PO-Revision-Date: 2009-08-08 17:18+0100\n"
12"Last-Translator: <linux@dominikbrodowski.net>\n"
13"Language-Team: NONE\n"
14"Language: \n"
15"MIME-Version: 1.0\n"
16"Content-Type: text/plain; charset=ISO-8859-1\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
20#: utils/idle_monitor/nhm_idle.c:36
21msgid "Processor Core C3"
22msgstr ""
23
24#: utils/idle_monitor/nhm_idle.c:43
25msgid "Processor Core C6"
26msgstr ""
27
28#: utils/idle_monitor/nhm_idle.c:51
29msgid "Processor Package C3"
30msgstr ""
31
32#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
33msgid "Processor Package C6"
34msgstr ""
35
36#: utils/idle_monitor/snb_idle.c:33
37msgid "Processor Core C7"
38msgstr ""
39
40#: utils/idle_monitor/snb_idle.c:40
41msgid "Processor Package C2"
42msgstr ""
43
44#: utils/idle_monitor/snb_idle.c:47
45msgid "Processor Package C7"
46msgstr ""
47
48#: utils/idle_monitor/amd_fam14h_idle.c:56
49msgid "Package in sleep state (PC1 or deeper)"
50msgstr ""
51
52#: utils/idle_monitor/amd_fam14h_idle.c:63
53msgid "Processor Package C1"
54msgstr ""
55
56#: utils/idle_monitor/amd_fam14h_idle.c:77
57msgid "North Bridge P1 boolean counter (returns 0 or 1)"
58msgstr ""
59
60#: utils/idle_monitor/mperf_monitor.c:35
61msgid "Processor Core not idle"
62msgstr ""
63
64#: utils/idle_monitor/mperf_monitor.c:42
65msgid "Processor Core in an idle state"
66msgstr ""
67
68#: utils/idle_monitor/mperf_monitor.c:50
69msgid "Average Frequency (including boost) in MHz"
70msgstr ""
71
72#: utils/idle_monitor/cpupower-monitor.c:66
73#, c-format
74msgid ""
75"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
76"interval_sec | -c command ...]\n"
77msgstr ""
78
79#: utils/idle_monitor/cpupower-monitor.c:69
80#, c-format
81msgid ""
82"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
83"interval_sec | -c command ...]\n"
84msgstr ""
85
86#: utils/idle_monitor/cpupower-monitor.c:71
87#, c-format
88msgid "\t -v: be more verbose\n"
89msgstr ""
90
91#: utils/idle_monitor/cpupower-monitor.c:73
92#, c-format
93msgid "\t -h: print this help\n"
94msgstr ""
95
96#: utils/idle_monitor/cpupower-monitor.c:74
97#, c-format
98msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
99msgstr ""
100
101#: utils/idle_monitor/cpupower-monitor.c:75
102#, c-format
103msgid "\t -t: show CPU topology/hierarchy\n"
104msgstr ""
105
106#: utils/idle_monitor/cpupower-monitor.c:76
107#, c-format
108msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
109msgstr ""
110
111#: utils/idle_monitor/cpupower-monitor.c:77
112#, c-format
113msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
114msgstr ""
115
116#: utils/idle_monitor/cpupower-monitor.c:79
117#, c-format
118msgid ""
119"only one of: -t, -l, -m are allowed\n"
120"If none of them is passed,"
121msgstr ""
122
123#: utils/idle_monitor/cpupower-monitor.c:80
124#, c-format
125msgid " all supported monitors are shown\n"
126msgstr ""
127
128#: utils/idle_monitor/cpupower-monitor.c:197
129#, c-format
130msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
131msgstr ""
132
133#: utils/idle_monitor/cpupower-monitor.c:207
134#, c-format
135msgid " *is offline\n"
136msgstr ""
137
138#: utils/idle_monitor/cpupower-monitor.c:236
139#, c-format
140msgid "%s: max monitor name length (%d) exceeded\n"
141msgstr ""
142
143#: utils/idle_monitor/cpupower-monitor.c:250
144#, c-format
145msgid "No matching monitor found in %s, try -l option\n"
146msgstr ""
147
148#: utils/idle_monitor/cpupower-monitor.c:266
149#, c-format
150msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
151msgstr ""
152
153#: utils/idle_monitor/cpupower-monitor.c:319
154#, c-format
155msgid "%s took %.5f seconds and exited with status %d\n"
156msgstr ""
157
158#: utils/idle_monitor/cpupower-monitor.c:406
159#, c-format
160msgid "Cannot read number of available processors\n"
161msgstr ""
162
163#: utils/idle_monitor/cpupower-monitor.c:417
164#, c-format
165msgid "Available monitor %s needs root access\n"
166msgstr ""
167
168#: utils/idle_monitor/cpupower-monitor.c:428
169#, c-format
170msgid "No HW Cstate monitors found\n"
171msgstr ""
172
173#: utils/cpupower.c:78
174#, c-format
175msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
176msgstr ""
177
178#: utils/cpupower.c:79
179#, c-format
180msgid "cpupower --version\n"
181msgstr ""
182
183#: utils/cpupower.c:80
184#, c-format
185msgid "Supported subcommands are:\n"
186msgstr ""
187
188#: utils/cpupower.c:83
189#, c-format
190msgid ""
191"\n"
192"Some subcommands can make use of the -c cpulist option.\n"
193msgstr ""
194
195#: utils/cpupower.c:84
196#, c-format
197msgid "Look at the general cpupower manpage how to use it\n"
198msgstr ""
199
200#: utils/cpupower.c:85
201#, c-format
202msgid "and read up the subcommand's manpage whether it is supported.\n"
203msgstr ""
204
205#: utils/cpupower.c:86
206#, c-format
207msgid ""
208"\n"
209"Use cpupower help subcommand for getting help for above subcommands.\n"
210msgstr ""
211
212#: utils/cpupower.c:91
213#, c-format
214msgid "Report errors and bugs to %s, please.\n"
215msgstr "Bitte melden Sie Fehler an %s.\n"
216
217#: utils/cpupower.c:114
218#, c-format
219msgid "Error parsing cpu list\n"
220msgstr ""
221
222#: utils/cpupower.c:172
223#, c-format
224msgid "Subcommand %s needs root privileges\n"
225msgstr ""
226
227#: utils/cpufreq-info.c:31
228#, c-format
229msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
230msgstr ""
231"Konnte nicht die Anzahl der CPUs herausfinden (%s : %s), nehme daher 1 an.\n"
232
233#: utils/cpufreq-info.c:63
234#, c-format
235msgid ""
236" minimum CPU frequency - maximum CPU frequency - governor\n"
237msgstr ""
238" minimale CPU-Taktfreq. - maximale CPU-Taktfreq. - Regler \n"
239
240#: utils/cpufreq-info.c:151
241#, c-format
242msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
243msgstr ""
244
245#. P state changes via MSR are identified via cpuid 80000007
246#. on Intel and AMD, but we assume boost capable machines can do that
247#. if (cpuid_eax(0x80000000) >= 0x80000007
248#. && (cpuid_edx(0x80000007) & (1 << 7)))
249#.
250#: utils/cpufreq-info.c:161
251#, c-format
252msgid " boost state support: \n"
253msgstr ""
254
255#: utils/cpufreq-info.c:163
256#, c-format
257msgid " Supported: %s\n"
258msgstr ""
259
260#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
261msgid "yes"
262msgstr ""
263
264#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
265msgid "no"
266msgstr ""
267
268#: utils/cpufreq-info.c:164
269#, fuzzy, c-format
270msgid " Active: %s\n"
271msgstr " Treiber: %s\n"
272
273#: utils/cpufreq-info.c:177
274#, c-format
275msgid " Boost States: %d\n"
276msgstr ""
277
278#: utils/cpufreq-info.c:178
279#, c-format
280msgid " Total States: %d\n"
281msgstr ""
282
283#: utils/cpufreq-info.c:181
284#, c-format
285msgid " Pstate-Pb%d: %luMHz (boost state)\n"
286msgstr ""
287
288#: utils/cpufreq-info.c:184
289#, c-format
290msgid " Pstate-P%d: %luMHz\n"
291msgstr ""
292
293#: utils/cpufreq-info.c:211
294#, c-format
295msgid " no or unknown cpufreq driver is active on this CPU\n"
296msgstr " kein oder nicht bestimmbarer cpufreq-Treiber aktiv\n"
297
298#: utils/cpufreq-info.c:213
299#, c-format
300msgid " driver: %s\n"
301msgstr " Treiber: %s\n"
302
303#: utils/cpufreq-info.c:219
304#, c-format
305msgid " CPUs which run at the same hardware frequency: "
306msgstr " Folgende CPUs laufen mit der gleichen Hardware-Taktfrequenz: "
307
308#: utils/cpufreq-info.c:230
309#, c-format
310msgid " CPUs which need to have their frequency coordinated by software: "
311msgstr " Die Taktfrequenz folgender CPUs werden per Software koordiniert: "
312
313#: utils/cpufreq-info.c:241
314#, c-format
315msgid " maximum transition latency: "
316msgstr " Maximale Dauer eines Taktfrequenzwechsels: "
317
318#: utils/cpufreq-info.c:247
319#, c-format
320msgid " hardware limits: "
321msgstr " Hardwarebedingte Grenzen der Taktfrequenz: "
322
323#: utils/cpufreq-info.c:256
324#, c-format
325msgid " available frequency steps: "
326msgstr " mögliche Taktfrequenzen: "
327
328#: utils/cpufreq-info.c:269
329#, c-format
330msgid " available cpufreq governors: "
331msgstr " mögliche Regler: "
332
333#: utils/cpufreq-info.c:280
334#, c-format
335msgid " current policy: frequency should be within "
336msgstr " momentane Taktik: die Frequenz soll innerhalb "
337
338#: utils/cpufreq-info.c:282
339#, c-format
340msgid " and "
341msgstr " und "
342
343#: utils/cpufreq-info.c:286
344#, c-format
345msgid ""
346"The governor \"%s\" may decide which speed to use\n"
347" within this range.\n"
348msgstr ""
349" liegen. Der Regler \"%s\" kann frei entscheiden,\n"
350" welche Taktfrequenz innerhalb dieser Grenze verwendet "
351"wird.\n"
352
353#: utils/cpufreq-info.c:293
354#, c-format
355msgid " current CPU frequency is "
356msgstr " momentane Taktfrequenz ist "
357
358#: utils/cpufreq-info.c:296
359#, c-format
360msgid " (asserted by call to hardware)"
361msgstr " (verifiziert durch Nachfrage bei der Hardware)"
362
363#: utils/cpufreq-info.c:304
364#, c-format
365msgid " cpufreq stats: "
366msgstr " Statistik:"
367
368#: utils/cpufreq-info.c:472
369#, fuzzy, c-format
370msgid "Usage: cpupower freqinfo [options]\n"
371msgstr "Aufruf: cpufreq-info [Optionen]\n"
372
373#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
374#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
375#, c-format
376msgid "Options:\n"
377msgstr "Optionen:\n"
378
379#: utils/cpufreq-info.c:474
380#, fuzzy, c-format
381msgid " -e, --debug Prints out debug information [default]\n"
382msgstr ""
383" -e, --debug Erzeugt detaillierte Informationen, hilfreich\n"
384" zum Aufspüren von Fehlern\n"
385
386#: utils/cpufreq-info.c:475
387#, c-format
388msgid ""
389" -f, --freq Get frequency the CPU currently runs at, according\n"
390" to the cpufreq core *\n"
391msgstr ""
392" -f, --freq Findet die momentane CPU-Taktfrquenz heraus (nach\n"
393" Meinung des Betriebssystems) *\n"
394
395#: utils/cpufreq-info.c:477
396#, c-format
397msgid ""
398" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
399" it from hardware (only available to root) *\n"
400msgstr ""
401" -w, --hwfreq Findet die momentane CPU-Taktfrequenz heraus\n"
402" (verifiziert durch Nachfrage bei der Hardware)\n"
403" [nur der Administrator kann dies tun] *\n"
404
405#: utils/cpufreq-info.c:479
406#, c-format
407msgid ""
408" -l, --hwlimits Determine the minimum and maximum CPU frequency "
409"allowed *\n"
410msgstr ""
411" -l, --hwlimits Findet die minimale und maximale Taktfrequenz heraus "
412"*\n"
413
414#: utils/cpufreq-info.c:480
415#, c-format
416msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
417msgstr " -d, --driver Findet den momentanen Treiber heraus *\n"
418
419#: utils/cpufreq-info.c:481
420#, c-format
421msgid " -p, --policy Gets the currently used cpufreq policy *\n"
422msgstr " -p, --policy Findet die momentane Taktik heraus *\n"
423
424#: utils/cpufreq-info.c:482
425#, c-format
426msgid " -g, --governors Determines available cpufreq governors *\n"
427msgstr " -g, --governors Erzeugt eine Liste mit verfügbaren Reglern *\n"
428
429#: utils/cpufreq-info.c:483
430#, c-format
431msgid ""
432" -r, --related-cpus Determines which CPUs run at the same hardware "
433"frequency *\n"
434msgstr ""
435" -r, --related-cpus Findet heraus, welche CPUs mit derselben "
436"physikalischen\n"
437" Taktfrequenz laufen *\n"
438
439#: utils/cpufreq-info.c:484
440#, c-format
441msgid ""
442" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
443" coordinated by software *\n"
444msgstr ""
445" -a, --affected-cpus Findet heraus, von welchen CPUs die Taktfrequenz "
446"durch\n"
447" Software koordiniert werden muss *\n"
448
449#: utils/cpufreq-info.c:486
450#, c-format
451msgid " -s, --stats Shows cpufreq statistics if available\n"
452msgstr ""
453" -s, --stats Zeigt, sofern möglich, Statistiken über cpufreq an.\n"
454
455#: utils/cpufreq-info.c:487
456#, c-format
457msgid ""
458" -y, --latency Determines the maximum latency on CPU frequency "
459"changes *\n"
460msgstr ""
461" -y, --latency Findet die maximale Dauer eines Taktfrequenzwechsels "
462"heraus *\n"
463
464#: utils/cpufreq-info.c:488
465#, c-format
466msgid " -b, --boost Checks for turbo or boost modes *\n"
467msgstr ""
468
469#: utils/cpufreq-info.c:489
470#, c-format
471msgid ""
472" -o, --proc Prints out information like provided by the /proc/"
473"cpufreq\n"
474" interface in 2.4. and early 2.6. kernels\n"
475msgstr ""
476" -o, --proc Erzeugt Informationen in einem ähnlichem Format zu "
477"dem\n"
478" der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
479" Kernel-Versionen\n"
480
481#: utils/cpufreq-info.c:491
482#, c-format
483msgid ""
484" -m, --human human-readable output for the -f, -w, -s and -y "
485"parameters\n"
486msgstr ""
487" -m, --human Formatiert Taktfrequenz- und Zeitdauerangaben in "
488"besser\n"
489" lesbarer Form (MHz, GHz; us, ms)\n"
490
491#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
492#, c-format
493msgid " -h, --help Prints out this screen\n"
494msgstr " -h, --help Gibt diese Kurzübersicht aus\n"
495
496#: utils/cpufreq-info.c:495
497#, c-format
498msgid ""
499"If no argument or only the -c, --cpu parameter is given, debug output about\n"
500"cpufreq is printed which is useful e.g. for reporting bugs.\n"
501msgstr ""
502"Sofern kein anderer Parameter als '-c, --cpu' angegeben wird, liefert "
503"dieses\n"
504"Programm Informationen, die z.B. zum Berichten von Fehlern nützlich sind.\n"
505
506#: utils/cpufreq-info.c:497
507#, c-format
508msgid ""
509"For the arguments marked with *, omitting the -c or --cpu argument is\n"
510"equivalent to setting it to zero\n"
511msgstr ""
512"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n"
513"mittels -c oder --cpu etwas anderes angegeben wird\n"
514
515#: utils/cpufreq-info.c:580
516#, c-format
517msgid ""
518"The argument passed to this tool can't be combined with passing a --cpu "
519"argument\n"
520msgstr "Diese Option kann nicht mit der --cpu-Option kombiniert werden\n"
521
522#: utils/cpufreq-info.c:596
523#, c-format
524msgid ""
525"You can't specify more than one --cpu parameter and/or\n"
526"more than one output-specific argument\n"
527msgstr ""
528"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n"
529"informationsspezifischen Parameter gleichzeitig angeben\n"
530
531#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
532#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
533#, c-format
534msgid "invalid or unknown argument\n"
535msgstr "unbekannter oder falscher Parameter\n"
536
537#: utils/cpufreq-info.c:617
538#, c-format
539msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
540msgstr ""
541"Konnte nicht die CPU %d analysieren, da sie (scheinbar?) nicht existiert.\n"
542
543#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
544#, c-format
545msgid "analyzing CPU %d:\n"
546msgstr "analysiere CPU %d:\n"
547
548#: utils/cpufreq-set.c:25
549#, fuzzy, c-format
550msgid "Usage: cpupower frequency-set [options]\n"
551msgstr "Aufruf: cpufreq-set [Optionen]\n"
552
553#: utils/cpufreq-set.c:27
554#, c-format
555msgid ""
556" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
557"select\n"
558msgstr ""
559" -d FREQ, --min FREQ neue minimale Taktfrequenz, die der Regler\n"
560" auswählen darf\n"
561
562#: utils/cpufreq-set.c:28
563#, c-format
564msgid ""
565" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
566"select\n"
567msgstr ""
568" -u FREQ, --max FREQ neue maximale Taktfrequenz, die der Regler\n"
569" auswählen darf\n"
570
571#: utils/cpufreq-set.c:29
572#, c-format
573msgid " -g GOV, --governor GOV new cpufreq governor\n"
574msgstr " -g GOV, --governors GOV wechsle zu Regler GOV\n"
575
576#: utils/cpufreq-set.c:30
577#, c-format
578msgid ""
579" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
580" governor to be available and loaded\n"
581msgstr ""
582" -f FREQ, --freq FREQ setze exakte Taktfrequenz. Benötigt den Regler\n"
583" 'userspace'.\n"
584
585#: utils/cpufreq-set.c:32
586#, c-format
587msgid " -r, --related Switches all hardware-related CPUs\n"
588msgstr ""
589" -r, --related Setze Werte für alle CPUs, deren Taktfrequenz\n"
590" hardwarebedingt identisch ist.\n"
591
592#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
593#, c-format
594msgid " -h, --help Prints out this screen\n"
595msgstr " -h, --help Gibt diese Kurzübersicht aus\n"
596
597#: utils/cpufreq-set.c:35
598#, fuzzy, c-format
599msgid ""
600"Notes:\n"
601"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
602msgstr ""
603"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n"
604"mittels -c oder --cpu etwas anderes angegeben wird\n"
605
606#: utils/cpufreq-set.c:37
607#, fuzzy, c-format
608msgid ""
609"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
610"parameter\n"
611" except the -c CPU, --cpu CPU parameter\n"
612"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
613" by postfixing the value with the wanted unit name, without any space\n"
614" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
615msgstr ""
616"Hinweise:\n"
617"1. Sofern kein -c oder --cpu-Parameter angegeben ist, wird '--cpu 0'\n"
618" angenommen\n"
619"2. Der Parameter -f bzw. --freq kann mit keinem anderen als dem Parameter\n"
620" -c bzw. --cpu kombiniert werden\n"
621"3. FREQuenzen können in Hz, kHz (Standard), MHz, GHz oder THz eingegeben\n"
622" werden, indem der Wert und unmittelbar anschließend (ohne Leerzeichen!)\n"
623" die Einheit angegeben werden. (Bsp: 1GHz )\n"
624" (FREQuenz in kHz =^ MHz * 1000 =^ GHz * 1000000).\n"
625
626#: utils/cpufreq-set.c:57
627#, c-format
628msgid ""
629"Error setting new values. Common errors:\n"
630"- Do you have proper administration rights? (super-user?)\n"
631"- Is the governor you requested available and modprobed?\n"
632"- Trying to set an invalid policy?\n"
633"- Trying to set a specific frequency, but userspace governor is not "
634"available,\n"
635" for example because of hardware which cannot be set to a specific "
636"frequency\n"
637" or because the userspace governor isn't loaded?\n"
638msgstr ""
639"Beim Einstellen ist ein Fehler aufgetreten. Typische Fehlerquellen sind:\n"
640"- nicht ausreichende Rechte (Administrator)\n"
641"- der Regler ist nicht verfügbar bzw. nicht geladen\n"
642"- die angegebene Taktik ist inkorrekt\n"
643"- eine spezifische Frequenz wurde angegeben, aber der Regler 'userspace'\n"
644" kann entweder hardwarebedingt nicht genutzt werden oder ist nicht geladen\n"
645
646#: utils/cpufreq-set.c:170
647#, c-format
648msgid "wrong, unknown or unhandled CPU?\n"
649msgstr "unbekannte oder nicht regelbare CPU\n"
650
651#: utils/cpufreq-set.c:302
652#, c-format
653msgid ""
654"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
655"-g/--governor parameters\n"
656msgstr ""
657"Der -f bzw. --freq-Parameter kann nicht mit den Parametern -d/--min, -u/--"
658"max\n"
659"oder -g/--governor kombiniert werden\n"
660
661#: utils/cpufreq-set.c:308
662#, c-format
663msgid ""
664"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
665"-g/--governor must be passed\n"
666msgstr ""
667"Es muss mindestens ein Parameter aus -f/--freq, -d/--min, -u/--max oder\n"
668"-g/--governor angegeben werden.\n"
669
670#: utils/cpufreq-set.c:347
671#, c-format
672msgid "Setting cpu: %d\n"
673msgstr ""
674
675#: utils/cpupower-set.c:22
676#, c-format
677msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
678msgstr ""
679
680#: utils/cpupower-set.c:24
681#, c-format
682msgid ""
683" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
684" Intel models [0-15], see manpage for details\n"
685msgstr ""
686
687#: utils/cpupower-set.c:26
688#, c-format
689msgid ""
690" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
691msgstr ""
692
693#: utils/cpupower-set.c:27
694#, c-format
695msgid ""
696" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
697"policy.\n"
698msgstr ""
699
700#: utils/cpupower-set.c:80
701#, c-format
702msgid "--perf-bias param out of range [0-%d]\n"
703msgstr ""
704
705#: utils/cpupower-set.c:91
706#, c-format
707msgid "--sched-mc param out of range [0-%d]\n"
708msgstr ""
709
710#: utils/cpupower-set.c:102
711#, c-format
712msgid "--sched-smt param out of range [0-%d]\n"
713msgstr ""
714
715#: utils/cpupower-set.c:121
716#, c-format
717msgid "Error setting sched-mc %s\n"
718msgstr ""
719
720#: utils/cpupower-set.c:127
721#, c-format
722msgid "Error setting sched-smt %s\n"
723msgstr ""
724
725#: utils/cpupower-set.c:146
726#, c-format
727msgid "Error setting perf-bias value on CPU %d\n"
728msgstr ""
729
730#: utils/cpupower-info.c:21
731#, c-format
732msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
733msgstr ""
734
735#: utils/cpupower-info.c:23
736#, c-format
737msgid ""
738" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
739" Intel models [0-15], see manpage for details\n"
740msgstr ""
741
742#: utils/cpupower-info.c:25
743#, fuzzy, c-format
744msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
745msgstr " -p, --policy Findet die momentane Taktik heraus *\n"
746
747#: utils/cpupower-info.c:26
748#, c-format
749msgid ""
750" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
751msgstr ""
752
753#: utils/cpupower-info.c:28
754#, c-format
755msgid ""
756"\n"
757"Passing no option will show all info, by default only on core 0\n"
758msgstr ""
759
760#: utils/cpupower-info.c:102
761#, c-format
762msgid "System's multi core scheduler setting: "
763msgstr ""
764
765#. if sysfs file is missing it's: errno == ENOENT
766#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
767#, c-format
768msgid "not supported\n"
769msgstr ""
770
771#: utils/cpupower-info.c:111
772#, c-format
773msgid "System's thread sibling scheduler setting: "
774msgstr ""
775
776#: utils/cpupower-info.c:126
777#, c-format
778msgid "Intel's performance bias setting needs root privileges\n"
779msgstr ""
780
781#: utils/cpupower-info.c:128
782#, c-format
783msgid "System does not support Intel's performance bias setting\n"
784msgstr ""
785
786#: utils/cpupower-info.c:147
787#, c-format
788msgid "Could not read perf-bias value\n"
789msgstr ""
790
791#: utils/cpupower-info.c:150
792#, c-format
793msgid "perf-bias: %d\n"
794msgstr ""
795
796#: utils/cpuidle-info.c:28
797#, fuzzy, c-format
798msgid "Analyzing CPU %d:\n"
799msgstr "analysiere CPU %d:\n"
800
801#: utils/cpuidle-info.c:32
802#, c-format
803msgid "CPU %u: No idle states\n"
804msgstr ""
805
806#: utils/cpuidle-info.c:36
807#, c-format
808msgid "CPU %u: Can't read idle state info\n"
809msgstr ""
810
811#: utils/cpuidle-info.c:41
812#, c-format
813msgid "Could not determine max idle state %u\n"
814msgstr ""
815
816#: utils/cpuidle-info.c:46
817#, c-format
818msgid "Number of idle states: %d\n"
819msgstr ""
820
821#: utils/cpuidle-info.c:48
822#, fuzzy, c-format
823msgid "Available idle states:"
824msgstr " mögliche Taktfrequenzen: "
825
826#: utils/cpuidle-info.c:71
827#, c-format
828msgid "Flags/Description: %s\n"
829msgstr ""
830
831#: utils/cpuidle-info.c:74
832#, c-format
833msgid "Latency: %lu\n"
834msgstr ""
835
836#: utils/cpuidle-info.c:76
837#, c-format
838msgid "Usage: %lu\n"
839msgstr ""
840
841#: utils/cpuidle-info.c:78
842#, c-format
843msgid "Duration: %llu\n"
844msgstr ""
845
846#: utils/cpuidle-info.c:90
847#, c-format
848msgid "Could not determine cpuidle driver\n"
849msgstr ""
850
851#: utils/cpuidle-info.c:94
852#, fuzzy, c-format
853msgid "CPUidle driver: %s\n"
854msgstr " Treiber: %s\n"
855
856#: utils/cpuidle-info.c:99
857#, c-format
858msgid "Could not determine cpuidle governor\n"
859msgstr ""
860
861#: utils/cpuidle-info.c:103
862#, c-format
863msgid "CPUidle governor: %s\n"
864msgstr ""
865
866#: utils/cpuidle-info.c:122
867#, c-format
868msgid "CPU %u: Can't read C-state info\n"
869msgstr ""
870
871#. printf("Cstates: %d\n", cstates);
872#: utils/cpuidle-info.c:127
873#, c-format
874msgid "active state: C0\n"
875msgstr ""
876
877#: utils/cpuidle-info.c:128
878#, c-format
879msgid "max_cstate: C%u\n"
880msgstr ""
881
882#: utils/cpuidle-info.c:129
883#, fuzzy, c-format
884msgid "maximum allowed latency: %lu usec\n"
885msgstr " Maximale Dauer eines Taktfrequenzwechsels: "
886
887#: utils/cpuidle-info.c:130
888#, c-format
889msgid "states:\t\n"
890msgstr ""
891
892#: utils/cpuidle-info.c:132
893#, c-format
894msgid " C%d: type[C%d] "
895msgstr ""
896
897#: utils/cpuidle-info.c:134
898#, c-format
899msgid "promotion[--] demotion[--] "
900msgstr ""
901
902#: utils/cpuidle-info.c:135
903#, c-format
904msgid "latency[%03lu] "
905msgstr ""
906
907#: utils/cpuidle-info.c:137
908#, c-format
909msgid "usage[%08lu] "
910msgstr ""
911
912#: utils/cpuidle-info.c:139
913#, c-format
914msgid "duration[%020Lu] \n"
915msgstr ""
916
917#: utils/cpuidle-info.c:147
918#, fuzzy, c-format
919msgid "Usage: cpupower idleinfo [options]\n"
920msgstr "Aufruf: cpufreq-info [Optionen]\n"
921
922#: utils/cpuidle-info.c:149
923#, fuzzy, c-format
924msgid " -s, --silent Only show general C-state information\n"
925msgstr ""
926" -e, --debug Erzeugt detaillierte Informationen, hilfreich\n"
927" zum Aufspüren von Fehlern\n"
928
929#: utils/cpuidle-info.c:150
930#, fuzzy, c-format
931msgid ""
932" -o, --proc Prints out information like provided by the /proc/"
933"acpi/processor/*/power\n"
934" interface in older kernels\n"
935msgstr ""
936" -o, --proc Erzeugt Informationen in einem ähnlichem Format zu "
937"dem\n"
938" der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
939" Kernel-Versionen\n"
940
941#: utils/cpuidle-info.c:209
942#, fuzzy, c-format
943msgid "You can't specify more than one output-specific argument\n"
944msgstr ""
945"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n"
946"informationsspezifischen Parameter gleichzeitig angeben\n"
947
948#~ msgid ""
949#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
950#~ "about\n"
951#~ msgstr ""
952#~ " -c CPU, --cpu CPU Nummer der CPU, über die Informationen "
953#~ "herausgefunden werden sollen\n"
954
955#~ msgid ""
956#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
957#~ "modified\n"
958#~ msgstr ""
959#~ " -c CPU, --cpu CPU Nummer der CPU, deren Taktfrequenz-"
960#~ "Einstellung\n"
961#~ " werden soll\n"
diff --git a/tools/power/cpupower/po/fr.po b/tools/power/cpupower/po/fr.po
new file mode 100644
index 000000000000..245ad20a9bf9
--- /dev/null
+++ b/tools/power/cpupower/po/fr.po
@@ -0,0 +1,947 @@
1# French translations for cpufrequtils package
2# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
3# This file is distributed under the same license as the cpufrequtils package.
4# Ducrot Bruno <ducrot@poupinou.org>, 2004.
5#
6#, fuzzy
7msgid ""
8msgstr ""
9"Project-Id-Version: cpufrequtils 0.1-pre2\n"
10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2011-03-08 17:03+0100\n"
12"PO-Revision-Date: 2004-11-17 15:53+1000\n"
13"Last-Translator: Bruno Ducrot <ducrot@poupinou.org>\n"
14"Language-Team: NONE\n"
15"Language: \n"
16"MIME-Version: 1.0\n"
17"Content-Type: text/plain; charset=ISO-8859-1\n"
18"Content-Transfer-Encoding: 8bit\n"
19
20#: utils/idle_monitor/nhm_idle.c:36
21msgid "Processor Core C3"
22msgstr ""
23
24#: utils/idle_monitor/nhm_idle.c:43
25msgid "Processor Core C6"
26msgstr ""
27
28#: utils/idle_monitor/nhm_idle.c:51
29msgid "Processor Package C3"
30msgstr ""
31
32#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
33msgid "Processor Package C6"
34msgstr ""
35
36#: utils/idle_monitor/snb_idle.c:33
37msgid "Processor Core C7"
38msgstr ""
39
40#: utils/idle_monitor/snb_idle.c:40
41msgid "Processor Package C2"
42msgstr ""
43
44#: utils/idle_monitor/snb_idle.c:47
45msgid "Processor Package C7"
46msgstr ""
47
48#: utils/idle_monitor/amd_fam14h_idle.c:56
49msgid "Package in sleep state (PC1 or deeper)"
50msgstr ""
51
52#: utils/idle_monitor/amd_fam14h_idle.c:63
53msgid "Processor Package C1"
54msgstr ""
55
56#: utils/idle_monitor/amd_fam14h_idle.c:77
57msgid "North Bridge P1 boolean counter (returns 0 or 1)"
58msgstr ""
59
60#: utils/idle_monitor/mperf_monitor.c:35
61msgid "Processor Core not idle"
62msgstr ""
63
64#: utils/idle_monitor/mperf_monitor.c:42
65msgid "Processor Core in an idle state"
66msgstr ""
67
68#: utils/idle_monitor/mperf_monitor.c:50
69msgid "Average Frequency (including boost) in MHz"
70msgstr ""
71
72#: utils/idle_monitor/cpupower-monitor.c:66
73#, c-format
74msgid ""
75"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
76"interval_sec | -c command ...]\n"
77msgstr ""
78
79#: utils/idle_monitor/cpupower-monitor.c:69
80#, c-format
81msgid ""
82"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
83"interval_sec | -c command ...]\n"
84msgstr ""
85
86#: utils/idle_monitor/cpupower-monitor.c:71
87#, c-format
88msgid "\t -v: be more verbose\n"
89msgstr ""
90
91#: utils/idle_monitor/cpupower-monitor.c:73
92#, c-format
93msgid "\t -h: print this help\n"
94msgstr ""
95
96#: utils/idle_monitor/cpupower-monitor.c:74
97#, c-format
98msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
99msgstr ""
100
101#: utils/idle_monitor/cpupower-monitor.c:75
102#, c-format
103msgid "\t -t: show CPU topology/hierarchy\n"
104msgstr ""
105
106#: utils/idle_monitor/cpupower-monitor.c:76
107#, c-format
108msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
109msgstr ""
110
111#: utils/idle_monitor/cpupower-monitor.c:77
112#, c-format
113msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
114msgstr ""
115
116#: utils/idle_monitor/cpupower-monitor.c:79
117#, c-format
118msgid ""
119"only one of: -t, -l, -m are allowed\n"
120"If none of them is passed,"
121msgstr ""
122
123#: utils/idle_monitor/cpupower-monitor.c:80
124#, c-format
125msgid " all supported monitors are shown\n"
126msgstr ""
127
128#: utils/idle_monitor/cpupower-monitor.c:197
129#, c-format
130msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
131msgstr ""
132
133#: utils/idle_monitor/cpupower-monitor.c:207
134#, c-format
135msgid " *is offline\n"
136msgstr ""
137
138#: utils/idle_monitor/cpupower-monitor.c:236
139#, c-format
140msgid "%s: max monitor name length (%d) exceeded\n"
141msgstr ""
142
143#: utils/idle_monitor/cpupower-monitor.c:250
144#, c-format
145msgid "No matching monitor found in %s, try -l option\n"
146msgstr ""
147
148#: utils/idle_monitor/cpupower-monitor.c:266
149#, c-format
150msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
151msgstr ""
152
153#: utils/idle_monitor/cpupower-monitor.c:319
154#, c-format
155msgid "%s took %.5f seconds and exited with status %d\n"
156msgstr ""
157
158#: utils/idle_monitor/cpupower-monitor.c:406
159#, c-format
160msgid "Cannot read number of available processors\n"
161msgstr ""
162
163#: utils/idle_monitor/cpupower-monitor.c:417
164#, c-format
165msgid "Available monitor %s needs root access\n"
166msgstr ""
167
168#: utils/idle_monitor/cpupower-monitor.c:428
169#, c-format
170msgid "No HW Cstate monitors found\n"
171msgstr ""
172
173#: utils/cpupower.c:78
174#, c-format
175msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
176msgstr ""
177
178#: utils/cpupower.c:79
179#, c-format
180msgid "cpupower --version\n"
181msgstr ""
182
183#: utils/cpupower.c:80
184#, c-format
185msgid "Supported subcommands are:\n"
186msgstr ""
187
188#: utils/cpupower.c:83
189#, c-format
190msgid ""
191"\n"
192"Some subcommands can make use of the -c cpulist option.\n"
193msgstr ""
194
195#: utils/cpupower.c:84
196#, c-format
197msgid "Look at the general cpupower manpage how to use it\n"
198msgstr ""
199
200#: utils/cpupower.c:85
201#, c-format
202msgid "and read up the subcommand's manpage whether it is supported.\n"
203msgstr ""
204
205#: utils/cpupower.c:86
206#, c-format
207msgid ""
208"\n"
209"Use cpupower help subcommand for getting help for above subcommands.\n"
210msgstr ""
211
212#: utils/cpupower.c:91
213#, c-format
214msgid "Report errors and bugs to %s, please.\n"
215msgstr "Veuillez rapportez les erreurs et les bogues à %s, s'il vous plait.\n"
216
217#: utils/cpupower.c:114
218#, c-format
219msgid "Error parsing cpu list\n"
220msgstr ""
221
222#: utils/cpupower.c:172
223#, c-format
224msgid "Subcommand %s needs root privileges\n"
225msgstr ""
226
227#: utils/cpufreq-info.c:31
228#, c-format
229msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
230msgstr "Détermination du nombre de CPUs (%s : %s) impossible. Assume 1\n"
231
232#: utils/cpufreq-info.c:63
233#, c-format
234msgid ""
235" minimum CPU frequency - maximum CPU frequency - governor\n"
236msgstr ""
237" Fréquence CPU minimale - Fréquence CPU maximale - régulateur\n"
238
239#: utils/cpufreq-info.c:151
240#, c-format
241msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
242msgstr ""
243
244#. P state changes via MSR are identified via cpuid 80000007
245#. on Intel and AMD, but we assume boost capable machines can do that
246#. if (cpuid_eax(0x80000000) >= 0x80000007
247#. && (cpuid_edx(0x80000007) & (1 << 7)))
248#.
249#: utils/cpufreq-info.c:161
250#, c-format
251msgid " boost state support: \n"
252msgstr ""
253
254#: utils/cpufreq-info.c:163
255#, c-format
256msgid " Supported: %s\n"
257msgstr ""
258
259#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
260msgid "yes"
261msgstr ""
262
263#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
264msgid "no"
265msgstr ""
266
267#: utils/cpufreq-info.c:164
268#, fuzzy, c-format
269msgid " Active: %s\n"
270msgstr " pilote : %s\n"
271
272#: utils/cpufreq-info.c:177
273#, c-format
274msgid " Boost States: %d\n"
275msgstr ""
276
277#: utils/cpufreq-info.c:178
278#, c-format
279msgid " Total States: %d\n"
280msgstr ""
281
282#: utils/cpufreq-info.c:181
283#, c-format
284msgid " Pstate-Pb%d: %luMHz (boost state)\n"
285msgstr ""
286
287#: utils/cpufreq-info.c:184
288#, c-format
289msgid " Pstate-P%d: %luMHz\n"
290msgstr ""
291
292#: utils/cpufreq-info.c:211
293#, c-format
294msgid " no or unknown cpufreq driver is active on this CPU\n"
295msgstr " pas de pilotes cpufreq reconnu pour ce CPU\n"
296
297#: utils/cpufreq-info.c:213
298#, c-format
299msgid " driver: %s\n"
300msgstr " pilote : %s\n"
301
302#: utils/cpufreq-info.c:219
303#, fuzzy, c-format
304msgid " CPUs which run at the same hardware frequency: "
305msgstr " CPUs qui doivent changer de fréquences en même temps : "
306
307#: utils/cpufreq-info.c:230
308#, fuzzy, c-format
309msgid " CPUs which need to have their frequency coordinated by software: "
310msgstr " CPUs qui doivent changer de fréquences en même temps : "
311
312#: utils/cpufreq-info.c:241
313#, c-format
314msgid " maximum transition latency: "
315msgstr ""
316
317#: utils/cpufreq-info.c:247
318#, c-format
319msgid " hardware limits: "
320msgstr " limitation matérielle : "
321
322#: utils/cpufreq-info.c:256
323#, c-format
324msgid " available frequency steps: "
325msgstr " plage de fréquence : "
326
327#: utils/cpufreq-info.c:269
328#, c-format
329msgid " available cpufreq governors: "
330msgstr " régulateurs disponibles : "
331
332#: utils/cpufreq-info.c:280
333#, c-format
334msgid " current policy: frequency should be within "
335msgstr " tactique actuelle : la fréquence doit être comprise entre "
336
337#: utils/cpufreq-info.c:282
338#, c-format
339msgid " and "
340msgstr " et "
341
342#: utils/cpufreq-info.c:286
343#, c-format
344msgid ""
345"The governor \"%s\" may decide which speed to use\n"
346" within this range.\n"
347msgstr ""
348"Le régulateur \"%s\" est libre de choisir la vitesse\n"
349" dans cette plage de fréquences.\n"
350
351#: utils/cpufreq-info.c:293
352#, c-format
353msgid " current CPU frequency is "
354msgstr " la fréquence actuelle de ce CPU est "
355
356#: utils/cpufreq-info.c:296
357#, c-format
358msgid " (asserted by call to hardware)"
359msgstr " (vérifié par un appel direct du matériel)"
360
361#: utils/cpufreq-info.c:304
362#, c-format
363msgid " cpufreq stats: "
364msgstr " des statistique concernant cpufreq:"
365
366#: utils/cpufreq-info.c:472
367#, fuzzy, c-format
368msgid "Usage: cpupower freqinfo [options]\n"
369msgstr "Usage : cpufreq-info [options]\n"
370
371#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
372#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
373#, c-format
374msgid "Options:\n"
375msgstr "Options :\n"
376
377#: utils/cpufreq-info.c:474
378#, fuzzy, c-format
379msgid " -e, --debug Prints out debug information [default]\n"
380msgstr " -e, --debug Afficher les informations de déboguage\n"
381
382#: utils/cpufreq-info.c:475
383#, c-format
384msgid ""
385" -f, --freq Get frequency the CPU currently runs at, according\n"
386" to the cpufreq core *\n"
387msgstr ""
388" -f, --freq Obtenir la fréquence actuelle du CPU selon le point\n"
389" de vue du coeur du système de cpufreq *\n"
390
391#: utils/cpufreq-info.c:477
392#, c-format
393msgid ""
394" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
395" it from hardware (only available to root) *\n"
396msgstr ""
397" -w, --hwfreq Obtenir la fréquence actuelle du CPU directement par\n"
398" le matériel (doit être root) *\n"
399
400#: utils/cpufreq-info.c:479
401#, c-format
402msgid ""
403" -l, --hwlimits Determine the minimum and maximum CPU frequency "
404"allowed *\n"
405msgstr ""
406" -l, --hwlimits Affiche les fréquences minimales et maximales du CPU "
407"*\n"
408
409#: utils/cpufreq-info.c:480
410#, c-format
411msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
412msgstr " -d, --driver Affiche le pilote cpufreq utilisé *\n"
413
414#: utils/cpufreq-info.c:481
415#, c-format
416msgid " -p, --policy Gets the currently used cpufreq policy *\n"
417msgstr " -p, --policy Affiche la tactique actuelle de cpufreq *\n"
418
419#: utils/cpufreq-info.c:482
420#, c-format
421msgid " -g, --governors Determines available cpufreq governors *\n"
422msgstr ""
423" -g, --governors Affiche les régulateurs disponibles de cpufreq *\n"
424
425#: utils/cpufreq-info.c:483
426#, fuzzy, c-format
427msgid ""
428" -r, --related-cpus Determines which CPUs run at the same hardware "
429"frequency *\n"
430msgstr ""
431" -a, --affected-cpus Affiche quels sont les CPUs qui doivent changer de\n"
432" fréquences en même temps *\n"
433
434#: utils/cpufreq-info.c:484
435#, fuzzy, c-format
436msgid ""
437" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
438" coordinated by software *\n"
439msgstr ""
440" -a, --affected-cpus Affiche quels sont les CPUs qui doivent changer de\n"
441" fréquences en même temps *\n"
442
443#: utils/cpufreq-info.c:486
444#, c-format
445msgid " -s, --stats Shows cpufreq statistics if available\n"
446msgstr ""
447" -s, --stats Indique des statistiques concernant cpufreq, si\n"
448" disponibles\n"
449
450#: utils/cpufreq-info.c:487
451#, fuzzy, c-format
452msgid ""
453" -y, --latency Determines the maximum latency on CPU frequency "
454"changes *\n"
455msgstr ""
456" -l, --hwlimits Affiche les fréquences minimales et maximales du CPU "
457"*\n"
458
459#: utils/cpufreq-info.c:488
460#, c-format
461msgid " -b, --boost Checks for turbo or boost modes *\n"
462msgstr ""
463
464#: utils/cpufreq-info.c:489
465#, c-format
466msgid ""
467" -o, --proc Prints out information like provided by the /proc/"
468"cpufreq\n"
469" interface in 2.4. and early 2.6. kernels\n"
470msgstr ""
471" -o, --proc Affiche les informations en utilisant l'interface\n"
472" fournie par /proc/cpufreq, présente dans les "
473"versions\n"
474" 2.4 et les anciennes versions 2.6 du noyau\n"
475
476#: utils/cpufreq-info.c:491
477#, fuzzy, c-format
478msgid ""
479" -m, --human human-readable output for the -f, -w, -s and -y "
480"parameters\n"
481msgstr ""
482" -m, --human affiche dans un format lisible pour un humain\n"
483" pour les options -f, -w et -s (MHz, GHz)\n"
484
485#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
486#, c-format
487msgid " -h, --help Prints out this screen\n"
488msgstr " -h, --help affiche l'aide-mémoire\n"
489
490#: utils/cpufreq-info.c:495
491#, c-format
492msgid ""
493"If no argument or only the -c, --cpu parameter is given, debug output about\n"
494"cpufreq is printed which is useful e.g. for reporting bugs.\n"
495msgstr ""
496"Par défaut, les informations de déboguage seront affichées si aucun\n"
497"argument, ou bien si seulement l'argument -c (--cpu) est donné, afin de\n"
498"faciliter les rapports de bogues par exemple\n"
499
500#: utils/cpufreq-info.c:497
501#, c-format
502msgid ""
503"For the arguments marked with *, omitting the -c or --cpu argument is\n"
504"equivalent to setting it to zero\n"
505msgstr "Les arguments avec un * utiliseront le CPU 0 si -c (--cpu) est omis\n"
506
507#: utils/cpufreq-info.c:580
508#, c-format
509msgid ""
510"The argument passed to this tool can't be combined with passing a --cpu "
511"argument\n"
512msgstr "Cette option est incompatible avec --cpu\n"
513
514#: utils/cpufreq-info.c:596
515#, c-format
516msgid ""
517"You can't specify more than one --cpu parameter and/or\n"
518"more than one output-specific argument\n"
519msgstr ""
520"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
521"spécifier plus d'un argument de formatage\n"
522
523#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
524#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
525#, c-format
526msgid "invalid or unknown argument\n"
527msgstr "option invalide\n"
528
529#: utils/cpufreq-info.c:617
530#, c-format
531msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
532msgstr "analyse du CPU %d impossible puisqu'il ne semble pas être présent\n"
533
534#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
535#, c-format
536msgid "analyzing CPU %d:\n"
537msgstr "analyse du CPU %d :\n"
538
539#: utils/cpufreq-set.c:25
540#, fuzzy, c-format
541msgid "Usage: cpupower frequency-set [options]\n"
542msgstr "Usage : cpufreq-set [options]\n"
543
544#: utils/cpufreq-set.c:27
545#, c-format
546msgid ""
547" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
548"select\n"
549msgstr ""
550" -d FREQ, --min FREQ nouvelle fréquence minimale du CPU à utiliser\n"
551" par le régulateur\n"
552
553#: utils/cpufreq-set.c:28
554#, c-format
555msgid ""
556" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
557"select\n"
558msgstr ""
559" -u FREQ, --max FREQ nouvelle fréquence maximale du CPU à utiliser\n"
560" par le régulateur\n"
561
562#: utils/cpufreq-set.c:29
563#, c-format
564msgid " -g GOV, --governor GOV new cpufreq governor\n"
565msgstr " -g GOV, --governor GOV active le régulateur GOV\n"
566
567#: utils/cpufreq-set.c:30
568#, c-format
569msgid ""
570" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
571" governor to be available and loaded\n"
572msgstr ""
573" -f FREQ, --freq FREQ fixe la fréquence du processeur à FREQ. Il faut\n"
574" que le régulateur « userspace » soit disponible \n"
575" et activé.\n"
576
577#: utils/cpufreq-set.c:32
578#, c-format
579msgid " -r, --related Switches all hardware-related CPUs\n"
580msgstr ""
581
582#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
583#, fuzzy, c-format
584msgid " -h, --help Prints out this screen\n"
585msgstr " -h, --help affiche l'aide-mémoire\n"
586
587#: utils/cpufreq-set.c:35
588#, fuzzy, c-format
589msgid ""
590"Notes:\n"
591"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
592msgstr "Les arguments avec un * utiliseront le CPU 0 si -c (--cpu) est omis\n"
593
594#: utils/cpufreq-set.c:37
595#, fuzzy, c-format
596msgid ""
597"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
598"parameter\n"
599" except the -c CPU, --cpu CPU parameter\n"
600"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
601" by postfixing the value with the wanted unit name, without any space\n"
602" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
603msgstr ""
604"Remarque :\n"
605"1. Le CPU numéro 0 sera utilisé par défaut si -c (ou --cpu) est omis ;\n"
606"2. l'argument -f FREQ (ou --freq FREQ) ne peut être utilisé qu'avec --cpu ;\n"
607"3. on pourra préciser l'unité des fréquences en postfixant sans aucune "
608"espace\n"
609" les valeurs par hz, kHz (par défaut), MHz, GHz ou THz\n"
610" (kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
611
612#: utils/cpufreq-set.c:57
613#, c-format
614msgid ""
615"Error setting new values. Common errors:\n"
616"- Do you have proper administration rights? (super-user?)\n"
617"- Is the governor you requested available and modprobed?\n"
618"- Trying to set an invalid policy?\n"
619"- Trying to set a specific frequency, but userspace governor is not "
620"available,\n"
621" for example because of hardware which cannot be set to a specific "
622"frequency\n"
623" or because the userspace governor isn't loaded?\n"
624msgstr ""
625"En ajustant les nouveaux paramètres, une erreur est apparue. Les sources\n"
626"d'erreur typique sont :\n"
627"- droit d'administration insuffisant (êtes-vous root ?) ;\n"
628"- le régulateur choisi n'est pas disponible, ou bien n'est pas disponible "
629"en\n"
630" tant que module noyau ;\n"
631"- la tactique n'est pas disponible ;\n"
632"- vous voulez utiliser l'option -f/--freq, mais le régulateur « userspace »\n"
633" n'est pas disponible, par exemple parce que le matériel ne le supporte\n"
634" pas, ou bien n'est tout simplement pas chargé.\n"
635
636#: utils/cpufreq-set.c:170
637#, c-format
638msgid "wrong, unknown or unhandled CPU?\n"
639msgstr "CPU inconnu ou non supporté ?\n"
640
641#: utils/cpufreq-set.c:302
642#, c-format
643msgid ""
644"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
645"-g/--governor parameters\n"
646msgstr ""
647"l'option -f/--freq est incompatible avec les options -d/--min, -u/--max et\n"
648"-g/--governor\n"
649
650#: utils/cpufreq-set.c:308
651#, c-format
652msgid ""
653"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
654"-g/--governor must be passed\n"
655msgstr ""
656"L'un de ces paramètres est obligatoire : -f/--freq, -d/--min, -u/--max et\n"
657"-g/--governor\n"
658
659#: utils/cpufreq-set.c:347
660#, c-format
661msgid "Setting cpu: %d\n"
662msgstr ""
663
664#: utils/cpupower-set.c:22
665#, c-format
666msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
667msgstr ""
668
669#: utils/cpupower-set.c:24
670#, c-format
671msgid ""
672" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
673" Intel models [0-15], see manpage for details\n"
674msgstr ""
675
676#: utils/cpupower-set.c:26
677#, c-format
678msgid ""
679" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
680msgstr ""
681
682#: utils/cpupower-set.c:27
683#, c-format
684msgid ""
685" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
686"policy.\n"
687msgstr ""
688
689#: utils/cpupower-set.c:80
690#, c-format
691msgid "--perf-bias param out of range [0-%d]\n"
692msgstr ""
693
694#: utils/cpupower-set.c:91
695#, c-format
696msgid "--sched-mc param out of range [0-%d]\n"
697msgstr ""
698
699#: utils/cpupower-set.c:102
700#, c-format
701msgid "--sched-smt param out of range [0-%d]\n"
702msgstr ""
703
704#: utils/cpupower-set.c:121
705#, c-format
706msgid "Error setting sched-mc %s\n"
707msgstr ""
708
709#: utils/cpupower-set.c:127
710#, c-format
711msgid "Error setting sched-smt %s\n"
712msgstr ""
713
714#: utils/cpupower-set.c:146
715#, c-format
716msgid "Error setting perf-bias value on CPU %d\n"
717msgstr ""
718
719#: utils/cpupower-info.c:21
720#, c-format
721msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
722msgstr ""
723
724#: utils/cpupower-info.c:23
725#, c-format
726msgid ""
727" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
728" Intel models [0-15], see manpage for details\n"
729msgstr ""
730
731#: utils/cpupower-info.c:25
732#, fuzzy, c-format
733msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
734msgstr " -p, --policy Affiche la tactique actuelle de cpufreq *\n"
735
736#: utils/cpupower-info.c:26
737#, c-format
738msgid ""
739" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
740msgstr ""
741
742#: utils/cpupower-info.c:28
743#, c-format
744msgid ""
745"\n"
746"Passing no option will show all info, by default only on core 0\n"
747msgstr ""
748
749#: utils/cpupower-info.c:102
750#, c-format
751msgid "System's multi core scheduler setting: "
752msgstr ""
753
754#. if sysfs file is missing it's: errno == ENOENT
755#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
756#, c-format
757msgid "not supported\n"
758msgstr ""
759
760#: utils/cpupower-info.c:111
761#, c-format
762msgid "System's thread sibling scheduler setting: "
763msgstr ""
764
765#: utils/cpupower-info.c:126
766#, c-format
767msgid "Intel's performance bias setting needs root privileges\n"
768msgstr ""
769
770#: utils/cpupower-info.c:128
771#, c-format
772msgid "System does not support Intel's performance bias setting\n"
773msgstr ""
774
775#: utils/cpupower-info.c:147
776#, c-format
777msgid "Could not read perf-bias value\n"
778msgstr ""
779
780#: utils/cpupower-info.c:150
781#, c-format
782msgid "perf-bias: %d\n"
783msgstr ""
784
785#: utils/cpuidle-info.c:28
786#, fuzzy, c-format
787msgid "Analyzing CPU %d:\n"
788msgstr "analyse du CPU %d :\n"
789
790#: utils/cpuidle-info.c:32
791#, c-format
792msgid "CPU %u: No idle states\n"
793msgstr ""
794
795#: utils/cpuidle-info.c:36
796#, c-format
797msgid "CPU %u: Can't read idle state info\n"
798msgstr ""
799
800#: utils/cpuidle-info.c:41
801#, c-format
802msgid "Could not determine max idle state %u\n"
803msgstr ""
804
805#: utils/cpuidle-info.c:46
806#, c-format
807msgid "Number of idle states: %d\n"
808msgstr ""
809
810#: utils/cpuidle-info.c:48
811#, fuzzy, c-format
812msgid "Available idle states:"
813msgstr " plage de fréquence : "
814
815#: utils/cpuidle-info.c:71
816#, c-format
817msgid "Flags/Description: %s\n"
818msgstr ""
819
820#: utils/cpuidle-info.c:74
821#, c-format
822msgid "Latency: %lu\n"
823msgstr ""
824
825#: utils/cpuidle-info.c:76
826#, c-format
827msgid "Usage: %lu\n"
828msgstr ""
829
830#: utils/cpuidle-info.c:78
831#, c-format
832msgid "Duration: %llu\n"
833msgstr ""
834
835#: utils/cpuidle-info.c:90
836#, c-format
837msgid "Could not determine cpuidle driver\n"
838msgstr ""
839
840#: utils/cpuidle-info.c:94
841#, fuzzy, c-format
842msgid "CPUidle driver: %s\n"
843msgstr " pilote : %s\n"
844
845#: utils/cpuidle-info.c:99
846#, c-format
847msgid "Could not determine cpuidle governor\n"
848msgstr ""
849
850#: utils/cpuidle-info.c:103
851#, c-format
852msgid "CPUidle governor: %s\n"
853msgstr ""
854
855#: utils/cpuidle-info.c:122
856#, c-format
857msgid "CPU %u: Can't read C-state info\n"
858msgstr ""
859
860#. printf("Cstates: %d\n", cstates);
861#: utils/cpuidle-info.c:127
862#, c-format
863msgid "active state: C0\n"
864msgstr ""
865
866#: utils/cpuidle-info.c:128
867#, c-format
868msgid "max_cstate: C%u\n"
869msgstr ""
870
871#: utils/cpuidle-info.c:129
872#, c-format
873msgid "maximum allowed latency: %lu usec\n"
874msgstr ""
875
876#: utils/cpuidle-info.c:130
877#, c-format
878msgid "states:\t\n"
879msgstr ""
880
881#: utils/cpuidle-info.c:132
882#, c-format
883msgid " C%d: type[C%d] "
884msgstr ""
885
886#: utils/cpuidle-info.c:134
887#, c-format
888msgid "promotion[--] demotion[--] "
889msgstr ""
890
891#: utils/cpuidle-info.c:135
892#, c-format
893msgid "latency[%03lu] "
894msgstr ""
895
896#: utils/cpuidle-info.c:137
897#, c-format
898msgid "usage[%08lu] "
899msgstr ""
900
901#: utils/cpuidle-info.c:139
902#, c-format
903msgid "duration[%020Lu] \n"
904msgstr ""
905
906#: utils/cpuidle-info.c:147
907#, fuzzy, c-format
908msgid "Usage: cpupower idleinfo [options]\n"
909msgstr "Usage : cpufreq-info [options]\n"
910
911#: utils/cpuidle-info.c:149
912#, fuzzy, c-format
913msgid " -s, --silent Only show general C-state information\n"
914msgstr " -e, --debug Afficher les informations de déboguage\n"
915
916#: utils/cpuidle-info.c:150
917#, fuzzy, c-format
918msgid ""
919" -o, --proc Prints out information like provided by the /proc/"
920"acpi/processor/*/power\n"
921" interface in older kernels\n"
922msgstr ""
923" -o, --proc Affiche les informations en utilisant l'interface\n"
924" fournie par /proc/cpufreq, présente dans les "
925"versions\n"
926" 2.4 et les anciennes versions 2.6 du noyau\n"
927
928#: utils/cpuidle-info.c:209
929#, fuzzy, c-format
930msgid "You can't specify more than one output-specific argument\n"
931msgstr ""
932"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
933"spécifier plus d'un argument de formatage\n"
934
935#~ msgid ""
936#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
937#~ "about\n"
938#~ msgstr ""
939#~ " -c CPU, --cpu CPU Numéro du CPU pour lequel l'information sera "
940#~ "affichée\n"
941
942#~ msgid ""
943#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
944#~ "modified\n"
945#~ msgstr ""
946#~ " -c CPU, --cpu CPU numéro du CPU à prendre en compte pour les\n"
947#~ " changements\n"
diff --git a/tools/power/cpupower/po/it.po b/tools/power/cpupower/po/it.po
new file mode 100644
index 000000000000..f80c4ddb9bda
--- /dev/null
+++ b/tools/power/cpupower/po/it.po
@@ -0,0 +1,961 @@
1# Italian translations for cpufrequtils package
2# Copyright (C) 2004-2009
3# This file is distributed under the same license as the cpufrequtils package.
4# Mattia Dongili <malattia@gmail.com>.
5#
6#
7msgid ""
8msgstr ""
9"Project-Id-Version: cpufrequtils 0.3\n"
10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2011-03-08 17:03+0100\n"
12"PO-Revision-Date: 2009-08-15 12:00+0900\n"
13"Last-Translator: Mattia Dongili <malattia@gmail.com>\n"
14"Language-Team: NONE\n"
15"Language: \n"
16"MIME-Version: 1.0\n"
17"Content-Type: text/plain; charset=UTF-8\n"
18"Content-Transfer-Encoding: 8bit\n"
19
20#: utils/idle_monitor/nhm_idle.c:36
21msgid "Processor Core C3"
22msgstr ""
23
24#: utils/idle_monitor/nhm_idle.c:43
25msgid "Processor Core C6"
26msgstr ""
27
28#: utils/idle_monitor/nhm_idle.c:51
29msgid "Processor Package C3"
30msgstr ""
31
32#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
33msgid "Processor Package C6"
34msgstr ""
35
36#: utils/idle_monitor/snb_idle.c:33
37msgid "Processor Core C7"
38msgstr ""
39
40#: utils/idle_monitor/snb_idle.c:40
41msgid "Processor Package C2"
42msgstr ""
43
44#: utils/idle_monitor/snb_idle.c:47
45msgid "Processor Package C7"
46msgstr ""
47
48#: utils/idle_monitor/amd_fam14h_idle.c:56
49msgid "Package in sleep state (PC1 or deeper)"
50msgstr ""
51
52#: utils/idle_monitor/amd_fam14h_idle.c:63
53msgid "Processor Package C1"
54msgstr ""
55
56#: utils/idle_monitor/amd_fam14h_idle.c:77
57msgid "North Bridge P1 boolean counter (returns 0 or 1)"
58msgstr ""
59
60#: utils/idle_monitor/mperf_monitor.c:35
61msgid "Processor Core not idle"
62msgstr ""
63
64#: utils/idle_monitor/mperf_monitor.c:42
65msgid "Processor Core in an idle state"
66msgstr ""
67
68#: utils/idle_monitor/mperf_monitor.c:50
69msgid "Average Frequency (including boost) in MHz"
70msgstr ""
71
72#: utils/idle_monitor/cpupower-monitor.c:66
73#, c-format
74msgid ""
75"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
76"interval_sec | -c command ...]\n"
77msgstr ""
78
79#: utils/idle_monitor/cpupower-monitor.c:69
80#, c-format
81msgid ""
82"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
83"interval_sec | -c command ...]\n"
84msgstr ""
85
86#: utils/idle_monitor/cpupower-monitor.c:71
87#, c-format
88msgid "\t -v: be more verbose\n"
89msgstr ""
90
91#: utils/idle_monitor/cpupower-monitor.c:73
92#, c-format
93msgid "\t -h: print this help\n"
94msgstr ""
95
96#: utils/idle_monitor/cpupower-monitor.c:74
97#, c-format
98msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
99msgstr ""
100
101#: utils/idle_monitor/cpupower-monitor.c:75
102#, c-format
103msgid "\t -t: show CPU topology/hierarchy\n"
104msgstr ""
105
106#: utils/idle_monitor/cpupower-monitor.c:76
107#, c-format
108msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
109msgstr ""
110
111#: utils/idle_monitor/cpupower-monitor.c:77
112#, c-format
113msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
114msgstr ""
115
116#: utils/idle_monitor/cpupower-monitor.c:79
117#, c-format
118msgid ""
119"only one of: -t, -l, -m are allowed\n"
120"If none of them is passed,"
121msgstr ""
122
123#: utils/idle_monitor/cpupower-monitor.c:80
124#, c-format
125msgid " all supported monitors are shown\n"
126msgstr ""
127
128#: utils/idle_monitor/cpupower-monitor.c:197
129#, c-format
130msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
131msgstr ""
132
133#: utils/idle_monitor/cpupower-monitor.c:207
134#, c-format
135msgid " *is offline\n"
136msgstr ""
137
138#: utils/idle_monitor/cpupower-monitor.c:236
139#, c-format
140msgid "%s: max monitor name length (%d) exceeded\n"
141msgstr ""
142
143#: utils/idle_monitor/cpupower-monitor.c:250
144#, c-format
145msgid "No matching monitor found in %s, try -l option\n"
146msgstr ""
147
148#: utils/idle_monitor/cpupower-monitor.c:266
149#, c-format
150msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
151msgstr ""
152
153#: utils/idle_monitor/cpupower-monitor.c:319
154#, c-format
155msgid "%s took %.5f seconds and exited with status %d\n"
156msgstr ""
157
158#: utils/idle_monitor/cpupower-monitor.c:406
159#, c-format
160msgid "Cannot read number of available processors\n"
161msgstr ""
162
163#: utils/idle_monitor/cpupower-monitor.c:417
164#, c-format
165msgid "Available monitor %s needs root access\n"
166msgstr ""
167
168#: utils/idle_monitor/cpupower-monitor.c:428
169#, c-format
170msgid "No HW Cstate monitors found\n"
171msgstr ""
172
173#: utils/cpupower.c:78
174#, c-format
175msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
176msgstr ""
177
178#: utils/cpupower.c:79
179#, c-format
180msgid "cpupower --version\n"
181msgstr ""
182
183#: utils/cpupower.c:80
184#, c-format
185msgid "Supported subcommands are:\n"
186msgstr ""
187
188#: utils/cpupower.c:83
189#, c-format
190msgid ""
191"\n"
192"Some subcommands can make use of the -c cpulist option.\n"
193msgstr ""
194
195#: utils/cpupower.c:84
196#, c-format
197msgid "Look at the general cpupower manpage how to use it\n"
198msgstr ""
199
200#: utils/cpupower.c:85
201#, c-format
202msgid "and read up the subcommand's manpage whether it is supported.\n"
203msgstr ""
204
205#: utils/cpupower.c:86
206#, c-format
207msgid ""
208"\n"
209"Use cpupower help subcommand for getting help for above subcommands.\n"
210msgstr ""
211
212#: utils/cpupower.c:91
213#, c-format
214msgid "Report errors and bugs to %s, please.\n"
215msgstr "Per favore, comunicare errori e malfunzionamenti a %s.\n"
216
217#: utils/cpupower.c:114
218#, c-format
219msgid "Error parsing cpu list\n"
220msgstr ""
221
222#: utils/cpupower.c:172
223#, c-format
224msgid "Subcommand %s needs root privileges\n"
225msgstr ""
226
227#: utils/cpufreq-info.c:31
228#, c-format
229msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
230msgstr "Impossibile determinare il numero di CPU (%s: %s), assumo sia 1\n"
231
232#: utils/cpufreq-info.c:63
233#, c-format
234msgid ""
235" minimum CPU frequency - maximum CPU frequency - governor\n"
236msgstr ""
237" frequenza minima CPU - frequenza massima CPU - gestore\n"
238
239#: utils/cpufreq-info.c:151
240#, c-format
241msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
242msgstr ""
243
244#. P state changes via MSR are identified via cpuid 80000007
245#. on Intel and AMD, but we assume boost capable machines can do that
246#. if (cpuid_eax(0x80000000) >= 0x80000007
247#. && (cpuid_edx(0x80000007) & (1 << 7)))
248#.
249#: utils/cpufreq-info.c:161
250#, c-format
251msgid " boost state support: \n"
252msgstr ""
253
254#: utils/cpufreq-info.c:163
255#, c-format
256msgid " Supported: %s\n"
257msgstr ""
258
259#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
260msgid "yes"
261msgstr ""
262
263#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
264msgid "no"
265msgstr ""
266
267#: utils/cpufreq-info.c:164
268#, fuzzy, c-format
269msgid " Active: %s\n"
270msgstr " modulo %s\n"
271
272#: utils/cpufreq-info.c:177
273#, c-format
274msgid " Boost States: %d\n"
275msgstr ""
276
277#: utils/cpufreq-info.c:178
278#, c-format
279msgid " Total States: %d\n"
280msgstr ""
281
282#: utils/cpufreq-info.c:181
283#, c-format
284msgid " Pstate-Pb%d: %luMHz (boost state)\n"
285msgstr ""
286
287#: utils/cpufreq-info.c:184
288#, c-format
289msgid " Pstate-P%d: %luMHz\n"
290msgstr ""
291
292#: utils/cpufreq-info.c:211
293#, c-format
294msgid " no or unknown cpufreq driver is active on this CPU\n"
295msgstr " nessun modulo o modulo cpufreq sconosciuto per questa CPU\n"
296
297#: utils/cpufreq-info.c:213
298#, c-format
299msgid " driver: %s\n"
300msgstr " modulo %s\n"
301
302#: utils/cpufreq-info.c:219
303#, c-format
304msgid " CPUs which run at the same hardware frequency: "
305msgstr " CPU che operano alla stessa frequenza hardware: "
306
307#: utils/cpufreq-info.c:230
308#, c-format
309msgid " CPUs which need to have their frequency coordinated by software: "
310msgstr " CPU che è necessario siano coordinate dal software: "
311
312#: utils/cpufreq-info.c:241
313#, c-format
314msgid " maximum transition latency: "
315msgstr " latenza massima durante la transizione: "
316
317#: utils/cpufreq-info.c:247
318#, c-format
319msgid " hardware limits: "
320msgstr " limiti hardware: "
321
322#: utils/cpufreq-info.c:256
323#, c-format
324msgid " available frequency steps: "
325msgstr " frequenze disponibili: "
326
327#: utils/cpufreq-info.c:269
328#, c-format
329msgid " available cpufreq governors: "
330msgstr " gestori disponibili: "
331
332#: utils/cpufreq-info.c:280
333#, c-format
334msgid " current policy: frequency should be within "
335msgstr " gestore attuale: la frequenza deve mantenersi tra "
336
337#: utils/cpufreq-info.c:282
338#, c-format
339msgid " and "
340msgstr " e "
341
342#: utils/cpufreq-info.c:286
343#, c-format
344msgid ""
345"The governor \"%s\" may decide which speed to use\n"
346" within this range.\n"
347msgstr ""
348" Il gestore \"%s\" può decidere quale velocità usare\n"
349" in questo intervallo.\n"
350
351#: utils/cpufreq-info.c:293
352#, c-format
353msgid " current CPU frequency is "
354msgstr " la frequenza attuale della CPU è "
355
356#: utils/cpufreq-info.c:296
357#, c-format
358msgid " (asserted by call to hardware)"
359msgstr " (ottenuta da una chiamata diretta all'hardware)"
360
361#: utils/cpufreq-info.c:304
362#, c-format
363msgid " cpufreq stats: "
364msgstr " statistiche cpufreq:"
365
366#: utils/cpufreq-info.c:472
367#, fuzzy, c-format
368msgid "Usage: cpupower freqinfo [options]\n"
369msgstr "Uso: cpufreq-info [opzioni]\n"
370
371#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
372#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
373#, c-format
374msgid "Options:\n"
375msgstr "Opzioni:\n"
376
377#: utils/cpufreq-info.c:474
378#, fuzzy, c-format
379msgid " -e, --debug Prints out debug information [default]\n"
380msgstr " -e, --debug Mostra informazioni di debug\n"
381
382#: utils/cpufreq-info.c:475
383#, c-format
384msgid ""
385" -f, --freq Get frequency the CPU currently runs at, according\n"
386" to the cpufreq core *\n"
387msgstr ""
388" -f, --freq Mostra la frequenza attuale della CPU secondo\n"
389" il modulo cpufreq *\n"
390
391#: utils/cpufreq-info.c:477
392#, c-format
393msgid ""
394" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
395" it from hardware (only available to root) *\n"
396msgstr ""
397" -w, --hwfreq Mostra la frequenza attuale della CPU leggendola\n"
398" dall'hardware (disponibile solo per l'utente root) *\n"
399
400#: utils/cpufreq-info.c:479
401#, c-format
402msgid ""
403" -l, --hwlimits Determine the minimum and maximum CPU frequency "
404"allowed *\n"
405msgstr ""
406" -l, --hwlimits Determina le frequenze minima e massima possibili per "
407"la CPU *\n"
408
409#: utils/cpufreq-info.c:480
410#, c-format
411msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
412msgstr ""
413" -d, --driver Determina il modulo cpufreq del kernel in uso *\n"
414
415#: utils/cpufreq-info.c:481
416#, c-format
417msgid " -p, --policy Gets the currently used cpufreq policy *\n"
418msgstr ""
419" -p, --policy Mostra il gestore cpufreq attualmente in uso *\n"
420
421#: utils/cpufreq-info.c:482
422#, c-format
423msgid " -g, --governors Determines available cpufreq governors *\n"
424msgstr " -g, --governors Determina i gestori cpufreq disponibili *\n"
425
426#: utils/cpufreq-info.c:483
427#, c-format
428msgid ""
429" -r, --related-cpus Determines which CPUs run at the same hardware "
430"frequency *\n"
431msgstr ""
432" -r, --related-cpus Determina quali CPU operano alla stessa frequenza *\n"
433
434#: utils/cpufreq-info.c:484
435#, c-format
436msgid ""
437" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
438" coordinated by software *\n"
439msgstr ""
440" -a, --affected-cpus Determina quali CPU devono avere la frequenza\n"
441" coordinata dal software *\n"
442
443#: utils/cpufreq-info.c:486
444#, c-format
445msgid " -s, --stats Shows cpufreq statistics if available\n"
446msgstr " -s, --stats Mostra le statistiche se disponibili\n"
447
448#: utils/cpufreq-info.c:487
449#, c-format
450msgid ""
451" -y, --latency Determines the maximum latency on CPU frequency "
452"changes *\n"
453msgstr ""
454" -y, --latency Determina la latenza massima durante i cambi di "
455"frequenza *\n"
456
457#: utils/cpufreq-info.c:488
458#, c-format
459msgid " -b, --boost Checks for turbo or boost modes *\n"
460msgstr ""
461
462#: utils/cpufreq-info.c:489
463#, c-format
464msgid ""
465" -o, --proc Prints out information like provided by the /proc/"
466"cpufreq\n"
467" interface in 2.4. and early 2.6. kernels\n"
468msgstr ""
469" -o, --proc Stampa le informazioni come se provenissero dalla\n"
470" interfaccia cpufreq /proc/ presente nei kernel\n"
471" 2.4 ed i primi 2.6\n"
472
473#: utils/cpufreq-info.c:491
474#, c-format
475msgid ""
476" -m, --human human-readable output for the -f, -w, -s and -y "
477"parameters\n"
478msgstr ""
479" -m, --human formatta l'output delle opzioni -f, -w, -s e -y in "
480"maniera\n"
481" leggibile da un essere umano\n"
482
483#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
484#, c-format
485msgid " -h, --help Prints out this screen\n"
486msgstr " -h, --help Stampa questa schermata\n"
487
488#: utils/cpufreq-info.c:495
489#, c-format
490msgid ""
491"If no argument or only the -c, --cpu parameter is given, debug output about\n"
492"cpufreq is printed which is useful e.g. for reporting bugs.\n"
493msgstr ""
494"Se non viene specificata nessuna opzione o viene specificata solo l'opzione -"
495"c, --cpu,\n"
496"le informazioni di debug per cpufreq saranno utili ad esempio a riportare i "
497"bug.\n"
498
499#: utils/cpufreq-info.c:497
500#, c-format
501msgid ""
502"For the arguments marked with *, omitting the -c or --cpu argument is\n"
503"equivalent to setting it to zero\n"
504msgstr ""
505"Per le opzioni segnalate con *, omettere l'opzione -c o --cpu è come "
506"specificarla\n"
507"con il valore 0\n"
508
509#: utils/cpufreq-info.c:580
510#, c-format
511msgid ""
512"The argument passed to this tool can't be combined with passing a --cpu "
513"argument\n"
514msgstr ""
515"L'opzione specificata a questo programma non può essere combinata con --cpu\n"
516
517#: utils/cpufreq-info.c:596
518#, c-format
519msgid ""
520"You can't specify more than one --cpu parameter and/or\n"
521"more than one output-specific argument\n"
522msgstr ""
523"Non è possibile specificare più di una volta l'opzione --cpu e/o\n"
524"specificare più di un parametro di output specifico\n"
525
526#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
527#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
528#, c-format
529msgid "invalid or unknown argument\n"
530msgstr "opzione sconosciuta o non valida\n"
531
532#: utils/cpufreq-info.c:617
533#, c-format
534msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
535msgstr "impossibile analizzare la CPU %d poiché non sembra essere presente\n"
536
537#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
538#, c-format
539msgid "analyzing CPU %d:\n"
540msgstr "analisi della CPU %d:\n"
541
542#: utils/cpufreq-set.c:25
543#, fuzzy, c-format
544msgid "Usage: cpupower frequency-set [options]\n"
545msgstr "Uso: cpufreq-set [opzioni]\n"
546
547#: utils/cpufreq-set.c:27
548#, c-format
549msgid ""
550" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
551"select\n"
552msgstr ""
553" -d FREQ, --min FREQ la nuova frequenza minima che il gestore cpufreq "
554"può scegliere\n"
555
556#: utils/cpufreq-set.c:28
557#, c-format
558msgid ""
559" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
560"select\n"
561msgstr ""
562" -u FREQ, --max FREQ la nuova frequenza massima che il gestore cpufreq "
563"può scegliere\n"
564
565#: utils/cpufreq-set.c:29
566#, c-format
567msgid " -g GOV, --governor GOV new cpufreq governor\n"
568msgstr " -g GOV, --governor GOV nuovo gestore cpufreq\n"
569
570#: utils/cpufreq-set.c:30
571#, c-format
572msgid ""
573" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
574" governor to be available and loaded\n"
575msgstr ""
576" -f FREQ, --freq FREQ specifica la frequenza a cui impostare la CPU.\n"
577" È necessario che il gestore userspace sia "
578"disponibile e caricato\n"
579
580#: utils/cpufreq-set.c:32
581#, c-format
582msgid " -r, --related Switches all hardware-related CPUs\n"
583msgstr ""
584" -r, --related Modifica tutte le CPU coordinate dall'hardware\n"
585
586#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
587#, c-format
588msgid " -h, --help Prints out this screen\n"
589msgstr " -h, --help Stampa questa schermata\n"
590
591#: utils/cpufreq-set.c:35
592#, fuzzy, c-format
593msgid ""
594"Notes:\n"
595"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
596msgstr ""
597"Per le opzioni segnalate con *, omettere l'opzione -c o --cpu è come "
598"specificarla\n"
599"con il valore 0\n"
600
601#: utils/cpufreq-set.c:37
602#, fuzzy, c-format
603msgid ""
604"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
605"parameter\n"
606" except the -c CPU, --cpu CPU parameter\n"
607"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
608" by postfixing the value with the wanted unit name, without any space\n"
609" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
610msgstr ""
611"Note:\n"
612"1. Omettere l'opzione -c o --cpu è equivalente a impostarlo a 0\n"
613"2. l'opzione -f FREQ, --freq FREQ non può essere specificata con altre "
614"opzioni\n"
615" ad eccezione dell'opzione -c CPU o --cpu CPU\n"
616"3. le FREQuenze possono essere specuficate in Hz, kHz (default), MHz, GHz, "
617"or THz\n"
618" postponendo l'unità di misura al valore senza nessuno spazio fra loro\n"
619" (FREQuenza in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
620
621#: utils/cpufreq-set.c:57
622#, c-format
623msgid ""
624"Error setting new values. Common errors:\n"
625"- Do you have proper administration rights? (super-user?)\n"
626"- Is the governor you requested available and modprobed?\n"
627"- Trying to set an invalid policy?\n"
628"- Trying to set a specific frequency, but userspace governor is not "
629"available,\n"
630" for example because of hardware which cannot be set to a specific "
631"frequency\n"
632" or because the userspace governor isn't loaded?\n"
633msgstr ""
634"Si sono verificati degli errori impostando i nuovi valori.\n"
635"Alcuni errori comuni possono essere:\n"
636"- Hai i necessari diritti di amministrazione? (super-user?)\n"
637"- Il gestore che hai richiesto è disponibile e caricato?\n"
638"- Stai provando ad impostare una politica di gestione non valida?\n"
639"- Stai provando a impostare una specifica frequenza ma il gestore\n"
640" userspace non è disponibile, per esempio a causa dell'hardware\n"
641" che non supporta frequenze fisse o a causa del fatto che\n"
642" il gestore userspace non è caricato?\n"
643
644#: utils/cpufreq-set.c:170
645#, c-format
646msgid "wrong, unknown or unhandled CPU?\n"
647msgstr "CPU errata, sconosciuta o non gestita?\n"
648
649#: utils/cpufreq-set.c:302
650#, c-format
651msgid ""
652"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
653"-g/--governor parameters\n"
654msgstr ""
655"l'opzione -f/--freq non può venire combinata con i parametri\n"
656" -d/--min, -u/--max o -g/--governor\n"
657
658#: utils/cpufreq-set.c:308
659#, c-format
660msgid ""
661"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
662"-g/--governor must be passed\n"
663msgstr ""
664"Almeno una delle opzioni -f/--freq, -d/--min, -u/--max, e -g/--governor\n"
665"deve essere specificata\n"
666
667#: utils/cpufreq-set.c:347
668#, c-format
669msgid "Setting cpu: %d\n"
670msgstr ""
671
672#: utils/cpupower-set.c:22
673#, c-format
674msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
675msgstr ""
676
677#: utils/cpupower-set.c:24
678#, c-format
679msgid ""
680" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
681" Intel models [0-15], see manpage for details\n"
682msgstr ""
683
684#: utils/cpupower-set.c:26
685#, c-format
686msgid ""
687" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
688msgstr ""
689
690#: utils/cpupower-set.c:27
691#, c-format
692msgid ""
693" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
694"policy.\n"
695msgstr ""
696
697#: utils/cpupower-set.c:80
698#, c-format
699msgid "--perf-bias param out of range [0-%d]\n"
700msgstr ""
701
702#: utils/cpupower-set.c:91
703#, c-format
704msgid "--sched-mc param out of range [0-%d]\n"
705msgstr ""
706
707#: utils/cpupower-set.c:102
708#, c-format
709msgid "--sched-smt param out of range [0-%d]\n"
710msgstr ""
711
712#: utils/cpupower-set.c:121
713#, c-format
714msgid "Error setting sched-mc %s\n"
715msgstr ""
716
717#: utils/cpupower-set.c:127
718#, c-format
719msgid "Error setting sched-smt %s\n"
720msgstr ""
721
722#: utils/cpupower-set.c:146
723#, c-format
724msgid "Error setting perf-bias value on CPU %d\n"
725msgstr ""
726
727#: utils/cpupower-info.c:21
728#, c-format
729msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
730msgstr ""
731
732#: utils/cpupower-info.c:23
733#, c-format
734msgid ""
735" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
736" Intel models [0-15], see manpage for details\n"
737msgstr ""
738
739#: utils/cpupower-info.c:25
740#, fuzzy, c-format
741msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
742msgstr ""
743" -p, --policy Mostra il gestore cpufreq attualmente in uso *\n"
744
745#: utils/cpupower-info.c:26
746#, c-format
747msgid ""
748" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
749msgstr ""
750
751#: utils/cpupower-info.c:28
752#, c-format
753msgid ""
754"\n"
755"Passing no option will show all info, by default only on core 0\n"
756msgstr ""
757
758#: utils/cpupower-info.c:102
759#, c-format
760msgid "System's multi core scheduler setting: "
761msgstr ""
762
763#. if sysfs file is missing it's: errno == ENOENT
764#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
765#, c-format
766msgid "not supported\n"
767msgstr ""
768
769#: utils/cpupower-info.c:111
770#, c-format
771msgid "System's thread sibling scheduler setting: "
772msgstr ""
773
774#: utils/cpupower-info.c:126
775#, c-format
776msgid "Intel's performance bias setting needs root privileges\n"
777msgstr ""
778
779#: utils/cpupower-info.c:128
780#, c-format
781msgid "System does not support Intel's performance bias setting\n"
782msgstr ""
783
784#: utils/cpupower-info.c:147
785#, c-format
786msgid "Could not read perf-bias value\n"
787msgstr ""
788
789#: utils/cpupower-info.c:150
790#, c-format
791msgid "perf-bias: %d\n"
792msgstr ""
793
794#: utils/cpuidle-info.c:28
795#, fuzzy, c-format
796msgid "Analyzing CPU %d:\n"
797msgstr "analisi della CPU %d:\n"
798
799#: utils/cpuidle-info.c:32
800#, c-format
801msgid "CPU %u: No idle states\n"
802msgstr ""
803
804#: utils/cpuidle-info.c:36
805#, c-format
806msgid "CPU %u: Can't read idle state info\n"
807msgstr ""
808
809#: utils/cpuidle-info.c:41
810#, c-format
811msgid "Could not determine max idle state %u\n"
812msgstr ""
813
814#: utils/cpuidle-info.c:46
815#, c-format
816msgid "Number of idle states: %d\n"
817msgstr ""
818
819#: utils/cpuidle-info.c:48
820#, fuzzy, c-format
821msgid "Available idle states:"
822msgstr " frequenze disponibili: "
823
824#: utils/cpuidle-info.c:71
825#, c-format
826msgid "Flags/Description: %s\n"
827msgstr ""
828
829#: utils/cpuidle-info.c:74
830#, c-format
831msgid "Latency: %lu\n"
832msgstr ""
833
834#: utils/cpuidle-info.c:76
835#, c-format
836msgid "Usage: %lu\n"
837msgstr ""
838
839#: utils/cpuidle-info.c:78
840#, c-format
841msgid "Duration: %llu\n"
842msgstr ""
843
844#: utils/cpuidle-info.c:90
845#, c-format
846msgid "Could not determine cpuidle driver\n"
847msgstr ""
848
849#: utils/cpuidle-info.c:94
850#, fuzzy, c-format
851msgid "CPUidle driver: %s\n"
852msgstr " modulo %s\n"
853
854#: utils/cpuidle-info.c:99
855#, c-format
856msgid "Could not determine cpuidle governor\n"
857msgstr ""
858
859#: utils/cpuidle-info.c:103
860#, c-format
861msgid "CPUidle governor: %s\n"
862msgstr ""
863
864#: utils/cpuidle-info.c:122
865#, c-format
866msgid "CPU %u: Can't read C-state info\n"
867msgstr ""
868
869#. printf("Cstates: %d\n", cstates);
870#: utils/cpuidle-info.c:127
871#, c-format
872msgid "active state: C0\n"
873msgstr ""
874
875#: utils/cpuidle-info.c:128
876#, c-format
877msgid "max_cstate: C%u\n"
878msgstr ""
879
880#: utils/cpuidle-info.c:129
881#, fuzzy, c-format
882msgid "maximum allowed latency: %lu usec\n"
883msgstr " latenza massima durante la transizione: "
884
885#: utils/cpuidle-info.c:130
886#, c-format
887msgid "states:\t\n"
888msgstr ""
889
890#: utils/cpuidle-info.c:132
891#, c-format
892msgid " C%d: type[C%d] "
893msgstr ""
894
895#: utils/cpuidle-info.c:134
896#, c-format
897msgid "promotion[--] demotion[--] "
898msgstr ""
899
900#: utils/cpuidle-info.c:135
901#, c-format
902msgid "latency[%03lu] "
903msgstr ""
904
905#: utils/cpuidle-info.c:137
906#, c-format
907msgid "usage[%08lu] "
908msgstr ""
909
910#: utils/cpuidle-info.c:139
911#, c-format
912msgid "duration[%020Lu] \n"
913msgstr ""
914
915#: utils/cpuidle-info.c:147
916#, fuzzy, c-format
917msgid "Usage: cpupower idleinfo [options]\n"
918msgstr "Uso: cpufreq-info [opzioni]\n"
919
920#: utils/cpuidle-info.c:149
921#, fuzzy, c-format
922msgid " -s, --silent Only show general C-state information\n"
923msgstr " -e, --debug Mostra informazioni di debug\n"
924
925#: utils/cpuidle-info.c:150
926#, fuzzy, c-format
927msgid ""
928" -o, --proc Prints out information like provided by the /proc/"
929"acpi/processor/*/power\n"
930" interface in older kernels\n"
931msgstr ""
932" -o, --proc Stampa le informazioni come se provenissero dalla\n"
933" interfaccia cpufreq /proc/ presente nei kernel\n"
934" 2.4 ed i primi 2.6\n"
935
936#: utils/cpuidle-info.c:209
937#, fuzzy, c-format
938msgid "You can't specify more than one output-specific argument\n"
939msgstr ""
940"Non è possibile specificare più di una volta l'opzione --cpu e/o\n"
941"specificare più di un parametro di output specifico\n"
942
943#~ msgid ""
944#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
945#~ "about\n"
946#~ msgstr ""
947#~ " -c CPU, --cpu CPU Numero di CPU per la quale ottenere le "
948#~ "informazioni\n"
949
950#~ msgid ""
951#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
952#~ "modified\n"
953#~ msgstr ""
954#~ " -c CPU, --cpu CPU numero di CPU per la quale modificare le "
955#~ "impostazioni\n"
956
957#, fuzzy
958#~ msgid " CPUs which coordinate software frequency requirements: "
959#~ msgstr ""
960#~ " CPU per le quali e` necessario cambiare la frequenza "
961#~ "contemporaneamente: "
diff --git a/tools/power/cpupower/po/pt.po b/tools/power/cpupower/po/pt.po
new file mode 100644
index 000000000000..990f5267ffe8
--- /dev/null
+++ b/tools/power/cpupower/po/pt.po
@@ -0,0 +1,957 @@
1# Brazilian Portuguese translations for cpufrequtils package
2# Copyright (C) 2008 THE cpufrequtils'S COPYRIGHT HOLDER
3# This file is distributed under the same license as the cpufrequtils package.
4# Claudio Eduardo <claudioeddy@gmail.com>, 2009.
5#
6#
7msgid ""
8msgstr ""
9"Project-Id-Version: cpufrequtils 004\n"
10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2011-03-08 17:03+0100\n"
12"PO-Revision-Date: 2008-06-14 22:16-0400\n"
13"Last-Translator: Claudio Eduardo <claudioeddy@gmail.com>\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
17
18#: utils/idle_monitor/nhm_idle.c:36
19msgid "Processor Core C3"
20msgstr ""
21
22#: utils/idle_monitor/nhm_idle.c:43
23msgid "Processor Core C6"
24msgstr ""
25
26#: utils/idle_monitor/nhm_idle.c:51
27msgid "Processor Package C3"
28msgstr ""
29
30#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
31msgid "Processor Package C6"
32msgstr ""
33
34#: utils/idle_monitor/snb_idle.c:33
35msgid "Processor Core C7"
36msgstr ""
37
38#: utils/idle_monitor/snb_idle.c:40
39msgid "Processor Package C2"
40msgstr ""
41
42#: utils/idle_monitor/snb_idle.c:47
43msgid "Processor Package C7"
44msgstr ""
45
46#: utils/idle_monitor/amd_fam14h_idle.c:56
47msgid "Package in sleep state (PC1 or deeper)"
48msgstr ""
49
50#: utils/idle_monitor/amd_fam14h_idle.c:63
51msgid "Processor Package C1"
52msgstr ""
53
54#: utils/idle_monitor/amd_fam14h_idle.c:77
55msgid "North Bridge P1 boolean counter (returns 0 or 1)"
56msgstr ""
57
58#: utils/idle_monitor/mperf_monitor.c:35
59msgid "Processor Core not idle"
60msgstr ""
61
62#: utils/idle_monitor/mperf_monitor.c:42
63msgid "Processor Core in an idle state"
64msgstr ""
65
66#: utils/idle_monitor/mperf_monitor.c:50
67msgid "Average Frequency (including boost) in MHz"
68msgstr ""
69
70#: utils/idle_monitor/cpupower-monitor.c:66
71#, c-format
72msgid ""
73"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
74"interval_sec | -c command ...]\n"
75msgstr ""
76
77#: utils/idle_monitor/cpupower-monitor.c:69
78#, c-format
79msgid ""
80"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
81"interval_sec | -c command ...]\n"
82msgstr ""
83
84#: utils/idle_monitor/cpupower-monitor.c:71
85#, c-format
86msgid "\t -v: be more verbose\n"
87msgstr ""
88
89#: utils/idle_monitor/cpupower-monitor.c:73
90#, c-format
91msgid "\t -h: print this help\n"
92msgstr ""
93
94#: utils/idle_monitor/cpupower-monitor.c:74
95#, c-format
96msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
97msgstr ""
98
99#: utils/idle_monitor/cpupower-monitor.c:75
100#, c-format
101msgid "\t -t: show CPU topology/hierarchy\n"
102msgstr ""
103
104#: utils/idle_monitor/cpupower-monitor.c:76
105#, c-format
106msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
107msgstr ""
108
109#: utils/idle_monitor/cpupower-monitor.c:77
110#, c-format
111msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
112msgstr ""
113
114#: utils/idle_monitor/cpupower-monitor.c:79
115#, c-format
116msgid ""
117"only one of: -t, -l, -m are allowed\n"
118"If none of them is passed,"
119msgstr ""
120
121#: utils/idle_monitor/cpupower-monitor.c:80
122#, c-format
123msgid " all supported monitors are shown\n"
124msgstr ""
125
126#: utils/idle_monitor/cpupower-monitor.c:197
127#, c-format
128msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
129msgstr ""
130
131#: utils/idle_monitor/cpupower-monitor.c:207
132#, c-format
133msgid " *is offline\n"
134msgstr ""
135
136#: utils/idle_monitor/cpupower-monitor.c:236
137#, c-format
138msgid "%s: max monitor name length (%d) exceeded\n"
139msgstr ""
140
141#: utils/idle_monitor/cpupower-monitor.c:250
142#, c-format
143msgid "No matching monitor found in %s, try -l option\n"
144msgstr ""
145
146#: utils/idle_monitor/cpupower-monitor.c:266
147#, c-format
148msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
149msgstr ""
150
151#: utils/idle_monitor/cpupower-monitor.c:319
152#, c-format
153msgid "%s took %.5f seconds and exited with status %d\n"
154msgstr ""
155
156#: utils/idle_monitor/cpupower-monitor.c:406
157#, c-format
158msgid "Cannot read number of available processors\n"
159msgstr ""
160
161#: utils/idle_monitor/cpupower-monitor.c:417
162#, c-format
163msgid "Available monitor %s needs root access\n"
164msgstr ""
165
166#: utils/idle_monitor/cpupower-monitor.c:428
167#, c-format
168msgid "No HW Cstate monitors found\n"
169msgstr ""
170
171#: utils/cpupower.c:78
172#, c-format
173msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
174msgstr ""
175
176#: utils/cpupower.c:79
177#, c-format
178msgid "cpupower --version\n"
179msgstr ""
180
181#: utils/cpupower.c:80
182#, c-format
183msgid "Supported subcommands are:\n"
184msgstr ""
185
186#: utils/cpupower.c:83
187#, c-format
188msgid ""
189"\n"
190"Some subcommands can make use of the -c cpulist option.\n"
191msgstr ""
192
193#: utils/cpupower.c:84
194#, c-format
195msgid "Look at the general cpupower manpage how to use it\n"
196msgstr ""
197
198#: utils/cpupower.c:85
199#, c-format
200msgid "and read up the subcommand's manpage whether it is supported.\n"
201msgstr ""
202
203#: utils/cpupower.c:86
204#, c-format
205msgid ""
206"\n"
207"Use cpupower help subcommand for getting help for above subcommands.\n"
208msgstr ""
209
210#: utils/cpupower.c:91
211#, c-format
212msgid "Report errors and bugs to %s, please.\n"
213msgstr "Reporte erros e bugs para %s, por favor.\n"
214
215#: utils/cpupower.c:114
216#, c-format
217msgid "Error parsing cpu list\n"
218msgstr ""
219
220#: utils/cpupower.c:172
221#, c-format
222msgid "Subcommand %s needs root privileges\n"
223msgstr ""
224
225#: utils/cpufreq-info.c:31
226#, c-format
227msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
228msgstr "Não foi possível contar o número de CPUs (%s: %s), assumindo 1\n"
229
230#: utils/cpufreq-info.c:63
231#, c-format
232msgid ""
233" minimum CPU frequency - maximum CPU frequency - governor\n"
234msgstr ""
235" frequência mínina do CPU - frequência máxima do CPU - "
236"regulador\n"
237
238#: utils/cpufreq-info.c:151
239#, c-format
240msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
241msgstr ""
242
243#. P state changes via MSR are identified via cpuid 80000007
244#. on Intel and AMD, but we assume boost capable machines can do that
245#. if (cpuid_eax(0x80000000) >= 0x80000007
246#. && (cpuid_edx(0x80000007) & (1 << 7)))
247#.
248#: utils/cpufreq-info.c:161
249#, c-format
250msgid " boost state support: \n"
251msgstr ""
252
253#: utils/cpufreq-info.c:163
254#, c-format
255msgid " Supported: %s\n"
256msgstr ""
257
258#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
259msgid "yes"
260msgstr ""
261
262#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
263msgid "no"
264msgstr ""
265
266#: utils/cpufreq-info.c:164
267#, fuzzy, c-format
268msgid " Active: %s\n"
269msgstr " driver: %s\n"
270
271#: utils/cpufreq-info.c:177
272#, c-format
273msgid " Boost States: %d\n"
274msgstr ""
275
276#: utils/cpufreq-info.c:178
277#, c-format
278msgid " Total States: %d\n"
279msgstr ""
280
281#: utils/cpufreq-info.c:181
282#, c-format
283msgid " Pstate-Pb%d: %luMHz (boost state)\n"
284msgstr ""
285
286#: utils/cpufreq-info.c:184
287#, c-format
288msgid " Pstate-P%d: %luMHz\n"
289msgstr ""
290
291#: utils/cpufreq-info.c:211
292#, c-format
293msgid " no or unknown cpufreq driver is active on this CPU\n"
294msgstr " nenhum ou driver do cpufreq deconhecido está ativo nesse CPU\n"
295
296#: utils/cpufreq-info.c:213
297#, c-format
298msgid " driver: %s\n"
299msgstr " driver: %s\n"
300
301#: utils/cpufreq-info.c:219
302#, c-format
303msgid " CPUs which run at the same hardware frequency: "
304msgstr " CPUs que rodam na mesma frequência de hardware: "
305
306#: utils/cpufreq-info.c:230
307#, c-format
308msgid " CPUs which need to have their frequency coordinated by software: "
309msgstr " CPUs que precisam ter suas frequências coordenadas por software: "
310
311#: utils/cpufreq-info.c:241
312#, c-format
313msgid " maximum transition latency: "
314msgstr " maior latência de transição: "
315
316#: utils/cpufreq-info.c:247
317#, c-format
318msgid " hardware limits: "
319msgstr " limites do hardware: "
320
321#: utils/cpufreq-info.c:256
322#, c-format
323msgid " available frequency steps: "
324msgstr " níveis de frequência disponíveis: "
325
326#: utils/cpufreq-info.c:269
327#, c-format
328msgid " available cpufreq governors: "
329msgstr " reguladores do cpufreq disponíveis: "
330
331#: utils/cpufreq-info.c:280
332#, c-format
333msgid " current policy: frequency should be within "
334msgstr " política de frequência atual deve estar entre "
335
336#: utils/cpufreq-info.c:282
337#, c-format
338msgid " and "
339msgstr " e "
340
341#: utils/cpufreq-info.c:286
342#, c-format
343msgid ""
344"The governor \"%s\" may decide which speed to use\n"
345" within this range.\n"
346msgstr ""
347"O regulador \"%s\" deve decidir qual velocidade usar\n"
348" dentro desse limite.\n"
349
350#: utils/cpufreq-info.c:293
351#, c-format
352msgid " current CPU frequency is "
353msgstr " frequência atual do CPU é "
354
355#: utils/cpufreq-info.c:296
356#, c-format
357msgid " (asserted by call to hardware)"
358msgstr " (declarado por chamada ao hardware)"
359
360#: utils/cpufreq-info.c:304
361#, c-format
362msgid " cpufreq stats: "
363msgstr " status do cpufreq: "
364
365#: utils/cpufreq-info.c:472
366#, fuzzy, c-format
367msgid "Usage: cpupower freqinfo [options]\n"
368msgstr "Uso: cpufreq-info [opções]\n"
369
370#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
371#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
372#, c-format
373msgid "Options:\n"
374msgstr "Opções:\n"
375
376#: utils/cpufreq-info.c:474
377#, fuzzy, c-format
378msgid " -e, --debug Prints out debug information [default]\n"
379msgstr " -e, --debug Mostra informação de debug\n"
380
381#: utils/cpufreq-info.c:475
382#, c-format
383msgid ""
384" -f, --freq Get frequency the CPU currently runs at, according\n"
385" to the cpufreq core *\n"
386msgstr ""
387" -f, --freq Obtem a frequência na qual o CPU roda no momento, de "
388"acordo\n"
389" com o núcleo do cpufreq *\n"
390
391#: utils/cpufreq-info.c:477
392#, c-format
393msgid ""
394" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
395" it from hardware (only available to root) *\n"
396msgstr ""
397" -w, --hwfreq Obtem a frequência na qual o CPU está operando no "
398"momento,\n"
399" através de leitura no hardware (disponível somente "
400"para root) *\n"
401
402#: utils/cpufreq-info.c:479
403#, c-format
404msgid ""
405" -l, --hwlimits Determine the minimum and maximum CPU frequency "
406"allowed *\n"
407msgstr ""
408" -l, --hwlimits Determina a frequência mínima e máxima do CPU "
409"permitida *\n"
410
411#: utils/cpufreq-info.c:480
412#, c-format
413msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
414msgstr ""
415" -d, --driver Determina o driver do kernel do cpufreq usado *\n"
416
417#: utils/cpufreq-info.c:481
418#, c-format
419msgid " -p, --policy Gets the currently used cpufreq policy *\n"
420msgstr ""
421"--p, --policy Obtem a política do cpufreq em uso no momento *\n"
422
423#: utils/cpufreq-info.c:482
424#, c-format
425msgid " -g, --governors Determines available cpufreq governors *\n"
426msgstr ""
427" -g, --governors Determina reguladores do cpufreq disponíveis *\n"
428
429#: utils/cpufreq-info.c:483
430#, c-format
431msgid ""
432" -r, --related-cpus Determines which CPUs run at the same hardware "
433"frequency *\n"
434msgstr ""
435" -r, --related-cpus Determina quais CPUs rodam na mesma frequência de "
436"hardware *\n"
437
438#: utils/cpufreq-info.c:484
439#, c-format
440msgid ""
441" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
442" coordinated by software *\n"
443msgstr ""
444" -a, --affected-cpus Determina quais CPUs precisam ter suas frequências\n"
445" coordenadas por software *\n"
446
447#: utils/cpufreq-info.c:486
448#, c-format
449msgid " -s, --stats Shows cpufreq statistics if available\n"
450msgstr " -s, --stats Mostra estatísticas do cpufreq se disponíveis\n"
451
452#: utils/cpufreq-info.c:487
453#, c-format
454msgid ""
455" -y, --latency Determines the maximum latency on CPU frequency "
456"changes *\n"
457msgstr ""
458" -y, --latency Determina a latência máxima nas trocas de frequência "
459"do CPU *\n"
460
461#: utils/cpufreq-info.c:488
462#, c-format
463msgid " -b, --boost Checks for turbo or boost modes *\n"
464msgstr ""
465
466#: utils/cpufreq-info.c:489
467#, c-format
468msgid ""
469" -o, --proc Prints out information like provided by the /proc/"
470"cpufreq\n"
471" interface in 2.4. and early 2.6. kernels\n"
472msgstr ""
473" -o, --proc Mostra informação do tipo provida pela interface /"
474"proc/cpufreq\n"
475" em kernels 2.4. e mais recentes 2.6\n"
476
477#: utils/cpufreq-info.c:491
478#, c-format
479msgid ""
480" -m, --human human-readable output for the -f, -w, -s and -y "
481"parameters\n"
482msgstr ""
483" -m, --human saída legível para humanos para os parâmetros -f, -w, "
484"-s e -y\n"
485
486#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
487#, c-format
488msgid " -h, --help Prints out this screen\n"
489msgstr " -h, --help Imprime essa tela\n"
490
491#: utils/cpufreq-info.c:495
492#, c-format
493msgid ""
494"If no argument or only the -c, --cpu parameter is given, debug output about\n"
495"cpufreq is printed which is useful e.g. for reporting bugs.\n"
496msgstr ""
497"Se nenhum argumento ou somente o parâmetro -c, --cpu é dado, informação de "
498"debug sobre\n"
499"o cpufreq é mostrada, o que é útil por exemplo para reportar bugs.\n"
500
501#: utils/cpufreq-info.c:497
502#, c-format
503msgid ""
504"For the arguments marked with *, omitting the -c or --cpu argument is\n"
505"equivalent to setting it to zero\n"
506msgstr ""
507"Para os argumentos marcados com *, omitir o argumento -c ou --cpu é\n"
508"equivalente a setá-lo como zero\n"
509
510#: utils/cpufreq-info.c:580
511#, c-format
512msgid ""
513"The argument passed to this tool can't be combined with passing a --cpu "
514"argument\n"
515msgstr ""
516"O argumento usado pra essa ferramenta não pode ser combinado com um "
517"argumento --cpu\n"
518
519#: utils/cpufreq-info.c:596
520#, c-format
521msgid ""
522"You can't specify more than one --cpu parameter and/or\n"
523"more than one output-specific argument\n"
524msgstr ""
525"Você não pode especificar mais do que um parâmetro --cpu e/ou\n"
526"mais do que um argumento de saída específico\n"
527
528#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
529#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
530#, c-format
531msgid "invalid or unknown argument\n"
532msgstr "argumento inválido ou desconhecido\n"
533
534#: utils/cpufreq-info.c:617
535#, c-format
536msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
537msgstr ""
538"não foi possível analisar o CPU % já que o mesmo parece não estar presente\n"
539
540#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
541#, c-format
542msgid "analyzing CPU %d:\n"
543msgstr "analisando o CPU %d:\n"
544
545#: utils/cpufreq-set.c:25
546#, fuzzy, c-format
547msgid "Usage: cpupower frequency-set [options]\n"
548msgstr "Uso: cpufreq-set [opções]\n"
549
550#: utils/cpufreq-set.c:27
551#, c-format
552msgid ""
553" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
554"select\n"
555msgstr ""
556" -d FREQ, --min FREQ nova frequência mínima do CPU que o regulador "
557"deve selecionar\n"
558
559#: utils/cpufreq-set.c:28
560#, c-format
561msgid ""
562" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
563"select\n"
564msgstr ""
565" -u FREQ, --max FREQ nova frequência máxima do CPU que o regulador "
566"deve escolher\n"
567
568#: utils/cpufreq-set.c:29
569#, c-format
570msgid " -g GOV, --governor GOV new cpufreq governor\n"
571msgstr " -g GOV, --governor GOV novo regulador do cpufreq\n"
572
573#: utils/cpufreq-set.c:30
574#, c-format
575msgid ""
576" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
577" governor to be available and loaded\n"
578msgstr ""
579" -f FREQ, --freq FREQ frequência específica para ser setada. Necessita "
580"que o regulador em\n"
581" nível de usuário esteja disponível e carregado\n"
582
583#: utils/cpufreq-set.c:32
584#, c-format
585msgid " -r, --related Switches all hardware-related CPUs\n"
586msgstr ""
587" -r, --related Modifica todos os CPUs relacionados ao hardware\n"
588
589#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
590#, c-format
591msgid " -h, --help Prints out this screen\n"
592msgstr " -h, --help Mostra essa tela\n"
593
594#: utils/cpufreq-set.c:35
595#, fuzzy, c-format
596msgid ""
597"Notes:\n"
598"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
599msgstr ""
600"Para os argumentos marcados com *, omitir o argumento -c ou --cpu é\n"
601"equivalente a setá-lo como zero\n"
602
603#: utils/cpufreq-set.c:37
604#, fuzzy, c-format
605msgid ""
606"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
607"parameter\n"
608" except the -c CPU, --cpu CPU parameter\n"
609"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
610" by postfixing the value with the wanted unit name, without any space\n"
611" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
612msgstr ""
613"Notas:\n"
614"1. Omitir o argumento -c or --cpu é equivalente a setá-lo como zero\n"
615"2. O parâmetro -f FREQ, --freq FREQ não pode ser combinado com qualquer "
616"outro parâmetro\n"
617" exceto com o parâmetro -c CPU, --cpu CPU\n"
618"3. FREQuências podem ser usadas em Hz, kHz (padrão), MHz, GHz, o THz\n"
619" colocando o nome desejado da unidade após o valor, sem qualquer espaço\n"
620" (FREQuência em kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
621
622#: utils/cpufreq-set.c:57
623#, c-format
624msgid ""
625"Error setting new values. Common errors:\n"
626"- Do you have proper administration rights? (super-user?)\n"
627"- Is the governor you requested available and modprobed?\n"
628"- Trying to set an invalid policy?\n"
629"- Trying to set a specific frequency, but userspace governor is not "
630"available,\n"
631" for example because of hardware which cannot be set to a specific "
632"frequency\n"
633" or because the userspace governor isn't loaded?\n"
634msgstr ""
635"Erro ao setar novos valores. Erros comuns:\n"
636"- Você tem direitos administrativos necessários? (super-usuário?)\n"
637"- O regulador que você requesitou está disponível e foi \"modprobed\"?\n"
638"- Tentando setar uma política inválida?\n"
639"- Tentando setar uma frequência específica, mas o regulador em nível de "
640"usuário não está disponível,\n"
641" por exemplo devido ao hardware que não pode ser setado pra uma frequência "
642"específica\n"
643" ou porque o regulador em nível de usuário não foi carregado?\n"
644
645#: utils/cpufreq-set.c:170
646#, c-format
647msgid "wrong, unknown or unhandled CPU?\n"
648msgstr "CPU errado, desconhecido ou inesperado?\n"
649
650#: utils/cpufreq-set.c:302
651#, c-format
652msgid ""
653"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
654"-g/--governor parameters\n"
655msgstr ""
656"o parâmetro -f/--freq não pode ser combinado com os parâmetros -d/--min, -"
657"u/--max ou\n"
658"-g/--governor\n"
659
660#: utils/cpufreq-set.c:308
661#, c-format
662msgid ""
663"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
664"-g/--governor must be passed\n"
665msgstr ""
666"Pelo menos um parâmetro entre -f/--freq, -d/--min, -u/--max, e\n"
667"-g/--governor deve ser usado\n"
668
669#: utils/cpufreq-set.c:347
670#, c-format
671msgid "Setting cpu: %d\n"
672msgstr ""
673
674#: utils/cpupower-set.c:22
675#, c-format
676msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
677msgstr ""
678
679#: utils/cpupower-set.c:24
680#, c-format
681msgid ""
682" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
683" Intel models [0-15], see manpage for details\n"
684msgstr ""
685
686#: utils/cpupower-set.c:26
687#, c-format
688msgid ""
689" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
690msgstr ""
691
692#: utils/cpupower-set.c:27
693#, c-format
694msgid ""
695" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
696"policy.\n"
697msgstr ""
698
699#: utils/cpupower-set.c:80
700#, c-format
701msgid "--perf-bias param out of range [0-%d]\n"
702msgstr ""
703
704#: utils/cpupower-set.c:91
705#, c-format
706msgid "--sched-mc param out of range [0-%d]\n"
707msgstr ""
708
709#: utils/cpupower-set.c:102
710#, c-format
711msgid "--sched-smt param out of range [0-%d]\n"
712msgstr ""
713
714#: utils/cpupower-set.c:121
715#, c-format
716msgid "Error setting sched-mc %s\n"
717msgstr ""
718
719#: utils/cpupower-set.c:127
720#, c-format
721msgid "Error setting sched-smt %s\n"
722msgstr ""
723
724#: utils/cpupower-set.c:146
725#, c-format
726msgid "Error setting perf-bias value on CPU %d\n"
727msgstr ""
728
729#: utils/cpupower-info.c:21
730#, c-format
731msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
732msgstr ""
733
734#: utils/cpupower-info.c:23
735#, c-format
736msgid ""
737" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
738" Intel models [0-15], see manpage for details\n"
739msgstr ""
740
741#: utils/cpupower-info.c:25
742#, fuzzy, c-format
743msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
744msgstr ""
745"--p, --policy Obtem a política do cpufreq em uso no momento *\n"
746
747#: utils/cpupower-info.c:26
748#, c-format
749msgid ""
750" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
751msgstr ""
752
753#: utils/cpupower-info.c:28
754#, c-format
755msgid ""
756"\n"
757"Passing no option will show all info, by default only on core 0\n"
758msgstr ""
759
760#: utils/cpupower-info.c:102
761#, c-format
762msgid "System's multi core scheduler setting: "
763msgstr ""
764
765#. if sysfs file is missing it's: errno == ENOENT
766#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
767#, c-format
768msgid "not supported\n"
769msgstr ""
770
771#: utils/cpupower-info.c:111
772#, c-format
773msgid "System's thread sibling scheduler setting: "
774msgstr ""
775
776#: utils/cpupower-info.c:126
777#, c-format
778msgid "Intel's performance bias setting needs root privileges\n"
779msgstr ""
780
781#: utils/cpupower-info.c:128
782#, c-format
783msgid "System does not support Intel's performance bias setting\n"
784msgstr ""
785
786#: utils/cpupower-info.c:147
787#, c-format
788msgid "Could not read perf-bias value\n"
789msgstr ""
790
791#: utils/cpupower-info.c:150
792#, c-format
793msgid "perf-bias: %d\n"
794msgstr ""
795
796#: utils/cpuidle-info.c:28
797#, fuzzy, c-format
798msgid "Analyzing CPU %d:\n"
799msgstr "analisando o CPU %d:\n"
800
801#: utils/cpuidle-info.c:32
802#, c-format
803msgid "CPU %u: No idle states\n"
804msgstr ""
805
806#: utils/cpuidle-info.c:36
807#, c-format
808msgid "CPU %u: Can't read idle state info\n"
809msgstr ""
810
811#: utils/cpuidle-info.c:41
812#, c-format
813msgid "Could not determine max idle state %u\n"
814msgstr ""
815
816#: utils/cpuidle-info.c:46
817#, c-format
818msgid "Number of idle states: %d\n"
819msgstr ""
820
821#: utils/cpuidle-info.c:48
822#, fuzzy, c-format
823msgid "Available idle states:"
824msgstr " níveis de frequência disponíveis: "
825
826#: utils/cpuidle-info.c:71
827#, c-format
828msgid "Flags/Description: %s\n"
829msgstr ""
830
831#: utils/cpuidle-info.c:74
832#, c-format
833msgid "Latency: %lu\n"
834msgstr ""
835
836#: utils/cpuidle-info.c:76
837#, c-format
838msgid "Usage: %lu\n"
839msgstr ""
840
841#: utils/cpuidle-info.c:78
842#, c-format
843msgid "Duration: %llu\n"
844msgstr ""
845
846#: utils/cpuidle-info.c:90
847#, c-format
848msgid "Could not determine cpuidle driver\n"
849msgstr ""
850
851#: utils/cpuidle-info.c:94
852#, fuzzy, c-format
853msgid "CPUidle driver: %s\n"
854msgstr " driver: %s\n"
855
856#: utils/cpuidle-info.c:99
857#, c-format
858msgid "Could not determine cpuidle governor\n"
859msgstr ""
860
861#: utils/cpuidle-info.c:103
862#, c-format
863msgid "CPUidle governor: %s\n"
864msgstr ""
865
866#: utils/cpuidle-info.c:122
867#, c-format
868msgid "CPU %u: Can't read C-state info\n"
869msgstr ""
870
871#. printf("Cstates: %d\n", cstates);
872#: utils/cpuidle-info.c:127
873#, c-format
874msgid "active state: C0\n"
875msgstr ""
876
877#: utils/cpuidle-info.c:128
878#, c-format
879msgid "max_cstate: C%u\n"
880msgstr ""
881
882#: utils/cpuidle-info.c:129
883#, fuzzy, c-format
884msgid "maximum allowed latency: %lu usec\n"
885msgstr " maior latência de transição: "
886
887#: utils/cpuidle-info.c:130
888#, c-format
889msgid "states:\t\n"
890msgstr ""
891
892#: utils/cpuidle-info.c:132
893#, c-format
894msgid " C%d: type[C%d] "
895msgstr ""
896
897#: utils/cpuidle-info.c:134
898#, c-format
899msgid "promotion[--] demotion[--] "
900msgstr ""
901
902#: utils/cpuidle-info.c:135
903#, c-format
904msgid "latency[%03lu] "
905msgstr ""
906
907#: utils/cpuidle-info.c:137
908#, c-format
909msgid "usage[%08lu] "
910msgstr ""
911
912#: utils/cpuidle-info.c:139
913#, c-format
914msgid "duration[%020Lu] \n"
915msgstr ""
916
917#: utils/cpuidle-info.c:147
918#, fuzzy, c-format
919msgid "Usage: cpupower idleinfo [options]\n"
920msgstr "Uso: cpufreq-info [opções]\n"
921
922#: utils/cpuidle-info.c:149
923#, fuzzy, c-format
924msgid " -s, --silent Only show general C-state information\n"
925msgstr " -e, --debug Mostra informação de debug\n"
926
927#: utils/cpuidle-info.c:150
928#, fuzzy, c-format
929msgid ""
930" -o, --proc Prints out information like provided by the /proc/"
931"acpi/processor/*/power\n"
932" interface in older kernels\n"
933msgstr ""
934" -o, --proc Mostra informação do tipo provida pela interface /"
935"proc/cpufreq\n"
936" em kernels 2.4. e mais recentes 2.6\n"
937
938#: utils/cpuidle-info.c:209
939#, fuzzy, c-format
940msgid "You can't specify more than one output-specific argument\n"
941msgstr ""
942"Você não pode especificar mais do que um parâmetro --cpu e/ou\n"
943"mais do que um argumento de saída específico\n"
944
945#~ msgid ""
946#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
947#~ "about\n"
948#~ msgstr ""
949#~ " -c CPU, --cpu CPU número do CPU sobre o qual as inforções devem ser "
950#~ "determinadas\n"
951
952#~ msgid ""
953#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
954#~ "modified\n"
955#~ msgstr ""
956#~ " -c CPU, --cpu CPU número do CPU onde as configurações do cpufreq "
957#~ "vão ser modificadas\n"
diff --git a/tools/power/cpupower/utils/builtin.h b/tools/power/cpupower/utils/builtin.h
new file mode 100644
index 000000000000..c10496fbe3c6
--- /dev/null
+++ b/tools/power/cpupower/utils/builtin.h
@@ -0,0 +1,11 @@
1#ifndef BUILTIN_H
2#define BUILTIN_H
3
4extern int cmd_set(int argc, const char **argv);
5extern int cmd_info(int argc, const char **argv);
6extern int cmd_freq_set(int argc, const char **argv);
7extern int cmd_freq_info(int argc, const char **argv);
8extern int cmd_idle_info(int argc, const char **argv);
9extern int cmd_monitor(int argc, const char **argv);
10
11#endif
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
new file mode 100644
index 000000000000..28953c9a7bd5
--- /dev/null
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -0,0 +1,668 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <unistd.h>
9#include <stdio.h>
10#include <errno.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include <getopt.h>
15
16#include "cpufreq.h"
17#include "helpers/helpers.h"
18#include "helpers/bitmask.h"
19
20#define LINE_LEN 10
21
22static unsigned int count_cpus(void)
23{
24 FILE *fp;
25 char value[LINE_LEN];
26 unsigned int ret = 0;
27 unsigned int cpunr = 0;
28
29 fp = fopen("/proc/stat", "r");
30 if (!fp) {
31 printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
32 return 1;
33 }
34
35 while (!feof(fp)) {
36 if (!fgets(value, LINE_LEN, fp))
37 continue;
38 value[LINE_LEN - 1] = '\0';
39 if (strlen(value) < (LINE_LEN - 2))
40 continue;
41 if (strstr(value, "cpu "))
42 continue;
43 if (sscanf(value, "cpu%d ", &cpunr) != 1)
44 continue;
45 if (cpunr > ret)
46 ret = cpunr;
47 }
48 fclose(fp);
49
50 /* cpu count starts from 0, on error return 1 (UP) */
51 return ret + 1;
52}
53
54
55static void proc_cpufreq_output(void)
56{
57 unsigned int cpu, nr_cpus;
58 struct cpufreq_policy *policy;
59 unsigned int min_pctg = 0;
60 unsigned int max_pctg = 0;
61 unsigned long min, max;
62
63 printf(_(" minimum CPU frequency - maximum CPU frequency - governor\n"));
64
65 nr_cpus = count_cpus();
66 for (cpu = 0; cpu < nr_cpus; cpu++) {
67 policy = cpufreq_get_policy(cpu);
68 if (!policy)
69 continue;
70
71 if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
72 max = 0;
73 } else {
74 min_pctg = (policy->min * 100) / max;
75 max_pctg = (policy->max * 100) / max;
76 }
77 printf("CPU%3d %9lu kHz (%3d %%) - %9lu kHz (%3d %%) - %s\n",
78 cpu , policy->min, max ? min_pctg : 0, policy->max,
79 max ? max_pctg : 0, policy->governor);
80
81 cpufreq_put_policy(policy);
82 }
83}
84
85static void print_speed(unsigned long speed)
86{
87 unsigned long tmp;
88
89 if (speed > 1000000) {
90 tmp = speed % 10000;
91 if (tmp >= 5000)
92 speed += 10000;
93 printf("%u.%02u GHz", ((unsigned int) speed/1000000),
94 ((unsigned int) (speed%1000000)/10000));
95 } else if (speed > 100000) {
96 tmp = speed % 1000;
97 if (tmp >= 500)
98 speed += 1000;
99 printf("%u MHz", ((unsigned int) speed / 1000));
100 } else if (speed > 1000) {
101 tmp = speed % 100;
102 if (tmp >= 50)
103 speed += 100;
104 printf("%u.%01u MHz", ((unsigned int) speed/1000),
105 ((unsigned int) (speed%1000)/100));
106 } else
107 printf("%lu kHz", speed);
108
109 return;
110}
111
112static void print_duration(unsigned long duration)
113{
114 unsigned long tmp;
115
116 if (duration > 1000000) {
117 tmp = duration % 10000;
118 if (tmp >= 5000)
119 duration += 10000;
120 printf("%u.%02u ms", ((unsigned int) duration/1000000),
121 ((unsigned int) (duration%1000000)/10000));
122 } else if (duration > 100000) {
123 tmp = duration % 1000;
124 if (tmp >= 500)
125 duration += 1000;
126 printf("%u us", ((unsigned int) duration / 1000));
127 } else if (duration > 1000) {
128 tmp = duration % 100;
129 if (tmp >= 50)
130 duration += 100;
131 printf("%u.%01u us", ((unsigned int) duration/1000),
132 ((unsigned int) (duration%1000)/100));
133 } else
134 printf("%lu ns", duration);
135
136 return;
137}
138
139/* --boost / -b */
140
141static int get_boost_mode(unsigned int cpu)
142{
143 int support, active, b_states = 0, ret, pstate_no, i;
144 /* ToDo: Make this more global */
145 unsigned long pstates[MAX_HW_PSTATES] = {0,};
146
147 if (cpupower_cpu_info.vendor != X86_VENDOR_AMD &&
148 cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
149 return 0;
150
151 ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states);
152 if (ret) {
153 printf(_("Error while evaluating Boost Capabilities"
154 " on CPU %d -- are you root?\n"), cpu);
155 return ret;
156 }
157 /* P state changes via MSR are identified via cpuid 80000007
158 on Intel and AMD, but we assume boost capable machines can do that
159 if (cpuid_eax(0x80000000) >= 0x80000007
160 && (cpuid_edx(0x80000007) & (1 << 7)))
161 */
162
163 printf(_(" boost state support:\n"));
164
165 printf(_(" Supported: %s\n"), support ? _("yes") : _("no"));
166 printf(_(" Active: %s\n"), active ? _("yes") : _("no"));
167
168 if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
169 cpupower_cpu_info.family >= 0x10) {
170 ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
171 pstates, &pstate_no);
172 if (ret)
173 return ret;
174
175 printf(_(" Boost States: %d\n"), b_states);
176 printf(_(" Total States: %d\n"), pstate_no);
177 for (i = 0; i < pstate_no; i++) {
178 if (i < b_states)
179 printf(_(" Pstate-Pb%d: %luMHz (boost state)"
180 "\n"), i, pstates[i]);
181 else
182 printf(_(" Pstate-P%d: %luMHz\n"),
183 i - b_states, pstates[i]);
184 }
185 } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) {
186 double bclk;
187 unsigned long long intel_turbo_ratio = 0;
188 unsigned int ratio;
189
190 /* Any way to autodetect this ? */
191 if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB)
192 bclk = 100.00;
193 else
194 bclk = 133.33;
195 intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu);
196 dprint (" Ratio: 0x%llx - bclk: %f\n",
197 intel_turbo_ratio, bclk);
198
199 ratio = (intel_turbo_ratio >> 24) & 0xFF;
200 if (ratio)
201 printf(_(" %.0f MHz max turbo 4 active cores\n"),
202 ratio * bclk);
203
204 ratio = (intel_turbo_ratio >> 16) & 0xFF;
205 if (ratio)
206 printf(_(" %.0f MHz max turbo 3 active cores\n"),
207 ratio * bclk);
208
209 ratio = (intel_turbo_ratio >> 8) & 0xFF;
210 if (ratio)
211 printf(_(" %.0f MHz max turbo 2 active cores\n"),
212 ratio * bclk);
213
214 ratio = (intel_turbo_ratio >> 0) & 0xFF;
215 if (ratio)
216 printf(_(" %.0f MHz max turbo 1 active cores\n"),
217 ratio * bclk);
218 }
219 return 0;
220}
221
222static void debug_output_one(unsigned int cpu)
223{
224 char *driver;
225 struct cpufreq_affected_cpus *cpus;
226 struct cpufreq_available_frequencies *freqs;
227 unsigned long min, max, freq_kernel, freq_hardware;
228 unsigned long total_trans, latency;
229 unsigned long long total_time;
230 struct cpufreq_policy *policy;
231 struct cpufreq_available_governors *governors;
232 struct cpufreq_stats *stats;
233
234 if (cpufreq_cpu_exists(cpu))
235 return;
236
237 freq_kernel = cpufreq_get_freq_kernel(cpu);
238 freq_hardware = cpufreq_get_freq_hardware(cpu);
239
240 driver = cpufreq_get_driver(cpu);
241 if (!driver) {
242 printf(_(" no or unknown cpufreq driver is active on this CPU\n"));
243 } else {
244 printf(_(" driver: %s\n"), driver);
245 cpufreq_put_driver(driver);
246 }
247
248 cpus = cpufreq_get_related_cpus(cpu);
249 if (cpus) {
250 printf(_(" CPUs which run at the same hardware frequency: "));
251 while (cpus->next) {
252 printf("%d ", cpus->cpu);
253 cpus = cpus->next;
254 }
255 printf("%d\n", cpus->cpu);
256 cpufreq_put_related_cpus(cpus);
257 }
258
259 cpus = cpufreq_get_affected_cpus(cpu);
260 if (cpus) {
261 printf(_(" CPUs which need to have their frequency coordinated by software: "));
262 while (cpus->next) {
263 printf("%d ", cpus->cpu);
264 cpus = cpus->next;
265 }
266 printf("%d\n", cpus->cpu);
267 cpufreq_put_affected_cpus(cpus);
268 }
269
270 latency = cpufreq_get_transition_latency(cpu);
271 if (latency) {
272 printf(_(" maximum transition latency: "));
273 print_duration(latency);
274 printf(".\n");
275 }
276
277 if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) {
278 printf(_(" hardware limits: "));
279 print_speed(min);
280 printf(" - ");
281 print_speed(max);
282 printf("\n");
283 }
284
285 freqs = cpufreq_get_available_frequencies(cpu);
286 if (freqs) {
287 printf(_(" available frequency steps: "));
288 while (freqs->next) {
289 print_speed(freqs->frequency);
290 printf(", ");
291 freqs = freqs->next;
292 }
293 print_speed(freqs->frequency);
294 printf("\n");
295 cpufreq_put_available_frequencies(freqs);
296 }
297
298 governors = cpufreq_get_available_governors(cpu);
299 if (governors) {
300 printf(_(" available cpufreq governors: "));
301 while (governors->next) {
302 printf("%s, ", governors->governor);
303 governors = governors->next;
304 }
305 printf("%s\n", governors->governor);
306 cpufreq_put_available_governors(governors);
307 }
308
309 policy = cpufreq_get_policy(cpu);
310 if (policy) {
311 printf(_(" current policy: frequency should be within "));
312 print_speed(policy->min);
313 printf(_(" and "));
314 print_speed(policy->max);
315
316 printf(".\n ");
317 printf(_("The governor \"%s\" may"
318 " decide which speed to use\n within this range.\n"),
319 policy->governor);
320 cpufreq_put_policy(policy);
321 }
322
323 if (freq_kernel || freq_hardware) {
324 printf(_(" current CPU frequency is "));
325 if (freq_hardware) {
326 print_speed(freq_hardware);
327 printf(_(" (asserted by call to hardware)"));
328 } else
329 print_speed(freq_kernel);
330 printf(".\n");
331 }
332 stats = cpufreq_get_stats(cpu, &total_time);
333 if (stats) {
334 printf(_(" cpufreq stats: "));
335 while (stats) {
336 print_speed(stats->frequency);
337 printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
338 stats = stats->next;
339 if (stats)
340 printf(", ");
341 }
342 cpufreq_put_stats(stats);
343 total_trans = cpufreq_get_transitions(cpu);
344 if (total_trans)
345 printf(" (%lu)\n", total_trans);
346 else
347 printf("\n");
348 }
349 get_boost_mode(cpu);
350
351}
352
353/* --freq / -f */
354
355static int get_freq_kernel(unsigned int cpu, unsigned int human)
356{
357 unsigned long freq = cpufreq_get_freq_kernel(cpu);
358 if (!freq)
359 return -EINVAL;
360 if (human) {
361 print_speed(freq);
362 printf("\n");
363 } else
364 printf("%lu\n", freq);
365 return 0;
366}
367
368
369/* --hwfreq / -w */
370
371static int get_freq_hardware(unsigned int cpu, unsigned int human)
372{
373 unsigned long freq = cpufreq_get_freq_hardware(cpu);
374 if (!freq)
375 return -EINVAL;
376 if (human) {
377 print_speed(freq);
378 printf("\n");
379 } else
380 printf("%lu\n", freq);
381 return 0;
382}
383
384/* --hwlimits / -l */
385
386static int get_hardware_limits(unsigned int cpu)
387{
388 unsigned long min, max;
389 if (cpufreq_get_hardware_limits(cpu, &min, &max))
390 return -EINVAL;
391 printf("%lu %lu\n", min, max);
392 return 0;
393}
394
395/* --driver / -d */
396
397static int get_driver(unsigned int cpu)
398{
399 char *driver = cpufreq_get_driver(cpu);
400 if (!driver)
401 return -EINVAL;
402 printf("%s\n", driver);
403 cpufreq_put_driver(driver);
404 return 0;
405}
406
407/* --policy / -p */
408
409static int get_policy(unsigned int cpu)
410{
411 struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
412 if (!policy)
413 return -EINVAL;
414 printf("%lu %lu %s\n", policy->min, policy->max, policy->governor);
415 cpufreq_put_policy(policy);
416 return 0;
417}
418
419/* --governors / -g */
420
421static int get_available_governors(unsigned int cpu)
422{
423 struct cpufreq_available_governors *governors =
424 cpufreq_get_available_governors(cpu);
425 if (!governors)
426 return -EINVAL;
427
428 while (governors->next) {
429 printf("%s ", governors->governor);
430 governors = governors->next;
431 }
432 printf("%s\n", governors->governor);
433 cpufreq_put_available_governors(governors);
434 return 0;
435}
436
437
438/* --affected-cpus / -a */
439
440static int get_affected_cpus(unsigned int cpu)
441{
442 struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
443 if (!cpus)
444 return -EINVAL;
445
446 while (cpus->next) {
447 printf("%d ", cpus->cpu);
448 cpus = cpus->next;
449 }
450 printf("%d\n", cpus->cpu);
451 cpufreq_put_affected_cpus(cpus);
452 return 0;
453}
454
455/* --related-cpus / -r */
456
457static int get_related_cpus(unsigned int cpu)
458{
459 struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
460 if (!cpus)
461 return -EINVAL;
462
463 while (cpus->next) {
464 printf("%d ", cpus->cpu);
465 cpus = cpus->next;
466 }
467 printf("%d\n", cpus->cpu);
468 cpufreq_put_related_cpus(cpus);
469 return 0;
470}
471
472/* --stats / -s */
473
474static int get_freq_stats(unsigned int cpu, unsigned int human)
475{
476 unsigned long total_trans = cpufreq_get_transitions(cpu);
477 unsigned long long total_time;
478 struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
479 while (stats) {
480 if (human) {
481 print_speed(stats->frequency);
482 printf(":%.2f%%",
483 (100.0 * stats->time_in_state) / total_time);
484 } else
485 printf("%lu:%llu",
486 stats->frequency, stats->time_in_state);
487 stats = stats->next;
488 if (stats)
489 printf(", ");
490 }
491 cpufreq_put_stats(stats);
492 if (total_trans)
493 printf(" (%lu)\n", total_trans);
494 return 0;
495}
496
497/* --latency / -y */
498
499static int get_latency(unsigned int cpu, unsigned int human)
500{
501 unsigned long latency = cpufreq_get_transition_latency(cpu);
502 if (!latency)
503 return -EINVAL;
504
505 if (human) {
506 print_duration(latency);
507 printf("\n");
508 } else
509 printf("%lu\n", latency);
510 return 0;
511}
512
513static struct option info_opts[] = {
514 { .name = "debug", .has_arg = no_argument, .flag = NULL, .val = 'e'},
515 { .name = "boost", .has_arg = no_argument, .flag = NULL, .val = 'b'},
516 { .name = "freq", .has_arg = no_argument, .flag = NULL, .val = 'f'},
517 { .name = "hwfreq", .has_arg = no_argument, .flag = NULL, .val = 'w'},
518 { .name = "hwlimits", .has_arg = no_argument, .flag = NULL, .val = 'l'},
519 { .name = "driver", .has_arg = no_argument, .flag = NULL, .val = 'd'},
520 { .name = "policy", .has_arg = no_argument, .flag = NULL, .val = 'p'},
521 { .name = "governors", .has_arg = no_argument, .flag = NULL, .val = 'g'},
522 { .name = "related-cpus", .has_arg = no_argument, .flag = NULL, .val = 'r'},
523 { .name = "affected-cpus",.has_arg = no_argument, .flag = NULL, .val = 'a'},
524 { .name = "stats", .has_arg = no_argument, .flag = NULL, .val = 's'},
525 { .name = "latency", .has_arg = no_argument, .flag = NULL, .val = 'y'},
526 { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'},
527 { .name = "human", .has_arg = no_argument, .flag = NULL, .val = 'm'},
528 { },
529};
530
531int cmd_freq_info(int argc, char **argv)
532{
533 extern char *optarg;
534 extern int optind, opterr, optopt;
535 int ret = 0, cont = 1;
536 unsigned int cpu = 0;
537 unsigned int human = 0;
538 int output_param = 0;
539
540 do {
541 ret = getopt_long(argc, argv, "oefwldpgrasmyb", info_opts, NULL);
542 switch (ret) {
543 case '?':
544 output_param = '?';
545 cont = 0;
546 break;
547 case -1:
548 cont = 0;
549 break;
550 case 'b':
551 case 'o':
552 case 'a':
553 case 'r':
554 case 'g':
555 case 'p':
556 case 'd':
557 case 'l':
558 case 'w':
559 case 'f':
560 case 'e':
561 case 's':
562 case 'y':
563 if (output_param) {
564 output_param = -1;
565 cont = 0;
566 break;
567 }
568 output_param = ret;
569 break;
570 case 'm':
571 if (human) {
572 output_param = -1;
573 cont = 0;
574 break;
575 }
576 human = 1;
577 break;
578 default:
579 fprintf(stderr, "invalid or unknown argument\n");
580 return EXIT_FAILURE;
581 }
582 } while (cont);
583
584 switch (output_param) {
585 case 'o':
586 if (!bitmask_isallclear(cpus_chosen)) {
587 printf(_("The argument passed to this tool can't be "
588 "combined with passing a --cpu argument\n"));
589 return -EINVAL;
590 }
591 break;
592 case 0:
593 output_param = 'e';
594 }
595
596 ret = 0;
597
598 /* Default is: show output of CPU 0 only */
599 if (bitmask_isallclear(cpus_chosen))
600 bitmask_setbit(cpus_chosen, 0);
601
602 switch (output_param) {
603 case -1:
604 printf(_("You can't specify more than one --cpu parameter and/or\n"
605 "more than one output-specific argument\n"));
606 return -EINVAL;
607 case '?':
608 printf(_("invalid or unknown argument\n"));
609 return -EINVAL;
610 case 'o':
611 proc_cpufreq_output();
612 return EXIT_SUCCESS;
613 }
614
615 for (cpu = bitmask_first(cpus_chosen);
616 cpu <= bitmask_last(cpus_chosen); cpu++) {
617
618 if (!bitmask_isbitset(cpus_chosen, cpu))
619 continue;
620 if (cpufreq_cpu_exists(cpu)) {
621 printf(_("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu);
622 continue;
623 }
624 printf(_("analyzing CPU %d:\n"), cpu);
625
626 switch (output_param) {
627 case 'b':
628 get_boost_mode(cpu);
629 break;
630 case 'e':
631 debug_output_one(cpu);
632 break;
633 case 'a':
634 ret = get_affected_cpus(cpu);
635 break;
636 case 'r':
637 ret = get_related_cpus(cpu);
638 break;
639 case 'g':
640 ret = get_available_governors(cpu);
641 break;
642 case 'p':
643 ret = get_policy(cpu);
644 break;
645 case 'd':
646 ret = get_driver(cpu);
647 break;
648 case 'l':
649 ret = get_hardware_limits(cpu);
650 break;
651 case 'w':
652 ret = get_freq_hardware(cpu, human);
653 break;
654 case 'f':
655 ret = get_freq_kernel(cpu, human);
656 break;
657 case 's':
658 ret = get_freq_stats(cpu, human);
659 break;
660 case 'y':
661 ret = get_latency(cpu, human);
662 break;
663 }
664 if (ret)
665 return ret;
666 }
667 return ret;
668}
diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c
new file mode 100644
index 000000000000..dd1539eb8c63
--- /dev/null
+++ b/tools/power/cpupower/utils/cpufreq-set.c
@@ -0,0 +1,331 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <unistd.h>
9#include <stdio.h>
10#include <errno.h>
11#include <stdlib.h>
12#include <limits.h>
13#include <string.h>
14#include <ctype.h>
15
16#include <getopt.h>
17
18#include "cpufreq.h"
19#include "helpers/helpers.h"
20
21#define NORM_FREQ_LEN 32
22
23static struct option set_opts[] = {
24 { .name = "min", .has_arg = required_argument, .flag = NULL, .val = 'd'},
25 { .name = "max", .has_arg = required_argument, .flag = NULL, .val = 'u'},
26 { .name = "governor", .has_arg = required_argument, .flag = NULL, .val = 'g'},
27 { .name = "freq", .has_arg = required_argument, .flag = NULL, .val = 'f'},
28 { .name = "related", .has_arg = no_argument, .flag = NULL, .val='r'},
29 { },
30};
31
32static void print_error(void)
33{
34 printf(_("Error setting new values. Common errors:\n"
35 "- Do you have proper administration rights? (super-user?)\n"
36 "- Is the governor you requested available and modprobed?\n"
37 "- Trying to set an invalid policy?\n"
38 "- Trying to set a specific frequency, but userspace governor is not available,\n"
39 " for example because of hardware which cannot be set to a specific frequency\n"
40 " or because the userspace governor isn't loaded?\n"));
41};
42
43struct freq_units {
44 char *str_unit;
45 int power_of_ten;
46};
47
48const struct freq_units def_units[] = {
49 {"hz", -3},
50 {"khz", 0}, /* default */
51 {"mhz", 3},
52 {"ghz", 6},
53 {"thz", 9},
54 {NULL, 0}
55};
56
57static void print_unknown_arg(void)
58{
59 printf(_("invalid or unknown argument\n"));
60}
61
62static unsigned long string_to_frequency(const char *str)
63{
64 char normalized[NORM_FREQ_LEN];
65 const struct freq_units *unit;
66 const char *scan;
67 char *end;
68 unsigned long freq;
69 int power = 0, match_count = 0, i, cp, pad;
70
71 while (*str == '0')
72 str++;
73
74 for (scan = str; isdigit(*scan) || *scan == '.'; scan++) {
75 if (*scan == '.' && match_count == 0)
76 match_count = 1;
77 else if (*scan == '.' && match_count == 1)
78 return 0;
79 }
80
81 if (*scan) {
82 match_count = 0;
83 for (unit = def_units; unit->str_unit; unit++) {
84 for (i = 0;
85 scan[i] && tolower(scan[i]) == unit->str_unit[i];
86 ++i)
87 continue;
88 if (scan[i])
89 continue;
90 match_count++;
91 power = unit->power_of_ten;
92 }
93 if (match_count != 1)
94 return 0;
95 }
96
97 /* count the number of digits to be copied */
98 for (cp = 0; isdigit(str[cp]); cp++)
99 continue;
100
101 if (str[cp] == '.') {
102 while (power > -1 && isdigit(str[cp+1]))
103 cp++, power--;
104 }
105 if (power >= -1) /* not enough => pad */
106 pad = power + 1;
107 else /* to much => strip */
108 pad = 0, cp += power + 1;
109 /* check bounds */
110 if (cp <= 0 || cp + pad > NORM_FREQ_LEN - 1)
111 return 0;
112
113 /* copy digits */
114 for (i = 0; i < cp; i++, str++) {
115 if (*str == '.')
116 str++;
117 normalized[i] = *str;
118 }
119 /* and pad */
120 for (; i < cp + pad; i++)
121 normalized[i] = '0';
122
123 /* round up, down ? */
124 match_count = (normalized[i-1] >= '5');
125 /* and drop the decimal part */
126 normalized[i-1] = 0; /* cp > 0 && pad >= 0 ==> i > 0 */
127
128 /* final conversion (and applying rounding) */
129 errno = 0;
130 freq = strtoul(normalized, &end, 10);
131 if (errno)
132 return 0;
133 else {
134 if (match_count && freq != ULONG_MAX)
135 freq++;
136 return freq;
137 }
138}
139
140static int do_new_policy(unsigned int cpu, struct cpufreq_policy *new_pol)
141{
142 struct cpufreq_policy *cur_pol = cpufreq_get_policy(cpu);
143 int ret;
144
145 if (!cur_pol) {
146 printf(_("wrong, unknown or unhandled CPU?\n"));
147 return -EINVAL;
148 }
149
150 if (!new_pol->min)
151 new_pol->min = cur_pol->min;
152
153 if (!new_pol->max)
154 new_pol->max = cur_pol->max;
155
156 if (!new_pol->governor)
157 new_pol->governor = cur_pol->governor;
158
159 ret = cpufreq_set_policy(cpu, new_pol);
160
161 cpufreq_put_policy(cur_pol);
162
163 return ret;
164}
165
166
167static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol,
168 unsigned long freq, unsigned int pc)
169{
170 switch (pc) {
171 case 0:
172 return cpufreq_set_frequency(cpu, freq);
173
174 case 1:
175 /* if only one value of a policy is to be changed, we can
176 * use a "fast path".
177 */
178 if (new_pol->min)
179 return cpufreq_modify_policy_min(cpu, new_pol->min);
180 else if (new_pol->max)
181 return cpufreq_modify_policy_max(cpu, new_pol->max);
182 else if (new_pol->governor)
183 return cpufreq_modify_policy_governor(cpu,
184 new_pol->governor);
185
186 default:
187 /* slow path */
188 return do_new_policy(cpu, new_pol);
189 }
190}
191
192int cmd_freq_set(int argc, char **argv)
193{
194 extern char *optarg;
195 extern int optind, opterr, optopt;
196 int ret = 0, cont = 1;
197 int double_parm = 0, related = 0, policychange = 0;
198 unsigned long freq = 0;
199 char gov[20];
200 unsigned int cpu;
201
202 struct cpufreq_policy new_pol = {
203 .min = 0,
204 .max = 0,
205 .governor = NULL,
206 };
207
208 /* parameter parsing */
209 do {
210 ret = getopt_long(argc, argv, "d:u:g:f:r", set_opts, NULL);
211 switch (ret) {
212 case '?':
213 print_unknown_arg();
214 return -EINVAL;
215 case -1:
216 cont = 0;
217 break;
218 case 'r':
219 if (related)
220 double_parm++;
221 related++;
222 break;
223 case 'd':
224 if (new_pol.min)
225 double_parm++;
226 policychange++;
227 new_pol.min = string_to_frequency(optarg);
228 if (new_pol.min == 0) {
229 print_unknown_arg();
230 return -EINVAL;
231 }
232 break;
233 case 'u':
234 if (new_pol.max)
235 double_parm++;
236 policychange++;
237 new_pol.max = string_to_frequency(optarg);
238 if (new_pol.max == 0) {
239 print_unknown_arg();
240 return -EINVAL;
241 }
242 break;
243 case 'f':
244 if (freq)
245 double_parm++;
246 freq = string_to_frequency(optarg);
247 if (freq == 0) {
248 print_unknown_arg();
249 return -EINVAL;
250 }
251 break;
252 case 'g':
253 if (new_pol.governor)
254 double_parm++;
255 policychange++;
256 if ((strlen(optarg) < 3) || (strlen(optarg) > 18)) {
257 print_unknown_arg();
258 return -EINVAL;
259 }
260 if ((sscanf(optarg, "%s", gov)) != 1) {
261 print_unknown_arg();
262 return -EINVAL;
263 }
264 new_pol.governor = gov;
265 break;
266 }
267 } while (cont);
268
269 /* parameter checking */
270 if (double_parm) {
271 printf("the same parameter was passed more than once\n");
272 return -EINVAL;
273 }
274
275 if (freq && policychange) {
276 printf(_("the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
277 "-g/--governor parameters\n"));
278 return -EINVAL;
279 }
280
281 if (!freq && !policychange) {
282 printf(_("At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
283 "-g/--governor must be passed\n"));
284 return -EINVAL;
285 }
286
287 /* Default is: set all CPUs */
288 if (bitmask_isallclear(cpus_chosen))
289 bitmask_setall(cpus_chosen);
290
291 /* Also set frequency settings for related CPUs if -r is passed */
292 if (related) {
293 for (cpu = bitmask_first(cpus_chosen);
294 cpu <= bitmask_last(cpus_chosen); cpu++) {
295 struct cpufreq_affected_cpus *cpus;
296
297 if (!bitmask_isbitset(cpus_chosen, cpu) ||
298 cpufreq_cpu_exists(cpu))
299 continue;
300
301 cpus = cpufreq_get_related_cpus(cpu);
302 if (!cpus)
303 break;
304 while (cpus->next) {
305 bitmask_setbit(cpus_chosen, cpus->cpu);
306 cpus = cpus->next;
307 }
308 cpufreq_put_related_cpus(cpus);
309 }
310 }
311
312
313 /* loop over CPUs */
314 for (cpu = bitmask_first(cpus_chosen);
315 cpu <= bitmask_last(cpus_chosen); cpu++) {
316
317 if (!bitmask_isbitset(cpus_chosen, cpu) ||
318 cpufreq_cpu_exists(cpu))
319 continue;
320
321 printf(_("Setting cpu: %d\n"), cpu);
322 ret = do_one_cpu(cpu, &new_pol, freq, policychange);
323 if (ret)
324 break;
325 }
326
327 if (ret)
328 print_error();
329
330 return ret;
331}
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
new file mode 100644
index 000000000000..b028267c1376
--- /dev/null
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -0,0 +1,222 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 * (C) 2010 Thomas Renninger <trenn@suse.de>
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 */
7
8
9#include <unistd.h>
10#include <stdio.h>
11#include <errno.h>
12#include <stdlib.h>
13#include <string.h>
14#include <getopt.h>
15#include <cpufreq.h>
16
17#include "helpers/helpers.h"
18#include "helpers/sysfs.h"
19#include "helpers/bitmask.h"
20
21#define LINE_LEN 10
22
23static void cpuidle_cpu_output(unsigned int cpu, int verbose)
24{
25 int idlestates, idlestate;
26 char *tmp;
27
28 printf(_ ("Analyzing CPU %d:\n"), cpu);
29
30 idlestates = sysfs_get_idlestate_count(cpu);
31 if (idlestates == 0) {
32 printf(_("CPU %u: No idle states\n"), cpu);
33 return;
34 } else if (idlestates <= 0) {
35 printf(_("CPU %u: Can't read idle state info\n"), cpu);
36 return;
37 }
38 tmp = sysfs_get_idlestate_name(cpu, idlestates - 1);
39 if (!tmp) {
40 printf(_("Could not determine max idle state %u\n"),
41 idlestates - 1);
42 return;
43 }
44
45 printf(_("Number of idle states: %d\n"), idlestates);
46
47 printf(_("Available idle states:"));
48 for (idlestate = 1; idlestate < idlestates; idlestate++) {
49 tmp = sysfs_get_idlestate_name(cpu, idlestate);
50 if (!tmp)
51 continue;
52 printf(" %s", tmp);
53 free(tmp);
54 }
55 printf("\n");
56
57 if (!verbose)
58 return;
59
60 for (idlestate = 1; idlestate < idlestates; idlestate++) {
61 tmp = sysfs_get_idlestate_name(cpu, idlestate);
62 if (!tmp)
63 continue;
64 printf("%s:\n", tmp);
65 free(tmp);
66
67 tmp = sysfs_get_idlestate_desc(cpu, idlestate);
68 if (!tmp)
69 continue;
70 printf(_("Flags/Description: %s\n"), tmp);
71 free(tmp);
72
73 printf(_("Latency: %lu\n"),
74 sysfs_get_idlestate_latency(cpu, idlestate));
75 printf(_("Usage: %lu\n"),
76 sysfs_get_idlestate_usage(cpu, idlestate));
77 printf(_("Duration: %llu\n"),
78 sysfs_get_idlestate_time(cpu, idlestate));
79 }
80 printf("\n");
81}
82
83static void cpuidle_general_output(void)
84{
85 char *tmp;
86
87 tmp = sysfs_get_cpuidle_driver();
88 if (!tmp) {
89 printf(_("Could not determine cpuidle driver\n"));
90 return;
91 }
92
93 printf(_("CPUidle driver: %s\n"), tmp);
94 free(tmp);
95
96 tmp = sysfs_get_cpuidle_governor();
97 if (!tmp) {
98 printf(_("Could not determine cpuidle governor\n"));
99 return;
100 }
101
102 printf(_("CPUidle governor: %s\n"), tmp);
103 free(tmp);
104}
105
106static void proc_cpuidle_cpu_output(unsigned int cpu)
107{
108 long max_allowed_cstate = 2000000000;
109 int cstates, cstate;
110
111 cstates = sysfs_get_idlestate_count(cpu);
112 if (cstates == 0) {
113 /*
114 * Go on and print same useless info as you'd see with
115 * cat /proc/acpi/processor/../power
116 * printf(_("CPU %u: No C-states available\n"), cpu);
117 * return;
118 */
119 } else if (cstates <= 0) {
120 printf(_("CPU %u: Can't read C-state info\n"), cpu);
121 return;
122 }
123 /* printf("Cstates: %d\n", cstates); */
124
125 printf(_("active state: C0\n"));
126 printf(_("max_cstate: C%u\n"), cstates-1);
127 printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate);
128 printf(_("states:\t\n"));
129 for (cstate = 1; cstate < cstates; cstate++) {
130 printf(_(" C%d: "
131 "type[C%d] "), cstate, cstate);
132 printf(_("promotion[--] demotion[--] "));
133 printf(_("latency[%03lu] "),
134 sysfs_get_idlestate_latency(cpu, cstate));
135 printf(_("usage[%08lu] "),
136 sysfs_get_idlestate_usage(cpu, cstate));
137 printf(_("duration[%020Lu] \n"),
138 sysfs_get_idlestate_time(cpu, cstate));
139 }
140}
141
142static struct option info_opts[] = {
143 { .name = "silent", .has_arg = no_argument, .flag = NULL, .val = 's'},
144 { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'},
145 { },
146};
147
148static inline void cpuidle_exit(int fail)
149{
150 exit(EXIT_FAILURE);
151}
152
153int cmd_idle_info(int argc, char **argv)
154{
155 extern char *optarg;
156 extern int optind, opterr, optopt;
157 int ret = 0, cont = 1, output_param = 0, verbose = 1;
158 unsigned int cpu = 0;
159
160 do {
161 ret = getopt_long(argc, argv, "os", info_opts, NULL);
162 if (ret == -1)
163 break;
164 switch (ret) {
165 case '?':
166 output_param = '?';
167 cont = 0;
168 break;
169 case 's':
170 verbose = 0;
171 break;
172 case -1:
173 cont = 0;
174 break;
175 case 'o':
176 if (output_param) {
177 output_param = -1;
178 cont = 0;
179 break;
180 }
181 output_param = ret;
182 break;
183 }
184 } while (cont);
185
186 switch (output_param) {
187 case -1:
188 printf(_("You can't specify more than one "
189 "output-specific argument\n"));
190 cpuidle_exit(EXIT_FAILURE);
191 case '?':
192 printf(_("invalid or unknown argument\n"));
193 cpuidle_exit(EXIT_FAILURE);
194 }
195
196 /* Default is: show output of CPU 0 only */
197 if (bitmask_isallclear(cpus_chosen))
198 bitmask_setbit(cpus_chosen, 0);
199
200 if (output_param == 0)
201 cpuidle_general_output();
202
203 for (cpu = bitmask_first(cpus_chosen);
204 cpu <= bitmask_last(cpus_chosen); cpu++) {
205
206 if (!bitmask_isbitset(cpus_chosen, cpu) ||
207 cpufreq_cpu_exists(cpu))
208 continue;
209
210 switch (output_param) {
211
212 case 'o':
213 proc_cpuidle_cpu_output(cpu);
214 break;
215 case 0:
216 printf("\n");
217 cpuidle_cpu_output(cpu, verbose);
218 break;
219 }
220 }
221 return EXIT_SUCCESS;
222}
diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c
new file mode 100644
index 000000000000..3f68632c28c7
--- /dev/null
+++ b/tools/power/cpupower/utils/cpupower-info.c
@@ -0,0 +1,135 @@
1/*
2 * (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <unistd.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <errno.h>
12#include <string.h>
13#include <getopt.h>
14
15#include <cpufreq.h>
16#include "helpers/helpers.h"
17#include "helpers/sysfs.h"
18
19static struct option set_opts[] = {
20 { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'},
21 { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'},
22 { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'},
23 { },
24};
25
26static void print_wrong_arg_exit(void)
27{
28 printf(_("invalid or unknown argument\n"));
29 exit(EXIT_FAILURE);
30}
31
32int cmd_info(int argc, char **argv)
33{
34 extern char *optarg;
35 extern int optind, opterr, optopt;
36 unsigned int cpu;
37
38 union {
39 struct {
40 int sched_mc:1;
41 int sched_smt:1;
42 int perf_bias:1;
43 };
44 int params;
45 } params = {};
46 int ret = 0;
47
48 setlocale(LC_ALL, "");
49 textdomain(PACKAGE);
50
51 /* parameter parsing */
52 while ((ret = getopt_long(argc, argv, "msb", set_opts, NULL)) != -1) {
53 switch (ret) {
54 case 'b':
55 if (params.perf_bias)
56 print_wrong_arg_exit();
57 params.perf_bias = 1;
58 break;
59 case 'm':
60 if (params.sched_mc)
61 print_wrong_arg_exit();
62 params.sched_mc = 1;
63 break;
64 case 's':
65 if (params.sched_smt)
66 print_wrong_arg_exit();
67 params.sched_smt = 1;
68 break;
69 default:
70 print_wrong_arg_exit();
71 }
72 };
73
74 if (!params.params)
75 params.params = 0x7;
76
77 /* Default is: show output of CPU 0 only */
78 if (bitmask_isallclear(cpus_chosen))
79 bitmask_setbit(cpus_chosen, 0);
80
81 if (params.sched_mc) {
82 ret = sysfs_get_sched("mc");
83 printf(_("System's multi core scheduler setting: "));
84 if (ret < 0)
85 /* if sysfs file is missing it's: errno == ENOENT */
86 printf(_("not supported\n"));
87 else
88 printf("%d\n", ret);
89 }
90 if (params.sched_smt) {
91 ret = sysfs_get_sched("smt");
92 printf(_("System's thread sibling scheduler setting: "));
93 if (ret < 0)
94 /* if sysfs file is missing it's: errno == ENOENT */
95 printf(_("not supported\n"));
96 else
97 printf("%d\n", ret);
98 }
99
100 /* Add more per cpu options here */
101 if (!params.perf_bias)
102 return ret;
103
104 if (params.perf_bias) {
105 if (!run_as_root) {
106 params.perf_bias = 0;
107 printf(_("Intel's performance bias setting needs root privileges\n"));
108 } else if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) {
109 printf(_("System does not support Intel's performance"
110 " bias setting\n"));
111 params.perf_bias = 0;
112 }
113 }
114
115 /* loop over CPUs */
116 for (cpu = bitmask_first(cpus_chosen);
117 cpu <= bitmask_last(cpus_chosen); cpu++) {
118
119 if (!bitmask_isbitset(cpus_chosen, cpu) ||
120 cpufreq_cpu_exists(cpu))
121 continue;
122
123 printf(_("analyzing CPU %d:\n"), cpu);
124
125 if (params.perf_bias) {
126 ret = msr_intel_get_perf_bias(cpu);
127 if (ret < 0) {
128 printf(_("Could not read perf-bias value\n"));
129 break;
130 } else
131 printf(_("perf-bias: %d\n"), ret);
132 }
133 }
134 return ret;
135}
diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c
new file mode 100644
index 000000000000..dc4de3762111
--- /dev/null
+++ b/tools/power/cpupower/utils/cpupower-set.c
@@ -0,0 +1,134 @@
1/*
2 * (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <unistd.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <errno.h>
12#include <string.h>
13#include <getopt.h>
14
15#include <cpufreq.h>
16#include "helpers/helpers.h"
17#include "helpers/sysfs.h"
18#include "helpers/bitmask.h"
19
20static struct option set_opts[] = {
21 { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'},
22 { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'},
23 { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'},
24 { },
25};
26
27static void print_wrong_arg_exit(void)
28{
29 printf(_("invalid or unknown argument\n"));
30 exit(EXIT_FAILURE);
31}
32
33int cmd_set(int argc, char **argv)
34{
35 extern char *optarg;
36 extern int optind, opterr, optopt;
37 unsigned int cpu;
38
39 union {
40 struct {
41 int sched_mc:1;
42 int sched_smt:1;
43 int perf_bias:1;
44 };
45 int params;
46 } params;
47 int sched_mc = 0, sched_smt = 0, perf_bias = 0;
48 int ret = 0;
49
50 setlocale(LC_ALL, "");
51 textdomain(PACKAGE);
52
53 params.params = 0;
54 /* parameter parsing */
55 while ((ret = getopt_long(argc, argv, "m:s:b:",
56 set_opts, NULL)) != -1) {
57 switch (ret) {
58 case 'b':
59 if (params.perf_bias)
60 print_wrong_arg_exit();
61 perf_bias = atoi(optarg);
62 if (perf_bias < 0 || perf_bias > 15) {
63 printf(_("--perf-bias param out "
64 "of range [0-%d]\n"), 15);
65 print_wrong_arg_exit();
66 }
67 params.perf_bias = 1;
68 break;
69 case 'm':
70 if (params.sched_mc)
71 print_wrong_arg_exit();
72 sched_mc = atoi(optarg);
73 if (sched_mc < 0 || sched_mc > 2) {
74 printf(_("--sched-mc param out "
75 "of range [0-%d]\n"), 2);
76 print_wrong_arg_exit();
77 }
78 params.sched_mc = 1;
79 break;
80 case 's':
81 if (params.sched_smt)
82 print_wrong_arg_exit();
83 sched_smt = atoi(optarg);
84 if (sched_smt < 0 || sched_smt > 2) {
85 printf(_("--sched-smt param out "
86 "of range [0-%d]\n"), 2);
87 print_wrong_arg_exit();
88 }
89 params.sched_smt = 1;
90 break;
91 default:
92 print_wrong_arg_exit();
93 }
94 };
95
96 if (!params.params)
97 print_wrong_arg_exit();
98
99 if (params.sched_mc) {
100 ret = sysfs_set_sched("mc", sched_mc);
101 if (ret)
102 fprintf(stderr, _("Error setting sched-mc %s\n"),
103 (ret == -ENODEV) ? "not supported" : "");
104 }
105 if (params.sched_smt) {
106 ret = sysfs_set_sched("smt", sched_smt);
107 if (ret)
108 fprintf(stderr, _("Error setting sched-smt %s\n"),
109 (ret == -ENODEV) ? "not supported" : "");
110 }
111
112 /* Default is: set all CPUs */
113 if (bitmask_isallclear(cpus_chosen))
114 bitmask_setall(cpus_chosen);
115
116 /* loop over CPUs */
117 for (cpu = bitmask_first(cpus_chosen);
118 cpu <= bitmask_last(cpus_chosen); cpu++) {
119
120 if (!bitmask_isbitset(cpus_chosen, cpu) ||
121 cpufreq_cpu_exists(cpu))
122 continue;
123
124 if (params.perf_bias) {
125 ret = msr_intel_set_perf_bias(cpu, perf_bias);
126 if (ret) {
127 fprintf(stderr, _("Error setting perf-bias "
128 "value on CPU %d\n"), cpu);
129 break;
130 }
131 }
132 }
133 return ret;
134}
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
new file mode 100644
index 000000000000..52bee591c1c5
--- /dev/null
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -0,0 +1,214 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Ideas taken over from the perf userspace tool (included in the Linus
7 * kernel git repo): subcommand builtins and param parsing.
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14#include <errno.h>
15
16#include "builtin.h"
17#include "helpers/helpers.h"
18#include "helpers/bitmask.h"
19
20struct cmd_struct {
21 const char *cmd;
22 int (*main)(int, const char **);
23 int needs_root;
24};
25
26#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
27
28static int cmd_help(int argc, const char **argv);
29
30/* Global cpu_info object available for all binaries
31 * Info only retrieved from CPU 0
32 *
33 * Values will be zero/unknown on non X86 archs
34 */
35struct cpupower_cpu_info cpupower_cpu_info;
36int run_as_root;
37/* Affected cpus chosen by -c/--cpu param */
38struct bitmask *cpus_chosen;
39
40#ifdef DEBUG
41int be_verbose;
42#endif
43
44static void print_help(void);
45
46static struct cmd_struct commands[] = {
47 { "frequency-info", cmd_freq_info, 0 },
48 { "frequency-set", cmd_freq_set, 1 },
49 { "idle-info", cmd_idle_info, 0 },
50 { "set", cmd_set, 1 },
51 { "info", cmd_info, 0 },
52 { "monitor", cmd_monitor, 0 },
53 { "help", cmd_help, 0 },
54 /* { "bench", cmd_bench, 1 }, */
55};
56
57static void print_help(void)
58{
59 unsigned int i;
60
61#ifdef DEBUG
62 printf(_("Usage:\tcpupower [-d|--debug] [-c|--cpu cpulist ] <command> [<args>]\n"));
63#else
64 printf(_("Usage:\tcpupower [-c|--cpu cpulist ] <command> [<args>]\n"));
65#endif
66 printf(_("Supported commands are:\n"));
67 for (i = 0; i < ARRAY_SIZE(commands); i++)
68 printf("\t%s\n", commands[i].cmd);
69 printf(_("\nNot all commands can make use of the -c cpulist option.\n"));
70 printf(_("\nUse 'cpupower help <command>' for getting help for above commands.\n"));
71}
72
73static int print_man_page(const char *subpage)
74{
75 int len;
76 char *page;
77
78 len = 10; /* enough for "cpupower-" */
79 if (subpage != NULL)
80 len += strlen(subpage);
81
82 page = malloc(len);
83 if (!page)
84 return -ENOMEM;
85
86 sprintf(page, "cpupower");
87 if ((subpage != NULL) && strcmp(subpage, "help")) {
88 strcat(page, "-");
89 strcat(page, subpage);
90 }
91
92 execlp("man", "man", page, NULL);
93
94 /* should not be reached */
95 return -EINVAL;
96}
97
98static int cmd_help(int argc, const char **argv)
99{
100 if (argc > 1) {
101 print_man_page(argv[1]); /* exits within execlp() */
102 return EXIT_FAILURE;
103 }
104
105 print_help();
106 return EXIT_SUCCESS;
107}
108
109static void print_version(void)
110{
111 printf(PACKAGE " " VERSION "\n");
112 printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
113}
114
115static void handle_options(int *argc, const char ***argv)
116{
117 int ret, x, new_argc = 0;
118
119 if (*argc < 1)
120 return;
121
122 for (x = 0; x < *argc && ((*argv)[x])[0] == '-'; x++) {
123 const char *param = (*argv)[x];
124 if (!strcmp(param, "-h") || !strcmp(param, "--help")) {
125 print_help();
126 exit(EXIT_SUCCESS);
127 } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")) {
128 if (*argc < 2) {
129 print_help();
130 exit(EXIT_FAILURE);
131 }
132 if (!strcmp((*argv)[x+1], "all"))
133 bitmask_setall(cpus_chosen);
134 else {
135 ret = bitmask_parselist(
136 (*argv)[x+1], cpus_chosen);
137 if (ret < 0) {
138 fprintf(stderr, _("Error parsing cpu "
139 "list\n"));
140 exit(EXIT_FAILURE);
141 }
142 }
143 x += 1;
144 /* Cut out param: cpupower -c 1 info -> cpupower info */
145 new_argc += 2;
146 continue;
147 } else if (!strcmp(param, "-v") ||
148 !strcmp(param, "--version")) {
149 print_version();
150 exit(EXIT_SUCCESS);
151#ifdef DEBUG
152 } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")) {
153 be_verbose = 1;
154 new_argc++;
155 continue;
156#endif
157 } else {
158 fprintf(stderr, "Unknown option: %s\n", param);
159 print_help();
160 exit(EXIT_FAILURE);
161 }
162 }
163 *argc -= new_argc;
164 *argv += new_argc;
165}
166
167int main(int argc, const char *argv[])
168{
169 const char *cmd;
170 unsigned int i, ret;
171
172 cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
173
174 argc--;
175 argv += 1;
176
177 handle_options(&argc, &argv);
178
179 cmd = argv[0];
180
181 if (argc < 1) {
182 print_help();
183 return EXIT_FAILURE;
184 }
185
186 setlocale(LC_ALL, "");
187 textdomain(PACKAGE);
188
189 /* Turn "perf cmd --help" into "perf help cmd" */
190 if (argc > 1 && !strcmp(argv[1], "--help")) {
191 argv[1] = argv[0];
192 argv[0] = cmd = "help";
193 }
194
195 get_cpu_info(0, &cpupower_cpu_info);
196 run_as_root = !getuid();
197
198 for (i = 0; i < ARRAY_SIZE(commands); i++) {
199 struct cmd_struct *p = commands + i;
200 if (strcmp(p->cmd, cmd))
201 continue;
202 if (!run_as_root && p->needs_root) {
203 fprintf(stderr, _("Subcommand %s needs root "
204 "privileges\n"), cmd);
205 return EXIT_FAILURE;
206 }
207 ret = p->main(argc, argv);
208 if (cpus_chosen)
209 bitmask_free(cpus_chosen);
210 return ret;
211 }
212 print_help();
213 return EXIT_FAILURE;
214}
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
new file mode 100644
index 000000000000..87d5605bdda8
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/amd.c
@@ -0,0 +1,137 @@
1#if defined(__i386__) || defined(__x86_64__)
2#include <unistd.h>
3#include <errno.h>
4#include <stdio.h>
5#include <stdint.h>
6
7#include <pci/pci.h>
8
9#include "helpers/helpers.h"
10
11#define MSR_AMD_PSTATE_STATUS 0xc0010063
12#define MSR_AMD_PSTATE 0xc0010064
13#define MSR_AMD_PSTATE_LIMIT 0xc0010061
14
15union msr_pstate {
16 struct {
17 unsigned fid:6;
18 unsigned did:3;
19 unsigned vid:7;
20 unsigned res1:6;
21 unsigned nbdid:1;
22 unsigned res2:2;
23 unsigned nbvid:7;
24 unsigned iddval:8;
25 unsigned idddiv:2;
26 unsigned res3:21;
27 unsigned en:1;
28 } bits;
29 unsigned long long val;
30};
31
32static int get_did(int family, union msr_pstate pstate)
33{
34 int t;
35
36 if (family == 0x12)
37 t = pstate.val & 0xf;
38 else
39 t = pstate.bits.did;
40
41 return t;
42}
43
44static int get_cof(int family, union msr_pstate pstate)
45{
46 int t;
47 int fid, did;
48
49 did = get_did(family, pstate);
50
51 t = 0x10;
52 fid = pstate.bits.fid;
53 if (family == 0x11)
54 t = 0x8;
55
56 return (100 * (fid + t)) >> did;
57}
58
59/* Needs:
60 * cpu -> the cpu that gets evaluated
61 * cpu_family -> The cpu's family (0x10, 0x12,...)
62 * boots_states -> how much boost states the machines support
63 *
64 * Fills up:
65 * pstates -> a pointer to an array of size MAX_HW_PSTATES
66 * must be initialized with zeros.
67 * All available HW pstates (including boost states)
68 * no -> amount of pstates above array got filled up with
69 *
70 * returns zero on success, -1 on failure
71 */
72int decode_pstates(unsigned int cpu, unsigned int cpu_family,
73 int boost_states, unsigned long *pstates, int *no)
74{
75 int i, psmax, pscur;
76 union msr_pstate pstate;
77 unsigned long long val;
78
79 /* Only read out frequencies from HW when CPU might be boostable
80 to keep the code as short and clean as possible.
81 Otherwise frequencies are exported via ACPI tables.
82 */
83 if (cpu_family < 0x10 || cpu_family == 0x14)
84 return -1;
85
86 if (read_msr(cpu, MSR_AMD_PSTATE_LIMIT, &val))
87 return -1;
88
89 psmax = (val >> 4) & 0x7;
90
91 if (read_msr(cpu, MSR_AMD_PSTATE_STATUS, &val))
92 return -1;
93
94 pscur = val & 0x7;
95
96 pscur += boost_states;
97 psmax += boost_states;
98 for (i = 0; i <= psmax; i++) {
99 if (i >= MAX_HW_PSTATES) {
100 fprintf(stderr, "HW pstates [%d] exceeding max [%d]\n",
101 psmax, MAX_HW_PSTATES);
102 return -1;
103 }
104 if (read_msr(cpu, MSR_AMD_PSTATE + i, &pstate.val))
105 return -1;
106 pstates[i] = get_cof(cpu_family, pstate);
107 }
108 *no = i;
109 return 0;
110}
111
112int amd_pci_get_num_boost_states(int *active, int *states)
113{
114 struct pci_access *pci_acc;
115 int vendor_id = 0x1022;
116 int boost_dev_ids[4] = {0x1204, 0x1604, 0x1704, 0};
117 struct pci_dev *device;
118 uint8_t val = 0;
119
120 *active = *states = 0;
121
122 device = pci_acc_init(&pci_acc, vendor_id, boost_dev_ids);
123
124 if (device == NULL)
125 return -ENODEV;
126
127 val = pci_read_byte(device, 0x15c);
128 if (val & 3)
129 *active = 1;
130 else
131 *active = 0;
132 *states = (val >> 2) & 7;
133
134 pci_cleanup(pci_acc);
135 return 0;
136}
137#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/helpers/bitmask.c b/tools/power/cpupower/utils/helpers/bitmask.c
new file mode 100644
index 000000000000..5c074c60f904
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/bitmask.c
@@ -0,0 +1,292 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include <helpers/bitmask.h>
6
7/* How many bits in an unsigned long */
8#define bitsperlong (8 * sizeof(unsigned long))
9
10/* howmany(a,b) : how many elements of size b needed to hold all of a */
11#define howmany(x, y) (((x)+((y)-1))/(y))
12
13/* How many longs in mask of n bits */
14#define longsperbits(n) howmany(n, bitsperlong)
15
16#define max(a, b) ((a) > (b) ? (a) : (b))
17
18/*
19 * Allocate and free `struct bitmask *`
20 */
21
22/* Allocate a new `struct bitmask` with a size of n bits */
23struct bitmask *bitmask_alloc(unsigned int n)
24{
25 struct bitmask *bmp;
26
27 bmp = malloc(sizeof(*bmp));
28 if (bmp == 0)
29 return 0;
30 bmp->size = n;
31 bmp->maskp = calloc(longsperbits(n), sizeof(unsigned long));
32 if (bmp->maskp == 0) {
33 free(bmp);
34 return 0;
35 }
36 return bmp;
37}
38
39/* Free `struct bitmask` */
40void bitmask_free(struct bitmask *bmp)
41{
42 if (bmp == 0)
43 return;
44 free(bmp->maskp);
45 bmp->maskp = (unsigned long *)0xdeadcdef; /* double free tripwire */
46 free(bmp);
47}
48
49/*
50 * The routines _getbit() and _setbit() are the only
51 * routines that actually understand the layout of bmp->maskp[].
52 *
53 * On little endian architectures, this could simply be an array of
54 * bytes. But the kernel layout of bitmasks _is_ visible to userspace
55 * via the sched_(set/get)affinity calls in Linux 2.6, and on big
56 * endian architectures, it is painfully obvious that this is an
57 * array of unsigned longs.
58 */
59
60/* Return the value (0 or 1) of bit n in bitmask bmp */
61static unsigned int _getbit(const struct bitmask *bmp, unsigned int n)
62{
63 if (n < bmp->size)
64 return (bmp->maskp[n/bitsperlong] >> (n % bitsperlong)) & 1;
65 else
66 return 0;
67}
68
69/* Set bit n in bitmask bmp to value v (0 or 1) */
70static void _setbit(struct bitmask *bmp, unsigned int n, unsigned int v)
71{
72 if (n < bmp->size) {
73 if (v)
74 bmp->maskp[n/bitsperlong] |= 1UL << (n % bitsperlong);
75 else
76 bmp->maskp[n/bitsperlong] &=
77 ~(1UL << (n % bitsperlong));
78 }
79}
80
81/*
82 * When parsing bitmask lists, only allow numbers, separated by one
83 * of the allowed next characters.
84 *
85 * The parameter 'sret' is the return from a sscanf "%u%c". It is
86 * -1 if the sscanf input string was empty. It is 0 if the first
87 * character in the sscanf input string was not a decimal number.
88 * It is 1 if the unsigned number matching the "%u" was the end of the
89 * input string. It is 2 if one or more additional characters followed
90 * the matched unsigned number. If it is 2, then 'nextc' is the first
91 * character following the number. The parameter 'ok_next_chars'
92 * is the nul-terminated list of allowed next characters.
93 *
94 * The mask term just scanned was ok if and only if either the numbers
95 * matching the %u were all of the input or if the next character in
96 * the input past the numbers was one of the allowed next characters.
97 */
98static int scan_was_ok(int sret, char nextc, const char *ok_next_chars)
99{
100 return sret == 1 ||
101 (sret == 2 && strchr(ok_next_chars, nextc) != NULL);
102}
103
104static const char *nexttoken(const char *q, int sep)
105{
106 if (q)
107 q = strchr(q, sep);
108 if (q)
109 q++;
110 return q;
111}
112
113/* Set a single bit i in bitmask */
114struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i)
115{
116 _setbit(bmp, i, 1);
117 return bmp;
118}
119
120/* Set all bits in bitmask: bmp = ~0 */
121struct bitmask *bitmask_setall(struct bitmask *bmp)
122{
123 unsigned int i;
124 for (i = 0; i < bmp->size; i++)
125 _setbit(bmp, i, 1);
126 return bmp;
127}
128
129/* Clear all bits in bitmask: bmp = 0 */
130struct bitmask *bitmask_clearall(struct bitmask *bmp)
131{
132 unsigned int i;
133 for (i = 0; i < bmp->size; i++)
134 _setbit(bmp, i, 0);
135 return bmp;
136}
137
138/* True if all bits are clear */
139int bitmask_isallclear(const struct bitmask *bmp)
140{
141 unsigned int i;
142 for (i = 0; i < bmp->size; i++)
143 if (_getbit(bmp, i))
144 return 0;
145 return 1;
146}
147
148/* True if specified bit i is set */
149int bitmask_isbitset(const struct bitmask *bmp, unsigned int i)
150{
151 return _getbit(bmp, i);
152}
153
154/* Number of lowest set bit (min) */
155unsigned int bitmask_first(const struct bitmask *bmp)
156{
157 return bitmask_next(bmp, 0);
158}
159
160/* Number of highest set bit (max) */
161unsigned int bitmask_last(const struct bitmask *bmp)
162{
163 unsigned int i;
164 unsigned int m = bmp->size;
165 for (i = 0; i < bmp->size; i++)
166 if (_getbit(bmp, i))
167 m = i;
168 return m;
169}
170
171/* Number of next set bit at or above given bit i */
172unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i)
173{
174 unsigned int n;
175 for (n = i; n < bmp->size; n++)
176 if (_getbit(bmp, n))
177 break;
178 return n;
179}
180
181/*
182 * Parses a comma-separated list of numbers and ranges of numbers,
183 * with optional ':%u' strides modifying ranges, into provided bitmask.
184 * Some examples of input lists and their equivalent simple list:
185 * Input Equivalent to
186 * 0-3 0,1,2,3
187 * 0-7:2 0,2,4,6
188 * 1,3,5-7 1,3,5,6,7
189 * 0-3:2,8-15:4 0,2,8,12
190 */
191int bitmask_parselist(const char *buf, struct bitmask *bmp)
192{
193 const char *p, *q;
194
195 bitmask_clearall(bmp);
196
197 q = buf;
198 while (p = q, q = nexttoken(q, ','), p) {
199 unsigned int a; /* begin of range */
200 unsigned int b; /* end of range */
201 unsigned int s; /* stride */
202 const char *c1, *c2; /* next tokens after '-' or ',' */
203 char nextc; /* char after sscanf %u match */
204 int sret; /* sscanf return (number of matches) */
205
206 sret = sscanf(p, "%u%c", &a, &nextc);
207 if (!scan_was_ok(sret, nextc, ",-"))
208 goto err;
209 b = a;
210 s = 1;
211 c1 = nexttoken(p, '-');
212 c2 = nexttoken(p, ',');
213 if (c1 != NULL && (c2 == NULL || c1 < c2)) {
214 sret = sscanf(c1, "%u%c", &b, &nextc);
215 if (!scan_was_ok(sret, nextc, ",:"))
216 goto err;
217 c1 = nexttoken(c1, ':');
218 if (c1 != NULL && (c2 == NULL || c1 < c2)) {
219 sret = sscanf(c1, "%u%c", &s, &nextc);
220 if (!scan_was_ok(sret, nextc, ","))
221 goto err;
222 }
223 }
224 if (!(a <= b))
225 goto err;
226 if (b >= bmp->size)
227 goto err;
228 while (a <= b) {
229 _setbit(bmp, a, 1);
230 a += s;
231 }
232 }
233 return 0;
234err:
235 bitmask_clearall(bmp);
236 return -1;
237}
238
239/*
240 * emit(buf, buflen, rbot, rtop, len)
241 *
242 * Helper routine for bitmask_displaylist(). Write decimal number
243 * or range to buf+len, suppressing output past buf+buflen, with optional
244 * comma-prefix. Return len of what would be written to buf, if it
245 * all fit.
246 */
247
248static inline int emit(char *buf, int buflen, int rbot, int rtop, int len)
249{
250 if (len > 0)
251 len += snprintf(buf + len, max(buflen - len, 0), ",");
252 if (rbot == rtop)
253 len += snprintf(buf + len, max(buflen - len, 0), "%d", rbot);
254 else
255 len += snprintf(buf + len, max(buflen - len, 0), "%d-%d",
256 rbot, rtop);
257 return len;
258}
259
260/*
261 * Write decimal list representation of bmp to buf.
262 *
263 * Output format is a comma-separated list of decimal numbers and
264 * ranges. Consecutively set bits are shown as two hyphen-separated
265 * decimal numbers, the smallest and largest bit numbers set in
266 * the range. Output format is compatible with the format
267 * accepted as input by bitmap_parselist().
268 *
269 * The return value is the number of characters which would be
270 * generated for the given input, excluding the trailing '\0', as
271 * per ISO C99.
272 */
273
274int bitmask_displaylist(char *buf, int buflen, const struct bitmask *bmp)
275{
276 int len = 0;
277 /* current bit is 'cur', most recently seen range is [rbot, rtop] */
278 unsigned int cur, rbot, rtop;
279
280 if (buflen > 0)
281 *buf = 0;
282 rbot = cur = bitmask_first(bmp);
283 while (cur < bmp->size) {
284 rtop = cur;
285 cur = bitmask_next(bmp, cur+1);
286 if (cur >= bmp->size || cur > rtop + 1) {
287 len = emit(buf, buflen, rbot, rtop, len);
288 rbot = cur;
289 }
290 }
291 return len;
292}
diff --git a/tools/power/cpupower/utils/helpers/bitmask.h b/tools/power/cpupower/utils/helpers/bitmask.h
new file mode 100644
index 000000000000..eb289df41053
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/bitmask.h
@@ -0,0 +1,33 @@
1#ifndef __CPUPOWER_BITMASK__
2#define __CPUPOWER_BITMASK__
3
4/* Taken over from libbitmask, a project initiated from sgi:
5 * Url: http://oss.sgi.com/projects/cpusets/
6 * Unfortunately it's not very widespread, therefore relevant parts are
7 * pasted here.
8 */
9
10struct bitmask {
11 unsigned int size;
12 unsigned long *maskp;
13};
14
15struct bitmask *bitmask_alloc(unsigned int n);
16void bitmask_free(struct bitmask *bmp);
17
18struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i);
19struct bitmask *bitmask_setall(struct bitmask *bmp);
20struct bitmask *bitmask_clearall(struct bitmask *bmp);
21
22unsigned int bitmask_first(const struct bitmask *bmp);
23unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i);
24unsigned int bitmask_last(const struct bitmask *bmp);
25int bitmask_isallclear(const struct bitmask *bmp);
26int bitmask_isbitset(const struct bitmask *bmp, unsigned int i);
27
28int bitmask_parselist(const char *buf, struct bitmask *bmp);
29int bitmask_displaylist(char *buf, int len, const struct bitmask *bmp);
30
31
32
33#endif /*__CPUPOWER_BITMASK__ */
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
new file mode 100644
index 000000000000..906895d21cce
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -0,0 +1,176 @@
1#include <stdio.h>
2#include <errno.h>
3#include <string.h>
4#include <unistd.h>
5#include <stdlib.h>
6
7#include "helpers/helpers.h"
8
9static const char *cpu_vendor_table[X86_VENDOR_MAX] = {
10 "Unknown", "GenuineIntel", "AuthenticAMD",
11};
12
13#if defined(__i386__) || defined(__x86_64__)
14
15/* from gcc */
16#include <cpuid.h>
17
18/*
19 * CPUID functions returning a single datum
20 *
21 * Define unsigned int cpuid_e[abcd]x(unsigned int op)
22 */
23#define cpuid_func(reg) \
24 unsigned int cpuid_##reg(unsigned int op) \
25 { \
26 unsigned int eax, ebx, ecx, edx; \
27 __cpuid(op, eax, ebx, ecx, edx); \
28 return reg; \
29 }
30cpuid_func(eax);
31cpuid_func(ebx);
32cpuid_func(ecx);
33cpuid_func(edx);
34
35#endif /* defined(__i386__) || defined(__x86_64__) */
36
37/* get_cpu_info
38 *
39 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
40 *
41 * Returns 0 on success or a negativ error code
42 *
43 * TBD: Should there be a cpuid alternative for this if /proc is not mounted?
44 */
45int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info)
46{
47 FILE *fp;
48 char value[64];
49 unsigned int proc, x;
50 unsigned int unknown = 0xffffff;
51 unsigned int cpuid_level, ext_cpuid_level;
52
53 int ret = -EINVAL;
54
55 cpu_info->vendor = X86_VENDOR_UNKNOWN;
56 cpu_info->family = unknown;
57 cpu_info->model = unknown;
58 cpu_info->stepping = unknown;
59 cpu_info->caps = 0;
60
61 fp = fopen("/proc/cpuinfo", "r");
62 if (!fp)
63 return -EIO;
64
65 while (!feof(fp)) {
66 if (!fgets(value, 64, fp))
67 continue;
68 value[63 - 1] = '\0';
69
70 if (!strncmp(value, "processor\t: ", 12))
71 sscanf(value, "processor\t: %u", &proc);
72
73 if (proc != cpu)
74 continue;
75
76 /* Get CPU vendor */
77 if (!strncmp(value, "vendor_id", 9)) {
78 for (x = 1; x < X86_VENDOR_MAX; x++) {
79 if (strstr(value, cpu_vendor_table[x]))
80 cpu_info->vendor = x;
81 }
82 /* Get CPU family, etc. */
83 } else if (!strncmp(value, "cpu family\t: ", 13)) {
84 sscanf(value, "cpu family\t: %u",
85 &cpu_info->family);
86 } else if (!strncmp(value, "model\t\t: ", 9)) {
87 sscanf(value, "model\t\t: %u",
88 &cpu_info->model);
89 } else if (!strncmp(value, "stepping\t: ", 10)) {
90 sscanf(value, "stepping\t: %u",
91 &cpu_info->stepping);
92
93 /* Exit -> all values must have been set */
94 if (cpu_info->vendor == X86_VENDOR_UNKNOWN ||
95 cpu_info->family == unknown ||
96 cpu_info->model == unknown ||
97 cpu_info->stepping == unknown) {
98 ret = -EINVAL;
99 goto out;
100 }
101
102 ret = 0;
103 goto out;
104 }
105 }
106 ret = -ENODEV;
107out:
108 fclose(fp);
109 /* Get some useful CPU capabilities from cpuid */
110 if (cpu_info->vendor != X86_VENDOR_AMD &&
111 cpu_info->vendor != X86_VENDOR_INTEL)
112 return ret;
113
114 cpuid_level = cpuid_eax(0);
115 ext_cpuid_level = cpuid_eax(0x80000000);
116
117 /* Invariant TSC */
118 if (ext_cpuid_level >= 0x80000007 &&
119 (cpuid_edx(0x80000007) & (1 << 8)))
120 cpu_info->caps |= CPUPOWER_CAP_INV_TSC;
121
122 /* Aperf/Mperf registers support */
123 if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1))
124 cpu_info->caps |= CPUPOWER_CAP_APERF;
125
126 /* AMD Boost state enable/disable register */
127 if (cpu_info->vendor == X86_VENDOR_AMD) {
128 if (ext_cpuid_level >= 0x80000007 &&
129 (cpuid_edx(0x80000007) & (1 << 9)))
130 cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
131 }
132
133 if (cpu_info->vendor == X86_VENDOR_INTEL) {
134 if (cpuid_level >= 6 &&
135 (cpuid_eax(6) & (1 << 1)))
136 cpu_info->caps |= CPUPOWER_CAP_INTEL_IDA;
137 }
138
139 if (cpu_info->vendor == X86_VENDOR_INTEL) {
140 /* Intel's perf-bias MSR support */
141 if (cpuid_level >= 6 && (cpuid_ecx(6) & (1 << 3)))
142 cpu_info->caps |= CPUPOWER_CAP_PERF_BIAS;
143
144 /* Intel's Turbo Ratio Limit support */
145 if (cpu_info->family == 6) {
146 switch (cpu_info->model) {
147 case 0x1A: /* Core i7, Xeon 5500 series
148 * Bloomfield, Gainstown NHM-EP
149 */
150 case 0x1E: /* Core i7 and i5 Processor
151 * Clarksfield, Lynnfield, Jasper Forest
152 */
153 case 0x1F: /* Core i7 and i5 Processor - Nehalem */
154 case 0x25: /* Westmere Client
155 * Clarkdale, Arrandale
156 */
157 case 0x2C: /* Westmere EP - Gulftown */
158 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
159 case 0x2A: /* SNB */
160 case 0x2D: /* SNB Xeon */
161 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
162 cpu_info->caps |= CPUPOWER_CAP_IS_SNB;
163 break;
164 case 0x2E: /* Nehalem-EX Xeon - Beckton */
165 case 0x2F: /* Westmere-EX Xeon - Eagleton */
166 default:
167 break;
168 }
169 }
170 }
171
172 /* printf("ID: %u - Extid: 0x%x - Caps: 0x%llx\n",
173 cpuid_level, ext_cpuid_level, cpu_info->caps);
174 */
175 return ret;
176}
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
new file mode 100644
index 000000000000..2747e738efb0
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -0,0 +1,190 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Miscellaneous helpers which do not fit or are worth
7 * to put into separate headers
8 */
9
10#ifndef __CPUPOWERUTILS_HELPERS__
11#define __CPUPOWERUTILS_HELPERS__
12
13#include <libintl.h>
14#include <locale.h>
15
16#include "helpers/bitmask.h"
17
18/* Internationalization ****************************/
19#ifdef NLS
20
21#define _(String) gettext(String)
22#ifndef gettext_noop
23#define gettext_noop(String) String
24#endif
25#define N_(String) gettext_noop(String)
26
27#else /* !NLS */
28
29#define _(String) String
30#define N_(String) String
31
32#endif
33/* Internationalization ****************************/
34
35extern int run_as_root;
36extern struct bitmask *cpus_chosen;
37
38/* Global verbose (-d) stuff *********************************/
39/*
40 * define DEBUG via global Makefile variable
41 * Debug output is sent to stderr, do:
42 * cpupower monitor 2>/tmp/debug
43 * to split debug output away from normal output
44*/
45#ifdef DEBUG
46extern int be_verbose;
47
48#define dprint(fmt, ...) { \
49 if (be_verbose) { \
50 fprintf(stderr, "%s: " fmt, \
51 __func__, ##__VA_ARGS__); \
52 } \
53 }
54#else
55static inline void dprint(const char *fmt, ...) { }
56#endif
57extern int be_verbose;
58/* Global verbose (-v) stuff *********************************/
59
60/* cpuid and cpuinfo helpers **************************/
61enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
62 X86_VENDOR_AMD, X86_VENDOR_MAX};
63
64#define CPUPOWER_CAP_INV_TSC 0x00000001
65#define CPUPOWER_CAP_APERF 0x00000002
66#define CPUPOWER_CAP_AMD_CBP 0x00000004
67#define CPUPOWER_CAP_PERF_BIAS 0x00000008
68#define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010
69#define CPUPOWER_CAP_IS_SNB 0x00000011
70#define CPUPOWER_CAP_INTEL_IDA 0x00000012
71
72#define MAX_HW_PSTATES 10
73
74struct cpupower_cpu_info {
75 enum cpupower_cpu_vendor vendor;
76 unsigned int family;
77 unsigned int model;
78 unsigned int stepping;
79 /* CPU capabilities read out from cpuid */
80 unsigned long long caps;
81};
82
83/* get_cpu_info
84 *
85 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
86 *
87 * Returns 0 on success or a negativ error code
88 * Only used on x86, below global's struct values are zero/unknown on
89 * other archs
90 */
91extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
92extern struct cpupower_cpu_info cpupower_cpu_info;
93/* cpuid and cpuinfo helpers **************************/
94
95
96/* CPU topology/hierarchy parsing ******************/
97struct cpupower_topology {
98 /* Amount of CPU cores, packages and threads per core in the system */
99 unsigned int cores;
100 unsigned int pkgs;
101 unsigned int threads; /* per core */
102
103 /* Array gets mallocated with cores entries, holding per core info */
104 struct {
105 int pkg;
106 int core;
107 int cpu;
108
109 /* flags */
110 unsigned int is_online:1;
111 } *core_info;
112};
113
114extern int get_cpu_topology(struct cpupower_topology *cpu_top);
115extern void cpu_topology_release(struct cpupower_topology cpu_top);
116/* CPU topology/hierarchy parsing ******************/
117
118/* X86 ONLY ****************************************/
119#if defined(__i386__) || defined(__x86_64__)
120
121#include <pci/pci.h>
122
123/* Read/Write msr ****************************/
124extern int read_msr(int cpu, unsigned int idx, unsigned long long *val);
125extern int write_msr(int cpu, unsigned int idx, unsigned long long val);
126
127extern int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val);
128extern int msr_intel_get_perf_bias(unsigned int cpu);
129extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu);
130
131/* Read/Write msr ****************************/
132
133/* PCI stuff ****************************/
134extern int amd_pci_get_num_boost_states(int *active, int *states);
135extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
136 int *dev_ids);
137
138/* PCI stuff ****************************/
139
140/* AMD HW pstate decoding **************************/
141
142extern int decode_pstates(unsigned int cpu, unsigned int cpu_family,
143 int boost_states, unsigned long *pstates, int *no);
144
145/* AMD HW pstate decoding **************************/
146
147extern int cpufreq_has_boost_support(unsigned int cpu, int *support,
148 int *active, int * states);
149/*
150 * CPUID functions returning a single datum
151 */
152unsigned int cpuid_eax(unsigned int op);
153unsigned int cpuid_ebx(unsigned int op);
154unsigned int cpuid_ecx(unsigned int op);
155unsigned int cpuid_edx(unsigned int op);
156
157/* cpuid and cpuinfo helpers **************************/
158/* X86 ONLY ********************************************/
159#else
160static inline int decode_pstates(unsigned int cpu, unsigned int cpu_family,
161 int boost_states, unsigned long *pstates,
162 int *no)
163{ return -1; };
164
165static inline int read_msr(int cpu, unsigned int idx, unsigned long long *val)
166{ return -1; };
167static inline int write_msr(int cpu, unsigned int idx, unsigned long long val)
168{ return -1; };
169static inline int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val)
170{ return -1; };
171static inline int msr_intel_get_perf_bias(unsigned int cpu)
172{ return -1; };
173static inline unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu)
174{ return 0; };
175
176/* Read/Write msr ****************************/
177
178static inline int cpufreq_has_boost_support(unsigned int cpu, int *support,
179 int *active, int * states)
180{ return -1; }
181
182/* cpuid and cpuinfo helpers **************************/
183
184static inline unsigned int cpuid_eax(unsigned int op) { return 0; };
185static inline unsigned int cpuid_ebx(unsigned int op) { return 0; };
186static inline unsigned int cpuid_ecx(unsigned int op) { return 0; };
187static inline unsigned int cpuid_edx(unsigned int op) { return 0; };
188#endif /* defined(__i386__) || defined(__x86_64__) */
189
190#endif /* __CPUPOWERUTILS_HELPERS__ */
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
new file mode 100644
index 000000000000..1609243f5c64
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -0,0 +1,27 @@
1#if defined(__i386__) || defined(__x86_64__)
2
3#include "helpers/helpers.h"
4
5int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
6 int *states)
7{
8 struct cpupower_cpu_info cpu_info;
9 int ret;
10
11 *support = *active = *states = 0;
12
13 ret = get_cpu_info(0, &cpu_info);
14 if (ret)
15 return ret;
16
17 if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CBP) {
18 *support = 1;
19 amd_pci_get_num_boost_states(active, states);
20 if (ret <= 0)
21 return ret;
22 *support = 1;
23 } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
24 *support = *active = 1;
25 return 0;
26}
27#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/helpers/msr.c b/tools/power/cpupower/utils/helpers/msr.c
new file mode 100644
index 000000000000..31a4b24a8bc6
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/msr.c
@@ -0,0 +1,115 @@
1#if defined(__i386__) || defined(__x86_64__)
2
3#include <fcntl.h>
4#include <stdio.h>
5#include <unistd.h>
6#include <stdint.h>
7
8#include "helpers/helpers.h"
9
10/* Intel specific MSRs */
11#define MSR_IA32_PERF_STATUS 0x198
12#define MSR_IA32_MISC_ENABLES 0x1a0
13#define MSR_IA32_ENERGY_PERF_BIAS 0x1b0
14#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1ad
15
16/*
17 * read_msr
18 *
19 * Will return 0 on success and -1 on failure.
20 * Possible errno values could be:
21 * EFAULT -If the read/write did not fully complete
22 * EIO -If the CPU does not support MSRs
23 * ENXIO -If the CPU does not exist
24 */
25
26int read_msr(int cpu, unsigned int idx, unsigned long long *val)
27{
28 int fd;
29 char msr_file_name[64];
30
31 sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
32 fd = open(msr_file_name, O_RDONLY);
33 if (fd < 0)
34 return -1;
35 if (lseek(fd, idx, SEEK_CUR) == -1)
36 goto err;
37 if (read(fd, val, sizeof *val) != sizeof *val)
38 goto err;
39 close(fd);
40 return 0;
41 err:
42 close(fd);
43 return -1;
44}
45
46/*
47 * write_msr
48 *
49 * Will return 0 on success and -1 on failure.
50 * Possible errno values could be:
51 * EFAULT -If the read/write did not fully complete
52 * EIO -If the CPU does not support MSRs
53 * ENXIO -If the CPU does not exist
54 */
55int write_msr(int cpu, unsigned int idx, unsigned long long val)
56{
57 int fd;
58 char msr_file_name[64];
59
60 sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
61 fd = open(msr_file_name, O_WRONLY);
62 if (fd < 0)
63 return -1;
64 if (lseek(fd, idx, SEEK_CUR) == -1)
65 goto err;
66 if (write(fd, &val, sizeof val) != sizeof val)
67 goto err;
68 close(fd);
69 return 0;
70 err:
71 close(fd);
72 return -1;
73}
74
75int msr_intel_get_perf_bias(unsigned int cpu)
76{
77 unsigned long long val;
78 int ret;
79
80 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
81 return -1;
82
83 ret = read_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &val);
84 if (ret)
85 return ret;
86 return val;
87}
88
89int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val)
90{
91 int ret;
92
93 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
94 return -1;
95
96 ret = write_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, val);
97 if (ret)
98 return ret;
99 return 0;
100}
101
102unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu)
103{
104 unsigned long long val;
105 int ret;
106
107 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO))
108 return -1;
109
110 ret = read_msr(cpu, MSR_NEHALEM_TURBO_RATIO_LIMIT, &val);
111 if (ret)
112 return ret;
113 return val;
114}
115#endif
diff --git a/tools/power/cpupower/utils/helpers/pci.c b/tools/power/cpupower/utils/helpers/pci.c
new file mode 100644
index 000000000000..cd2eb6fe41c4
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/pci.c
@@ -0,0 +1,44 @@
1#if defined(__i386__) || defined(__x86_64__)
2
3#include <helpers/helpers.h>
4
5/*
6 * pci_acc_init
7 *
8 * PCI access helper function depending on libpci
9 *
10 * **pacc : if a valid pci_dev is returned
11 * *pacc must be passed to pci_acc_cleanup to free it
12 *
13 * vendor_id : the pci vendor id matching the pci device to access
14 * dev_ids : device ids matching the pci device to access
15 *
16 * Returns :
17 * struct pci_dev which can be used with pci_{read,write}_* functions
18 * to access the PCI config space of matching pci devices
19 */
20struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
21 int *dev_ids)
22{
23 struct pci_filter filter_nb_link = { -1, -1, -1, -1, vendor_id, 0};
24 struct pci_dev *device;
25 unsigned int i;
26
27 *pacc = pci_alloc();
28 if (*pacc == NULL)
29 return NULL;
30
31 pci_init(*pacc);
32 pci_scan_bus(*pacc);
33
34 for (i = 0; dev_ids[i] != 0; i++) {
35 filter_nb_link.device = dev_ids[i];
36 for (device = (*pacc)->devices; device; device = device->next) {
37 if (pci_filter_match(&filter_nb_link, device))
38 return device;
39 }
40 }
41 pci_cleanup(*pacc);
42 return NULL;
43}
44#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c
new file mode 100644
index 000000000000..c6343024a611
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/sysfs.c
@@ -0,0 +1,408 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 * (C) 2011 Thomas Renninger <trenn@novell.com> Novell Inc.
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 */
7
8#include <stdio.h>
9#include <errno.h>
10#include <stdlib.h>
11#include <string.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include "helpers/sysfs.h"
18
19unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
20{
21 int fd;
22 ssize_t numread;
23
24 fd = open(path, O_RDONLY);
25 if (fd == -1)
26 return 0;
27
28 numread = read(fd, buf, buflen - 1);
29 if (numread < 1) {
30 close(fd);
31 return 0;
32 }
33
34 buf[numread] = '\0';
35 close(fd);
36
37 return (unsigned int) numread;
38}
39
40static unsigned int sysfs_write_file(const char *path,
41 const char *value, size_t len)
42{
43 int fd;
44 ssize_t numwrite;
45
46 fd = open(path, O_WRONLY);
47 if (fd == -1)
48 return 0;
49
50 numwrite = write(fd, value, len);
51 if (numwrite < 1) {
52 close(fd);
53 return 0;
54 }
55 close(fd);
56 return (unsigned int) numwrite;
57}
58
59/*
60 * Detect whether a CPU is online
61 *
62 * Returns:
63 * 1 -> if CPU is online
64 * 0 -> if CPU is offline
65 * negative errno values in error case
66 */
67int sysfs_is_cpu_online(unsigned int cpu)
68{
69 char path[SYSFS_PATH_MAX];
70 int fd;
71 ssize_t numread;
72 unsigned long long value;
73 char linebuf[MAX_LINE_LEN];
74 char *endp;
75 struct stat statbuf;
76
77 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u", cpu);
78
79 if (stat(path, &statbuf) != 0)
80 return 0;
81
82 /*
83 * kernel without CONFIG_HOTPLUG_CPU
84 * -> cpuX directory exists, but not cpuX/online file
85 */
86 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/online", cpu);
87 if (stat(path, &statbuf) != 0)
88 return 1;
89
90 fd = open(path, O_RDONLY);
91 if (fd == -1)
92 return -errno;
93
94 numread = read(fd, linebuf, MAX_LINE_LEN - 1);
95 if (numread < 1) {
96 close(fd);
97 return -EIO;
98 }
99 linebuf[numread] = '\0';
100 close(fd);
101
102 value = strtoull(linebuf, &endp, 0);
103 if (value > 1 || value < 0)
104 return -EINVAL;
105
106 return value;
107}
108
109/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
110
111/*
112 * helper function to read file from /sys into given buffer
113 * fname is a relative path under "cpuX/cpuidle/stateX/" dir
114 * cstates starting with 0, C0 is not counted as cstate.
115 * This means if you want C1 info, pass 0 as idlestate param
116 */
117unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate,
118 const char *fname, char *buf, size_t buflen)
119{
120 char path[SYSFS_PATH_MAX];
121 int fd;
122 ssize_t numread;
123
124 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
125 cpu, idlestate, fname);
126
127 fd = open(path, O_RDONLY);
128 if (fd == -1)
129 return 0;
130
131 numread = read(fd, buf, buflen - 1);
132 if (numread < 1) {
133 close(fd);
134 return 0;
135 }
136
137 buf[numread] = '\0';
138 close(fd);
139
140 return (unsigned int) numread;
141}
142
143/* read access to files which contain one numeric value */
144
145enum idlestate_value {
146 IDLESTATE_USAGE,
147 IDLESTATE_POWER,
148 IDLESTATE_LATENCY,
149 IDLESTATE_TIME,
150 MAX_IDLESTATE_VALUE_FILES
151};
152
153static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
154 [IDLESTATE_USAGE] = "usage",
155 [IDLESTATE_POWER] = "power",
156 [IDLESTATE_LATENCY] = "latency",
157 [IDLESTATE_TIME] = "time",
158};
159
160static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu,
161 unsigned int idlestate,
162 enum idlestate_value which)
163{
164 unsigned long long value;
165 unsigned int len;
166 char linebuf[MAX_LINE_LEN];
167 char *endp;
168
169 if (which >= MAX_IDLESTATE_VALUE_FILES)
170 return 0;
171
172 len = sysfs_idlestate_read_file(cpu, idlestate,
173 idlestate_value_files[which],
174 linebuf, sizeof(linebuf));
175 if (len == 0)
176 return 0;
177
178 value = strtoull(linebuf, &endp, 0);
179
180 if (endp == linebuf || errno == ERANGE)
181 return 0;
182
183 return value;
184}
185
186/* read access to files which contain one string */
187
188enum idlestate_string {
189 IDLESTATE_DESC,
190 IDLESTATE_NAME,
191 MAX_IDLESTATE_STRING_FILES
192};
193
194static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = {
195 [IDLESTATE_DESC] = "desc",
196 [IDLESTATE_NAME] = "name",
197};
198
199
200static char *sysfs_idlestate_get_one_string(unsigned int cpu,
201 unsigned int idlestate,
202 enum idlestate_string which)
203{
204 char linebuf[MAX_LINE_LEN];
205 char *result;
206 unsigned int len;
207
208 if (which >= MAX_IDLESTATE_STRING_FILES)
209 return NULL;
210
211 len = sysfs_idlestate_read_file(cpu, idlestate,
212 idlestate_string_files[which],
213 linebuf, sizeof(linebuf));
214 if (len == 0)
215 return NULL;
216
217 result = strdup(linebuf);
218 if (result == NULL)
219 return NULL;
220
221 if (result[strlen(result) - 1] == '\n')
222 result[strlen(result) - 1] = '\0';
223
224 return result;
225}
226
227unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
228 unsigned int idlestate)
229{
230 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
231}
232
233unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
234 unsigned int idlestate)
235{
236 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_USAGE);
237}
238
239unsigned long long sysfs_get_idlestate_time(unsigned int cpu,
240 unsigned int idlestate)
241{
242 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_TIME);
243}
244
245char *sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate)
246{
247 return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_NAME);
248}
249
250char *sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate)
251{
252 return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_DESC);
253}
254
255/*
256 * Returns number of supported C-states of CPU core cpu
257 * Negativ in error case
258 * Zero if cpuidle does not export any C-states
259 */
260int sysfs_get_idlestate_count(unsigned int cpu)
261{
262 char file[SYSFS_PATH_MAX];
263 struct stat statbuf;
264 int idlestates = 1;
265
266
267 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
268 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
269 return -ENODEV;
270
271 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
272 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
273 return 0;
274
275 while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
276 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
277 "cpu%u/cpuidle/state%d", cpu, idlestates);
278 idlestates++;
279 }
280 idlestates--;
281 return idlestates;
282}
283
284/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
285
286/*
287 * helper function to read file from /sys into given buffer
288 * fname is a relative path under "cpu/cpuidle/" dir
289 */
290static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
291 size_t buflen)
292{
293 char path[SYSFS_PATH_MAX];
294
295 snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
296
297 return sysfs_read_file(path, buf, buflen);
298}
299
300
301
302/* read access to files which contain one string */
303
304enum cpuidle_string {
305 CPUIDLE_GOVERNOR,
306 CPUIDLE_GOVERNOR_RO,
307 CPUIDLE_DRIVER,
308 MAX_CPUIDLE_STRING_FILES
309};
310
311static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
312 [CPUIDLE_GOVERNOR] = "current_governor",
313 [CPUIDLE_GOVERNOR_RO] = "current_governor_ro",
314 [CPUIDLE_DRIVER] = "current_driver",
315};
316
317
318static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which)
319{
320 char linebuf[MAX_LINE_LEN];
321 char *result;
322 unsigned int len;
323
324 if (which >= MAX_CPUIDLE_STRING_FILES)
325 return NULL;
326
327 len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
328 linebuf, sizeof(linebuf));
329 if (len == 0)
330 return NULL;
331
332 result = strdup(linebuf);
333 if (result == NULL)
334 return NULL;
335
336 if (result[strlen(result) - 1] == '\n')
337 result[strlen(result) - 1] = '\0';
338
339 return result;
340}
341
342char *sysfs_get_cpuidle_governor(void)
343{
344 char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
345 if (!tmp)
346 return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
347 else
348 return tmp;
349}
350
351char *sysfs_get_cpuidle_driver(void)
352{
353 return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
354}
355/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
356
357/*
358 * Get sched_mc or sched_smt settings
359 * Pass "mc" or "smt" as argument
360 *
361 * Returns negative value on failure
362 */
363int sysfs_get_sched(const char *smt_mc)
364{
365 unsigned long value;
366 char linebuf[MAX_LINE_LEN];
367 char *endp;
368 char path[SYSFS_PATH_MAX];
369
370 if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc))
371 return -EINVAL;
372
373 snprintf(path, sizeof(path),
374 PATH_TO_CPU "sched_%s_power_savings", smt_mc);
375 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
376 return -1;
377 value = strtoul(linebuf, &endp, 0);
378 if (endp == linebuf || errno == ERANGE)
379 return -1;
380 return value;
381}
382
383/*
384 * Get sched_mc or sched_smt settings
385 * Pass "mc" or "smt" as argument
386 *
387 * Returns negative value on failure
388 */
389int sysfs_set_sched(const char *smt_mc, int val)
390{
391 char linebuf[MAX_LINE_LEN];
392 char path[SYSFS_PATH_MAX];
393 struct stat statbuf;
394
395 if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc))
396 return -EINVAL;
397
398 snprintf(path, sizeof(path),
399 PATH_TO_CPU "sched_%s_power_savings", smt_mc);
400 sprintf(linebuf, "%d", val);
401
402 if (stat(path, &statbuf) != 0)
403 return -ENODEV;
404
405 if (sysfs_write_file(path, linebuf, MAX_LINE_LEN) == 0)
406 return -1;
407 return 0;
408}
diff --git a/tools/power/cpupower/utils/helpers/sysfs.h b/tools/power/cpupower/utils/helpers/sysfs.h
new file mode 100644
index 000000000000..8cb797bbceb0
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/sysfs.h
@@ -0,0 +1,30 @@
1#ifndef __CPUPOWER_HELPERS_SYSFS_H__
2#define __CPUPOWER_HELPERS_SYSFS_H__
3
4#define PATH_TO_CPU "/sys/devices/system/cpu/"
5#define MAX_LINE_LEN 255
6#define SYSFS_PATH_MAX 255
7
8extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
9
10extern int sysfs_is_cpu_online(unsigned int cpu);
11
12extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
13 unsigned int idlestate);
14extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
15 unsigned int idlestate);
16extern unsigned long long sysfs_get_idlestate_time(unsigned int cpu,
17 unsigned int idlestate);
18extern char *sysfs_get_idlestate_name(unsigned int cpu,
19 unsigned int idlestate);
20extern char *sysfs_get_idlestate_desc(unsigned int cpu,
21 unsigned int idlestate);
22extern int sysfs_get_idlestate_count(unsigned int cpu);
23
24extern char *sysfs_get_cpuidle_governor(void);
25extern char *sysfs_get_cpuidle_driver(void);
26
27extern int sysfs_get_sched(const char *smt_mc);
28extern int sysfs_set_sched(const char *smt_mc, int val);
29
30#endif /* __CPUPOWER_HELPERS_SYSFS_H__ */
diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c
new file mode 100644
index 000000000000..4eae2c47ba48
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/topology.c
@@ -0,0 +1,111 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * ToDo: Needs to be done more properly for AMD/Intel specifics
7 */
8
9/* Helper struct for qsort, must be in sync with cpupower_topology.cpu_info */
10/* Be careful: Need to pass unsigned to the sort, so that offlined cores are
11 in the end, but double check for -1 for offlined cpus at other places */
12
13#include <stdlib.h>
14#include <stdio.h>
15#include <unistd.h>
16#include <errno.h>
17#include <fcntl.h>
18
19#include <helpers/helpers.h>
20#include <helpers/sysfs.h>
21
22/* returns -1 on failure, 0 on success */
23int sysfs_topology_read_file(unsigned int cpu, const char *fname)
24{
25 unsigned long value;
26 char linebuf[MAX_LINE_LEN];
27 char *endp;
28 char path[SYSFS_PATH_MAX];
29
30 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
31 cpu, fname);
32 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
33 return -1;
34 value = strtoul(linebuf, &endp, 0);
35 if (endp == linebuf || errno == ERANGE)
36 return -1;
37 return value;
38}
39
40struct cpuid_core_info {
41 unsigned int pkg;
42 unsigned int thread;
43 unsigned int cpu;
44 /* flags */
45 unsigned int is_online:1;
46};
47
48static int __compare(const void *t1, const void *t2)
49{
50 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
51 struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
52 if (top1->pkg < top2->pkg)
53 return -1;
54 else if (top1->pkg > top2->pkg)
55 return 1;
56 else if (top1->thread < top2->thread)
57 return -1;
58 else if (top1->thread > top2->thread)
59 return 1;
60 else if (top1->cpu < top2->cpu)
61 return -1;
62 else if (top1->cpu > top2->cpu)
63 return 1;
64 else
65 return 0;
66}
67
68/*
69 * Returns amount of cpus, negative on error, cpu_top must be
70 * passed to cpu_topology_release to free resources
71 *
72 * Array is sorted after ->pkg, ->core, then ->cpu
73 */
74int get_cpu_topology(struct cpupower_topology *cpu_top)
75{
76 int cpu, cpus = sysconf(_SC_NPROCESSORS_CONF);
77
78 cpu_top->core_info = malloc(sizeof(struct cpupower_topology) * cpus);
79 if (cpu_top->core_info == NULL)
80 return -ENOMEM;
81 cpu_top->pkgs = cpu_top->cores = 0;
82 for (cpu = 0; cpu < cpus; cpu++) {
83 cpu_top->core_info[cpu].cpu = cpu;
84 cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
85 cpu_top->core_info[cpu].pkg =
86 sysfs_topology_read_file(cpu, "physical_package_id");
87 if ((int)cpu_top->core_info[cpu].pkg != -1 &&
88 cpu_top->core_info[cpu].pkg > cpu_top->pkgs)
89 cpu_top->pkgs = cpu_top->core_info[cpu].pkg;
90 cpu_top->core_info[cpu].core =
91 sysfs_topology_read_file(cpu, "core_id");
92 }
93 cpu_top->pkgs++;
94
95 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
96 __compare);
97
98 /* Intel's cores count is not consecutively numbered, there may
99 * be a core_id of 3, but none of 2. Assume there always is 0
100 * Get amount of cores by counting duplicates in a package
101 for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
102 if (cpu_top->core_info[cpu].core == 0)
103 cpu_top->cores++;
104 */
105 return cpus;
106}
107
108void cpu_topology_release(struct cpupower_topology cpu_top)
109{
110 free(cpu_top.core_info);
111}
diff --git a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
new file mode 100644
index 000000000000..202e555988be
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
@@ -0,0 +1,338 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * PCI initialization based on example code from:
7 * Andreas Herrmann <andreas.herrmann3@amd.com>
8 */
9
10#if defined(__i386__) || defined(__x86_64__)
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <stdint.h>
15#include <time.h>
16#include <string.h>
17
18#include <pci/pci.h>
19
20#include "idle_monitor/cpupower-monitor.h"
21#include "helpers/helpers.h"
22
23/******** PCI parts could go into own file and get shared ***************/
24
25#define PCI_NON_PC0_OFFSET 0xb0
26#define PCI_PC1_OFFSET 0xb4
27#define PCI_PC6_OFFSET 0xb8
28
29#define PCI_MONITOR_ENABLE_REG 0xe0
30
31#define PCI_NON_PC0_ENABLE_BIT 0
32#define PCI_PC1_ENABLE_BIT 1
33#define PCI_PC6_ENABLE_BIT 2
34
35#define PCI_NBP1_STAT_OFFSET 0x98
36#define PCI_NBP1_ACTIVE_BIT 2
37#define PCI_NBP1_ENTERED_BIT 1
38
39#define PCI_NBP1_CAP_OFFSET 0x90
40#define PCI_NBP1_CAPABLE_BIT 31
41
42#define OVERFLOW_MS 343597 /* 32 bit register filled at 12500 HZ
43 (1 tick per 80ns) */
44
45enum amd_fam14h_states {NON_PC0 = 0, PC1, PC6, NBP1,
46 AMD_FAM14H_STATE_NUM};
47
48static int fam14h_get_count_percent(unsigned int self_id, double *percent,
49 unsigned int cpu);
50static int fam14h_nbp1_count(unsigned int id, unsigned long long *count,
51 unsigned int cpu);
52
53static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = {
54 {
55 .name = "!PC0",
56 .desc = N_("Package in sleep state (PC1 or deeper)"),
57 .id = NON_PC0,
58 .range = RANGE_PACKAGE,
59 .get_count_percent = fam14h_get_count_percent,
60 },
61 {
62 .name = "PC1",
63 .desc = N_("Processor Package C1"),
64 .id = PC1,
65 .range = RANGE_PACKAGE,
66 .get_count_percent = fam14h_get_count_percent,
67 },
68 {
69 .name = "PC6",
70 .desc = N_("Processor Package C6"),
71 .id = PC6,
72 .range = RANGE_PACKAGE,
73 .get_count_percent = fam14h_get_count_percent,
74 },
75 {
76 .name = "NBP1",
77 .desc = N_("North Bridge P1 boolean counter (returns 0 or 1)"),
78 .id = NBP1,
79 .range = RANGE_PACKAGE,
80 .get_count = fam14h_nbp1_count,
81 },
82};
83
84static struct pci_access *pci_acc;
85static int pci_vendor_id = 0x1022;
86static int pci_dev_ids[2] = {0x1716, 0};
87static struct pci_dev *amd_fam14h_pci_dev;
88
89static int nbp1_entered;
90
91struct timespec start_time;
92static unsigned long long timediff;
93
94#ifdef DEBUG
95struct timespec dbg_time;
96long dbg_timediff;
97#endif
98
99static unsigned long long *previous_count[AMD_FAM14H_STATE_NUM];
100static unsigned long long *current_count[AMD_FAM14H_STATE_NUM];
101
102static int amd_fam14h_get_pci_info(struct cstate *state,
103 unsigned int *pci_offset,
104 unsigned int *enable_bit,
105 unsigned int cpu)
106{
107 switch (state->id) {
108 case NON_PC0:
109 *enable_bit = PCI_NON_PC0_ENABLE_BIT;
110 *pci_offset = PCI_NON_PC0_OFFSET;
111 break;
112 case PC1:
113 *enable_bit = PCI_PC1_ENABLE_BIT;
114 *pci_offset = PCI_PC1_OFFSET;
115 break;
116 case PC6:
117 *enable_bit = PCI_PC6_ENABLE_BIT;
118 *pci_offset = PCI_PC6_OFFSET;
119 break;
120 case NBP1:
121 *enable_bit = PCI_NBP1_ENTERED_BIT;
122 *pci_offset = PCI_NBP1_STAT_OFFSET;
123 break;
124 default:
125 return -1;
126 };
127 return 0;
128}
129
130static int amd_fam14h_init(cstate_t *state, unsigned int cpu)
131{
132 int enable_bit, pci_offset, ret;
133 uint32_t val;
134
135 ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu);
136 if (ret)
137 return ret;
138
139 /* NBP1 needs extra treating -> write 1 to D18F6x98 bit 1 for init */
140 if (state->id == NBP1) {
141 val = pci_read_long(amd_fam14h_pci_dev, pci_offset);
142 val |= 1 << enable_bit;
143 val = pci_write_long(amd_fam14h_pci_dev, pci_offset, val);
144 return ret;
145 }
146
147 /* Enable monitor */
148 val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG);
149 dprint("Init %s: read at offset: 0x%x val: %u\n", state->name,
150 PCI_MONITOR_ENABLE_REG, (unsigned int) val);
151 val |= 1 << enable_bit;
152 pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val);
153
154 dprint("Init %s: offset: 0x%x enable_bit: %d - val: %u (%u)\n",
155 state->name, PCI_MONITOR_ENABLE_REG, enable_bit,
156 (unsigned int) val, cpu);
157
158 /* Set counter to zero */
159 pci_write_long(amd_fam14h_pci_dev, pci_offset, 0);
160 previous_count[state->id][cpu] = 0;
161
162 return 0;
163}
164
165static int amd_fam14h_disable(cstate_t *state, unsigned int cpu)
166{
167 int enable_bit, pci_offset, ret;
168 uint32_t val;
169
170 ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu);
171 if (ret)
172 return ret;
173
174 val = pci_read_long(amd_fam14h_pci_dev, pci_offset);
175 dprint("%s: offset: 0x%x %u\n", state->name, pci_offset, val);
176 if (state->id == NBP1) {
177 /* was the bit whether NBP1 got entered set? */
178 nbp1_entered = (val & (1 << PCI_NBP1_ACTIVE_BIT)) |
179 (val & (1 << PCI_NBP1_ENTERED_BIT));
180
181 dprint("NBP1 was %sentered - 0x%x - enable_bit: "
182 "%d - pci_offset: 0x%x\n",
183 nbp1_entered ? "" : "not ",
184 val, enable_bit, pci_offset);
185 return ret;
186 }
187 current_count[state->id][cpu] = val;
188
189 dprint("%s: Current - %llu (%u)\n", state->name,
190 current_count[state->id][cpu], cpu);
191 dprint("%s: Previous - %llu (%u)\n", state->name,
192 previous_count[state->id][cpu], cpu);
193
194 val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG);
195 val &= ~(1 << enable_bit);
196 pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val);
197
198 return 0;
199}
200
201static int fam14h_nbp1_count(unsigned int id, unsigned long long *count,
202 unsigned int cpu)
203{
204 if (id == NBP1) {
205 if (nbp1_entered)
206 *count = 1;
207 else
208 *count = 0;
209 return 0;
210 }
211 return -1;
212}
213static int fam14h_get_count_percent(unsigned int id, double *percent,
214 unsigned int cpu)
215{
216 unsigned long diff;
217
218 if (id >= AMD_FAM14H_STATE_NUM)
219 return -1;
220 /* residency count in 80ns -> divide through 12.5 to get us residency */
221 diff = current_count[id][cpu] - previous_count[id][cpu];
222
223 if (timediff == 0)
224 *percent = 0.0;
225 else
226 *percent = 100.0 * diff / timediff / 12.5;
227
228 dprint("Timediff: %llu - res~: %lu us - percent: %.2f %%\n",
229 timediff, diff * 10 / 125, *percent);
230
231 return 0;
232}
233
234static int amd_fam14h_start(void)
235{
236 int num, cpu;
237 clock_gettime(CLOCK_REALTIME, &start_time);
238 for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) {
239 for (cpu = 0; cpu < cpu_count; cpu++)
240 amd_fam14h_init(&amd_fam14h_cstates[num], cpu);
241 }
242#ifdef DEBUG
243 clock_gettime(CLOCK_REALTIME, &dbg_time);
244 dbg_timediff = timespec_diff_us(start_time, dbg_time);
245 dprint("Enabling counters took: %lu us\n",
246 dbg_timediff);
247#endif
248 return 0;
249}
250
251static int amd_fam14h_stop(void)
252{
253 int num, cpu;
254 struct timespec end_time;
255
256 clock_gettime(CLOCK_REALTIME, &end_time);
257
258 for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) {
259 for (cpu = 0; cpu < cpu_count; cpu++)
260 amd_fam14h_disable(&amd_fam14h_cstates[num], cpu);
261 }
262#ifdef DEBUG
263 clock_gettime(CLOCK_REALTIME, &dbg_time);
264 dbg_timediff = timespec_diff_us(end_time, dbg_time);
265 dprint("Disabling counters took: %lu ns\n", dbg_timediff);
266#endif
267 timediff = timespec_diff_us(start_time, end_time);
268 if (timediff / 1000 > OVERFLOW_MS)
269 print_overflow_err((unsigned int)timediff / 1000000,
270 OVERFLOW_MS / 1000);
271
272 return 0;
273}
274
275static int is_nbp1_capable(void)
276{
277 uint32_t val;
278 val = pci_read_long(amd_fam14h_pci_dev, PCI_NBP1_CAP_OFFSET);
279 return val & (1 << 31);
280}
281
282struct cpuidle_monitor *amd_fam14h_register(void)
283{
284 int num;
285
286 if (cpupower_cpu_info.vendor != X86_VENDOR_AMD)
287 return NULL;
288
289 if (cpupower_cpu_info.family == 0x14) {
290 if (cpu_count <= 0 || cpu_count > 2) {
291 fprintf(stderr, "AMD fam14h: Invalid cpu count: %d\n",
292 cpu_count);
293 return NULL;
294 }
295 } else
296 return NULL;
297
298 /* We do not alloc for nbp1 machine wide counter */
299 for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) {
300 previous_count[num] = calloc(cpu_count,
301 sizeof(unsigned long long));
302 current_count[num] = calloc(cpu_count,
303 sizeof(unsigned long long));
304 }
305
306 amd_fam14h_pci_dev = pci_acc_init(&pci_acc, pci_vendor_id, pci_dev_ids);
307 if (amd_fam14h_pci_dev == NULL || pci_acc == NULL)
308 return NULL;
309
310 if (!is_nbp1_capable())
311 amd_fam14h_monitor.hw_states_num = AMD_FAM14H_STATE_NUM - 1;
312
313 amd_fam14h_monitor.name_len = strlen(amd_fam14h_monitor.name);
314 return &amd_fam14h_monitor;
315}
316
317static void amd_fam14h_unregister(void)
318{
319 int num;
320 for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) {
321 free(previous_count[num]);
322 free(current_count[num]);
323 }
324 pci_cleanup(pci_acc);
325}
326
327struct cpuidle_monitor amd_fam14h_monitor = {
328 .name = "Ontario",
329 .hw_states = amd_fam14h_cstates,
330 .hw_states_num = AMD_FAM14H_STATE_NUM,
331 .start = amd_fam14h_start,
332 .stop = amd_fam14h_stop,
333 .do_register = amd_fam14h_register,
334 .unregister = amd_fam14h_unregister,
335 .needs_root = 1,
336 .overflow_s = OVERFLOW_MS / 1000,
337};
338#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
new file mode 100644
index 000000000000..bcd22a1a3970
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
@@ -0,0 +1,196 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <stdint.h>
11#include <string.h>
12#include <limits.h>
13
14#include "helpers/sysfs.h"
15#include "helpers/helpers.h"
16#include "idle_monitor/cpupower-monitor.h"
17
18#define CPUIDLE_STATES_MAX 10
19static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX];
20struct cpuidle_monitor cpuidle_sysfs_monitor;
21
22static unsigned long long **previous_count;
23static unsigned long long **current_count;
24struct timespec start_time;
25static unsigned long long timediff;
26
27static int cpuidle_get_count_percent(unsigned int id, double *percent,
28 unsigned int cpu)
29{
30 unsigned long long statediff = current_count[cpu][id]
31 - previous_count[cpu][id];
32 dprint("%s: - diff: %llu - percent: %f (%u)\n",
33 cpuidle_cstates[id].name, timediff, *percent, cpu);
34
35 if (timediff == 0)
36 *percent = 0.0;
37 else
38 *percent = ((100.0 * statediff) / timediff);
39
40 dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n",
41 cpuidle_cstates[id].name, timediff, statediff, *percent, cpu);
42
43 return 0;
44}
45
46static int cpuidle_start(void)
47{
48 int cpu, state;
49 clock_gettime(CLOCK_REALTIME, &start_time);
50 for (cpu = 0; cpu < cpu_count; cpu++) {
51 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
52 state++) {
53 previous_count[cpu][state] =
54 sysfs_get_idlestate_time(cpu, state);
55 dprint("CPU %d - State: %d - Val: %llu\n",
56 cpu, state, previous_count[cpu][state]);
57 }
58 };
59 return 0;
60}
61
62static int cpuidle_stop(void)
63{
64 int cpu, state;
65 struct timespec end_time;
66 clock_gettime(CLOCK_REALTIME, &end_time);
67 timediff = timespec_diff_us(start_time, end_time);
68
69 for (cpu = 0; cpu < cpu_count; cpu++) {
70 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
71 state++) {
72 current_count[cpu][state] =
73 sysfs_get_idlestate_time(cpu, state);
74 dprint("CPU %d - State: %d - Val: %llu\n",
75 cpu, state, previous_count[cpu][state]);
76 }
77 };
78 return 0;
79}
80
81void fix_up_intel_idle_driver_name(char *tmp, int num)
82{
83 /* fix up cpuidle name for intel idle driver */
84 if (!strncmp(tmp, "NHM-", 4)) {
85 switch (num) {
86 case 1:
87 strcpy(tmp, "C1");
88 break;
89 case 2:
90 strcpy(tmp, "C3");
91 break;
92 case 3:
93 strcpy(tmp, "C6");
94 break;
95 }
96 } else if (!strncmp(tmp, "SNB-", 4)) {
97 switch (num) {
98 case 1:
99 strcpy(tmp, "C1");
100 break;
101 case 2:
102 strcpy(tmp, "C3");
103 break;
104 case 3:
105 strcpy(tmp, "C6");
106 break;
107 case 4:
108 strcpy(tmp, "C7");
109 break;
110 }
111 } else if (!strncmp(tmp, "ATM-", 4)) {
112 switch (num) {
113 case 1:
114 strcpy(tmp, "C1");
115 break;
116 case 2:
117 strcpy(tmp, "C2");
118 break;
119 case 3:
120 strcpy(tmp, "C4");
121 break;
122 case 4:
123 strcpy(tmp, "C6");
124 break;
125 }
126 }
127}
128
129static struct cpuidle_monitor *cpuidle_register(void)
130{
131 int num;
132 char *tmp;
133
134 /* Assume idle state count is the same for all CPUs */
135 cpuidle_sysfs_monitor.hw_states_num = sysfs_get_idlestate_count(0);
136
137 if (cpuidle_sysfs_monitor.hw_states_num <= 0)
138 return NULL;
139
140 for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
141 tmp = sysfs_get_idlestate_name(0, num);
142 if (tmp == NULL)
143 continue;
144
145 fix_up_intel_idle_driver_name(tmp, num);
146 strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
147 free(tmp);
148
149 tmp = sysfs_get_idlestate_desc(0, num);
150 if (tmp == NULL)
151 continue;
152 strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);
153 free(tmp);
154
155 cpuidle_cstates[num].range = RANGE_THREAD;
156 cpuidle_cstates[num].id = num;
157 cpuidle_cstates[num].get_count_percent =
158 cpuidle_get_count_percent;
159 };
160
161 /* Free this at program termination */
162 previous_count = malloc(sizeof(long long *) * cpu_count);
163 current_count = malloc(sizeof(long long *) * cpu_count);
164 for (num = 0; num < cpu_count; num++) {
165 previous_count[num] = malloc(sizeof(long long) *
166 cpuidle_sysfs_monitor.hw_states_num);
167 current_count[num] = malloc(sizeof(long long) *
168 cpuidle_sysfs_monitor.hw_states_num);
169 }
170
171 cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name);
172 return &cpuidle_sysfs_monitor;
173}
174
175void cpuidle_unregister(void)
176{
177 int num;
178
179 for (num = 0; num < cpu_count; num++) {
180 free(previous_count[num]);
181 free(current_count[num]);
182 }
183 free(previous_count);
184 free(current_count);
185}
186
187struct cpuidle_monitor cpuidle_sysfs_monitor = {
188 .name = "Idle_Stats",
189 .hw_states = cpuidle_cstates,
190 .start = cpuidle_start,
191 .stop = cpuidle_stop,
192 .do_register = cpuidle_register,
193 .unregister = cpuidle_unregister,
194 .needs_root = 0,
195 .overflow_s = UINT_MAX,
196};
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
new file mode 100644
index 000000000000..0d6571e418db
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
@@ -0,0 +1,440 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Output format inspired by Len Brown's <lenb@kernel.org> turbostat tool.
7 *
8 */
9
10
11#include <stdio.h>
12#include <unistd.h>
13#include <stdlib.h>
14#include <string.h>
15#include <time.h>
16#include <signal.h>
17#include <sys/types.h>
18#include <sys/wait.h>
19#include <libgen.h>
20
21#include "idle_monitor/cpupower-monitor.h"
22#include "idle_monitor/idle_monitors.h"
23#include "helpers/helpers.h"
24
25/* Define pointers to all monitors. */
26#define DEF(x) & x ## _monitor ,
27struct cpuidle_monitor *all_monitors[] = {
28#include "idle_monitors.def"
290
30};
31
32static struct cpuidle_monitor *monitors[MONITORS_MAX];
33static unsigned int avail_monitors;
34
35static char *progname;
36
37enum operation_mode_e { list = 1, show, show_all };
38static int mode;
39static int interval = 1;
40static char *show_monitors_param;
41static struct cpupower_topology cpu_top;
42
43/* ToDo: Document this in the manpage */
44static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', };
45
46static void print_wrong_arg_exit(void)
47{
48 printf(_("invalid or unknown argument\n"));
49 exit(EXIT_FAILURE);
50}
51
52long long timespec_diff_us(struct timespec start, struct timespec end)
53{
54 struct timespec temp;
55 if ((end.tv_nsec - start.tv_nsec) < 0) {
56 temp.tv_sec = end.tv_sec - start.tv_sec - 1;
57 temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
58 } else {
59 temp.tv_sec = end.tv_sec - start.tv_sec;
60 temp.tv_nsec = end.tv_nsec - start.tv_nsec;
61 }
62 return (temp.tv_sec * 1000000) + (temp.tv_nsec / 1000);
63}
64
65void print_n_spaces(int n)
66{
67 int x;
68 for (x = 0; x < n; x++)
69 printf(" ");
70}
71
72/* size of s must be at least n + 1 */
73int fill_string_with_spaces(char *s, int n)
74{
75 int len = strlen(s);
76 if (len > n)
77 return -1;
78 for (; len < n; len++)
79 s[len] = ' ';
80 s[len] = '\0';
81 return 0;
82}
83
84void print_header(int topology_depth)
85{
86 int unsigned mon;
87 int state, need_len, pr_mon_len;
88 cstate_t s;
89 char buf[128] = "";
90 int percent_width = 4;
91
92 fill_string_with_spaces(buf, topology_depth * 5 - 1);
93 printf("%s|", buf);
94
95 for (mon = 0; mon < avail_monitors; mon++) {
96 pr_mon_len = 0;
97 need_len = monitors[mon]->hw_states_num * (percent_width + 3)
98 - 1;
99 if (mon != 0) {
100 printf("|| ");
101 need_len--;
102 }
103 sprintf(buf, "%s", monitors[mon]->name);
104 fill_string_with_spaces(buf, need_len);
105 printf("%s", buf);
106 }
107 printf("\n");
108
109 if (topology_depth > 2)
110 printf("PKG |");
111 if (topology_depth > 1)
112 printf("CORE|");
113 if (topology_depth > 0)
114 printf("CPU |");
115
116 for (mon = 0; mon < avail_monitors; mon++) {
117 if (mon != 0)
118 printf("|| ");
119 else
120 printf(" ");
121 for (state = 0; state < monitors[mon]->hw_states_num; state++) {
122 if (state != 0)
123 printf(" | ");
124 s = monitors[mon]->hw_states[state];
125 sprintf(buf, "%s", s.name);
126 fill_string_with_spaces(buf, percent_width);
127 printf("%s", buf);
128 }
129 printf(" ");
130 }
131 printf("\n");
132}
133
134
135void print_results(int topology_depth, int cpu)
136{
137 unsigned int mon;
138 int state, ret;
139 double percent;
140 unsigned long long result;
141 cstate_t s;
142
143 /* Be careful CPUs may got resorted for pkg value do not just use cpu */
144 if (!bitmask_isbitset(cpus_chosen, cpu_top.core_info[cpu].cpu))
145 return;
146
147 if (topology_depth > 2)
148 printf("%4d|", cpu_top.core_info[cpu].pkg);
149 if (topology_depth > 1)
150 printf("%4d|", cpu_top.core_info[cpu].core);
151 if (topology_depth > 0)
152 printf("%4d|", cpu_top.core_info[cpu].cpu);
153
154 for (mon = 0; mon < avail_monitors; mon++) {
155 if (mon != 0)
156 printf("||");
157
158 for (state = 0; state < monitors[mon]->hw_states_num; state++) {
159 if (state != 0)
160 printf("|");
161
162 s = monitors[mon]->hw_states[state];
163
164 if (s.get_count_percent) {
165 ret = s.get_count_percent(s.id, &percent,
166 cpu_top.core_info[cpu].cpu);
167 if (ret)
168 printf("******");
169 else if (percent >= 100.0)
170 printf("%6.1f", percent);
171 else
172 printf("%6.2f", percent);
173 } else if (s.get_count) {
174 ret = s.get_count(s.id, &result,
175 cpu_top.core_info[cpu].cpu);
176 if (ret)
177 printf("******");
178 else
179 printf("%6llu", result);
180 } else {
181 printf(_("Monitor %s, Counter %s has no count "
182 "function. Implementation error\n"),
183 monitors[mon]->name, s.name);
184 exit(EXIT_FAILURE);
185 }
186 }
187 }
188 /*
189 * The monitor could still provide useful data, for example
190 * AMD HW counters partly sit in PCI config space.
191 * It's up to the monitor plug-in to check .is_online, this one
192 * is just for additional info.
193 */
194 if (!cpu_top.core_info[cpu].is_online) {
195 printf(_(" *is offline\n"));
196 return;
197 } else
198 printf("\n");
199}
200
201
202/* param: string passed by -m param (The list of monitors to show)
203 *
204 * Monitors must have been registered already, matching monitors
205 * are picked out and available monitors array is overridden
206 * with matching ones
207 *
208 * Monitors get sorted in the same order the user passes them
209*/
210
211static void parse_monitor_param(char *param)
212{
213 unsigned int num;
214 int mon, hits = 0;
215 char *tmp = param, *token;
216 struct cpuidle_monitor *tmp_mons[MONITORS_MAX];
217
218
219 for (mon = 0; mon < MONITORS_MAX; mon++, tmp = NULL) {
220 token = strtok(tmp, ",");
221 if (token == NULL)
222 break;
223 if (strlen(token) >= MONITOR_NAME_LEN) {
224 printf(_("%s: max monitor name length"
225 " (%d) exceeded\n"), token, MONITOR_NAME_LEN);
226 continue;
227 }
228
229 for (num = 0; num < avail_monitors; num++) {
230 if (!strcmp(monitors[num]->name, token)) {
231 dprint("Found requested monitor: %s\n", token);
232 tmp_mons[hits] = monitors[num];
233 hits++;
234 }
235 }
236 }
237 if (hits == 0) {
238 printf(_("No matching monitor found in %s, "
239 "try -l option\n"), param);
240 exit(EXIT_FAILURE);
241 }
242 /* Override detected/registerd monitors array with requested one */
243 memcpy(monitors, tmp_mons,
244 sizeof(struct cpuidle_monitor *) * MONITORS_MAX);
245 avail_monitors = hits;
246}
247
248void list_monitors(void)
249{
250 unsigned int mon;
251 int state;
252 cstate_t s;
253
254 for (mon = 0; mon < avail_monitors; mon++) {
255 printf(_("Monitor \"%s\" (%d states) - Might overflow after %u "
256 "s\n"),
257 monitors[mon]->name, monitors[mon]->hw_states_num,
258 monitors[mon]->overflow_s);
259
260 for (state = 0; state < monitors[mon]->hw_states_num; state++) {
261 s = monitors[mon]->hw_states[state];
262 /*
263 * ToDo show more state capabilities:
264 * percent, time (granlarity)
265 */
266 printf("%s\t[%c] -> %s\n", s.name, range_abbr[s.range],
267 gettext(s.desc));
268 }
269 }
270}
271
272int fork_it(char **argv)
273{
274 int status;
275 unsigned int num;
276 unsigned long long timediff;
277 pid_t child_pid;
278 struct timespec start, end;
279
280 child_pid = fork();
281 clock_gettime(CLOCK_REALTIME, &start);
282
283 for (num = 0; num < avail_monitors; num++)
284 monitors[num]->start();
285
286 if (!child_pid) {
287 /* child */
288 execvp(argv[0], argv);
289 } else {
290 /* parent */
291 if (child_pid == -1) {
292 perror("fork");
293 exit(1);
294 }
295
296 signal(SIGINT, SIG_IGN);
297 signal(SIGQUIT, SIG_IGN);
298 if (waitpid(child_pid, &status, 0) == -1) {
299 perror("wait");
300 exit(1);
301 }
302 }
303 clock_gettime(CLOCK_REALTIME, &end);
304 for (num = 0; num < avail_monitors; num++)
305 monitors[num]->stop();
306
307 timediff = timespec_diff_us(start, end);
308 if (WIFEXITED(status))
309 printf(_("%s took %.5f seconds and exited with status %d\n"),
310 argv[0], timediff / (1000.0 * 1000),
311 WEXITSTATUS(status));
312 return 0;
313}
314
315int do_interval_measure(int i)
316{
317 unsigned int num;
318
319 for (num = 0; num < avail_monitors; num++) {
320 dprint("HW C-state residency monitor: %s - States: %d\n",
321 monitors[num]->name, monitors[num]->hw_states_num);
322 monitors[num]->start();
323 }
324 sleep(i);
325 for (num = 0; num < avail_monitors; num++)
326 monitors[num]->stop();
327
328 return 0;
329}
330
331static void cmdline(int argc, char *argv[])
332{
333 int opt;
334 progname = basename(argv[0]);
335
336 while ((opt = getopt(argc, argv, "+li:m:")) != -1) {
337 switch (opt) {
338 case 'l':
339 if (mode)
340 print_wrong_arg_exit();
341 mode = list;
342 break;
343 case 'i':
344 /* only allow -i with -m or no option */
345 if (mode && mode != show)
346 print_wrong_arg_exit();
347 interval = atoi(optarg);
348 break;
349 case 'm':
350 if (mode)
351 print_wrong_arg_exit();
352 mode = show;
353 show_monitors_param = optarg;
354 break;
355 default:
356 print_wrong_arg_exit();
357 }
358 }
359 if (!mode)
360 mode = show_all;
361}
362
363int cmd_monitor(int argc, char **argv)
364{
365 unsigned int num;
366 struct cpuidle_monitor *test_mon;
367 int cpu;
368
369 cmdline(argc, argv);
370 cpu_count = get_cpu_topology(&cpu_top);
371 if (cpu_count < 0) {
372 printf(_("Cannot read number of available processors\n"));
373 return EXIT_FAILURE;
374 }
375
376 /* Default is: monitor all CPUs */
377 if (bitmask_isallclear(cpus_chosen))
378 bitmask_setall(cpus_chosen);
379
380 dprint("System has up to %d CPU cores\n", cpu_count);
381
382 for (num = 0; all_monitors[num]; num++) {
383 dprint("Try to register: %s\n", all_monitors[num]->name);
384 test_mon = all_monitors[num]->do_register();
385 if (test_mon) {
386 if (test_mon->needs_root && !run_as_root) {
387 fprintf(stderr, _("Available monitor %s needs "
388 "root access\n"), test_mon->name);
389 continue;
390 }
391 monitors[avail_monitors] = test_mon;
392 dprint("%s registered\n", all_monitors[num]->name);
393 avail_monitors++;
394 }
395 }
396
397 if (avail_monitors == 0) {
398 printf(_("No HW Cstate monitors found\n"));
399 return 1;
400 }
401
402 if (mode == list) {
403 list_monitors();
404 exit(EXIT_SUCCESS);
405 }
406
407 if (mode == show)
408 parse_monitor_param(show_monitors_param);
409
410 dprint("Packages: %d - Cores: %d - CPUs: %d\n",
411 cpu_top.pkgs, cpu_top.cores, cpu_count);
412
413 /*
414 * if any params left, it must be a command to fork
415 */
416 if (argc - optind)
417 fork_it(argv + optind);
418 else
419 do_interval_measure(interval);
420
421 /* ToDo: Topology parsing needs fixing first to do
422 this more generically */
423 if (cpu_top.pkgs > 1)
424 print_header(3);
425 else
426 print_header(1);
427
428 for (cpu = 0; cpu < cpu_count; cpu++) {
429 if (cpu_top.pkgs > 1)
430 print_results(3, cpu);
431 else
432 print_results(1, cpu);
433 }
434
435 for (num = 0; num < avail_monitors; num++)
436 monitors[num]->unregister();
437
438 cpu_topology_release(cpu_top);
439 return 0;
440}
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
new file mode 100644
index 000000000000..9312ee1f2dbc
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
@@ -0,0 +1,68 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 */
7
8#ifndef __CPUIDLE_INFO_HW__
9#define __CPUIDLE_INFO_HW__
10
11#include <stdarg.h>
12#include <time.h>
13
14#include "idle_monitor/idle_monitors.h"
15
16#define MONITORS_MAX 20
17#define MONITOR_NAME_LEN 20
18#define CSTATE_NAME_LEN 5
19#define CSTATE_DESC_LEN 60
20
21int cpu_count;
22
23/* Hard to define the right names ...: */
24enum power_range_e {
25 RANGE_THREAD, /* Lowest in topology hierarcy, AMD: core, Intel: thread
26 kernel sysfs: cpu */
27 RANGE_CORE, /* AMD: unit, Intel: core, kernel_sysfs: core_id */
28 RANGE_PACKAGE, /* Package, processor socket */
29 RANGE_MACHINE, /* Machine, platform wide */
30 RANGE_MAX };
31
32typedef struct cstate {
33 int id;
34 enum power_range_e range;
35 char name[CSTATE_NAME_LEN];
36 char desc[CSTATE_DESC_LEN];
37
38 /* either provide a percentage or a general count */
39 int (*get_count_percent)(unsigned int self_id, double *percent,
40 unsigned int cpu);
41 int (*get_count)(unsigned int self_id, unsigned long long *count,
42 unsigned int cpu);
43} cstate_t;
44
45struct cpuidle_monitor {
46 /* Name must not contain whitespaces */
47 char name[MONITOR_NAME_LEN];
48 int name_len;
49 int hw_states_num;
50 cstate_t *hw_states;
51 int (*start) (void);
52 int (*stop) (void);
53 struct cpuidle_monitor* (*do_register) (void);
54 void (*unregister)(void);
55 unsigned int overflow_s;
56 int needs_root;
57};
58
59extern long long timespec_diff_us(struct timespec start, struct timespec end);
60
61#define print_overflow_err(mes, ov) \
62{ \
63 fprintf(stderr, gettext("Measure took %u seconds, but registers could " \
64 "overflow at %u seconds, results " \
65 "could be inaccurate\n"), mes, ov); \
66}
67
68#endif /* __CPUIDLE_INFO_HW__ */
diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.def b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
new file mode 100644
index 000000000000..e3f8d9b2b18f
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
@@ -0,0 +1,7 @@
1#if defined(__i386__) || defined(__x86_64__)
2DEF(amd_fam14h)
3DEF(intel_nhm)
4DEF(intel_snb)
5DEF(mperf)
6#endif
7DEF(cpuidle_sysfs)
diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.h b/tools/power/cpupower/utils/idle_monitor/idle_monitors.h
new file mode 100644
index 000000000000..4fcdeb1e07e8
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/idle_monitors.h
@@ -0,0 +1,18 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on the idea from Michael Matz <matz@suse.de>
7 *
8 */
9
10#ifndef _CPUIDLE_IDLE_MONITORS_H_
11#define _CPUIDLE_IDLE_MONITORS_H_
12
13#define DEF(x) extern struct cpuidle_monitor x ##_monitor;
14#include "idle_monitors.def"
15#undef DEF
16extern struct cpuidle_monitor *all_monitors[];
17
18#endif /* _CPUIDLE_IDLE_MONITORS_H_ */
diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
new file mode 100644
index 000000000000..5650ab5a2c20
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
@@ -0,0 +1,338 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#if defined(__i386__) || defined(__x86_64__)
8
9#include <stdio.h>
10#include <stdint.h>
11#include <stdlib.h>
12#include <string.h>
13#include <limits.h>
14
15#include <cpufreq.h>
16
17#include "helpers/helpers.h"
18#include "idle_monitor/cpupower-monitor.h"
19
20#define MSR_APERF 0xE8
21#define MSR_MPERF 0xE7
22
23#define MSR_TSC 0x10
24
25#define MSR_AMD_HWCR 0xc0010015
26
27enum mperf_id { C0 = 0, Cx, AVG_FREQ, MPERF_CSTATE_COUNT };
28
29static int mperf_get_count_percent(unsigned int self_id, double *percent,
30 unsigned int cpu);
31static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
32 unsigned int cpu);
33static struct timespec time_start, time_end;
34
35static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
36 {
37 .name = "C0",
38 .desc = N_("Processor Core not idle"),
39 .id = C0,
40 .range = RANGE_THREAD,
41 .get_count_percent = mperf_get_count_percent,
42 },
43 {
44 .name = "Cx",
45 .desc = N_("Processor Core in an idle state"),
46 .id = Cx,
47 .range = RANGE_THREAD,
48 .get_count_percent = mperf_get_count_percent,
49 },
50
51 {
52 .name = "Freq",
53 .desc = N_("Average Frequency (including boost) in MHz"),
54 .id = AVG_FREQ,
55 .range = RANGE_THREAD,
56 .get_count = mperf_get_count_freq,
57 },
58};
59
60enum MAX_FREQ_MODE { MAX_FREQ_SYSFS, MAX_FREQ_TSC_REF };
61static int max_freq_mode;
62/*
63 * The max frequency mperf is ticking at (in C0), either retrieved via:
64 * 1) calculated after measurements if we know TSC ticks at mperf/P0 frequency
65 * 2) cpufreq /sys/devices/.../cpu0/cpufreq/cpuinfo_max_freq at init time
66 * 1. Is preferred as it also works without cpufreq subsystem (e.g. on Xen)
67 */
68static unsigned long max_frequency;
69
70static unsigned long long tsc_at_measure_start;
71static unsigned long long tsc_at_measure_end;
72static unsigned long long *mperf_previous_count;
73static unsigned long long *aperf_previous_count;
74static unsigned long long *mperf_current_count;
75static unsigned long long *aperf_current_count;
76
77/* valid flag for all CPUs. If a MSR read failed it will be zero */
78static int *is_valid;
79
80static int mperf_get_tsc(unsigned long long *tsc)
81{
82 int ret;
83 ret = read_msr(0, MSR_TSC, tsc);
84 if (ret)
85 dprint("Reading TSC MSR failed, returning %llu\n", *tsc);
86 return ret;
87}
88
89static int mperf_init_stats(unsigned int cpu)
90{
91 unsigned long long val;
92 int ret;
93
94 ret = read_msr(cpu, MSR_APERF, &val);
95 aperf_previous_count[cpu] = val;
96 ret |= read_msr(cpu, MSR_MPERF, &val);
97 mperf_previous_count[cpu] = val;
98 is_valid[cpu] = !ret;
99
100 return 0;
101}
102
103static int mperf_measure_stats(unsigned int cpu)
104{
105 unsigned long long val;
106 int ret;
107
108 ret = read_msr(cpu, MSR_APERF, &val);
109 aperf_current_count[cpu] = val;
110 ret |= read_msr(cpu, MSR_MPERF, &val);
111 mperf_current_count[cpu] = val;
112 is_valid[cpu] = !ret;
113
114 return 0;
115}
116
117static int mperf_get_count_percent(unsigned int id, double *percent,
118 unsigned int cpu)
119{
120 unsigned long long aperf_diff, mperf_diff, tsc_diff;
121 unsigned long long timediff;
122
123 if (!is_valid[cpu])
124 return -1;
125
126 if (id != C0 && id != Cx)
127 return -1;
128
129 mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu];
130 aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
131
132 if (max_freq_mode == MAX_FREQ_TSC_REF) {
133 tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
134 *percent = 100.0 * mperf_diff / tsc_diff;
135 dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
136 mperf_cstates[id].name, mperf_diff, tsc_diff);
137 } else if (max_freq_mode == MAX_FREQ_SYSFS) {
138 timediff = timespec_diff_us(time_start, time_end);
139 *percent = 100.0 * mperf_diff / timediff;
140 dprint("%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n",
141 mperf_cstates[id].name, mperf_diff, timediff);
142 } else
143 return -1;
144
145 if (id == Cx)
146 *percent = 100.0 - *percent;
147
148 dprint("%s: previous: %llu - current: %llu - (%u)\n",
149 mperf_cstates[id].name, mperf_diff, aperf_diff, cpu);
150 dprint("%s: %f\n", mperf_cstates[id].name, *percent);
151 return 0;
152}
153
154static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
155 unsigned int cpu)
156{
157 unsigned long long aperf_diff, mperf_diff, time_diff, tsc_diff;
158
159 if (id != AVG_FREQ)
160 return 1;
161
162 if (!is_valid[cpu])
163 return -1;
164
165 mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu];
166 aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
167
168 if (max_freq_mode == MAX_FREQ_TSC_REF) {
169 /* Calculate max_freq from TSC count */
170 tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
171 time_diff = timespec_diff_us(time_start, time_end);
172 max_frequency = tsc_diff / time_diff;
173 }
174
175 *count = max_frequency * ((double)aperf_diff / mperf_diff);
176 dprint("%s: Average freq based on %s maximum frequency:\n",
177 mperf_cstates[id].name,
178 (max_freq_mode == MAX_FREQ_TSC_REF) ? "TSC calculated" : "sysfs read");
179 dprint("%max_frequency: %lu", max_frequency);
180 dprint("aperf_diff: %llu\n", aperf_diff);
181 dprint("mperf_diff: %llu\n", mperf_diff);
182 dprint("avg freq: %llu\n", *count);
183 return 0;
184}
185
186static int mperf_start(void)
187{
188 int cpu;
189 unsigned long long dbg;
190
191 clock_gettime(CLOCK_REALTIME, &time_start);
192 mperf_get_tsc(&tsc_at_measure_start);
193
194 for (cpu = 0; cpu < cpu_count; cpu++)
195 mperf_init_stats(cpu);
196
197 mperf_get_tsc(&dbg);
198 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
199 return 0;
200}
201
202static int mperf_stop(void)
203{
204 unsigned long long dbg;
205 int cpu;
206
207 for (cpu = 0; cpu < cpu_count; cpu++)
208 mperf_measure_stats(cpu);
209
210 mperf_get_tsc(&tsc_at_measure_end);
211 clock_gettime(CLOCK_REALTIME, &time_end);
212
213 mperf_get_tsc(&dbg);
214 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
215
216 return 0;
217}
218
219/*
220 * Mperf register is defined to tick at P0 (maximum) frequency
221 *
222 * Instead of reading out P0 which can be tricky to read out from HW,
223 * we use TSC counter if it reliably ticks at P0/mperf frequency.
224 *
225 * Still try to fall back to:
226 * /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
227 * on older Intel HW without invariant TSC feature.
228 * Or on AMD machines where TSC does not tick at P0 (do not exist yet, but
229 * it's still double checked (MSR_AMD_HWCR)).
230 *
231 * On these machines the user would still get useful mperf
232 * stats when acpi-cpufreq driver is loaded.
233 */
234static int init_maxfreq_mode(void)
235{
236 int ret;
237 unsigned long long hwcr;
238 unsigned long min;
239
240 if (!cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC)
241 goto use_sysfs;
242
243 if (cpupower_cpu_info.vendor == X86_VENDOR_AMD) {
244 /* MSR_AMD_HWCR tells us whether TSC runs at P0/mperf
245 * freq.
246 * A test whether hwcr is accessable/available would be:
247 * (cpupower_cpu_info.family > 0x10 ||
248 * cpupower_cpu_info.family == 0x10 &&
249 * cpupower_cpu_info.model >= 0x2))
250 * This should be the case for all aperf/mperf
251 * capable AMD machines and is therefore safe to test here.
252 * Compare with Linus kernel git commit: acf01734b1747b1ec4
253 */
254 ret = read_msr(0, MSR_AMD_HWCR, &hwcr);
255 /*
256 * If the MSR read failed, assume a Xen system that did
257 * not explicitly provide access to it and assume TSC works
258 */
259 if (ret != 0) {
260 dprint("TSC read 0x%x failed - assume TSC working\n",
261 MSR_AMD_HWCR);
262 return 0;
263 } else if (1 & (hwcr >> 24)) {
264 max_freq_mode = MAX_FREQ_TSC_REF;
265 return 0;
266 } else { /* Use sysfs max frequency if available */ }
267 } else if (cpupower_cpu_info.vendor == X86_VENDOR_INTEL) {
268 /*
269 * On Intel we assume mperf (in C0) is ticking at same
270 * rate than TSC
271 */
272 max_freq_mode = MAX_FREQ_TSC_REF;
273 return 0;
274 }
275use_sysfs:
276 if (cpufreq_get_hardware_limits(0, &min, &max_frequency)) {
277 dprint("Cannot retrieve max freq from cpufreq kernel "
278 "subsystem\n");
279 return -1;
280 }
281 max_freq_mode = MAX_FREQ_SYSFS;
282 return 0;
283}
284
285/*
286 * This monitor provides:
287 *
288 * 1) Average frequency a CPU resided in
289 * This always works if the CPU has aperf/mperf capabilities
290 *
291 * 2) C0 and Cx (any sleep state) time a CPU resided in
292 * Works if mperf timer stops ticking in sleep states which
293 * seem to be the case on all current HW.
294 * Both is directly retrieved from HW registers and is independent
295 * from kernel statistics.
296 */
297struct cpuidle_monitor mperf_monitor;
298struct cpuidle_monitor *mperf_register(void)
299{
300 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF))
301 return NULL;
302
303 if (init_maxfreq_mode())
304 return NULL;
305
306 /* Free this at program termination */
307 is_valid = calloc(cpu_count, sizeof(int));
308 mperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
309 aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
310 mperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
311 aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
312
313 mperf_monitor.name_len = strlen(mperf_monitor.name);
314 return &mperf_monitor;
315}
316
317void mperf_unregister(void)
318{
319 free(mperf_previous_count);
320 free(aperf_previous_count);
321 free(mperf_current_count);
322 free(aperf_current_count);
323 free(is_valid);
324}
325
326struct cpuidle_monitor mperf_monitor = {
327 .name = "Mperf",
328 .hw_states_num = MPERF_CSTATE_COUNT,
329 .hw_states = mperf_cstates,
330 .start = mperf_start,
331 .stop = mperf_stop,
332 .do_register = mperf_register,
333 .unregister = mperf_unregister,
334 .needs_root = 1,
335 .overflow_s = 922000000 /* 922337203 seconds TSC overflow
336 at 20GHz */
337};
338#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
new file mode 100644
index 000000000000..d2a91dd0d563
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
@@ -0,0 +1,216 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on Len Brown's <lenb@kernel.org> turbostat tool.
7 */
8
9#if defined(__i386__) || defined(__x86_64__)
10
11#include <stdio.h>
12#include <stdint.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include "helpers/helpers.h"
17#include "idle_monitor/cpupower-monitor.h"
18
19#define MSR_PKG_C3_RESIDENCY 0x3F8
20#define MSR_PKG_C6_RESIDENCY 0x3F9
21#define MSR_CORE_C3_RESIDENCY 0x3FC
22#define MSR_CORE_C6_RESIDENCY 0x3FD
23
24#define MSR_TSC 0x10
25
26#define NHM_CSTATE_COUNT 4
27
28enum intel_nhm_id { C3 = 0, C6, PC3, PC6, TSC = 0xFFFF };
29
30static int nhm_get_count_percent(unsigned int self_id, double *percent,
31 unsigned int cpu);
32
33static cstate_t nhm_cstates[NHM_CSTATE_COUNT] = {
34 {
35 .name = "C3",
36 .desc = N_("Processor Core C3"),
37 .id = C3,
38 .range = RANGE_CORE,
39 .get_count_percent = nhm_get_count_percent,
40 },
41 {
42 .name = "C6",
43 .desc = N_("Processor Core C6"),
44 .id = C6,
45 .range = RANGE_CORE,
46 .get_count_percent = nhm_get_count_percent,
47 },
48
49 {
50 .name = "PC3",
51 .desc = N_("Processor Package C3"),
52 .id = PC3,
53 .range = RANGE_PACKAGE,
54 .get_count_percent = nhm_get_count_percent,
55 },
56 {
57 .name = "PC6",
58 .desc = N_("Processor Package C6"),
59 .id = PC6,
60 .range = RANGE_PACKAGE,
61 .get_count_percent = nhm_get_count_percent,
62 },
63};
64
65static unsigned long long tsc_at_measure_start;
66static unsigned long long tsc_at_measure_end;
67static unsigned long long *previous_count[NHM_CSTATE_COUNT];
68static unsigned long long *current_count[NHM_CSTATE_COUNT];
69/* valid flag for all CPUs. If a MSR read failed it will be zero */
70static int *is_valid;
71
72static int nhm_get_count(enum intel_nhm_id id, unsigned long long *val,
73 unsigned int cpu)
74{
75 int msr;
76
77 switch (id) {
78 case C3:
79 msr = MSR_CORE_C3_RESIDENCY;
80 break;
81 case C6:
82 msr = MSR_CORE_C6_RESIDENCY;
83 break;
84 case PC3:
85 msr = MSR_PKG_C3_RESIDENCY;
86 break;
87 case PC6:
88 msr = MSR_PKG_C6_RESIDENCY;
89 break;
90 case TSC:
91 msr = MSR_TSC;
92 break;
93 default:
94 return -1;
95 };
96 if (read_msr(cpu, msr, val))
97 return -1;
98
99 return 0;
100}
101
102static int nhm_get_count_percent(unsigned int id, double *percent,
103 unsigned int cpu)
104{
105 *percent = 0.0;
106
107 if (!is_valid[cpu])
108 return -1;
109
110 *percent = (100.0 *
111 (current_count[id][cpu] - previous_count[id][cpu])) /
112 (tsc_at_measure_end - tsc_at_measure_start);
113
114 dprint("%s: previous: %llu - current: %llu - (%u)\n",
115 nhm_cstates[id].name, previous_count[id][cpu],
116 current_count[id][cpu], cpu);
117
118 dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n",
119 nhm_cstates[id].name,
120 (unsigned long long) tsc_at_measure_end - tsc_at_measure_start,
121 current_count[id][cpu] - previous_count[id][cpu],
122 *percent, cpu);
123
124 return 0;
125}
126
127static int nhm_start(void)
128{
129 int num, cpu;
130 unsigned long long dbg, val;
131
132 nhm_get_count(TSC, &tsc_at_measure_start, 0);
133
134 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
135 for (cpu = 0; cpu < cpu_count; cpu++) {
136 is_valid[cpu] = !nhm_get_count(num, &val, cpu);
137 previous_count[num][cpu] = val;
138 }
139 }
140 nhm_get_count(TSC, &dbg, 0);
141 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
142 return 0;
143}
144
145static int nhm_stop(void)
146{
147 unsigned long long val;
148 unsigned long long dbg;
149 int num, cpu;
150
151 nhm_get_count(TSC, &tsc_at_measure_end, 0);
152
153 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
154 for (cpu = 0; cpu < cpu_count; cpu++) {
155 is_valid[cpu] = !nhm_get_count(num, &val, cpu);
156 current_count[num][cpu] = val;
157 }
158 }
159 nhm_get_count(TSC, &dbg, 0);
160 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
161
162 return 0;
163}
164
165struct cpuidle_monitor intel_nhm_monitor;
166
167struct cpuidle_monitor *intel_nhm_register(void)
168{
169 int num;
170
171 if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
172 return NULL;
173
174 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC))
175 return NULL;
176
177 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF))
178 return NULL;
179
180 /* Free this at program termination */
181 is_valid = calloc(cpu_count, sizeof(int));
182 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
183 previous_count[num] = calloc(cpu_count,
184 sizeof(unsigned long long));
185 current_count[num] = calloc(cpu_count,
186 sizeof(unsigned long long));
187 }
188
189 intel_nhm_monitor.name_len = strlen(intel_nhm_monitor.name);
190 return &intel_nhm_monitor;
191}
192
193void intel_nhm_unregister(void)
194{
195 int num;
196
197 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
198 free(previous_count[num]);
199 free(current_count[num]);
200 }
201 free(is_valid);
202}
203
204struct cpuidle_monitor intel_nhm_monitor = {
205 .name = "Nehalem",
206 .hw_states_num = NHM_CSTATE_COUNT,
207 .hw_states = nhm_cstates,
208 .start = nhm_start,
209 .stop = nhm_stop,
210 .do_register = intel_nhm_register,
211 .unregister = intel_nhm_unregister,
212 .needs_root = 1,
213 .overflow_s = 922000000 /* 922337203 seconds TSC overflow
214 at 20GHz */
215};
216#endif
diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
new file mode 100644
index 000000000000..a1bc07cd53e1
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
@@ -0,0 +1,190 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on Len Brown's <lenb@kernel.org> turbostat tool.
7 */
8
9#if defined(__i386__) || defined(__x86_64__)
10
11#include <stdio.h>
12#include <stdint.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include "helpers/helpers.h"
17#include "idle_monitor/cpupower-monitor.h"
18
19#define MSR_PKG_C2_RESIDENCY 0x60D
20#define MSR_PKG_C7_RESIDENCY 0x3FA
21#define MSR_CORE_C7_RESIDENCY 0x3FE
22
23#define MSR_TSC 0x10
24
25enum intel_snb_id { C7 = 0, PC2, PC7, SNB_CSTATE_COUNT, TSC = 0xFFFF };
26
27static int snb_get_count_percent(unsigned int self_id, double *percent,
28 unsigned int cpu);
29
30static cstate_t snb_cstates[SNB_CSTATE_COUNT] = {
31 {
32 .name = "C7",
33 .desc = N_("Processor Core C7"),
34 .id = C7,
35 .range = RANGE_CORE,
36 .get_count_percent = snb_get_count_percent,
37 },
38 {
39 .name = "PC2",
40 .desc = N_("Processor Package C2"),
41 .id = PC2,
42 .range = RANGE_PACKAGE,
43 .get_count_percent = snb_get_count_percent,
44 },
45 {
46 .name = "PC7",
47 .desc = N_("Processor Package C7"),
48 .id = PC7,
49 .range = RANGE_PACKAGE,
50 .get_count_percent = snb_get_count_percent,
51 },
52};
53
54static unsigned long long tsc_at_measure_start;
55static unsigned long long tsc_at_measure_end;
56static unsigned long long *previous_count[SNB_CSTATE_COUNT];
57static unsigned long long *current_count[SNB_CSTATE_COUNT];
58/* valid flag for all CPUs. If a MSR read failed it will be zero */
59static int *is_valid;
60
61static int snb_get_count(enum intel_snb_id id, unsigned long long *val,
62 unsigned int cpu)
63{
64 int msr;
65
66 switch (id) {
67 case C7:
68 msr = MSR_CORE_C7_RESIDENCY;
69 break;
70 case PC2:
71 msr = MSR_PKG_C2_RESIDENCY;
72 break;
73 case PC7:
74 msr = MSR_PKG_C7_RESIDENCY;
75 break;
76 case TSC:
77 msr = MSR_TSC;
78 break;
79 default:
80 return -1;
81 };
82 if (read_msr(cpu, msr, val))
83 return -1;
84 return 0;
85}
86
87static int snb_get_count_percent(unsigned int id, double *percent,
88 unsigned int cpu)
89{
90 *percent = 0.0;
91
92 if (!is_valid[cpu])
93 return -1;
94
95 *percent = (100.0 *
96 (current_count[id][cpu] - previous_count[id][cpu])) /
97 (tsc_at_measure_end - tsc_at_measure_start);
98
99 dprint("%s: previous: %llu - current: %llu - (%u)\n",
100 snb_cstates[id].name, previous_count[id][cpu],
101 current_count[id][cpu], cpu);
102
103 dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n",
104 snb_cstates[id].name,
105 (unsigned long long) tsc_at_measure_end - tsc_at_measure_start,
106 current_count[id][cpu] - previous_count[id][cpu],
107 *percent, cpu);
108
109 return 0;
110}
111
112static int snb_start(void)
113{
114 int num, cpu;
115 unsigned long long val;
116
117 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
118 for (cpu = 0; cpu < cpu_count; cpu++) {
119 snb_get_count(num, &val, cpu);
120 previous_count[num][cpu] = val;
121 }
122 }
123 snb_get_count(TSC, &tsc_at_measure_start, 0);
124 return 0;
125}
126
127static int snb_stop(void)
128{
129 unsigned long long val;
130 int num, cpu;
131
132 snb_get_count(TSC, &tsc_at_measure_end, 0);
133
134 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
135 for (cpu = 0; cpu < cpu_count; cpu++) {
136 is_valid[cpu] = !snb_get_count(num, &val, cpu);
137 current_count[num][cpu] = val;
138 }
139 }
140 return 0;
141}
142
143struct cpuidle_monitor intel_snb_monitor;
144
145static struct cpuidle_monitor *snb_register(void)
146{
147 int num;
148
149 if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL
150 || cpupower_cpu_info.family != 6)
151 return NULL;
152
153 if (cpupower_cpu_info.model != 0x2A
154 && cpupower_cpu_info.model != 0x2D)
155 return NULL;
156
157 is_valid = calloc(cpu_count, sizeof(int));
158 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
159 previous_count[num] = calloc(cpu_count,
160 sizeof(unsigned long long));
161 current_count[num] = calloc(cpu_count,
162 sizeof(unsigned long long));
163 }
164 intel_snb_monitor.name_len = strlen(intel_snb_monitor.name);
165 return &intel_snb_monitor;
166}
167
168void snb_unregister(void)
169{
170 int num;
171 free(is_valid);
172 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
173 free(previous_count[num]);
174 free(current_count[num]);
175 }
176}
177
178struct cpuidle_monitor intel_snb_monitor = {
179 .name = "SandyBridge",
180 .hw_states = snb_cstates,
181 .hw_states_num = SNB_CSTATE_COUNT,
182 .start = snb_start,
183 .stop = snb_stop,
184 .do_register = snb_register,
185 .unregister = snb_unregister,
186 .needs_root = 1,
187 .overflow_s = 922000000 /* 922337203 seconds TSC overflow
188 at 20GHz */
189};
190#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/version-gen.sh b/tools/power/cpupower/utils/version-gen.sh
new file mode 100755
index 000000000000..5ec41c556992
--- /dev/null
+++ b/tools/power/cpupower/utils/version-gen.sh
@@ -0,0 +1,35 @@
1#!/bin/sh
2#
3# Script which prints out the version to use for building cpupowerutils.
4# Must be called from tools/power/cpupower/
5#
6# Heavily based on tools/perf/util/PERF-VERSION-GEN .
7
8LF='
9'
10
11# First check if there is a .git to get the version from git describe
12# otherwise try to get the version from the kernel makefile
13if test -d ../../../.git -o -f ../../../.git &&
14 VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
15 case "$VN" in
16 *$LF*) (exit 1) ;;
17 v[0-9]*)
18 git update-index -q --refresh
19 test -z "$(git diff-index --name-only HEAD --)" ||
20 VN="$VN-dirty" ;;
21 esac
22then
23 VN=$(echo "$VN" | sed -e 's/-/./g');
24else
25 eval $(grep '^VERSION[[:space:]]*=' ../../../Makefile|tr -d ' ')
26 eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../../Makefile|tr -d ' ')
27 eval $(grep '^SUBLEVEL[[:space:]]*=' ../../../Makefile|tr -d ' ')
28 eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../../Makefile|tr -d ' ')
29
30 VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
31fi
32
33VN=$(expr "$VN" : v*'\(.*\)')
34
35echo $VN
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 6d8ef4a3a9b5..3c6f7808efae 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -128,53 +128,55 @@ unsigned long long get_msr(int cpu, off_t offset)
128void print_header(void) 128void print_header(void)
129{ 129{
130 if (show_pkg) 130 if (show_pkg)
131 fprintf(stderr, "pkg "); 131 fprintf(stderr, "pk");
132 if (show_core) 132 if (show_core)
133 fprintf(stderr, "core"); 133 fprintf(stderr, " cr");
134 if (show_cpu) 134 if (show_cpu)
135 fprintf(stderr, " CPU"); 135 fprintf(stderr, " CPU");
136 if (do_nhm_cstates) 136 if (do_nhm_cstates)
137 fprintf(stderr, " %%c0 "); 137 fprintf(stderr, " %%c0 ");
138 if (has_aperf) 138 if (has_aperf)
139 fprintf(stderr, " GHz"); 139 fprintf(stderr, " GHz");
140 fprintf(stderr, " TSC"); 140 fprintf(stderr, " TSC");
141 if (do_nhm_cstates) 141 if (do_nhm_cstates)
142 fprintf(stderr, " %%c1 "); 142 fprintf(stderr, " %%c1");
143 if (do_nhm_cstates) 143 if (do_nhm_cstates)
144 fprintf(stderr, " %%c3 "); 144 fprintf(stderr, " %%c3");
145 if (do_nhm_cstates) 145 if (do_nhm_cstates)
146 fprintf(stderr, " %%c6 "); 146 fprintf(stderr, " %%c6");
147 if (do_snb_cstates) 147 if (do_snb_cstates)
148 fprintf(stderr, " %%c7 "); 148 fprintf(stderr, " %%c7");
149 if (do_snb_cstates) 149 if (do_snb_cstates)
150 fprintf(stderr, " %%pc2 "); 150 fprintf(stderr, " %%pc2");
151 if (do_nhm_cstates) 151 if (do_nhm_cstates)
152 fprintf(stderr, " %%pc3 "); 152 fprintf(stderr, " %%pc3");
153 if (do_nhm_cstates) 153 if (do_nhm_cstates)
154 fprintf(stderr, " %%pc6 "); 154 fprintf(stderr, " %%pc6");
155 if (do_snb_cstates) 155 if (do_snb_cstates)
156 fprintf(stderr, " %%pc7 "); 156 fprintf(stderr, " %%pc7");
157 if (extra_msr_offset) 157 if (extra_msr_offset)
158 fprintf(stderr, " MSR 0x%x ", extra_msr_offset); 158 fprintf(stderr, " MSR 0x%x ", extra_msr_offset);
159 159
160 putc('\n', stderr); 160 putc('\n', stderr);
161} 161}
162 162
163void dump_cnt(struct counters *cnt) 163void dump_cnt(struct counters *cnt)
164{ 164{
165 fprintf(stderr, "package: %d ", cnt->pkg); 165 if (!cnt)
166 fprintf(stderr, "core:: %d ", cnt->core); 166 return;
167 fprintf(stderr, "CPU: %d ", cnt->cpu); 167 if (cnt->pkg) fprintf(stderr, "package: %d ", cnt->pkg);
168 fprintf(stderr, "TSC: %016llX\n", cnt->tsc); 168 if (cnt->core) fprintf(stderr, "core:: %d ", cnt->core);
169 fprintf(stderr, "c3: %016llX\n", cnt->c3); 169 if (cnt->cpu) fprintf(stderr, "CPU: %d ", cnt->cpu);
170 fprintf(stderr, "c6: %016llX\n", cnt->c6); 170 if (cnt->tsc) fprintf(stderr, "TSC: %016llX\n", cnt->tsc);
171 fprintf(stderr, "c7: %016llX\n", cnt->c7); 171 if (cnt->c3) fprintf(stderr, "c3: %016llX\n", cnt->c3);
172 fprintf(stderr, "aperf: %016llX\n", cnt->aperf); 172 if (cnt->c6) fprintf(stderr, "c6: %016llX\n", cnt->c6);
173 fprintf(stderr, "pc2: %016llX\n", cnt->pc2); 173 if (cnt->c7) fprintf(stderr, "c7: %016llX\n", cnt->c7);
174 fprintf(stderr, "pc3: %016llX\n", cnt->pc3); 174 if (cnt->aperf) fprintf(stderr, "aperf: %016llX\n", cnt->aperf);
175 fprintf(stderr, "pc6: %016llX\n", cnt->pc6); 175 if (cnt->pc2) fprintf(stderr, "pc2: %016llX\n", cnt->pc2);
176 fprintf(stderr, "pc7: %016llX\n", cnt->pc7); 176 if (cnt->pc3) fprintf(stderr, "pc3: %016llX\n", cnt->pc3);
177 fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, cnt->extra_msr); 177 if (cnt->pc6) fprintf(stderr, "pc6: %016llX\n", cnt->pc6);
178 if (cnt->pc7) fprintf(stderr, "pc7: %016llX\n", cnt->pc7);
179 if (cnt->extra_msr) fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, cnt->extra_msr);
178} 180}
179 181
180void dump_list(struct counters *cnt) 182void dump_list(struct counters *cnt)
@@ -194,14 +196,14 @@ void print_cnt(struct counters *p)
194 /* topology columns, print blanks on 1st (average) line */ 196 /* topology columns, print blanks on 1st (average) line */
195 if (p == cnt_average) { 197 if (p == cnt_average) {
196 if (show_pkg) 198 if (show_pkg)
197 fprintf(stderr, " "); 199 fprintf(stderr, " ");
198 if (show_core) 200 if (show_core)
199 fprintf(stderr, " "); 201 fprintf(stderr, " ");
200 if (show_cpu) 202 if (show_cpu)
201 fprintf(stderr, " "); 203 fprintf(stderr, " ");
202 } else { 204 } else {
203 if (show_pkg) 205 if (show_pkg)
204 fprintf(stderr, "%4d", p->pkg); 206 fprintf(stderr, "%d", p->pkg);
205 if (show_core) 207 if (show_core)
206 fprintf(stderr, "%4d", p->core); 208 fprintf(stderr, "%4d", p->core);
207 if (show_cpu) 209 if (show_cpu)
@@ -241,22 +243,22 @@ void print_cnt(struct counters *p)
241 if (!skip_c1) 243 if (!skip_c1)
242 fprintf(stderr, "%7.2f", 100.0 * p->c1/p->tsc); 244 fprintf(stderr, "%7.2f", 100.0 * p->c1/p->tsc);
243 else 245 else
244 fprintf(stderr, " ****"); 246 fprintf(stderr, " ****");
245 } 247 }
246 if (do_nhm_cstates) 248 if (do_nhm_cstates)
247 fprintf(stderr, "%7.2f", 100.0 * p->c3/p->tsc); 249 fprintf(stderr, " %6.2f", 100.0 * p->c3/p->tsc);
248 if (do_nhm_cstates) 250 if (do_nhm_cstates)
249 fprintf(stderr, "%7.2f", 100.0 * p->c6/p->tsc); 251 fprintf(stderr, " %6.2f", 100.0 * p->c6/p->tsc);
250 if (do_snb_cstates) 252 if (do_snb_cstates)
251 fprintf(stderr, "%7.2f", 100.0 * p->c7/p->tsc); 253 fprintf(stderr, " %6.2f", 100.0 * p->c7/p->tsc);
252 if (do_snb_cstates) 254 if (do_snb_cstates)
253 fprintf(stderr, "%7.2f", 100.0 * p->pc2/p->tsc); 255 fprintf(stderr, " %5.2f", 100.0 * p->pc2/p->tsc);
254 if (do_nhm_cstates) 256 if (do_nhm_cstates)
255 fprintf(stderr, "%7.2f", 100.0 * p->pc3/p->tsc); 257 fprintf(stderr, " %5.2f", 100.0 * p->pc3/p->tsc);
256 if (do_nhm_cstates) 258 if (do_nhm_cstates)
257 fprintf(stderr, "%7.2f", 100.0 * p->pc6/p->tsc); 259 fprintf(stderr, " %5.2f", 100.0 * p->pc6/p->tsc);
258 if (do_snb_cstates) 260 if (do_snb_cstates)
259 fprintf(stderr, "%7.2f", 100.0 * p->pc7/p->tsc); 261 fprintf(stderr, " %5.2f", 100.0 * p->pc7/p->tsc);
260 if (extra_msr_offset) 262 if (extra_msr_offset)
261 fprintf(stderr, " 0x%016llx", p->extra_msr); 263 fprintf(stderr, " 0x%016llx", p->extra_msr);
262 putc('\n', stderr); 264 putc('\n', stderr);
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
index 2618ef2ba31f..33c5c7ee148f 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
@@ -137,7 +137,6 @@ void cmdline(int argc, char **argv)
137void validate_cpuid(void) 137void validate_cpuid(void)
138{ 138{
139 unsigned int eax, ebx, ecx, edx, max_level; 139 unsigned int eax, ebx, ecx, edx, max_level;
140 char brand[16];
141 unsigned int fms, family, model, stepping; 140 unsigned int fms, family, model, stepping;
142 141
143 eax = ebx = ecx = edx = 0; 142 eax = ebx = ecx = edx = 0;
@@ -160,8 +159,8 @@ void validate_cpuid(void)
160 model += ((fms >> 16) & 0xf) << 4; 159 model += ((fms >> 16) & 0xf) << 4;
161 160
162 if (verbose > 1) 161 if (verbose > 1)
163 printf("CPUID %s %d levels family:model:stepping " 162 printf("CPUID %d levels family:model:stepping "
164 "0x%x:%x:%x (%d:%d:%d)\n", brand, max_level, 163 "0x%x:%x:%x (%d:%d:%d)\n", max_level,
165 family, model, stepping, family, model, stepping); 164 family, model, stepping, family, model, stepping);
166 165
167 if (!(edx & (1 << 5))) { 166 if (!(edx & (1 << 5))) {
diff --git a/tools/slub/slabinfo.c b/tools/slub/slabinfo.c
index 516551c9f172..164cbcf61106 100644
--- a/tools/slub/slabinfo.c
+++ b/tools/slub/slabinfo.c
@@ -2,8 +2,9 @@
2 * Slabinfo: Tool to get reports about slabs 2 * Slabinfo: Tool to get reports about slabs
3 * 3 *
4 * (C) 2007 sgi, Christoph Lameter 4 * (C) 2007 sgi, Christoph Lameter
5 * (C) 2011 Linux Foundation, Christoph Lameter
5 * 6 *
6 * Compile by: 7 * Compile with:
7 * 8 *
8 * gcc -o slabinfo slabinfo.c 9 * gcc -o slabinfo slabinfo.c
9 */ 10 */
@@ -39,6 +40,9 @@ struct slabinfo {
39 unsigned long cpuslab_flush, deactivate_full, deactivate_empty; 40 unsigned long cpuslab_flush, deactivate_full, deactivate_empty;
40 unsigned long deactivate_to_head, deactivate_to_tail; 41 unsigned long deactivate_to_head, deactivate_to_tail;
41 unsigned long deactivate_remote_frees, order_fallback; 42 unsigned long deactivate_remote_frees, order_fallback;
43 unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail;
44 unsigned long alloc_node_mismatch, deactivate_bypass;
45 unsigned long cpu_partial_alloc, cpu_partial_free;
42 int numa[MAX_NODES]; 46 int numa[MAX_NODES];
43 int numa_partial[MAX_NODES]; 47 int numa_partial[MAX_NODES];
44} slabinfo[MAX_SLABS]; 48} slabinfo[MAX_SLABS];
@@ -99,7 +103,7 @@ static void fatal(const char *x, ...)
99 103
100static void usage(void) 104static void usage(void)
101{ 105{
102 printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n" 106 printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n"
103 "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" 107 "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
104 "-a|--aliases Show aliases\n" 108 "-a|--aliases Show aliases\n"
105 "-A|--activity Most active slabs first\n" 109 "-A|--activity Most active slabs first\n"
@@ -293,7 +297,7 @@ int line = 0;
293static void first_line(void) 297static void first_line(void)
294{ 298{
295 if (show_activity) 299 if (show_activity)
296 printf("Name Objects Alloc Free %%Fast Fallb O\n"); 300 printf("Name Objects Alloc Free %%Fast Fallb O CmpX UL\n");
297 else 301 else
298 printf("Name Objects Objsize Space " 302 printf("Name Objects Objsize Space "
299 "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n"); 303 "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n");
@@ -379,14 +383,14 @@ static void show_tracking(struct slabinfo *s)
379 printf("\n%s: Kernel object allocation\n", s->name); 383 printf("\n%s: Kernel object allocation\n", s->name);
380 printf("-----------------------------------------------------------------------\n"); 384 printf("-----------------------------------------------------------------------\n");
381 if (read_slab_obj(s, "alloc_calls")) 385 if (read_slab_obj(s, "alloc_calls"))
382 printf(buffer); 386 printf("%s", buffer);
383 else 387 else
384 printf("No Data\n"); 388 printf("No Data\n");
385 389
386 printf("\n%s: Kernel object freeing\n", s->name); 390 printf("\n%s: Kernel object freeing\n", s->name);
387 printf("------------------------------------------------------------------------\n"); 391 printf("------------------------------------------------------------------------\n");
388 if (read_slab_obj(s, "free_calls")) 392 if (read_slab_obj(s, "free_calls"))
389 printf(buffer); 393 printf("%s", buffer);
390 else 394 else
391 printf("No Data\n"); 395 printf("No Data\n");
392 396
@@ -400,7 +404,7 @@ static void ops(struct slabinfo *s)
400 if (read_slab_obj(s, "ops")) { 404 if (read_slab_obj(s, "ops")) {
401 printf("\n%s: kmem_cache operations\n", s->name); 405 printf("\n%s: kmem_cache operations\n", s->name);
402 printf("--------------------------------------------\n"); 406 printf("--------------------------------------------\n");
403 printf(buffer); 407 printf("%s", buffer);
404 } else 408 } else
405 printf("\n%s has no kmem_cache operations\n", s->name); 409 printf("\n%s has no kmem_cache operations\n", s->name);
406} 410}
@@ -452,6 +456,11 @@ static void slab_stats(struct slabinfo *s)
452 s->alloc_from_partial * 100 / total_alloc, 456 s->alloc_from_partial * 100 / total_alloc,
453 s->free_remove_partial * 100 / total_free); 457 s->free_remove_partial * 100 / total_free);
454 458
459 printf("Cpu partial list %8lu %8lu %3lu %3lu\n",
460 s->cpu_partial_alloc, s->cpu_partial_free,
461 s->cpu_partial_alloc * 100 / total_alloc,
462 s->cpu_partial_free * 100 / total_free);
463
455 printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n", 464 printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n",
456 s->deactivate_remote_frees, s->free_frozen, 465 s->deactivate_remote_frees, s->free_frozen,
457 s->deactivate_remote_frees * 100 / total_alloc, 466 s->deactivate_remote_frees * 100 / total_alloc,
@@ -462,19 +471,32 @@ static void slab_stats(struct slabinfo *s)
462 if (s->cpuslab_flush) 471 if (s->cpuslab_flush)
463 printf("Flushes %8lu\n", s->cpuslab_flush); 472 printf("Flushes %8lu\n", s->cpuslab_flush);
464 473
465 if (s->alloc_refill)
466 printf("Refill %8lu\n", s->alloc_refill);
467
468 total = s->deactivate_full + s->deactivate_empty + 474 total = s->deactivate_full + s->deactivate_empty +
469 s->deactivate_to_head + s->deactivate_to_tail; 475 s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass;
470 476
471 if (total) 477 if (total) {
472 printf("Deactivate Full=%lu(%lu%%) Empty=%lu(%lu%%) " 478 printf("\nSlab Deactivation Ocurrences %%\n");
473 "ToHead=%lu(%lu%%) ToTail=%lu(%lu%%)\n", 479 printf("-------------------------------------------------\n");
474 s->deactivate_full, (s->deactivate_full * 100) / total, 480 printf("Slab full %7lu %3lu%%\n",
475 s->deactivate_empty, (s->deactivate_empty * 100) / total, 481 s->deactivate_full, (s->deactivate_full * 100) / total);
476 s->deactivate_to_head, (s->deactivate_to_head * 100) / total, 482 printf("Slab empty %7lu %3lu%%\n",
483 s->deactivate_empty, (s->deactivate_empty * 100) / total);
484 printf("Moved to head of partial list %7lu %3lu%%\n",
485 s->deactivate_to_head, (s->deactivate_to_head * 100) / total);
486 printf("Moved to tail of partial list %7lu %3lu%%\n",
477 s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total); 487 s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total);
488 printf("Deactivation bypass %7lu %3lu%%\n",
489 s->deactivate_bypass, (s->deactivate_bypass * 100) / total);
490 printf("Refilled from foreign frees %7lu %3lu%%\n",
491 s->alloc_refill, (s->alloc_refill * 100) / total);
492 printf("Node mismatch %7lu %3lu%%\n",
493 s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total);
494 }
495
496 if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail)
497 printf("\nCmpxchg_double Looping\n------------------------\n");
498 printf("Locked Cmpxchg Double redos %lu\nUnlocked Cmpxchg Double redos %lu\n",
499 s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail);
478} 500}
479 501
480static void report(struct slabinfo *s) 502static void report(struct slabinfo *s)
@@ -573,12 +595,13 @@ static void slabcache(struct slabinfo *s)
573 total_alloc = s->alloc_fastpath + s->alloc_slowpath; 595 total_alloc = s->alloc_fastpath + s->alloc_slowpath;
574 total_free = s->free_fastpath + s->free_slowpath; 596 total_free = s->free_fastpath + s->free_slowpath;
575 597
576 printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d\n", 598 printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d %4ld %4ld\n",
577 s->name, s->objects, 599 s->name, s->objects,
578 total_alloc, total_free, 600 total_alloc, total_free,
579 total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0, 601 total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0,
580 total_free ? (s->free_fastpath * 100 / total_free) : 0, 602 total_free ? (s->free_fastpath * 100 / total_free) : 0,
581 s->order_fallback, s->order); 603 s->order_fallback, s->order, s->cmpxchg_double_fail,
604 s->cmpxchg_double_cpu_fail);
582 } 605 }
583 else 606 else
584 printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n", 607 printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
@@ -1128,7 +1151,7 @@ static void read_slab_dir(void)
1128 switch (de->d_type) { 1151 switch (de->d_type) {
1129 case DT_LNK: 1152 case DT_LNK:
1130 alias->name = strdup(de->d_name); 1153 alias->name = strdup(de->d_name);
1131 count = readlink(de->d_name, buffer, sizeof(buffer)); 1154 count = readlink(de->d_name, buffer, sizeof(buffer)-1);
1132 1155
1133 if (count < 0) 1156 if (count < 0)
1134 fatal("Cannot read symlink %s\n", de->d_name); 1157 fatal("Cannot read symlink %s\n", de->d_name);
@@ -1190,6 +1213,12 @@ static void read_slab_dir(void)
1190 slab->deactivate_to_tail = get_obj("deactivate_to_tail"); 1213 slab->deactivate_to_tail = get_obj("deactivate_to_tail");
1191 slab->deactivate_remote_frees = get_obj("deactivate_remote_frees"); 1214 slab->deactivate_remote_frees = get_obj("deactivate_remote_frees");
1192 slab->order_fallback = get_obj("order_fallback"); 1215 slab->order_fallback = get_obj("order_fallback");
1216 slab->cmpxchg_double_cpu_fail = get_obj("cmpxchg_double_cpu_fail");
1217 slab->cmpxchg_double_fail = get_obj("cmpxchg_double_fail");
1218 slab->cpu_partial_alloc = get_obj("cpu_partial_alloc");
1219 slab->cpu_partial_free = get_obj("cpu_partial_free");
1220 slab->alloc_node_mismatch = get_obj("alloc_node_mismatch");
1221 slab->deactivate_bypass = get_obj("deactivate_bypass");
1193 chdir(".."); 1222 chdir("..");
1194 if (slab->name[0] == ':') 1223 if (slab->name[0] == ':')
1195 alias_targets++; 1224 alias_targets++;
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index cef28e6632b9..8b4c2535b266 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -27,7 +27,7 @@ $default{"TEST_TYPE"} = "test";
27$default{"BUILD_TYPE"} = "randconfig"; 27$default{"BUILD_TYPE"} = "randconfig";
28$default{"MAKE_CMD"} = "make"; 28$default{"MAKE_CMD"} = "make";
29$default{"TIMEOUT"} = 120; 29$default{"TIMEOUT"} = 120;
30$default{"TMP_DIR"} = "/tmp/ktest"; 30$default{"TMP_DIR"} = "/tmp/ktest/\${MACHINE}";
31$default{"SLEEP_TIME"} = 60; # sleep time between tests 31$default{"SLEEP_TIME"} = 60; # sleep time between tests
32$default{"BUILD_NOCLEAN"} = 0; 32$default{"BUILD_NOCLEAN"} = 0;
33$default{"REBOOT_ON_ERROR"} = 0; 33$default{"REBOOT_ON_ERROR"} = 0;
@@ -41,6 +41,8 @@ $default{"CLEAR_LOG"} = 0;
41$default{"BISECT_MANUAL"} = 0; 41$default{"BISECT_MANUAL"} = 0;
42$default{"BISECT_SKIP"} = 1; 42$default{"BISECT_SKIP"} = 1;
43$default{"SUCCESS_LINE"} = "login:"; 43$default{"SUCCESS_LINE"} = "login:";
44$default{"DETECT_TRIPLE_FAULT"} = 1;
45$default{"NO_INSTALL"} = 0;
44$default{"BOOTED_TIMEOUT"} = 1; 46$default{"BOOTED_TIMEOUT"} = 1;
45$default{"DIE_ON_FAILURE"} = 1; 47$default{"DIE_ON_FAILURE"} = 1;
46$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; 48$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
@@ -62,6 +64,10 @@ my $output_config;
62my $test_type; 64my $test_type;
63my $build_type; 65my $build_type;
64my $build_options; 66my $build_options;
67my $pre_build;
68my $post_build;
69my $pre_build_die;
70my $post_build_die;
65my $reboot_type; 71my $reboot_type;
66my $reboot_script; 72my $reboot_script;
67my $power_cycle; 73my $power_cycle;
@@ -79,14 +85,20 @@ my $grub_number;
79my $target; 85my $target;
80my $make; 86my $make;
81my $post_install; 87my $post_install;
88my $no_install;
82my $noclean; 89my $noclean;
83my $minconfig; 90my $minconfig;
91my $start_minconfig;
92my $start_minconfig_defined;
93my $output_minconfig;
94my $ignore_config;
84my $addconfig; 95my $addconfig;
85my $in_bisect = 0; 96my $in_bisect = 0;
86my $bisect_bad = ""; 97my $bisect_bad = "";
87my $reverse_bisect; 98my $reverse_bisect;
88my $bisect_manual; 99my $bisect_manual;
89my $bisect_skip; 100my $bisect_skip;
101my $config_bisect_good;
90my $in_patchcheck = 0; 102my $in_patchcheck = 0;
91my $run_test; 103my $run_test;
92my $redirect; 104my $redirect;
@@ -98,10 +110,14 @@ my $monitor_cnt = 0;
98my $sleep_time; 110my $sleep_time;
99my $bisect_sleep_time; 111my $bisect_sleep_time;
100my $patchcheck_sleep_time; 112my $patchcheck_sleep_time;
113my $ignore_warnings;
101my $store_failures; 114my $store_failures;
115my $test_name;
102my $timeout; 116my $timeout;
103my $booted_timeout; 117my $booted_timeout;
118my $detect_triplefault;
104my $console; 119my $console;
120my $reboot_success_line;
105my $success_line; 121my $success_line;
106my $stop_after_success; 122my $stop_after_success;
107my $stop_after_failure; 123my $stop_after_failure;
@@ -115,6 +131,13 @@ my $successes = 0;
115my %entered_configs; 131my %entered_configs;
116my %config_help; 132my %config_help;
117my %variable; 133my %variable;
134my %force_config;
135
136# do not force reboots on config problems
137my $no_reboot = 1;
138
139# default variables that can be used
140chomp ($variable{"PWD"} = `pwd`);
118 141
119$config_help{"MACHINE"} = << "EOF" 142$config_help{"MACHINE"} = << "EOF"
120 The machine hostname that you will test. 143 The machine hostname that you will test.
@@ -204,9 +227,30 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF"
204EOF 227EOF
205 ; 228 ;
206 229
230sub read_yn {
231 my ($prompt) = @_;
232
233 my $ans;
234
235 for (;;) {
236 print "$prompt [Y/n] ";
237 $ans = <STDIN>;
238 chomp $ans;
239 if ($ans =~ /^\s*$/) {
240 $ans = "y";
241 }
242 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
243 print "Please answer either 'y' or 'n'.\n";
244 }
245 if ($ans !~ /^y$/i) {
246 return 0;
247 }
248 return 1;
249}
207 250
208sub get_ktest_config { 251sub get_ktest_config {
209 my ($config) = @_; 252 my ($config) = @_;
253 my $ans;
210 254
211 return if (defined($opt{$config})); 255 return if (defined($opt{$config}));
212 256
@@ -220,16 +264,17 @@ sub get_ktest_config {
220 if (defined($default{$config})) { 264 if (defined($default{$config})) {
221 print "\[$default{$config}\] "; 265 print "\[$default{$config}\] ";
222 } 266 }
223 $entered_configs{$config} = <STDIN>; 267 $ans = <STDIN>;
224 $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/; 268 $ans =~ s/^\s*(.*\S)\s*$/$1/;
225 if ($entered_configs{$config} =~ /^\s*$/) { 269 if ($ans =~ /^\s*$/) {
226 if ($default{$config}) { 270 if ($default{$config}) {
227 $entered_configs{$config} = $default{$config}; 271 $ans = $default{$config};
228 } else { 272 } else {
229 print "Your answer can not be blank\n"; 273 print "Your answer can not be blank\n";
230 next; 274 next;
231 } 275 }
232 } 276 }
277 $entered_configs{$config} = process_variables($ans);
233 last; 278 last;
234 } 279 }
235} 280}
@@ -264,7 +309,7 @@ sub get_ktest_configs {
264} 309}
265 310
266sub process_variables { 311sub process_variables {
267 my ($value) = @_; 312 my ($value, $remove_undef) = @_;
268 my $retval = ""; 313 my $retval = "";
269 314
270 # We want to check for '\', and it is just easier 315 # We want to check for '\', and it is just easier
@@ -282,6 +327,10 @@ sub process_variables {
282 $retval = "$retval$begin"; 327 $retval = "$retval$begin";
283 if (defined($variable{$var})) { 328 if (defined($variable{$var})) {
284 $retval = "$retval$variable{$var}"; 329 $retval = "$retval$variable{$var}";
330 } elsif (defined($remove_undef) && $remove_undef) {
331 # for if statements, any variable that is not defined,
332 # we simple convert to 0
333 $retval = "${retval}0";
285 } else { 334 } else {
286 # put back the origin piece. 335 # put back the origin piece.
287 $retval = "$retval\$\{$var\}"; 336 $retval = "$retval\$\{$var\}";
@@ -297,10 +346,17 @@ sub process_variables {
297} 346}
298 347
299sub set_value { 348sub set_value {
300 my ($lvalue, $rvalue) = @_; 349 my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
301 350
302 if (defined($opt{$lvalue})) { 351 if (defined($opt{$lvalue})) {
303 die "Error: Option $lvalue defined more than once!\n"; 352 if (!$override || defined(${$overrides}{$lvalue})) {
353 my $extra = "";
354 if ($override) {
355 $extra = "In the same override section!\n";
356 }
357 die "$name: $.: Option $lvalue defined more than once!\n$extra";
358 }
359 ${$overrides}{$lvalue} = $rvalue;
304 } 360 }
305 if ($rvalue =~ /^\s*$/) { 361 if ($rvalue =~ /^\s*$/) {
306 delete $opt{$lvalue}; 362 delete $opt{$lvalue};
@@ -321,84 +377,274 @@ sub set_variable {
321 } 377 }
322} 378}
323 379
324sub read_config { 380sub process_compare {
325 my ($config) = @_; 381 my ($lval, $cmp, $rval) = @_;
382
383 # remove whitespace
384
385 $lval =~ s/^\s*//;
386 $lval =~ s/\s*$//;
387
388 $rval =~ s/^\s*//;
389 $rval =~ s/\s*$//;
390
391 if ($cmp eq "==") {
392 return $lval eq $rval;
393 } elsif ($cmp eq "!=") {
394 return $lval ne $rval;
395 }
396
397 my $statement = "$lval $cmp $rval";
398 my $ret = eval $statement;
399
400 # $@ stores error of eval
401 if ($@) {
402 return -1;
403 }
404
405 return $ret;
406}
407
408sub value_defined {
409 my ($val) = @_;
410
411 return defined($variable{$2}) ||
412 defined($opt{$2});
413}
414
415my $d = 0;
416sub process_expression {
417 my ($name, $val) = @_;
418
419 my $c = $d++;
420
421 while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
422 my $express = $1;
423
424 if (process_expression($name, $express)) {
425 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
426 } else {
427 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
428 }
429 }
430
431 $d--;
432 my $OR = "\\|\\|";
433 my $AND = "\\&\\&";
434
435 while ($val =~ s/^(.*?)($OR|$AND)//) {
436 my $express = $1;
437 my $op = $2;
326 438
327 open(IN, $config) || die "can't read file $config"; 439 if (process_expression($name, $express)) {
440 if ($op eq "||") {
441 return 1;
442 }
443 } else {
444 if ($op eq "&&") {
445 return 0;
446 }
447 }
448 }
449
450 if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
451 my $ret = process_compare($1, $2, $3);
452 if ($ret < 0) {
453 die "$name: $.: Unable to process comparison\n";
454 }
455 return $ret;
456 }
457
458 if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
459 if (defined $1) {
460 return !value_defined($2);
461 } else {
462 return value_defined($2);
463 }
464 }
465
466 if ($val =~ /^\s*0\s*$/) {
467 return 0;
468 } elsif ($val =~ /^\s*\d+\s*$/) {
469 return 1;
470 }
471
472 die ("$name: $.: Undefined content $val in if statement\n");
473}
474
475sub process_if {
476 my ($name, $value) = @_;
477
478 # Convert variables and replace undefined ones with 0
479 my $val = process_variables($value, 1);
480 my $ret = process_expression $name, $val;
481
482 return $ret;
483}
484
485sub __read_config {
486 my ($config, $current_test_num) = @_;
487
488 my $in;
489 open($in, $config) || die "can't read file $config";
328 490
329 my $name = $config; 491 my $name = $config;
330 $name =~ s,.*/(.*),$1,; 492 $name =~ s,.*/(.*),$1,;
331 493
332 my $test_num = 0; 494 my $test_num = $$current_test_num;
333 my $default = 1; 495 my $default = 1;
334 my $repeat = 1; 496 my $repeat = 1;
335 my $num_tests_set = 0; 497 my $num_tests_set = 0;
336 my $skip = 0; 498 my $skip = 0;
337 my $rest; 499 my $rest;
500 my $line;
501 my $test_case = 0;
502 my $if = 0;
503 my $if_set = 0;
504 my $override = 0;
338 505
339 while (<IN>) { 506 my %overrides;
507
508 while (<$in>) {
340 509
341 # ignore blank lines and comments 510 # ignore blank lines and comments
342 next if (/^\s*$/ || /\s*\#/); 511 next if (/^\s*$/ || /\s*\#/);
343 512
344 if (/^\s*TEST_START(.*)/) { 513 if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
345 514
346 $rest = $1; 515 my $type = $1;
516 $rest = $2;
517 $line = $2;
347 518
348 if ($num_tests_set) { 519 my $old_test_num;
349 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 520 my $old_repeat;
350 } 521 $override = 0;
351 522
352 my $old_test_num = $test_num; 523 if ($type eq "TEST_START") {
353 my $old_repeat = $repeat;
354 524
355 $test_num += $repeat; 525 if ($num_tests_set) {
356 $default = 0; 526 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
357 $repeat = 1; 527 }
528
529 $old_test_num = $test_num;
530 $old_repeat = $repeat;
531
532 $test_num += $repeat;
533 $default = 0;
534 $repeat = 1;
535 } else {
536 $default = 1;
537 }
358 538
359 if ($rest =~ /\s+SKIP(.*)/) { 539 # If SKIP is anywhere in the line, the command will be skipped
360 $rest = $1; 540 if ($rest =~ s/\s+SKIP\b//) {
361 $skip = 1; 541 $skip = 1;
362 } else { 542 } else {
543 $test_case = 1;
363 $skip = 0; 544 $skip = 0;
364 } 545 }
365 546
366 if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { 547 if ($rest =~ s/\sELSE\b//) {
367 $repeat = $1; 548 if (!$if) {
368 $rest = $2; 549 die "$name: $.: ELSE found with out matching IF section\n$_";
369 $repeat_tests{"$test_num"} = $repeat; 550 }
551 $if = 0;
552
553 if ($if_set) {
554 $skip = 1;
555 } else {
556 $skip = 0;
557 }
558 }
559
560 if ($rest =~ s/\sIF\s+(.*)//) {
561 if (process_if($name, $1)) {
562 $if_set = 1;
563 } else {
564 $skip = 1;
565 }
566 $if = 1;
567 } else {
568 $if = 0;
569 $if_set = 0;
370 } 570 }
371 571
372 if ($rest =~ /\s+SKIP(.*)/) { 572 if (!$skip) {
373 $rest = $1; 573 if ($type eq "TEST_START") {
374 $skip = 1; 574 if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
575 $repeat = $1;
576 $repeat_tests{"$test_num"} = $repeat;
577 }
578 } elsif ($rest =~ s/\sOVERRIDE\b//) {
579 # DEFAULT only
580 $override = 1;
581 # Clear previous overrides
582 %overrides = ();
583 }
375 } 584 }
376 585
377 if ($rest !~ /^\s*$/) { 586 if (!$skip && $rest !~ /^\s*$/) {
378 die "$name: $.: Gargbage found after TEST_START\n$_"; 587 die "$name: $.: Gargbage found after $type\n$_";
379 } 588 }
380 589
381 if ($skip) { 590 if ($skip && $type eq "TEST_START") {
382 $test_num = $old_test_num; 591 $test_num = $old_test_num;
383 $repeat = $old_repeat; 592 $repeat = $old_repeat;
384 } 593 }
385 594
386 } elsif (/^\s*DEFAULTS(.*)$/) { 595 } elsif (/^\s*ELSE\b(.*)$/) {
387 $default = 1; 596 if (!$if) {
388 597 die "$name: $.: ELSE found with out matching IF section\n$_";
598 }
389 $rest = $1; 599 $rest = $1;
390 600 if ($if_set) {
391 if ($rest =~ /\s+SKIP(.*)/) {
392 $rest = $1;
393 $skip = 1; 601 $skip = 1;
602 $rest = "";
394 } else { 603 } else {
395 $skip = 0; 604 $skip = 0;
605
606 if ($rest =~ /\sIF\s+(.*)/) {
607 # May be a ELSE IF section.
608 if (!process_if($name, $1)) {
609 $skip = 1;
610 }
611 $rest = "";
612 } else {
613 $if = 0;
614 }
396 } 615 }
397 616
398 if ($rest !~ /^\s*$/) { 617 if ($rest !~ /^\s*$/) {
399 die "$name: $.: Gargbage found after DEFAULTS\n$_"; 618 die "$name: $.: Gargbage found after DEFAULTS\n$_";
400 } 619 }
401 620
621 } elsif (/^\s*INCLUDE\s+(\S+)/) {
622
623 next if ($skip);
624
625 if (!$default) {
626 die "$name: $.: INCLUDE can only be done in default sections\n$_";
627 }
628
629 my $file = process_variables($1);
630
631 if ($file !~ m,^/,) {
632 # check the path of the config file first
633 if ($config =~ m,(.*)/,) {
634 if (-f "$1/$file") {
635 $file = "$1/$file";
636 }
637 }
638 }
639
640 if ( ! -r $file ) {
641 die "$name: $.: Can't read file $file\n$_";
642 }
643
644 if (__read_config($file, \$test_num)) {
645 $test_case = 1;
646 }
647
402 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 648 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
403 649
404 next if ($skip); 650 next if ($skip);
@@ -424,10 +670,10 @@ sub read_config {
424 } 670 }
425 671
426 if ($default || $lvalue =~ /\[\d+\]$/) { 672 if ($default || $lvalue =~ /\[\d+\]$/) {
427 set_value($lvalue, $rvalue); 673 set_value($lvalue, $rvalue, $override, \%overrides, $name);
428 } else { 674 } else {
429 my $val = "$lvalue\[$test_num\]"; 675 my $val = "$lvalue\[$test_num\]";
430 set_value($val, $rvalue); 676 set_value($val, $rvalue, $override, \%overrides, $name);
431 677
432 if ($repeat > 1) { 678 if ($repeat > 1) {
433 $repeats{$val} = $repeat; 679 $repeats{$val} = $repeat;
@@ -454,16 +700,38 @@ sub read_config {
454 } 700 }
455 } 701 }
456 702
457 close(IN);
458
459 if ($test_num) { 703 if ($test_num) {
460 $test_num += $repeat - 1; 704 $test_num += $repeat - 1;
461 $opt{"NUM_TESTS"} = $test_num; 705 $opt{"NUM_TESTS"} = $test_num;
462 } 706 }
463 707
708 close($in);
709
710 $$current_test_num = $test_num;
711
712 return $test_case;
713}
714
715sub read_config {
716 my ($config) = @_;
717
718 my $test_case;
719 my $test_num = 0;
720
721 $test_case = __read_config $config, \$test_num;
722
464 # make sure we have all mandatory configs 723 # make sure we have all mandatory configs
465 get_ktest_configs; 724 get_ktest_configs;
466 725
726 # was a test specified?
727 if (!$test_case) {
728 print "No test case specified.\n";
729 print "What test case would you like to run?\n";
730 my $ans = <STDIN>;
731 chomp $ans;
732 $default{"TEST_TYPE"} = $ans;
733 }
734
467 # set any defaults 735 # set any defaults
468 736
469 foreach my $default (keys %default) { 737 foreach my $default (keys %default) {
@@ -473,6 +741,85 @@ sub read_config {
473 } 741 }
474} 742}
475 743
744sub __eval_option {
745 my ($option, $i) = @_;
746
747 # Add space to evaluate the character before $
748 $option = " $option";
749 my $retval = "";
750 my $repeated = 0;
751 my $parent = 0;
752
753 foreach my $test (keys %repeat_tests) {
754 if ($i >= $test &&
755 $i < $test + $repeat_tests{$test}) {
756
757 $repeated = 1;
758 $parent = $test;
759 last;
760 }
761 }
762
763 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
764 my $start = $1;
765 my $var = $2;
766 my $end = $3;
767
768 # Append beginning of line
769 $retval = "$retval$start";
770
771 # If the iteration option OPT[$i] exists, then use that.
772 # otherwise see if the default OPT (without [$i]) exists.
773
774 my $o = "$var\[$i\]";
775 my $parento = "$var\[$parent\]";
776
777 if (defined($opt{$o})) {
778 $o = $opt{$o};
779 $retval = "$retval$o";
780 } elsif ($repeated && defined($opt{$parento})) {
781 $o = $opt{$parento};
782 $retval = "$retval$o";
783 } elsif (defined($opt{$var})) {
784 $o = $opt{$var};
785 $retval = "$retval$o";
786 } else {
787 $retval = "$retval\$\{$var\}";
788 }
789
790 $option = $end;
791 }
792
793 $retval = "$retval$option";
794
795 $retval =~ s/^ //;
796
797 return $retval;
798}
799
800sub eval_option {
801 my ($option, $i) = @_;
802
803 my $prev = "";
804
805 # Since an option can evaluate to another option,
806 # keep iterating until we do not evaluate any more
807 # options.
808 my $r = 0;
809 while ($prev ne $option) {
810 # Check for recursive evaluations.
811 # 100 deep should be more than enough.
812 if ($r++ > 100) {
813 die "Over 100 evaluations accurred with $option\n" .
814 "Check for recursive variables\n";
815 }
816 $prev = $option;
817 $option = __eval_option($option, $i);
818 }
819
820 return $option;
821}
822
476sub _logit { 823sub _logit {
477 if (defined($opt{"LOG_FILE"})) { 824 if (defined($opt{"LOG_FILE"})) {
478 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 825 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
@@ -495,8 +842,20 @@ sub doprint {
495} 842}
496 843
497sub run_command; 844sub run_command;
845sub start_monitor;
846sub end_monitor;
847sub wait_for_monitor;
498 848
499sub reboot { 849sub reboot {
850 my ($time) = @_;
851
852 if (defined($time)) {
853 start_monitor;
854 # flush out current monitor
855 # May contain the reboot success line
856 wait_for_monitor 1;
857 }
858
500 # try to reboot normally 859 # try to reboot normally
501 if (run_command $reboot) { 860 if (run_command $reboot) {
502 if (defined($powercycle_after_reboot)) { 861 if (defined($powercycle_after_reboot)) {
@@ -507,12 +866,17 @@ sub reboot {
507 # nope? power cycle it. 866 # nope? power cycle it.
508 run_command "$power_cycle"; 867 run_command "$power_cycle";
509 } 868 }
869
870 if (defined($time)) {
871 wait_for_monitor($time, $reboot_success_line);
872 end_monitor;
873 }
510} 874}
511 875
512sub do_not_reboot { 876sub do_not_reboot {
513 my $i = $iteration; 877 my $i = $iteration;
514 878
515 return $test_type eq "build" || 879 return $test_type eq "build" || $no_reboot ||
516 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 880 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
517 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 881 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
518} 882}
@@ -585,16 +949,29 @@ sub end_monitor {
585} 949}
586 950
587sub wait_for_monitor { 951sub wait_for_monitor {
588 my ($time) = @_; 952 my ($time, $stop) = @_;
953 my $full_line = "";
589 my $line; 954 my $line;
955 my $booted = 0;
590 956
591 doprint "** Wait for monitor to settle down **\n"; 957 doprint "** Wait for monitor to settle down **\n";
592 958
593 # read the monitor and wait for the system to calm down 959 # read the monitor and wait for the system to calm down
594 do { 960 while (!$booted) {
595 $line = wait_for_input($monitor_fp, $time); 961 $line = wait_for_input($monitor_fp, $time);
596 print "$line" if (defined($line)); 962 last if (!defined($line));
597 } while (defined($line)); 963 print "$line";
964 $full_line .= $line;
965
966 if (defined($stop) && $full_line =~ /$stop/) {
967 doprint "wait for monitor detected $stop\n";
968 $booted = 1;
969 }
970
971 if ($line =~ /\n/) {
972 $full_line = "";
973 }
974 }
598 print "** Monitor flushed **\n"; 975 print "** Monitor flushed **\n";
599} 976}
600 977
@@ -611,15 +988,18 @@ sub fail {
611 # no need to reboot for just building. 988 # no need to reboot for just building.
612 if (!do_not_reboot) { 989 if (!do_not_reboot) {
613 doprint "REBOOTING\n"; 990 doprint "REBOOTING\n";
614 reboot; 991 reboot $sleep_time;
615 start_monitor; 992 }
616 wait_for_monitor $sleep_time; 993
617 end_monitor; 994 my $name = "";
995
996 if (defined($test_name)) {
997 $name = " ($test_name)";
618 } 998 }
619 999
620 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1000 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
621 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1001 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
622 doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n"; 1002 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
623 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1003 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
624 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1004 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
625 1005
@@ -740,9 +1120,12 @@ sub get_grub_index {
740 open(IN, "$ssh_grub |") 1120 open(IN, "$ssh_grub |")
741 or die "unable to get menu.lst"; 1121 or die "unable to get menu.lst";
742 1122
1123 my $found = 0;
1124
743 while (<IN>) { 1125 while (<IN>) {
744 if (/^\s*title\s+$grub_menu\s*$/) { 1126 if (/^\s*title\s+$grub_menu\s*$/) {
745 $grub_number++; 1127 $grub_number++;
1128 $found = 1;
746 last; 1129 last;
747 } elsif (/^\s*title\s/) { 1130 } elsif (/^\s*title\s/) {
748 $grub_number++; 1131 $grub_number++;
@@ -751,7 +1134,7 @@ sub get_grub_index {
751 close(IN); 1134 close(IN);
752 1135
753 die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 1136 die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
754 if ($grub_number < 0); 1137 if (!$found);
755 doprint "$grub_number\n"; 1138 doprint "$grub_number\n";
756} 1139}
757 1140
@@ -788,7 +1171,8 @@ sub wait_for_input
788 1171
789sub reboot_to { 1172sub reboot_to {
790 if ($reboot_type eq "grub") { 1173 if ($reboot_type eq "grub") {
791 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'"; 1174 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1175 reboot;
792 return; 1176 return;
793 } 1177 }
794 1178
@@ -836,17 +1220,35 @@ sub monitor {
836 my $failure_start; 1220 my $failure_start;
837 my $monitor_start = time; 1221 my $monitor_start = time;
838 my $done = 0; 1222 my $done = 0;
1223 my $version_found = 0;
839 1224
840 while (!$done) { 1225 while (!$done) {
841 1226
842 if ($booted) { 1227 if ($bug && defined($stop_after_failure) &&
1228 $stop_after_failure >= 0) {
1229 my $time = $stop_after_failure - (time - $failure_start);
1230 $line = wait_for_input($monitor_fp, $time);
1231 if (!defined($line)) {
1232 doprint "bug timed out after $booted_timeout seconds\n";
1233 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1234 last;
1235 }
1236 } elsif ($booted) {
843 $line = wait_for_input($monitor_fp, $booted_timeout); 1237 $line = wait_for_input($monitor_fp, $booted_timeout);
1238 if (!defined($line)) {
1239 my $s = $booted_timeout == 1 ? "" : "s";
1240 doprint "Successful boot found: break after $booted_timeout second$s\n";
1241 last;
1242 }
844 } else { 1243 } else {
845 $line = wait_for_input($monitor_fp); 1244 $line = wait_for_input($monitor_fp);
1245 if (!defined($line)) {
1246 my $s = $timeout == 1 ? "" : "s";
1247 doprint "Timed out after $timeout second$s\n";
1248 last;
1249 }
846 } 1250 }
847 1251
848 last if (!defined($line));
849
850 doprint $line; 1252 doprint $line;
851 print DMESG $line; 1253 print DMESG $line;
852 1254
@@ -896,6 +1298,22 @@ sub monitor {
896 $bug = 1; 1298 $bug = 1;
897 } 1299 }
898 1300
1301 # Detect triple faults by testing the banner
1302 if ($full_line =~ /\bLinux version (\S+).*\n/) {
1303 if ($1 eq $version) {
1304 $version_found = 1;
1305 } elsif ($version_found && $detect_triplefault) {
1306 # We already booted into the kernel we are testing,
1307 # but now we booted into another kernel?
1308 # Consider this a triple fault.
1309 doprint "Aleady booted in Linux kernel $version, but now\n";
1310 doprint "we booted into Linux kernel $1.\n";
1311 doprint "Assuming that this is a triple fault.\n";
1312 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1313 last;
1314 }
1315 }
1316
899 if ($line =~ /\n/) { 1317 if ($line =~ /\n/) {
900 $full_line = ""; 1318 $full_line = "";
901 } 1319 }
@@ -923,8 +1341,20 @@ sub monitor {
923 return 1; 1341 return 1;
924} 1342}
925 1343
1344sub do_post_install {
1345
1346 return if (!defined($post_install));
1347
1348 my $cp_post_install = $post_install;
1349 $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1350 run_command "$cp_post_install" or
1351 dodie "Failed to run post install";
1352}
1353
926sub install { 1354sub install {
927 1355
1356 return if ($no_install);
1357
928 run_scp "$outputdir/$build_target", "$target_image" or 1358 run_scp "$outputdir/$build_target", "$target_image" or
929 dodie "failed to copy image"; 1359 dodie "failed to copy image";
930 1360
@@ -942,6 +1372,7 @@ sub install {
942 close(IN); 1372 close(IN);
943 1373
944 if (!$install_mods) { 1374 if (!$install_mods) {
1375 do_post_install;
945 doprint "No modules needed\n"; 1376 doprint "No modules needed\n";
946 return; 1377 return;
947 } 1378 }
@@ -964,17 +1395,34 @@ sub install {
964 1395
965 unlink "$tmpdir/$modtar"; 1396 unlink "$tmpdir/$modtar";
966 1397
967 run_ssh "'(cd / && tar xf /tmp/$modtar)'" or 1398 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
968 dodie "failed to tar modules"; 1399 dodie "failed to tar modules";
969 1400
970 run_ssh "rm -f /tmp/$modtar"; 1401 run_ssh "rm -f /tmp/$modtar";
971 1402
972 return if (!defined($post_install)); 1403 do_post_install;
1404}
973 1405
974 my $cp_post_install = $post_install; 1406sub get_version {
975 $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; 1407 # get the release name
976 run_command "$cp_post_install" or 1408 doprint "$make kernelrelease ... ";
977 dodie "Failed to run post install"; 1409 $version = `$make kernelrelease | tail -1`;
1410 chomp($version);
1411 doprint "$version\n";
1412}
1413
1414sub start_monitor_and_boot {
1415 # Make sure the stable kernel has finished booting
1416 start_monitor;
1417 wait_for_monitor 5;
1418 end_monitor;
1419
1420 get_grub_index;
1421 get_version;
1422 install;
1423
1424 start_monitor;
1425 return monitor;
978} 1426}
979 1427
980sub check_buildlog { 1428sub check_buildlog {
@@ -1009,24 +1457,88 @@ sub check_buildlog {
1009 return 1; 1457 return 1;
1010} 1458}
1011 1459
1460sub apply_min_config {
1461 my $outconfig = "$output_config.new";
1462
1463 # Read the config file and remove anything that
1464 # is in the force_config hash (from minconfig and others)
1465 # then add the force config back.
1466
1467 doprint "Applying minimum configurations into $output_config.new\n";
1468
1469 open (OUT, ">$outconfig") or
1470 dodie "Can't create $outconfig";
1471
1472 if (-f $output_config) {
1473 open (IN, $output_config) or
1474 dodie "Failed to open $output_config";
1475 while (<IN>) {
1476 if (/^(# )?(CONFIG_[^\s=]*)/) {
1477 next if (defined($force_config{$2}));
1478 }
1479 print OUT;
1480 }
1481 close IN;
1482 }
1483 foreach my $config (keys %force_config) {
1484 print OUT "$force_config{$config}\n";
1485 }
1486 close OUT;
1487
1488 run_command "mv $outconfig $output_config";
1489}
1490
1012sub make_oldconfig { 1491sub make_oldconfig {
1013 my ($defconfig) = @_;
1014 1492
1015 if (!run_command "$defconfig $make oldnoconfig") { 1493 my @force_list = keys %force_config;
1494
1495 if ($#force_list >= 0) {
1496 apply_min_config;
1497 }
1498
1499 if (!run_command "$make oldnoconfig") {
1016 # Perhaps oldnoconfig doesn't exist in this version of the kernel 1500 # Perhaps oldnoconfig doesn't exist in this version of the kernel
1017 # try a yes '' | oldconfig 1501 # try a yes '' | oldconfig
1018 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1502 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1019 run_command "yes '' | $defconfig $make oldconfig" or 1503 run_command "yes '' | $make oldconfig" or
1020 dodie "failed make config oldconfig"; 1504 dodie "failed make config oldconfig";
1021 } 1505 }
1022} 1506}
1023 1507
1508# read a config file and use this to force new configs.
1509sub load_force_config {
1510 my ($config) = @_;
1511
1512 open(IN, $config) or
1513 dodie "failed to read $config";
1514 while (<IN>) {
1515 chomp;
1516 if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1517 $force_config{$1} = $_;
1518 } elsif (/^# (CONFIG_\S*) is not set/) {
1519 $force_config{$1} = $_;
1520 }
1521 }
1522 close IN;
1523}
1524
1024sub build { 1525sub build {
1025 my ($type) = @_; 1526 my ($type) = @_;
1026 my $defconfig = "";
1027 1527
1028 unlink $buildlog; 1528 unlink $buildlog;
1029 1529
1530 # Failed builds should not reboot the target
1531 my $save_no_reboot = $no_reboot;
1532 $no_reboot = 1;
1533
1534 if (defined($pre_build)) {
1535 my $ret = run_command $pre_build;
1536 if (!$ret && defined($pre_build_die) &&
1537 $pre_build_die) {
1538 dodie "failed to pre_build\n";
1539 }
1540 }
1541
1030 if ($type =~ /^useconfig:(.*)/) { 1542 if ($type =~ /^useconfig:(.*)/) {
1031 run_command "cp $1 $output_config" or 1543 run_command "cp $1 $output_config" or
1032 dodie "could not copy $1 to .config"; 1544 dodie "could not copy $1 to .config";
@@ -1041,15 +1553,15 @@ sub build {
1041 # allow for empty configs 1553 # allow for empty configs
1042 run_command "touch $output_config"; 1554 run_command "touch $output_config";
1043 1555
1044 run_command "mv $output_config $outputdir/config_temp" or 1556 if (!$noclean) {
1045 dodie "moving .config"; 1557 run_command "mv $output_config $outputdir/config_temp" or
1558 dodie "moving .config";
1046 1559
1047 if (!$noclean && !run_command "$make mrproper") { 1560 run_command "$make mrproper" or dodie "make mrproper";
1048 dodie "make mrproper";
1049 }
1050 1561
1051 run_command "mv $outputdir/config_temp $output_config" or 1562 run_command "mv $outputdir/config_temp $output_config" or
1052 dodie "moving config_temp"; 1563 dodie "moving config_temp";
1564 }
1053 1565
1054 } elsif (!$noclean) { 1566 } elsif (!$noclean) {
1055 unlink "$output_config"; 1567 unlink "$output_config";
@@ -1063,24 +1575,38 @@ sub build {
1063 close(OUT); 1575 close(OUT);
1064 1576
1065 if (defined($minconfig)) { 1577 if (defined($minconfig)) {
1066 $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 1578 load_force_config($minconfig);
1067 } 1579 }
1068 1580
1069 if ($type eq "oldnoconfig") { 1581 if ($type ne "oldnoconfig") {
1070 make_oldconfig $defconfig; 1582 run_command "$make $type" or
1071 } else {
1072 run_command "$defconfig $make $type" or
1073 dodie "failed make config"; 1583 dodie "failed make config";
1074 } 1584 }
1585 # Run old config regardless, to enforce min configurations
1586 make_oldconfig;
1075 1587
1076 $redirect = "$buildlog"; 1588 $redirect = "$buildlog";
1077 if (!run_command "$make $build_options") { 1589 my $build_ret = run_command "$make $build_options";
1078 undef $redirect; 1590 undef $redirect;
1591
1592 if (defined($post_build)) {
1593 my $ret = run_command $post_build;
1594 if (!$ret && defined($post_build_die) &&
1595 $post_build_die) {
1596 dodie "failed to post_build\n";
1597 }
1598 }
1599
1600 if (!$build_ret) {
1079 # bisect may need this to pass 1601 # bisect may need this to pass
1080 return 0 if ($in_bisect); 1602 if ($in_bisect) {
1603 $no_reboot = $save_no_reboot;
1604 return 0;
1605 }
1081 fail "failed build" and return 0; 1606 fail "failed build" and return 0;
1082 } 1607 }
1083 undef $redirect; 1608
1609 $no_reboot = $save_no_reboot;
1084 1610
1085 return 1; 1611 return 1;
1086} 1612}
@@ -1102,29 +1628,24 @@ sub success {
1102 1628
1103 $successes++; 1629 $successes++;
1104 1630
1631 my $name = "";
1632
1633 if (defined($test_name)) {
1634 $name = " ($test_name)";
1635 }
1636
1105 doprint "\n\n*******************************************\n"; 1637 doprint "\n\n*******************************************\n";
1106 doprint "*******************************************\n"; 1638 doprint "*******************************************\n";
1107 doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n"; 1639 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n";
1108 doprint "*******************************************\n"; 1640 doprint "*******************************************\n";
1109 doprint "*******************************************\n"; 1641 doprint "*******************************************\n";
1110 1642
1111 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1643 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1112 doprint "Reboot and wait $sleep_time seconds\n"; 1644 doprint "Reboot and wait $sleep_time seconds\n";
1113 reboot; 1645 reboot $sleep_time;
1114 start_monitor;
1115 wait_for_monitor $sleep_time;
1116 end_monitor;
1117 } 1646 }
1118} 1647}
1119 1648
1120sub get_version {
1121 # get the release name
1122 doprint "$make kernelrelease ... ";
1123 $version = `$make kernelrelease | tail -1`;
1124 chomp($version);
1125 doprint "$version\n";
1126}
1127
1128sub answer_bisect { 1649sub answer_bisect {
1129 for (;;) { 1650 for (;;) {
1130 doprint "Pass or fail? [p/f]"; 1651 doprint "Pass or fail? [p/f]";
@@ -1262,10 +1783,7 @@ sub run_git_bisect {
1262 1783
1263sub bisect_reboot { 1784sub bisect_reboot {
1264 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 1785 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
1265 reboot; 1786 reboot $bisect_sleep_time;
1266 start_monitor;
1267 wait_for_monitor $bisect_sleep_time;
1268 end_monitor;
1269} 1787}
1270 1788
1271# returns 1 on success, 0 on failure, -1 on skip 1789# returns 1 on success, 0 on failure, -1 on skip
@@ -1289,12 +1807,7 @@ sub run_bisect_test {
1289 dodie "Failed on build" if $failed; 1807 dodie "Failed on build" if $failed;
1290 1808
1291 # Now boot the box 1809 # Now boot the box
1292 get_grub_index; 1810 start_monitor_and_boot or $failed = 1;
1293 get_version;
1294 install;
1295
1296 start_monitor;
1297 monitor or $failed = 1;
1298 1811
1299 if ($type ne "boot") { 1812 if ($type ne "boot") {
1300 if ($failed && $bisect_skip) { 1813 if ($failed && $bisect_skip) {
@@ -1473,21 +1986,27 @@ my %null_config;
1473 1986
1474my %dependency; 1987my %dependency;
1475 1988
1476sub process_config_ignore { 1989sub assign_configs {
1477 my ($config) = @_; 1990 my ($hash, $config) = @_;
1478 1991
1479 open (IN, $config) 1992 open (IN, $config)
1480 or dodie "Failed to read $config"; 1993 or dodie "Failed to read $config";
1481 1994
1482 while (<IN>) { 1995 while (<IN>) {
1483 if (/^((CONFIG\S*)=.*)/) { 1996 if (/^((CONFIG\S*)=.*)/) {
1484 $config_ignore{$2} = $1; 1997 ${$hash}{$2} = $1;
1485 } 1998 }
1486 } 1999 }
1487 2000
1488 close(IN); 2001 close(IN);
1489} 2002}
1490 2003
2004sub process_config_ignore {
2005 my ($config) = @_;
2006
2007 assign_configs \%config_ignore, $config;
2008}
2009
1491sub read_current_config { 2010sub read_current_config {
1492 my ($config_ref) = @_; 2011 my ($config_ref) = @_;
1493 2012
@@ -1546,7 +2065,7 @@ sub create_config {
1546 close(OUT); 2065 close(OUT);
1547 2066
1548# exit; 2067# exit;
1549 make_oldconfig ""; 2068 make_oldconfig;
1550} 2069}
1551 2070
1552sub compare_configs { 2071sub compare_configs {
@@ -1718,6 +2237,10 @@ sub config_bisect {
1718 2237
1719 my $tmpconfig = "$tmpdir/use_config"; 2238 my $tmpconfig = "$tmpdir/use_config";
1720 2239
2240 if (defined($config_bisect_good)) {
2241 process_config_ignore $config_bisect_good;
2242 }
2243
1721 # Make the file with the bad config and the min config 2244 # Make the file with the bad config and the min config
1722 if (defined($minconfig)) { 2245 if (defined($minconfig)) {
1723 # read the min config for things to ignore 2246 # read the min config for things to ignore
@@ -1727,15 +2250,8 @@ sub config_bisect {
1727 unlink $tmpconfig; 2250 unlink $tmpconfig;
1728 } 2251 }
1729 2252
1730 # Add other configs
1731 if (defined($addconfig)) {
1732 run_command "cat $addconfig >> $tmpconfig" or
1733 dodie "failed to append $addconfig";
1734 }
1735
1736 my $defconfig = "";
1737 if (-f $tmpconfig) { 2253 if (-f $tmpconfig) {
1738 $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig"; 2254 load_force_config($tmpconfig);
1739 process_config_ignore $tmpconfig; 2255 process_config_ignore $tmpconfig;
1740 } 2256 }
1741 2257
@@ -1755,8 +2271,8 @@ sub config_bisect {
1755 } 2271 }
1756 close(IN); 2272 close(IN);
1757 2273
1758 # Now run oldconfig with the minconfig (and addconfigs) 2274 # Now run oldconfig with the minconfig
1759 make_oldconfig $defconfig; 2275 make_oldconfig;
1760 2276
1761 # check to see what we lost (or gained) 2277 # check to see what we lost (or gained)
1762 open (IN, $output_config) 2278 open (IN, $output_config)
@@ -1830,10 +2346,7 @@ sub config_bisect {
1830 2346
1831sub patchcheck_reboot { 2347sub patchcheck_reboot {
1832 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 2348 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
1833 reboot; 2349 reboot $patchcheck_sleep_time;
1834 start_monitor;
1835 wait_for_monitor $patchcheck_sleep_time;
1836 end_monitor;
1837} 2350}
1838 2351
1839sub patchcheck { 2352sub patchcheck {
@@ -1882,6 +2395,13 @@ sub patchcheck {
1882 @list = reverse @list; 2395 @list = reverse @list;
1883 2396
1884 my $save_clean = $noclean; 2397 my $save_clean = $noclean;
2398 my %ignored_warnings;
2399
2400 if (defined($ignore_warnings)) {
2401 foreach my $sha1 (split /\s+/, $ignore_warnings) {
2402 $ignored_warnings{$sha1} = 1;
2403 }
2404 }
1885 2405
1886 $in_patchcheck = 1; 2406 $in_patchcheck = 1;
1887 foreach my $item (@list) { 2407 foreach my $item (@list) {
@@ -1908,18 +2428,16 @@ sub patchcheck {
1908 build "oldconfig" or return 0; 2428 build "oldconfig" or return 0;
1909 } 2429 }
1910 2430
1911 check_buildlog $sha1 or return 0;
1912 2431
1913 next if ($type eq "build"); 2432 if (!defined($ignored_warnings{$sha1})) {
2433 check_buildlog $sha1 or return 0;
2434 }
1914 2435
1915 get_grub_index; 2436 next if ($type eq "build");
1916 get_version;
1917 install;
1918 2437
1919 my $failed = 0; 2438 my $failed = 0;
1920 2439
1921 start_monitor; 2440 start_monitor_and_boot or $failed = 1;
1922 monitor or $failed = 1;
1923 2441
1924 if (!$failed && $type ne "boot"){ 2442 if (!$failed && $type ne "boot"){
1925 do_run_test or $failed = 1; 2443 do_run_test or $failed = 1;
@@ -1936,24 +2454,529 @@ sub patchcheck {
1936 return 1; 2454 return 1;
1937} 2455}
1938 2456
2457my %depends;
2458my %depcount;
2459my $iflevel = 0;
2460my @ifdeps;
2461
2462# prevent recursion
2463my %read_kconfigs;
2464
2465sub add_dep {
2466 # $config depends on $dep
2467 my ($config, $dep) = @_;
2468
2469 if (defined($depends{$config})) {
2470 $depends{$config} .= " " . $dep;
2471 } else {
2472 $depends{$config} = $dep;
2473 }
2474
2475 # record the number of configs depending on $dep
2476 if (defined $depcount{$dep}) {
2477 $depcount{$dep}++;
2478 } else {
2479 $depcount{$dep} = 1;
2480 }
2481}
2482
2483# taken from streamline_config.pl
2484sub read_kconfig {
2485 my ($kconfig) = @_;
2486
2487 my $state = "NONE";
2488 my $config;
2489 my @kconfigs;
2490
2491 my $cont = 0;
2492 my $line;
2493
2494
2495 if (! -f $kconfig) {
2496 doprint "file $kconfig does not exist, skipping\n";
2497 return;
2498 }
2499
2500 open(KIN, "$kconfig")
2501 or die "Can't open $kconfig";
2502 while (<KIN>) {
2503 chomp;
2504
2505 # Make sure that lines ending with \ continue
2506 if ($cont) {
2507 $_ = $line . " " . $_;
2508 }
2509
2510 if (s/\\$//) {
2511 $cont = 1;
2512 $line = $_;
2513 next;
2514 }
2515
2516 $cont = 0;
2517
2518 # collect any Kconfig sources
2519 if (/^source\s*"(.*)"/) {
2520 $kconfigs[$#kconfigs+1] = $1;
2521 }
2522
2523 # configs found
2524 if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2525 $state = "NEW";
2526 $config = $2;
2527
2528 for (my $i = 0; $i < $iflevel; $i++) {
2529 add_dep $config, $ifdeps[$i];
2530 }
2531
2532 # collect the depends for the config
2533 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2534
2535 add_dep $config, $1;
2536
2537 # Get the configs that select this config
2538 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
2539
2540 # selected by depends on config
2541 add_dep $1, $config;
2542
2543 # Check for if statements
2544 } elsif (/^if\s+(.*\S)\s*$/) {
2545 my $deps = $1;
2546 # remove beginning and ending non text
2547 $deps =~ s/^[^a-zA-Z0-9_]*//;
2548 $deps =~ s/[^a-zA-Z0-9_]*$//;
2549
2550 my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2551
2552 $ifdeps[$iflevel++] = join ':', @deps;
2553
2554 } elsif (/^endif/) {
2555
2556 $iflevel-- if ($iflevel);
2557
2558 # stop on "help"
2559 } elsif (/^\s*help\s*$/) {
2560 $state = "NONE";
2561 }
2562 }
2563 close(KIN);
2564
2565 # read in any configs that were found.
2566 foreach $kconfig (@kconfigs) {
2567 if (!defined($read_kconfigs{$kconfig})) {
2568 $read_kconfigs{$kconfig} = 1;
2569 read_kconfig("$builddir/$kconfig");
2570 }
2571 }
2572}
2573
2574sub read_depends {
2575 # find out which arch this is by the kconfig file
2576 open (IN, $output_config)
2577 or dodie "Failed to read $output_config";
2578 my $arch;
2579 while (<IN>) {
2580 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2581 $arch = $1;
2582 last;
2583 }
2584 }
2585 close IN;
2586
2587 if (!defined($arch)) {
2588 doprint "Could not find arch from config file\n";
2589 doprint "no dependencies used\n";
2590 return;
2591 }
2592
2593 # arch is really the subarch, we need to know
2594 # what directory to look at.
2595 if ($arch eq "i386" || $arch eq "x86_64") {
2596 $arch = "x86";
2597 } elsif ($arch =~ /^tile/) {
2598 $arch = "tile";
2599 }
2600
2601 my $kconfig = "$builddir/arch/$arch/Kconfig";
2602
2603 if (! -f $kconfig && $arch =~ /\d$/) {
2604 my $orig = $arch;
2605 # some subarchs have numbers, truncate them
2606 $arch =~ s/\d*$//;
2607 $kconfig = "$builddir/arch/$arch/Kconfig";
2608 if (! -f $kconfig) {
2609 doprint "No idea what arch dir $orig is for\n";
2610 doprint "no dependencies used\n";
2611 return;
2612 }
2613 }
2614
2615 read_kconfig($kconfig);
2616}
2617
2618sub read_config_list {
2619 my ($config) = @_;
2620
2621 open (IN, $config)
2622 or dodie "Failed to read $config";
2623
2624 while (<IN>) {
2625 if (/^((CONFIG\S*)=.*)/) {
2626 if (!defined($config_ignore{$2})) {
2627 $config_list{$2} = $1;
2628 }
2629 }
2630 }
2631
2632 close(IN);
2633}
2634
2635sub read_output_config {
2636 my ($config) = @_;
2637
2638 assign_configs \%config_ignore, $config;
2639}
2640
2641sub make_new_config {
2642 my @configs = @_;
2643
2644 open (OUT, ">$output_config")
2645 or dodie "Failed to write $output_config";
2646
2647 foreach my $config (@configs) {
2648 print OUT "$config\n";
2649 }
2650 close OUT;
2651}
2652
2653sub chomp_config {
2654 my ($config) = @_;
2655
2656 $config =~ s/CONFIG_//;
2657
2658 return $config;
2659}
2660
2661sub get_depends {
2662 my ($dep) = @_;
2663
2664 my $kconfig = chomp_config $dep;
2665
2666 $dep = $depends{"$kconfig"};
2667
2668 # the dep string we have saves the dependencies as they
2669 # were found, including expressions like ! && ||. We
2670 # want to split this out into just an array of configs.
2671
2672 my $valid = "A-Za-z_0-9";
2673
2674 my @configs;
2675
2676 while ($dep =~ /[$valid]/) {
2677
2678 if ($dep =~ /^[^$valid]*([$valid]+)/) {
2679 my $conf = "CONFIG_" . $1;
2680
2681 $configs[$#configs + 1] = $conf;
2682
2683 $dep =~ s/^[^$valid]*[$valid]+//;
2684 } else {
2685 die "this should never happen";
2686 }
2687 }
2688
2689 return @configs;
2690}
2691
2692my %min_configs;
2693my %keep_configs;
2694my %save_configs;
2695my %processed_configs;
2696my %nochange_config;
2697
2698sub test_this_config {
2699 my ($config) = @_;
2700
2701 my $found;
2702
2703 # if we already processed this config, skip it
2704 if (defined($processed_configs{$config})) {
2705 return undef;
2706 }
2707 $processed_configs{$config} = 1;
2708
2709 # if this config failed during this round, skip it
2710 if (defined($nochange_config{$config})) {
2711 return undef;
2712 }
2713
2714 my $kconfig = chomp_config $config;
2715
2716 # Test dependencies first
2717 if (defined($depends{"$kconfig"})) {
2718 my @parents = get_depends $config;
2719 foreach my $parent (@parents) {
2720 # if the parent is in the min config, check it first
2721 next if (!defined($min_configs{$parent}));
2722 $found = test_this_config($parent);
2723 if (defined($found)) {
2724 return $found;
2725 }
2726 }
2727 }
2728
2729 # Remove this config from the list of configs
2730 # do a make oldnoconfig and then read the resulting
2731 # .config to make sure it is missing the config that
2732 # we had before
2733 my %configs = %min_configs;
2734 delete $configs{$config};
2735 make_new_config ((values %configs), (values %keep_configs));
2736 make_oldconfig;
2737 undef %configs;
2738 assign_configs \%configs, $output_config;
2739
2740 return $config if (!defined($configs{$config}));
2741
2742 doprint "disabling config $config did not change .config\n";
2743
2744 $nochange_config{$config} = 1;
2745
2746 return undef;
2747}
2748
2749sub make_min_config {
2750 my ($i) = @_;
2751
2752 if (!defined($output_minconfig)) {
2753 fail "OUTPUT_MIN_CONFIG not defined" and return;
2754 }
2755
2756 # If output_minconfig exists, and the start_minconfig
2757 # came from min_config, than ask if we should use
2758 # that instead.
2759 if (-f $output_minconfig && !$start_minconfig_defined) {
2760 print "$output_minconfig exists\n";
2761 if (read_yn " Use it as minconfig?") {
2762 $start_minconfig = $output_minconfig;
2763 }
2764 }
2765
2766 if (!defined($start_minconfig)) {
2767 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
2768 }
2769
2770 my $temp_config = "$tmpdir/temp_config";
2771
2772 # First things first. We build an allnoconfig to find
2773 # out what the defaults are that we can't touch.
2774 # Some are selections, but we really can't handle selections.
2775
2776 my $save_minconfig = $minconfig;
2777 undef $minconfig;
2778
2779 run_command "$make allnoconfig" or return 0;
2780
2781 read_depends;
2782
2783 process_config_ignore $output_config;
2784
2785 undef %save_configs;
2786 undef %min_configs;
2787
2788 if (defined($ignore_config)) {
2789 # make sure the file exists
2790 `touch $ignore_config`;
2791 assign_configs \%save_configs, $ignore_config;
2792 }
2793
2794 %keep_configs = %save_configs;
2795
2796 doprint "Load initial configs from $start_minconfig\n";
2797
2798 # Look at the current min configs, and save off all the
2799 # ones that were set via the allnoconfig
2800 assign_configs \%min_configs, $start_minconfig;
2801
2802 my @config_keys = keys %min_configs;
2803
2804 # All configs need a depcount
2805 foreach my $config (@config_keys) {
2806 my $kconfig = chomp_config $config;
2807 if (!defined $depcount{$kconfig}) {
2808 $depcount{$kconfig} = 0;
2809 }
2810 }
2811
2812 # Remove anything that was set by the make allnoconfig
2813 # we shouldn't need them as they get set for us anyway.
2814 foreach my $config (@config_keys) {
2815 # Remove anything in the ignore_config
2816 if (defined($keep_configs{$config})) {
2817 my $file = $ignore_config;
2818 $file =~ s,.*/(.*?)$,$1,;
2819 doprint "$config set by $file ... ignored\n";
2820 delete $min_configs{$config};
2821 next;
2822 }
2823 # But make sure the settings are the same. If a min config
2824 # sets a selection, we do not want to get rid of it if
2825 # it is not the same as what we have. Just move it into
2826 # the keep configs.
2827 if (defined($config_ignore{$config})) {
2828 if ($config_ignore{$config} ne $min_configs{$config}) {
2829 doprint "$config is in allnoconfig as '$config_ignore{$config}'";
2830 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
2831 $keep_configs{$config} = $min_configs{$config};
2832 } else {
2833 doprint "$config set by allnoconfig ... ignored\n";
2834 }
2835 delete $min_configs{$config};
2836 }
2837 }
2838
2839 my $done = 0;
2840 my $take_two = 0;
2841
2842 while (!$done) {
2843
2844 my $config;
2845 my $found;
2846
2847 # Now disable each config one by one and do a make oldconfig
2848 # till we find a config that changes our list.
2849
2850 my @test_configs = keys %min_configs;
2851
2852 # Sort keys by who is most dependent on
2853 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
2854 @test_configs ;
2855
2856 # Put configs that did not modify the config at the end.
2857 my $reset = 1;
2858 for (my $i = 0; $i < $#test_configs; $i++) {
2859 if (!defined($nochange_config{$test_configs[0]})) {
2860 $reset = 0;
2861 last;
2862 }
2863 # This config didn't change the .config last time.
2864 # Place it at the end
2865 my $config = shift @test_configs;
2866 push @test_configs, $config;
2867 }
2868
2869 # if every test config has failed to modify the .config file
2870 # in the past, then reset and start over.
2871 if ($reset) {
2872 undef %nochange_config;
2873 }
2874
2875 undef %processed_configs;
2876
2877 foreach my $config (@test_configs) {
2878
2879 $found = test_this_config $config;
2880
2881 last if (defined($found));
2882
2883 # oh well, try another config
2884 }
2885
2886 if (!defined($found)) {
2887 # we could have failed due to the nochange_config hash
2888 # reset and try again
2889 if (!$take_two) {
2890 undef %nochange_config;
2891 $take_two = 1;
2892 next;
2893 }
2894 doprint "No more configs found that we can disable\n";
2895 $done = 1;
2896 last;
2897 }
2898 $take_two = 0;
2899
2900 $config = $found;
2901
2902 doprint "Test with $config disabled\n";
2903
2904 # set in_bisect to keep build and monitor from dieing
2905 $in_bisect = 1;
2906
2907 my $failed = 0;
2908 build "oldconfig";
2909 start_monitor_and_boot or $failed = 1;
2910 end_monitor;
2911
2912 $in_bisect = 0;
2913
2914 if ($failed) {
2915 doprint "$min_configs{$config} is needed to boot the box... keeping\n";
2916 # this config is needed, add it to the ignore list.
2917 $keep_configs{$config} = $min_configs{$config};
2918 $save_configs{$config} = $min_configs{$config};
2919 delete $min_configs{$config};
2920
2921 # update new ignore configs
2922 if (defined($ignore_config)) {
2923 open (OUT, ">$temp_config")
2924 or die "Can't write to $temp_config";
2925 foreach my $config (keys %save_configs) {
2926 print OUT "$save_configs{$config}\n";
2927 }
2928 close OUT;
2929 run_command "mv $temp_config $ignore_config" or
2930 dodie "failed to copy update to $ignore_config";
2931 }
2932
2933 } else {
2934 # We booted without this config, remove it from the minconfigs.
2935 doprint "$config is not needed, disabling\n";
2936
2937 delete $min_configs{$config};
2938
2939 # Also disable anything that is not enabled in this config
2940 my %configs;
2941 assign_configs \%configs, $output_config;
2942 my @config_keys = keys %min_configs;
2943 foreach my $config (@config_keys) {
2944 if (!defined($configs{$config})) {
2945 doprint "$config is not set, disabling\n";
2946 delete $min_configs{$config};
2947 }
2948 }
2949
2950 # Save off all the current mandidory configs
2951 open (OUT, ">$temp_config")
2952 or die "Can't write to $temp_config";
2953 foreach my $config (keys %keep_configs) {
2954 print OUT "$keep_configs{$config}\n";
2955 }
2956 foreach my $config (keys %min_configs) {
2957 print OUT "$min_configs{$config}\n";
2958 }
2959 close OUT;
2960
2961 run_command "mv $temp_config $output_minconfig" or
2962 dodie "failed to copy update to $output_minconfig";
2963 }
2964
2965 doprint "Reboot and wait $sleep_time seconds\n";
2966 reboot $sleep_time;
2967 }
2968
2969 success $i;
2970 return 1;
2971}
2972
1939$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 2973$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n";
1940 2974
1941if ($#ARGV == 0) { 2975if ($#ARGV == 0) {
1942 $ktest_config = $ARGV[0]; 2976 $ktest_config = $ARGV[0];
1943 if (! -f $ktest_config) { 2977 if (! -f $ktest_config) {
1944 print "$ktest_config does not exist.\n"; 2978 print "$ktest_config does not exist.\n";
1945 my $ans; 2979 if (!read_yn "Create it?") {
1946 for (;;) {
1947 print "Create it? [Y/n] ";
1948 $ans = <STDIN>;
1949 chomp $ans;
1950 if ($ans =~ /^\s*$/) {
1951 $ans = "y";
1952 }
1953 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
1954 print "Please answer either 'y' or 'n'.\n";
1955 }
1956 if ($ans !~ /^y$/i) {
1957 exit 0; 2980 exit 0;
1958 } 2981 }
1959 } 2982 }
@@ -1977,6 +3000,10 @@ EOF
1977} 3000}
1978read_config $ktest_config; 3001read_config $ktest_config;
1979 3002
3003if (defined($opt{"LOG_FILE"})) {
3004 $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
3005}
3006
1980# Append any configs entered in manually to the config file. 3007# Append any configs entered in manually to the config file.
1981my @new_configs = keys %entered_configs; 3008my @new_configs = keys %entered_configs;
1982if ($#new_configs >= 0) { 3009if ($#new_configs >= 0) {
@@ -2045,75 +3072,21 @@ sub __set_test_option {
2045 return undef; 3072 return undef;
2046} 3073}
2047 3074
2048sub eval_option {
2049 my ($option, $i) = @_;
2050
2051 # Add space to evaluate the character before $
2052 $option = " $option";
2053 my $retval = "";
2054
2055 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
2056 my $start = $1;
2057 my $var = $2;
2058 my $end = $3;
2059
2060 # Append beginning of line
2061 $retval = "$retval$start";
2062
2063 # If the iteration option OPT[$i] exists, then use that.
2064 # otherwise see if the default OPT (without [$i]) exists.
2065
2066 my $o = "$var\[$i\]";
2067
2068 if (defined($opt{$o})) {
2069 $o = $opt{$o};
2070 $retval = "$retval$o";
2071 } elsif (defined($opt{$var})) {
2072 $o = $opt{$var};
2073 $retval = "$retval$o";
2074 } else {
2075 $retval = "$retval\$\{$var\}";
2076 }
2077
2078 $option = $end;
2079 }
2080
2081 $retval = "$retval$option";
2082
2083 $retval =~ s/^ //;
2084
2085 return $retval;
2086}
2087
2088sub set_test_option { 3075sub set_test_option {
2089 my ($name, $i) = @_; 3076 my ($name, $i) = @_;
2090 3077
2091 my $option = __set_test_option($name, $i); 3078 my $option = __set_test_option($name, $i);
2092 return $option if (!defined($option)); 3079 return $option if (!defined($option));
2093 3080
2094 my $prev = ""; 3081 return eval_option($option, $i);
2095
2096 # Since an option can evaluate to another option,
2097 # keep iterating until we do not evaluate any more
2098 # options.
2099 my $r = 0;
2100 while ($prev ne $option) {
2101 # Check for recursive evaluations.
2102 # 100 deep should be more than enough.
2103 if ($r++ > 100) {
2104 die "Over 100 evaluations accurred with $name\n" .
2105 "Check for recursive variables\n";
2106 }
2107 $prev = $option;
2108 $option = eval_option($option, $i);
2109 }
2110
2111 return $option;
2112} 3082}
2113 3083
2114# First we need to do is the builds 3084# First we need to do is the builds
2115for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 3085for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2116 3086
3087 # Do not reboot on failing test options
3088 $no_reboot = 1;
3089
2117 $iteration = $i; 3090 $iteration = $i;
2118 3091
2119 my $makecmd = set_test_option("MAKE_CMD", $i); 3092 my $makecmd = set_test_option("MAKE_CMD", $i);
@@ -2126,15 +3099,23 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2126 $test_type = set_test_option("TEST_TYPE", $i); 3099 $test_type = set_test_option("TEST_TYPE", $i);
2127 $build_type = set_test_option("BUILD_TYPE", $i); 3100 $build_type = set_test_option("BUILD_TYPE", $i);
2128 $build_options = set_test_option("BUILD_OPTIONS", $i); 3101 $build_options = set_test_option("BUILD_OPTIONS", $i);
3102 $pre_build = set_test_option("PRE_BUILD", $i);
3103 $post_build = set_test_option("POST_BUILD", $i);
3104 $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
3105 $post_build_die = set_test_option("POST_BUILD_DIE", $i);
2129 $power_cycle = set_test_option("POWER_CYCLE", $i); 3106 $power_cycle = set_test_option("POWER_CYCLE", $i);
2130 $reboot = set_test_option("REBOOT", $i); 3107 $reboot = set_test_option("REBOOT", $i);
2131 $noclean = set_test_option("BUILD_NOCLEAN", $i); 3108 $noclean = set_test_option("BUILD_NOCLEAN", $i);
2132 $minconfig = set_test_option("MIN_CONFIG", $i); 3109 $minconfig = set_test_option("MIN_CONFIG", $i);
3110 $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
3111 $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
3112 $ignore_config = set_test_option("IGNORE_CONFIG", $i);
2133 $run_test = set_test_option("TEST", $i); 3113 $run_test = set_test_option("TEST", $i);
2134 $addconfig = set_test_option("ADD_CONFIG", $i); 3114 $addconfig = set_test_option("ADD_CONFIG", $i);
2135 $reboot_type = set_test_option("REBOOT_TYPE", $i); 3115 $reboot_type = set_test_option("REBOOT_TYPE", $i);
2136 $grub_menu = set_test_option("GRUB_MENU", $i); 3116 $grub_menu = set_test_option("GRUB_MENU", $i);
2137 $post_install = set_test_option("POST_INSTALL", $i); 3117 $post_install = set_test_option("POST_INSTALL", $i);
3118 $no_install = set_test_option("NO_INSTALL", $i);
2138 $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 3119 $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
2139 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 3120 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
2140 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 3121 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
@@ -2145,13 +3126,18 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2145 $sleep_time = set_test_option("SLEEP_TIME", $i); 3126 $sleep_time = set_test_option("SLEEP_TIME", $i);
2146 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 3127 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
2147 $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i); 3128 $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
3129 $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
2148 $bisect_manual = set_test_option("BISECT_MANUAL", $i); 3130 $bisect_manual = set_test_option("BISECT_MANUAL", $i);
2149 $bisect_skip = set_test_option("BISECT_SKIP", $i); 3131 $bisect_skip = set_test_option("BISECT_SKIP", $i);
3132 $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
2150 $store_failures = set_test_option("STORE_FAILURES", $i); 3133 $store_failures = set_test_option("STORE_FAILURES", $i);
3134 $test_name = set_test_option("TEST_NAME", $i);
2151 $timeout = set_test_option("TIMEOUT", $i); 3135 $timeout = set_test_option("TIMEOUT", $i);
2152 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 3136 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
2153 $console = set_test_option("CONSOLE", $i); 3137 $console = set_test_option("CONSOLE", $i);
3138 $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
2154 $success_line = set_test_option("SUCCESS_LINE", $i); 3139 $success_line = set_test_option("SUCCESS_LINE", $i);
3140 $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
2155 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 3141 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
2156 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 3142 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
2157 $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); 3143 $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
@@ -2161,11 +3147,20 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2161 $target_image = set_test_option("TARGET_IMAGE", $i); 3147 $target_image = set_test_option("TARGET_IMAGE", $i);
2162 $localversion = set_test_option("LOCALVERSION", $i); 3148 $localversion = set_test_option("LOCALVERSION", $i);
2163 3149
3150 $start_minconfig_defined = 1;
3151
3152 if (!defined($start_minconfig)) {
3153 $start_minconfig_defined = 0;
3154 $start_minconfig = $minconfig;
3155 }
3156
2164 chdir $builddir || die "can't change directory to $builddir"; 3157 chdir $builddir || die "can't change directory to $builddir";
2165 3158
2166 if (!-d $tmpdir) { 3159 foreach my $dir ($tmpdir, $outputdir) {
2167 mkpath($tmpdir) or 3160 if (!-d $dir) {
2168 die "can't create $tmpdir"; 3161 mkpath($dir) or
3162 die "can't create $dir";
3163 }
2169 } 3164 }
2170 3165
2171 $ENV{"SSH_USER"} = $ssh_user; 3166 $ENV{"SSH_USER"} = $ssh_user;
@@ -2193,22 +3188,30 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2193 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 3188 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
2194 } 3189 }
2195 3190
3191 if ($test_type eq "make_min_config") {
3192 $run_type = "";
3193 }
3194
2196 # mistake in config file? 3195 # mistake in config file?
2197 if (!defined($run_type)) { 3196 if (!defined($run_type)) {
2198 $run_type = "ERROR"; 3197 $run_type = "ERROR";
2199 } 3198 }
2200 3199
3200 my $installme = "";
3201 $installme = " no_install" if ($no_install);
3202
2201 doprint "\n\n"; 3203 doprint "\n\n";
2202 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; 3204 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
2203 3205
2204 unlink $dmesg; 3206 unlink $dmesg;
2205 unlink $buildlog; 3207 unlink $buildlog;
2206 3208
2207 if (!defined($minconfig)) { 3209 if (defined($addconfig)) {
2208 $minconfig = $addconfig; 3210 my $min = $minconfig;
2209 3211 if (!defined($minconfig)) {
2210 } elsif (defined($addconfig)) { 3212 $min = "";
2211 run_command "cat $addconfig $minconfig > $tmpdir/add_config" or 3213 }
3214 run_command "cat $addconfig $min > $tmpdir/add_config" or
2212 dodie "Failed to create temp config"; 3215 dodie "Failed to create temp config";
2213 $minconfig = "$tmpdir/add_config"; 3216 $minconfig = "$tmpdir/add_config";
2214 } 3217 }
@@ -2219,6 +3222,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2219 die "failed to checkout $checkout"; 3222 die "failed to checkout $checkout";
2220 } 3223 }
2221 3224
3225 $no_reboot = 0;
3226
3227
2222 if ($test_type eq "bisect") { 3228 if ($test_type eq "bisect") {
2223 bisect $i; 3229 bisect $i;
2224 next; 3230 next;
@@ -2228,20 +3234,25 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2228 } elsif ($test_type eq "patchcheck") { 3234 } elsif ($test_type eq "patchcheck") {
2229 patchcheck $i; 3235 patchcheck $i;
2230 next; 3236 next;
3237 } elsif ($test_type eq "make_min_config") {
3238 make_min_config $i;
3239 next;
2231 } 3240 }
2232 3241
2233 if ($build_type ne "nobuild") { 3242 if ($build_type ne "nobuild") {
2234 build $build_type or next; 3243 build $build_type or next;
2235 } 3244 }
2236 3245
2237 if ($test_type ne "build") { 3246 if ($test_type eq "install") {
2238 get_grub_index;
2239 get_version; 3247 get_version;
2240 install; 3248 install;
3249 success $i;
3250 next;
3251 }
2241 3252
3253 if ($test_type ne "build") {
2242 my $failed = 0; 3254 my $failed = 0;
2243 start_monitor; 3255 start_monitor_and_boot or $failed = 1;
2244 monitor or $failed = 1;;
2245 3256
2246 if (!$failed && $test_type ne "boot" && defined($run_test)) { 3257 if (!$failed && $test_type ne "boot" && defined($run_test)) {
2247 do_run_test or $failed = 1; 3258 do_run_test or $failed = 1;
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index 48cbcc80602a..dbedfa196727 100644
--- a/tools/testing/ktest/sample.conf
+++ b/tools/testing/ktest/sample.conf
@@ -72,6 +72,128 @@
72# the same option name under the same test or as default 72# the same option name under the same test or as default
73# ktest will fail to execute, and no tests will run. 73# ktest will fail to execute, and no tests will run.
74# 74#
75# DEFAULTS OVERRIDE
76#
77# Options defined in the DEFAULTS section can not be duplicated
78# even if they are defined in two different DEFAULT sections.
79# This is done to catch mistakes where an option is added but
80# the previous option was forgotten about and not commented.
81#
82# The OVERRIDE keyword can be added to a section to allow this
83# section to override other DEFAULT sections values that have
84# been defined previously. It will only override options that
85# have been defined before its use. Options defined later
86# in a non override section will still error. The same option
87# can not be defined in the same section even if that section
88# is marked OVERRIDE.
89#
90#
91#
92# Both TEST_START and DEFAULTS sections can also have the IF keyword
93# The value after the IF must evaluate into a 0 or non 0 positive
94# integer, and can use the config variables (explained below).
95#
96# DEFAULTS IF ${IS_X86_32}
97#
98# The above will process the DEFAULTS section if the config
99# variable IS_X86_32 evaluates to a non zero positive integer
100# otherwise if it evaluates to zero, it will act the same
101# as if the SKIP keyword was used.
102#
103# The ELSE keyword can be used directly after a section with
104# a IF statement.
105#
106# TEST_START IF ${RUN_NET_TESTS}
107# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
108#
109# ELSE
110#
111# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-normal
112#
113#
114# The ELSE keyword can also contain an IF statement to allow multiple
115# if then else sections. But all the sections must be either
116# DEFAULT or TEST_START, they can not be a mixture.
117#
118# TEST_START IF ${RUN_NET_TESTS}
119# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
120#
121# ELSE IF ${RUN_DISK_TESTS}
122# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-tests
123#
124# ELSE IF ${RUN_CPU_TESTS}
125# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-cpu
126#
127# ELSE
128# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
129#
130# The if statement may also have comparisons that will and for
131# == and !=, strings may be used for both sides.
132#
133# BOX_TYPE := x86_32
134#
135# DEFAULTS IF ${BOX_TYPE} == x86_32
136# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-32
137# ELSE
138# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-64
139#
140# The DEFINED keyword can be used by the IF statements too.
141# It returns true if the given config variable or option has been defined
142# or false otherwise.
143#
144#
145# DEFAULTS IF DEFINED USE_CC
146# CC := ${USE_CC}
147# ELSE
148# CC := gcc
149#
150#
151# As well as NOT DEFINED.
152#
153# DEFAULTS IF NOT DEFINED MAKE_CMD
154# MAKE_CMD := make ARCH=x86
155#
156#
157# And/or ops (&&,||) may also be used to make complex conditionals.
158#
159# TEST_START IF (DEFINED ALL_TESTS || ${MYTEST} == boottest) && ${MACHINE} == gandalf
160#
161# Notice the use of paranthesis. Without any paranthesis the above would be
162# processed the same as:
163#
164# TEST_START IF DEFINED ALL_TESTS || (${MYTEST} == boottest && ${MACHINE} == gandalf)
165#
166#
167#
168# INCLUDE file
169#
170# The INCLUDE keyword may be used in DEFAULT sections. This will
171# read another config file and process that file as well. The included
172# file can include other files, add new test cases or default
173# statements. Config variables will be passed to these files and changes
174# to config variables will be seen by top level config files. Including
175# a file is processed just like the contents of the file was cut and pasted
176# into the top level file, except, that include files that end with
177# TEST_START sections will have that section ended at the end of
178# the include file. That is, an included file is included followed
179# by another DEFAULT keyword.
180#
181# Unlike other files referenced in this config, the file path does not need
182# to be absolute. If the file does not start with '/', then the directory
183# that the current config file was located in is used. If no config by the
184# given name is found there, then the current directory is searched.
185#
186# INCLUDE myfile
187# DEFAULT
188#
189# is the same as:
190#
191# INCLUDE myfile
192#
193# Note, if the include file does not contain a full path, the file is
194# searched first by the location of the original include file, and then
195# by the location that ktest.pl was executed in.
196#
75 197
76#### Config variables #### 198#### Config variables ####
77# 199#
@@ -253,9 +375,10 @@
253 375
254# The default test type (default test) 376# The default test type (default test)
255# The test types may be: 377# The test types may be:
256# build - only build the kernel, do nothing else 378# build - only build the kernel, do nothing else
257# boot - build and boot the kernel 379# install - build and install, but do nothing else (does not reboot)
258# test - build, boot and if TEST is set, run the test script 380# boot - build, install, and boot the kernel
381# test - build, boot and if TEST is set, run the test script
259# (If TEST is not set, it defaults back to boot) 382# (If TEST is not set, it defaults back to boot)
260# bisect - Perform a bisect on the kernel (see BISECT_TYPE below) 383# bisect - Perform a bisect on the kernel (see BISECT_TYPE below)
261# patchcheck - Do a test on a series of commits in git (see PATCHCHECK below) 384# patchcheck - Do a test on a series of commits in git (see PATCHCHECK below)
@@ -293,6 +416,45 @@
293# or on some systems: 416# or on some systems:
294#POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION 417#POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
295 418
419# If for some reason you just want to boot the kernel and you do not
420# want the test to install anything new. For example, you may just want
421# to boot test the same kernel over and over and do not want to go through
422# the hassle of installing anything, you can set this option to 1
423# (default 0)
424#NO_INSTALL = 1
425
426# If there is a script that you require to run before the build is done
427# you can specify it with PRE_BUILD.
428#
429# One example may be if you must add a temporary patch to the build to
430# fix a unrelated bug to perform a patchcheck test. This will apply the
431# patch before each build that is made. Use the POST_BUILD to do a git reset --hard
432# to remove the patch.
433#
434# (default undef)
435#PRE_BUILD = cd ${BUILD_DIR} && patch -p1 < /tmp/temp.patch
436
437# To specify if the test should fail if the PRE_BUILD fails,
438# PRE_BUILD_DIE needs to be set to 1. Otherwise the PRE_BUILD
439# result is ignored.
440# (default 0)
441# PRE_BUILD_DIE = 1
442
443# If there is a script that should run after the build is done
444# you can specify it with POST_BUILD.
445#
446# As the example in PRE_BUILD, POST_BUILD can be used to reset modifications
447# made by the PRE_BUILD.
448#
449# (default undef)
450#POST_BUILD = cd ${BUILD_DIR} && git reset --hard
451
452# To specify if the test should fail if the POST_BUILD fails,
453# POST_BUILD_DIE needs to be set to 1. Otherwise the POST_BUILD
454# result is ignored.
455# (default 0)
456#POST_BUILD_DIE = 1
457
296# Way to reboot the box to the test kernel. 458# Way to reboot the box to the test kernel.
297# Only valid options so far are "grub" and "script" 459# Only valid options so far are "grub" and "script"
298# (default grub) 460# (default grub)
@@ -360,8 +522,8 @@
360#ADD_CONFIG = /home/test/config-broken 522#ADD_CONFIG = /home/test/config-broken
361 523
362# The location on the host where to write temp files 524# The location on the host where to write temp files
363# (default /tmp/ktest) 525# (default /tmp/ktest/${MACHINE})
364#TMP_DIR = /tmp/ktest 526#TMP_DIR = /tmp/ktest/${MACHINE}
365 527
366# Optional log file to write the status (recommended) 528# Optional log file to write the status (recommended)
367# Note, this is a DEFAULT section only option. 529# Note, this is a DEFAULT section only option.
@@ -383,6 +545,14 @@
383# (default "login:") 545# (default "login:")
384#SUCCESS_LINE = login: 546#SUCCESS_LINE = login:
385 547
548# To speed up between reboots, defining a line that the
549# default kernel produces that represents that the default
550# kernel has successfully booted and can be used to pass
551# a new test kernel to it. Otherwise ktest.pl will wait till
552# SLEEP_TIME to continue.
553# (default undefined)
554#REBOOT_SUCCESS_LINE = login:
555
386# In case the console constantly fills the screen, having 556# In case the console constantly fills the screen, having
387# a specified time to stop the test after success is recommended. 557# a specified time to stop the test after success is recommended.
388# (in seconds) 558# (in seconds)
@@ -448,6 +618,8 @@
448# another test. If a reboot to the reliable kernel happens, 618# another test. If a reboot to the reliable kernel happens,
449# we wait SLEEP_TIME for the console to stop producing output 619# we wait SLEEP_TIME for the console to stop producing output
450# before starting the next test. 620# before starting the next test.
621#
622# You can speed up reboot times even more by setting REBOOT_SUCCESS_LINE.
451# (default 60) 623# (default 60)
452#SLEEP_TIME = 60 624#SLEEP_TIME = 60
453 625
@@ -518,6 +690,16 @@
518# The variables SSH_USER and MACHINE are defined. 690# The variables SSH_USER and MACHINE are defined.
519#REBOOT = ssh $SSH_USER@$MACHINE reboot 691#REBOOT = ssh $SSH_USER@$MACHINE reboot
520 692
693# The way triple faults are detected is by testing the kernel
694# banner. If the kernel banner for the kernel we are testing is
695# found, and then later a kernel banner for another kernel version
696# is found, it is considered that we encountered a triple fault,
697# and there is no panic or callback, but simply a reboot.
698# To disable this (because it did a false positive) set the following
699# to 0.
700# (default 1)
701#DETECT_TRIPLE_FAULT = 0
702
521#### Per test run options #### 703#### Per test run options ####
522# The following options are only allowed in TEST_START sections. 704# The following options are only allowed in TEST_START sections.
523# They are ignored in the DEFAULTS sections. 705# They are ignored in the DEFAULTS sections.
@@ -535,6 +717,12 @@
535# all preceding tests until a new CHECKOUT is set. 717# all preceding tests until a new CHECKOUT is set.
536# 718#
537# 719#
720# TEST_NAME = name
721#
722# If you want the test to have a name that is displayed in
723# the test result banner at the end of the test, then use this
724# option. This is useful to search for the RESULT keyword and
725# not have to translate a test number to a test in the config.
538# 726#
539# For TEST_TYPE = patchcheck 727# For TEST_TYPE = patchcheck
540# 728#
@@ -556,7 +744,12 @@
556# build, boot, test. 744# build, boot, test.
557# 745#
558# Note, the build test will look for warnings, if a warning occurred 746# Note, the build test will look for warnings, if a warning occurred
559# in a file that a commit touches, the build will fail. 747# in a file that a commit touches, the build will fail, unless
748# IGNORE_WARNINGS is set for the given commit's sha1
749#
750# IGNORE_WARNINGS can be used to disable the failure of patchcheck
751# on a particuler commit (SHA1). You can add more than one commit
752# by adding a list of SHA1s that are space delimited.
560# 753#
561# If BUILD_NOCLEAN is set, then make mrproper will not be run on 754# If BUILD_NOCLEAN is set, then make mrproper will not be run on
562# any of the builds, just like all other TEST_TYPE tests. But 755# any of the builds, just like all other TEST_TYPE tests. But
@@ -571,6 +764,7 @@
571# PATCHCHECK_TYPE = boot 764# PATCHCHECK_TYPE = boot
572# PATCHCHECK_START = 747e94ae3d1b4c9bf5380e569f614eb9040b79e7 765# PATCHCHECK_START = 747e94ae3d1b4c9bf5380e569f614eb9040b79e7
573# PATCHCHECK_END = HEAD~2 766# PATCHCHECK_END = HEAD~2
767# IGNORE_WARNINGS = 42f9c6b69b54946ffc0515f57d01dc7f5c0e4712 0c17ca2c7187f431d8ffc79e81addc730f33d128
574# 768#
575# 769#
576# 770#
@@ -739,13 +933,18 @@
739# boot - bad builds but fails to boot 933# boot - bad builds but fails to boot
740# test - bad boots but fails a test 934# test - bad boots but fails a test
741# 935#
742# CONFIG_BISECT is the config that failed to boot 936# CONFIG_BISECT is the config that failed to boot
937#
938# If BISECT_MANUAL is set, it will pause between iterations.
939# This is useful to use just ktest.pl just for the config bisect.
940# If you set it to build, it will run the bisect and you can
941# control what happens in between iterations. It will ask you if
942# the test succeeded or not and continue the config bisect.
743# 943#
744# If BISECT_MANUAL is set, it will pause between iterations. 944# CONFIG_BISECT_GOOD (optional)
745# This is useful to use just ktest.pl just for the config bisect. 945# If you have a good config to start with, then you
746# If you set it to build, it will run the bisect and you can 946# can specify it with CONFIG_BISECT_GOOD. Otherwise
747# control what happens in between iterations. It will ask you if 947# the MIN_CONFIG is the base.
748# the test succeeded or not and continue the config bisect.
749# 948#
750# Example: 949# Example:
751# TEST_START 950# TEST_START
@@ -755,3 +954,68 @@
755# MIN_CONFIG = /home/test/config-min 954# MIN_CONFIG = /home/test/config-min
756# BISECT_MANUAL = 1 955# BISECT_MANUAL = 1
757# 956#
957#
958#
959# For TEST_TYPE = make_min_config
960#
961# After doing a make localyesconfig, your kernel configuration may
962# not be the most useful minimum configuration. Having a true minimum
963# config that you can use against other configs is very useful if
964# someone else has a config that breaks on your code. By only forcing
965# those configurations that are truly required to boot your machine
966# will give you less of a chance that one of your set configurations
967# will make the bug go away. This will give you a better chance to
968# be able to reproduce the reported bug matching the broken config.
969#
970# Note, this does take some time, and may require you to run the
971# test over night, or perhaps over the weekend. But it also allows
972# you to interrupt it, and gives you the current minimum config
973# that was found till that time.
974#
975# Note, this test automatically assumes a BUILD_TYPE of oldconfig
976# and its test type acts like boot.
977# TODO: add a test version that makes the config do more than just
978# boot, like having network access.
979#
980# To save time, the test does not just grab any option and test
981# it. The Kconfig files are examined to determine the dependencies
982# of the configs. If a config is chosen that depends on another
983# config, that config will be checked first. By checking the
984# parents first, we can eliminate whole groups of configs that
985# may have been enabled.
986#
987# For example, if a USB device config is chosen and depends on CONFIG_USB,
988# the CONFIG_USB will be tested before the device. If CONFIG_USB is
989# found not to be needed, it, as well as all configs that depend on
990# it, will be disabled and removed from the current min_config.
991#
992# OUTPUT_MIN_CONFIG is the path and filename of the file that will
993# be created from the MIN_CONFIG. If you interrupt the test, set
994# this file as your new min config, and use it to continue the test.
995# This file does not need to exist on start of test.
996# This file is not created until a config is found that can be removed.
997# If this file exists, you will be prompted if you want to use it
998# as the min_config (overriding MIN_CONFIG) if START_MIN_CONFIG
999# is not defined.
1000# (required field)
1001#
1002# START_MIN_CONFIG is the config to use to start the test with.
1003# you can set this as the same OUTPUT_MIN_CONFIG, but if you do
1004# the OUTPUT_MIN_CONFIG file must exist.
1005# (default MIN_CONFIG)
1006#
1007# IGNORE_CONFIG is used to specify a config file that has configs that
1008# you already know must be set. Configs are written here that have
1009# been tested and proved to be required. It is best to define this
1010# file if you intend on interrupting the test and running it where
1011# it left off. New configs that it finds will be written to this file
1012# and will not be tested again in later runs.
1013# (optional)
1014#
1015# Example:
1016#
1017# TEST_TYPE = make_min_config
1018# OUTPUT_MIN_CONFIG = /path/to/config-new-min
1019# START_MIN_CONFIG = /path/to/config-min
1020# IGNORE_CONFIG = /path/to/config-tested
1021#