aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/hv/hv_kvp_daemon.c458
-rw-r--r--tools/include/tools/be_byteshift.h70
-rw-r--r--tools/include/tools/le_byteshift.h70
-rw-r--r--tools/lguest/.gitignore1
-rw-r--r--tools/lguest/Makefile8
-rw-r--r--tools/lguest/extract58
-rw-r--r--tools/lguest/lguest.c2065
-rw-r--r--tools/lguest/lguest.txt129
-rwxr-xr-xtools/nfsd/inject_fault.sh49
-rw-r--r--tools/perf/Documentation/Makefile86
-rw-r--r--tools/perf/Documentation/perf-list.txt2
-rw-r--r--tools/perf/Documentation/perf-lock.txt20
-rw-r--r--tools/perf/Documentation/perf-record.txt38
-rw-r--r--tools/perf/Documentation/perf-report.txt15
-rw-r--r--tools/perf/Documentation/perf-script.txt5
-rw-r--r--tools/perf/Documentation/perf-stat.txt4
-rw-r--r--tools/perf/Documentation/perf-top.txt8
-rw-r--r--tools/perf/MANIFEST2
-rw-r--r--tools/perf/Makefile99
-rw-r--r--tools/perf/arch/powerpc/util/header.c2
-rw-r--r--tools/perf/arch/x86/util/header.c2
-rw-r--r--tools/perf/bench/bench.h1
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm-def.h8
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S12
-rw-r--r--tools/perf/bench/mem-memcpy.c12
-rw-r--r--tools/perf/bench/mem-memset-arch.h12
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm-def.h12
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm.S13
-rw-r--r--tools/perf/bench/mem-memset.c297
-rw-r--r--tools/perf/builtin-annotate.c7
-rw-r--r--tools/perf/builtin-bench.c3
-rw-r--r--tools/perf/builtin-diff.c60
-rw-r--r--tools/perf/builtin-kmem.c3
-rw-r--r--tools/perf/builtin-kvm.c6
-rw-r--r--tools/perf/builtin-lock.c4
-rw-r--r--tools/perf/builtin-probe.c14
-rw-r--r--tools/perf/builtin-record.c181
-rw-r--r--tools/perf/builtin-report.c218
-rw-r--r--tools/perf/builtin-sched.c1
-rw-r--r--tools/perf/builtin-script.c84
-rw-r--r--tools/perf/builtin-stat.c41
-rw-r--r--tools/perf/builtin-test.c364
-rw-r--r--tools/perf/builtin-top.c82
-rw-r--r--tools/perf/config/feature-tests.mak15
-rw-r--r--tools/perf/perf.h33
-rwxr-xr-xtools/perf/python/twatch.py2
-rw-r--r--tools/perf/util/annotate.c10
-rw-r--r--tools/perf/util/bitmap.c10
-rw-r--r--tools/perf/util/cache.h12
-rw-r--r--tools/perf/util/color.c9
-rw-r--r--tools/perf/util/cpumap.c11
-rw-r--r--tools/perf/util/cpumap.h4
-rw-r--r--tools/perf/util/ctype.c2
-rw-r--r--tools/perf/util/debugfs.c141
-rw-r--r--tools/perf/util/debugfs.h6
-rw-r--r--tools/perf/util/event.c3
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/evlist.c32
-rw-r--r--tools/perf/util/evlist.h9
-rw-r--r--tools/perf/util/evsel.c31
-rw-r--r--tools/perf/util/evsel.h5
-rw-r--r--tools/perf/util/gtk/browser.c189
-rw-r--r--tools/perf/util/gtk/gtk.h8
-rw-r--r--tools/perf/util/header.c592
-rw-r--r--tools/perf/util/header.h3
-rw-r--r--tools/perf/util/hist.c467
-rw-r--r--tools/perf/util/hist.h39
-rw-r--r--tools/perf/util/include/asm/dwarf2.h4
-rw-r--r--tools/perf/util/include/asm/unistd_32.h1
-rw-r--r--tools/perf/util/include/asm/unistd_64.h1
-rw-r--r--tools/perf/util/include/linux/bitmap.h11
-rw-r--r--tools/perf/util/include/linux/bitops.h2
-rw-r--r--tools/perf/util/include/linux/export.h (renamed from tools/perf/util/include/linux/module.h)0
-rw-r--r--tools/perf/util/map.c15
-rw-r--r--tools/perf/util/map.h1
-rw-r--r--tools/perf/util/parse-events.c614
-rw-r--r--tools/perf/util/parse-events.h49
-rw-r--r--tools/perf/util/parse-events.l127
-rw-r--r--tools/perf/util/parse-events.y229
-rw-r--r--tools/perf/util/pmu.c469
-rw-r--r--tools/perf/util/pmu.h41
-rw-r--r--tools/perf/util/pmu.l43
-rw-r--r--tools/perf/util/pmu.y93
-rw-r--r--tools/perf/util/probe-event.c41
-rw-r--r--tools/perf/util/probe-finder.c17
-rw-r--r--tools/perf/util/python-ext-sources19
-rw-r--r--tools/perf/util/python.c10
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c1
-rw-r--r--tools/perf/util/session.c127
-rw-r--r--tools/perf/util/session.h6
-rw-r--r--tools/perf/util/setup.py8
-rw-r--r--tools/perf/util/sort.c290
-rw-r--r--tools/perf/util/sort.h11
-rw-r--r--tools/perf/util/strbuf.c7
-rw-r--r--tools/perf/util/symbol.c28
-rw-r--r--tools/perf/util/symbol.h24
-rw-r--r--tools/perf/util/sysfs.c60
-rw-r--r--tools/perf/util/sysfs.h6
-rw-r--r--tools/perf/util/thread_map.c237
-rw-r--r--tools/perf/util/thread_map.h11
-rw-r--r--tools/perf/util/top.c13
-rw-r--r--tools/perf/util/top.h7
-rw-r--r--tools/perf/util/trace-event-info.c1
-rw-r--r--tools/perf/util/trace-event-parse.c26
-rw-r--r--tools/perf/util/trace-event-read.c1
-rw-r--r--tools/perf/util/trace-event-scripting.c1
-rw-r--r--tools/perf/util/ui/browser.h2
-rw-r--r--tools/perf/util/ui/browsers/annotate.c18
-rw-r--r--tools/perf/util/ui/browsers/hists.c133
-rw-r--r--tools/perf/util/ui/browsers/map.c2
-rw-r--r--tools/perf/util/ui/helpline.c3
-rw-r--r--tools/perf/util/ui/keysyms.h2
-rw-r--r--tools/perf/util/ui/util.c82
-rw-r--r--tools/perf/util/usage.c39
-rw-r--r--tools/perf/util/util.c17
-rw-r--r--tools/perf/util/util.h11
-rw-r--r--tools/power/cpupower/Makefile93
-rw-r--r--tools/power/cpupower/bench/Makefile23
-rw-r--r--tools/power/cpupower/debug/i386/Makefile40
-rw-r--r--tools/power/cpupower/debug/x86_64/Makefile26
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-info.14
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-set.14
-rw-r--r--tools/power/cpupower/man/cpupower-idle-info.190
-rw-r--r--tools/power/cpupower/man/cpupower-monitor.12
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c12
-rw-r--r--tools/power/cpupower/utils/helpers/amd.c4
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h11
-rw-r--r--tools/power/cpupower/utils/helpers/pci.c35
-rw-r--r--tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c25
-rw-r--r--tools/power/x86/turbostat/turbostat.899
-rw-r--r--tools/power/x86/turbostat/turbostat.c247
-rwxr-xr-xtools/testing/ktest/compare-ktest-sample.pl4
-rwxr-xr-xtools/testing/ktest/ktest.pl740
-rw-r--r--tools/testing/ktest/sample.conf101
-rw-r--r--tools/testing/selftests/Makefile16
-rw-r--r--tools/testing/selftests/breakpoints/Makefile23
-rw-r--r--tools/testing/selftests/breakpoints/breakpoint_test.c394
-rw-r--r--tools/testing/selftests/vm/Makefile14
-rw-r--r--tools/testing/selftests/vm/hugepage-mmap.c92
-rw-r--r--tools/testing/selftests/vm/hugepage-shm.c100
-rw-r--r--tools/testing/selftests/vm/map_hugetlb.c79
-rw-r--r--tools/testing/selftests/vm/run_vmtests77
-rw-r--r--tools/usb/Makefile2
-rw-r--r--tools/usb/ffs-test.c31
-rw-r--r--tools/usb/testusb.c2
-rw-r--r--tools/virtio/linux/hrtimer.h0
-rw-r--r--tools/virtio/linux/module.h0
-rw-r--r--tools/virtio/linux/virtio.h25
-rw-r--r--tools/virtio/virtio_test.c6
-rw-r--r--tools/vm/Makefile11
-rw-r--r--tools/vm/page-types.c1102
-rw-r--r--tools/vm/slabinfo.c (renamed from tools/slub/slabinfo.c)0
152 files changed, 10918 insertions, 1837 deletions
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 11224eddcdc2..146fd6147e84 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -34,21 +34,13 @@
34#include <errno.h> 34#include <errno.h>
35#include <arpa/inet.h> 35#include <arpa/inet.h>
36#include <linux/connector.h> 36#include <linux/connector.h>
37#include <linux/hyperv.h>
37#include <linux/netlink.h> 38#include <linux/netlink.h>
38#include <ifaddrs.h> 39#include <ifaddrs.h>
39#include <netdb.h> 40#include <netdb.h>
40#include <syslog.h> 41#include <syslog.h>
41 42#include <sys/stat.h>
42/* 43#include <fcntl.h>
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 44
53/* 45/*
54 * KVP protocol: The user mode component first registers with the 46 * KVP protocol: The user mode component first registers with the
@@ -60,25 +52,8 @@
60 * We use this infrastructure for also supporting queries from user mode 52 * We use this infrastructure for also supporting queries from user mode
61 * application for state that may be maintained in the KVP kernel component. 53 * application for state that may be maintained in the KVP kernel component.
62 * 54 *
63 * XXXKYS: Have a shared header file between the user and kernel (TODO)
64 */ 55 */
65 56
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 57
83enum key_index { 58enum key_index {
84 FullyQualifiedDomainName = 0, 59 FullyQualifiedDomainName = 0,
@@ -93,10 +68,6 @@ enum key_index {
93 ProcessorArchitecture 68 ProcessorArchitecture
94}; 69};
95 70
96/*
97 * End of shared definitions.
98 */
99
100static char kvp_send_buffer[4096]; 71static char kvp_send_buffer[4096];
101static char kvp_recv_buffer[4096]; 72static char kvp_recv_buffer[4096];
102static struct sockaddr_nl addr; 73static struct sockaddr_nl addr;
@@ -109,6 +80,345 @@ static char *os_build;
109static char *lic_version; 80static char *lic_version;
110static struct utsname uts_buf; 81static struct utsname uts_buf;
111 82
83
84#define MAX_FILE_NAME 100
85#define ENTRIES_PER_BLOCK 50
86
87struct kvp_record {
88 __u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
89 __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
90};
91
92struct kvp_file_state {
93 int fd;
94 int num_blocks;
95 struct kvp_record *records;
96 int num_records;
97 __u8 fname[MAX_FILE_NAME];
98};
99
100static struct kvp_file_state kvp_file_info[KVP_POOL_COUNT];
101
102static void kvp_acquire_lock(int pool)
103{
104 struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};
105 fl.l_pid = getpid();
106
107 if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) {
108 syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool);
109 exit(-1);
110 }
111}
112
113static void kvp_release_lock(int pool)
114{
115 struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
116 fl.l_pid = getpid();
117
118 if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) {
119 perror("fcntl");
120 syslog(LOG_ERR, "Failed to release the lock pool: %d", pool);
121 exit(-1);
122 }
123}
124
125static void kvp_update_file(int pool)
126{
127 FILE *filep;
128 size_t bytes_written;
129
130 /*
131 * We are going to write our in-memory registry out to
132 * disk; acquire the lock first.
133 */
134 kvp_acquire_lock(pool);
135
136 filep = fopen(kvp_file_info[pool].fname, "w");
137 if (!filep) {
138 kvp_release_lock(pool);
139 syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
140 exit(-1);
141 }
142
143 bytes_written = fwrite(kvp_file_info[pool].records,
144 sizeof(struct kvp_record),
145 kvp_file_info[pool].num_records, filep);
146
147 fflush(filep);
148 kvp_release_lock(pool);
149}
150
151static void kvp_update_mem_state(int pool)
152{
153 FILE *filep;
154 size_t records_read = 0;
155 struct kvp_record *record = kvp_file_info[pool].records;
156 struct kvp_record *readp;
157 int num_blocks = kvp_file_info[pool].num_blocks;
158 int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
159
160 kvp_acquire_lock(pool);
161
162 filep = fopen(kvp_file_info[pool].fname, "r");
163 if (!filep) {
164 kvp_release_lock(pool);
165 syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
166 exit(-1);
167 }
168 while (!feof(filep)) {
169 readp = &record[records_read];
170 records_read += fread(readp, sizeof(struct kvp_record),
171 ENTRIES_PER_BLOCK * num_blocks,
172 filep);
173
174 if (!feof(filep)) {
175 /*
176 * We have more data to read.
177 */
178 num_blocks++;
179 record = realloc(record, alloc_unit * num_blocks);
180
181 if (record == NULL) {
182 syslog(LOG_ERR, "malloc failed");
183 exit(-1);
184 }
185 continue;
186 }
187 break;
188 }
189
190 kvp_file_info[pool].num_blocks = num_blocks;
191 kvp_file_info[pool].records = record;
192 kvp_file_info[pool].num_records = records_read;
193
194 kvp_release_lock(pool);
195}
196static int kvp_file_init(void)
197{
198 int ret, fd;
199 FILE *filep;
200 size_t records_read;
201 __u8 *fname;
202 struct kvp_record *record;
203 struct kvp_record *readp;
204 int num_blocks;
205 int i;
206 int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
207
208 if (access("/var/opt/hyperv", F_OK)) {
209 if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) {
210 syslog(LOG_ERR, " Failed to create /var/opt/hyperv");
211 exit(-1);
212 }
213 }
214
215 for (i = 0; i < KVP_POOL_COUNT; i++) {
216 fname = kvp_file_info[i].fname;
217 records_read = 0;
218 num_blocks = 1;
219 sprintf(fname, "/var/opt/hyperv/.kvp_pool_%d", i);
220 fd = open(fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH);
221
222 if (fd == -1)
223 return 1;
224
225
226 filep = fopen(fname, "r");
227 if (!filep)
228 return 1;
229
230 record = malloc(alloc_unit * num_blocks);
231 if (record == NULL) {
232 fclose(filep);
233 return 1;
234 }
235 while (!feof(filep)) {
236 readp = &record[records_read];
237 records_read += fread(readp, sizeof(struct kvp_record),
238 ENTRIES_PER_BLOCK,
239 filep);
240
241 if (!feof(filep)) {
242 /*
243 * We have more data to read.
244 */
245 num_blocks++;
246 record = realloc(record, alloc_unit *
247 num_blocks);
248 if (record == NULL) {
249 fclose(filep);
250 return 1;
251 }
252 continue;
253 }
254 break;
255 }
256 kvp_file_info[i].fd = fd;
257 kvp_file_info[i].num_blocks = num_blocks;
258 kvp_file_info[i].records = record;
259 kvp_file_info[i].num_records = records_read;
260 fclose(filep);
261
262 }
263
264 return 0;
265}
266
267static int kvp_key_delete(int pool, __u8 *key, int key_size)
268{
269 int i;
270 int j, k;
271 int num_records;
272 struct kvp_record *record;
273
274 /*
275 * First update the in-memory state.
276 */
277 kvp_update_mem_state(pool);
278
279 num_records = kvp_file_info[pool].num_records;
280 record = kvp_file_info[pool].records;
281
282 for (i = 0; i < num_records; i++) {
283 if (memcmp(key, record[i].key, key_size))
284 continue;
285 /*
286 * Found a match; just move the remaining
287 * entries up.
288 */
289 if (i == num_records) {
290 kvp_file_info[pool].num_records--;
291 kvp_update_file(pool);
292 return 0;
293 }
294
295 j = i;
296 k = j + 1;
297 for (; k < num_records; k++) {
298 strcpy(record[j].key, record[k].key);
299 strcpy(record[j].value, record[k].value);
300 j++;
301 }
302
303 kvp_file_info[pool].num_records--;
304 kvp_update_file(pool);
305 return 0;
306 }
307 return 1;
308}
309
310static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value,
311 int value_size)
312{
313 int i;
314 int j, k;
315 int num_records;
316 struct kvp_record *record;
317 int num_blocks;
318
319 if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
320 (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
321 return 1;
322
323 /*
324 * First update the in-memory state.
325 */
326 kvp_update_mem_state(pool);
327
328 num_records = kvp_file_info[pool].num_records;
329 record = kvp_file_info[pool].records;
330 num_blocks = kvp_file_info[pool].num_blocks;
331
332 for (i = 0; i < num_records; i++) {
333 if (memcmp(key, record[i].key, key_size))
334 continue;
335 /*
336 * Found a match; just update the value -
337 * this is the modify case.
338 */
339 memcpy(record[i].value, value, value_size);
340 kvp_update_file(pool);
341 return 0;
342 }
343
344 /*
345 * Need to add a new entry;
346 */
347 if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) {
348 /* Need to allocate a larger array for reg entries. */
349 record = realloc(record, sizeof(struct kvp_record) *
350 ENTRIES_PER_BLOCK * (num_blocks + 1));
351
352 if (record == NULL)
353 return 1;
354 kvp_file_info[pool].num_blocks++;
355
356 }
357 memcpy(record[i].value, value, value_size);
358 memcpy(record[i].key, key, key_size);
359 kvp_file_info[pool].records = record;
360 kvp_file_info[pool].num_records++;
361 kvp_update_file(pool);
362 return 0;
363}
364
365static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
366 int value_size)
367{
368 int i;
369 int num_records;
370 struct kvp_record *record;
371
372 if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
373 (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
374 return 1;
375
376 /*
377 * First update the in-memory state.
378 */
379 kvp_update_mem_state(pool);
380
381 num_records = kvp_file_info[pool].num_records;
382 record = kvp_file_info[pool].records;
383
384 for (i = 0; i < num_records; i++) {
385 if (memcmp(key, record[i].key, key_size))
386 continue;
387 /*
388 * Found a match; just copy the value out.
389 */
390 memcpy(value, record[i].value, value_size);
391 return 0;
392 }
393
394 return 1;
395}
396
397static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
398 __u8 *value, int value_size)
399{
400 struct kvp_record *record;
401
402 /*
403 * First update our in-memory database.
404 */
405 kvp_update_mem_state(pool);
406 record = kvp_file_info[pool].records;
407
408 if (index >= kvp_file_info[pool].num_records) {
409 /*
410 * This is an invalid index; terminate enumeration;
411 * - a NULL value will do the trick.
412 */
413 strcpy(value, "");
414 return;
415 }
416
417 memcpy(key, record[index].key, key_size);
418 memcpy(value, record[index].value, value_size);
419}
420
421
112void kvp_get_os_info(void) 422void kvp_get_os_info(void)
113{ 423{
114 FILE *file; 424 FILE *file;
@@ -332,7 +642,7 @@ int main(void)
332 struct pollfd pfd; 642 struct pollfd pfd;
333 struct nlmsghdr *incoming_msg; 643 struct nlmsghdr *incoming_msg;
334 struct cn_msg *incoming_cn_msg; 644 struct cn_msg *incoming_cn_msg;
335 struct hv_ku_msg *hv_msg; 645 struct hv_kvp_msg *hv_msg;
336 char *p; 646 char *p;
337 char *key_value; 647 char *key_value;
338 char *key_name; 648 char *key_name;
@@ -345,6 +655,11 @@ int main(void)
345 */ 655 */
346 kvp_get_os_info(); 656 kvp_get_os_info();
347 657
658 if (kvp_file_init()) {
659 syslog(LOG_ERR, "Failed to initialize the pools");
660 exit(-1);
661 }
662
348 fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); 663 fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
349 if (fd < 0) { 664 if (fd < 0) {
350 syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); 665 syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
@@ -370,9 +685,11 @@ int main(void)
370 message = (struct cn_msg *)kvp_send_buffer; 685 message = (struct cn_msg *)kvp_send_buffer;
371 message->id.idx = CN_KVP_IDX; 686 message->id.idx = CN_KVP_IDX;
372 message->id.val = CN_KVP_VAL; 687 message->id.val = CN_KVP_VAL;
373 message->seq = KVP_REGISTER; 688
689 hv_msg = (struct hv_kvp_msg *)message->data;
690 hv_msg->kvp_hdr.operation = KVP_OP_REGISTER;
374 message->ack = 0; 691 message->ack = 0;
375 message->len = 0; 692 message->len = sizeof(struct hv_kvp_msg);
376 693
377 len = netlink_send(fd, message); 694 len = netlink_send(fd, message);
378 if (len < 0) { 695 if (len < 0) {
@@ -398,14 +715,15 @@ int main(void)
398 715
399 incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; 716 incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
400 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); 717 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
718 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
401 719
402 switch (incoming_cn_msg->seq) { 720 switch (hv_msg->kvp_hdr.operation) {
403 case KVP_REGISTER: 721 case KVP_OP_REGISTER:
404 /* 722 /*
405 * Driver is registering with us; stash away the version 723 * Driver is registering with us; stash away the version
406 * information. 724 * information.
407 */ 725 */
408 p = (char *)incoming_cn_msg->data; 726 p = (char *)hv_msg->body.kvp_register.version;
409 lic_version = malloc(strlen(p) + 1); 727 lic_version = malloc(strlen(p) + 1);
410 if (lic_version) { 728 if (lic_version) {
411 strcpy(lic_version, p); 729 strcpy(lic_version, p);
@@ -416,17 +734,65 @@ int main(void)
416 } 734 }
417 continue; 735 continue;
418 736
419 case KVP_KERNEL_GET: 737 /*
738 * The current protocol with the kernel component uses a
739 * NULL key name to pass an error condition.
740 * For the SET, GET and DELETE operations,
741 * use the existing protocol to pass back error.
742 */
743
744 case KVP_OP_SET:
745 if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool,
746 hv_msg->body.kvp_set.data.key,
747 hv_msg->body.kvp_set.data.key_size,
748 hv_msg->body.kvp_set.data.value,
749 hv_msg->body.kvp_set.data.value_size))
750 strcpy(hv_msg->body.kvp_set.data.key, "");
751 break;
752
753 case KVP_OP_GET:
754 if (kvp_get_value(hv_msg->kvp_hdr.pool,
755 hv_msg->body.kvp_set.data.key,
756 hv_msg->body.kvp_set.data.key_size,
757 hv_msg->body.kvp_set.data.value,
758 hv_msg->body.kvp_set.data.value_size))
759 strcpy(hv_msg->body.kvp_set.data.key, "");
760 break;
761
762 case KVP_OP_DELETE:
763 if (kvp_key_delete(hv_msg->kvp_hdr.pool,
764 hv_msg->body.kvp_delete.key,
765 hv_msg->body.kvp_delete.key_size))
766 strcpy(hv_msg->body.kvp_delete.key, "");
420 break; 767 break;
768
421 default: 769 default:
422 continue; 770 break;
771 }
772
773 if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE)
774 goto kvp_done;
775
776 /*
777 * If the pool is KVP_POOL_AUTO, dynamically generate
778 * both the key and the value; if not read from the
779 * appropriate pool.
780 */
781 if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) {
782 kvp_pool_enumerate(hv_msg->kvp_hdr.pool,
783 hv_msg->body.kvp_enum_data.index,
784 hv_msg->body.kvp_enum_data.data.key,
785 HV_KVP_EXCHANGE_MAX_KEY_SIZE,
786 hv_msg->body.kvp_enum_data.data.value,
787 HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
788 goto kvp_done;
423 } 789 }
424 790
425 hv_msg = (struct hv_ku_msg *)incoming_cn_msg->data; 791 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
426 key_name = (char *)hv_msg->kvp_key; 792 key_name = (char *)hv_msg->body.kvp_enum_data.data.key;
427 key_value = (char *)hv_msg->kvp_value; 793 key_value = (char *)hv_msg->body.kvp_enum_data.data.value;
428 794
429 switch (hv_msg->kvp_index) { 795 switch (hv_msg->body.kvp_enum_data.index) {
430 case FullyQualifiedDomainName: 796 case FullyQualifiedDomainName:
431 kvp_get_domain_name(key_value, 797 kvp_get_domain_name(key_value,
432 HV_KVP_EXCHANGE_MAX_VALUE_SIZE); 798 HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
@@ -483,12 +849,12 @@ int main(void)
483 * already in the receive buffer. Update the cn_msg header to 849 * already in the receive buffer. Update the cn_msg header to
484 * reflect the key value that has been added to the message 850 * reflect the key value that has been added to the message
485 */ 851 */
852kvp_done:
486 853
487 incoming_cn_msg->id.idx = CN_KVP_IDX; 854 incoming_cn_msg->id.idx = CN_KVP_IDX;
488 incoming_cn_msg->id.val = CN_KVP_VAL; 855 incoming_cn_msg->id.val = CN_KVP_VAL;
489 incoming_cn_msg->seq = KVP_USER_SET;
490 incoming_cn_msg->ack = 0; 856 incoming_cn_msg->ack = 0;
491 incoming_cn_msg->len = sizeof(struct hv_ku_msg); 857 incoming_cn_msg->len = sizeof(struct hv_kvp_msg);
492 858
493 len = netlink_send(fd, incoming_cn_msg); 859 len = netlink_send(fd, incoming_cn_msg);
494 if (len < 0) { 860 if (len < 0) {
diff --git a/tools/include/tools/be_byteshift.h b/tools/include/tools/be_byteshift.h
new file mode 100644
index 000000000000..f4912e2668ba
--- /dev/null
+++ b/tools/include/tools/be_byteshift.h
@@ -0,0 +1,70 @@
1#ifndef _TOOLS_BE_BYTESHIFT_H
2#define _TOOLS_BE_BYTESHIFT_H
3
4#include <linux/types.h>
5
6static inline __u16 __get_unaligned_be16(const __u8 *p)
7{
8 return p[0] << 8 | p[1];
9}
10
11static inline __u32 __get_unaligned_be32(const __u8 *p)
12{
13 return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
14}
15
16static inline __u64 __get_unaligned_be64(const __u8 *p)
17{
18 return (__u64)__get_unaligned_be32(p) << 32 |
19 __get_unaligned_be32(p + 4);
20}
21
22static inline void __put_unaligned_be16(__u16 val, __u8 *p)
23{
24 *p++ = val >> 8;
25 *p++ = val;
26}
27
28static inline void __put_unaligned_be32(__u32 val, __u8 *p)
29{
30 __put_unaligned_be16(val >> 16, p);
31 __put_unaligned_be16(val, p + 2);
32}
33
34static inline void __put_unaligned_be64(__u64 val, __u8 *p)
35{
36 __put_unaligned_be32(val >> 32, p);
37 __put_unaligned_be32(val, p + 4);
38}
39
40static inline __u16 get_unaligned_be16(const void *p)
41{
42 return __get_unaligned_be16((const __u8 *)p);
43}
44
45static inline __u32 get_unaligned_be32(const void *p)
46{
47 return __get_unaligned_be32((const __u8 *)p);
48}
49
50static inline __u64 get_unaligned_be64(const void *p)
51{
52 return __get_unaligned_be64((const __u8 *)p);
53}
54
55static inline void put_unaligned_be16(__u16 val, void *p)
56{
57 __put_unaligned_be16(val, p);
58}
59
60static inline void put_unaligned_be32(__u32 val, void *p)
61{
62 __put_unaligned_be32(val, p);
63}
64
65static inline void put_unaligned_be64(__u64 val, void *p)
66{
67 __put_unaligned_be64(val, p);
68}
69
70#endif /* _TOOLS_BE_BYTESHIFT_H */
diff --git a/tools/include/tools/le_byteshift.h b/tools/include/tools/le_byteshift.h
new file mode 100644
index 000000000000..c99d45a68bda
--- /dev/null
+++ b/tools/include/tools/le_byteshift.h
@@ -0,0 +1,70 @@
1#ifndef _TOOLS_LE_BYTESHIFT_H
2#define _TOOLS_LE_BYTESHIFT_H
3
4#include <linux/types.h>
5
6static inline __u16 __get_unaligned_le16(const __u8 *p)
7{
8 return p[0] | p[1] << 8;
9}
10
11static inline __u32 __get_unaligned_le32(const __u8 *p)
12{
13 return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
14}
15
16static inline __u64 __get_unaligned_le64(const __u8 *p)
17{
18 return (__u64)__get_unaligned_le32(p + 4) << 32 |
19 __get_unaligned_le32(p);
20}
21
22static inline void __put_unaligned_le16(__u16 val, __u8 *p)
23{
24 *p++ = val;
25 *p++ = val >> 8;
26}
27
28static inline void __put_unaligned_le32(__u32 val, __u8 *p)
29{
30 __put_unaligned_le16(val >> 16, p + 2);
31 __put_unaligned_le16(val, p);
32}
33
34static inline void __put_unaligned_le64(__u64 val, __u8 *p)
35{
36 __put_unaligned_le32(val >> 32, p + 4);
37 __put_unaligned_le32(val, p);
38}
39
40static inline __u16 get_unaligned_le16(const void *p)
41{
42 return __get_unaligned_le16((const __u8 *)p);
43}
44
45static inline __u32 get_unaligned_le32(const void *p)
46{
47 return __get_unaligned_le32((const __u8 *)p);
48}
49
50static inline __u64 get_unaligned_le64(const void *p)
51{
52 return __get_unaligned_le64((const __u8 *)p);
53}
54
55static inline void put_unaligned_le16(__u16 val, void *p)
56{
57 __put_unaligned_le16(val, p);
58}
59
60static inline void put_unaligned_le32(__u32 val, void *p)
61{
62 __put_unaligned_le32(val, p);
63}
64
65static inline void put_unaligned_le64(__u64 val, void *p)
66{
67 __put_unaligned_le64(val, p);
68}
69
70#endif /* _TOOLS_LE_BYTESHIFT_H */
diff --git a/tools/lguest/.gitignore b/tools/lguest/.gitignore
new file mode 100644
index 000000000000..115587fd5f65
--- /dev/null
+++ b/tools/lguest/.gitignore
@@ -0,0 +1 @@
lguest
diff --git a/tools/lguest/Makefile b/tools/lguest/Makefile
new file mode 100644
index 000000000000..0ac34206f7a7
--- /dev/null
+++ b/tools/lguest/Makefile
@@ -0,0 +1,8 @@
1# This creates the demonstration utility "lguest" which runs a Linux guest.
2# Missing headers? Add "-I../../../include -I../../../arch/x86/include"
3CFLAGS:=-m32 -Wall -Wmissing-declarations -Wmissing-prototypes -O3 -U_FORTIFY_SOURCE
4
5all: lguest
6
7clean:
8 rm -f lguest
diff --git a/tools/lguest/extract b/tools/lguest/extract
new file mode 100644
index 000000000000..7730bb6e4b94
--- /dev/null
+++ b/tools/lguest/extract
@@ -0,0 +1,58 @@
1#! /bin/sh
2
3set -e
4
5PREFIX=$1
6shift
7
8trap 'rm -r $TMPDIR' 0
9TMPDIR=`mktemp -d`
10
11exec 3>/dev/null
12for f; do
13 while IFS="
14" read -r LINE; do
15 case "$LINE" in
16 *$PREFIX:[0-9]*:\**)
17 NUM=`echo "$LINE" | sed "s/.*$PREFIX:\([0-9]*\).*/\1/"`
18 if [ -f $TMPDIR/$NUM ]; then
19 echo "$TMPDIR/$NUM already exits prior to $f"
20 exit 1
21 fi
22 exec 3>>$TMPDIR/$NUM
23 echo $f | sed 's,\.\./,,g' > $TMPDIR/.$NUM
24 /bin/echo "$LINE" | sed -e "s/$PREFIX:[0-9]*//" -e "s/:\*/*/" >&3
25 ;;
26 *$PREFIX:[0-9]*)
27 NUM=`echo "$LINE" | sed "s/.*$PREFIX:\([0-9]*\).*/\1/"`
28 if [ -f $TMPDIR/$NUM ]; then
29 echo "$TMPDIR/$NUM already exits prior to $f"
30 exit 1
31 fi
32 exec 3>>$TMPDIR/$NUM
33 echo $f | sed 's,\.\./,,g' > $TMPDIR/.$NUM
34 /bin/echo "$LINE" | sed "s/$PREFIX:[0-9]*//" >&3
35 ;;
36 *:\**)
37 /bin/echo "$LINE" | sed -e "s/:\*/*/" -e "s,/\*\*/,," >&3
38 echo >&3
39 exec 3>/dev/null
40 ;;
41 *)
42 /bin/echo "$LINE" >&3
43 ;;
44 esac
45 done < $f
46 echo >&3
47 exec 3>/dev/null
48done
49
50LASTFILE=""
51for f in $TMPDIR/*; do
52 if [ "$LASTFILE" != $(cat $TMPDIR/.$(basename $f) ) ]; then
53 LASTFILE=$(cat $TMPDIR/.$(basename $f) )
54 echo "[ $LASTFILE ]"
55 fi
56 cat $f
57done
58
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
new file mode 100644
index 000000000000..f759f4f097c7
--- /dev/null
+++ b/tools/lguest/lguest.c
@@ -0,0 +1,2065 @@
1/*P:100
2 * This is the Launcher code, a simple program which lays out the "physical"
3 * memory for the new Guest by mapping the kernel image and the virtual
4 * devices, then opens /dev/lguest to tell the kernel about the Guest and
5 * control it.
6:*/
7#define _LARGEFILE64_SOURCE
8#define _GNU_SOURCE
9#include <stdio.h>
10#include <string.h>
11#include <unistd.h>
12#include <err.h>
13#include <stdint.h>
14#include <stdlib.h>
15#include <elf.h>
16#include <sys/mman.h>
17#include <sys/param.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <sys/wait.h>
21#include <sys/eventfd.h>
22#include <fcntl.h>
23#include <stdbool.h>
24#include <errno.h>
25#include <ctype.h>
26#include <sys/socket.h>
27#include <sys/ioctl.h>
28#include <sys/time.h>
29#include <time.h>
30#include <netinet/in.h>
31#include <net/if.h>
32#include <linux/sockios.h>
33#include <linux/if_tun.h>
34#include <sys/uio.h>
35#include <termios.h>
36#include <getopt.h>
37#include <assert.h>
38#include <sched.h>
39#include <limits.h>
40#include <stddef.h>
41#include <signal.h>
42#include <pwd.h>
43#include <grp.h>
44
45#include <linux/virtio_config.h>
46#include <linux/virtio_net.h>
47#include <linux/virtio_blk.h>
48#include <linux/virtio_console.h>
49#include <linux/virtio_rng.h>
50#include <linux/virtio_ring.h>
51#include <asm/bootparam.h>
52#include "../../include/linux/lguest_launcher.h"
53/*L:110
54 * We can ignore the 43 include files we need for this program, but I do want
55 * to draw attention to the use of kernel-style types.
56 *
57 * As Linus said, "C is a Spartan language, and so should your naming be." I
58 * like these abbreviations, so we define them here. Note that u64 is always
59 * unsigned long long, which works on all Linux systems: this means that we can
60 * use %llu in printf for any u64.
61 */
62typedef unsigned long long u64;
63typedef uint32_t u32;
64typedef uint16_t u16;
65typedef uint8_t u8;
66/*:*/
67
68#define BRIDGE_PFX "bridge:"
69#ifndef SIOCBRADDIF
70#define SIOCBRADDIF 0x89a2 /* add interface to bridge */
71#endif
72/* We can have up to 256 pages for devices. */
73#define DEVICE_PAGES 256
74/* This will occupy 3 pages: it must be a power of 2. */
75#define VIRTQUEUE_NUM 256
76
77/*L:120
78 * verbose is both a global flag and a macro. The C preprocessor allows
79 * this, and although I wouldn't recommend it, it works quite nicely here.
80 */
81static bool verbose;
82#define verbose(args...) \
83 do { if (verbose) printf(args); } while(0)
84/*:*/
85
86/* The pointer to the start of guest memory. */
87static void *guest_base;
88/* The maximum guest physical address allowed, and maximum possible. */
89static unsigned long guest_limit, guest_max;
90/* The /dev/lguest file descriptor. */
91static int lguest_fd;
92
93/* a per-cpu variable indicating whose vcpu is currently running */
94static unsigned int __thread cpu_id;
95
96/* This is our list of devices. */
97struct device_list {
98 /* Counter to assign interrupt numbers. */
99 unsigned int next_irq;
100
101 /* Counter to print out convenient device numbers. */
102 unsigned int device_num;
103
104 /* The descriptor page for the devices. */
105 u8 *descpage;
106
107 /* A single linked list of devices. */
108 struct device *dev;
109 /* And a pointer to the last device for easy append. */
110 struct device *lastdev;
111};
112
113/* The list of Guest devices, based on command line arguments. */
114static struct device_list devices;
115
116/* The device structure describes a single device. */
117struct device {
118 /* The linked-list pointer. */
119 struct device *next;
120
121 /* The device's descriptor, as mapped into the Guest. */
122 struct lguest_device_desc *desc;
123
124 /* We can't trust desc values once Guest has booted: we use these. */
125 unsigned int feature_len;
126 unsigned int num_vq;
127
128 /* The name of this device, for --verbose. */
129 const char *name;
130
131 /* Any queues attached to this device */
132 struct virtqueue *vq;
133
134 /* Is it operational */
135 bool running;
136
137 /* Device-specific data. */
138 void *priv;
139};
140
141/* The virtqueue structure describes a queue attached to a device. */
142struct virtqueue {
143 struct virtqueue *next;
144
145 /* Which device owns me. */
146 struct device *dev;
147
148 /* The configuration for this queue. */
149 struct lguest_vqconfig config;
150
151 /* The actual ring of buffers. */
152 struct vring vring;
153
154 /* Last available index we saw. */
155 u16 last_avail_idx;
156
157 /* How many are used since we sent last irq? */
158 unsigned int pending_used;
159
160 /* Eventfd where Guest notifications arrive. */
161 int eventfd;
162
163 /* Function for the thread which is servicing this virtqueue. */
164 void (*service)(struct virtqueue *vq);
165 pid_t thread;
166};
167
168/* Remember the arguments to the program so we can "reboot" */
169static char **main_args;
170
171/* The original tty settings to restore on exit. */
172static struct termios orig_term;
173
174/*
175 * We have to be careful with barriers: our devices are all run in separate
176 * threads and so we need to make sure that changes visible to the Guest happen
177 * in precise order.
178 */
179#define wmb() __asm__ __volatile__("" : : : "memory")
180#define mb() __asm__ __volatile__("" : : : "memory")
181
182/*
183 * Convert an iovec element to the given type.
184 *
185 * This is a fairly ugly trick: we need to know the size of the type and
186 * alignment requirement to check the pointer is kosher. It's also nice to
187 * have the name of the type in case we report failure.
188 *
189 * Typing those three things all the time is cumbersome and error prone, so we
190 * have a macro which sets them all up and passes to the real function.
191 */
192#define convert(iov, type) \
193 ((type *)_convert((iov), sizeof(type), __alignof__(type), #type))
194
195static void *_convert(struct iovec *iov, size_t size, size_t align,
196 const char *name)
197{
198 if (iov->iov_len != size)
199 errx(1, "Bad iovec size %zu for %s", iov->iov_len, name);
200 if ((unsigned long)iov->iov_base % align != 0)
201 errx(1, "Bad alignment %p for %s", iov->iov_base, name);
202 return iov->iov_base;
203}
204
205/* Wrapper for the last available index. Makes it easier to change. */
206#define lg_last_avail(vq) ((vq)->last_avail_idx)
207
208/*
209 * The virtio configuration space is defined to be little-endian. x86 is
210 * little-endian too, but it's nice to be explicit so we have these helpers.
211 */
212#define cpu_to_le16(v16) (v16)
213#define cpu_to_le32(v32) (v32)
214#define cpu_to_le64(v64) (v64)
215#define le16_to_cpu(v16) (v16)
216#define le32_to_cpu(v32) (v32)
217#define le64_to_cpu(v64) (v64)
218
219/* Is this iovec empty? */
220static bool iov_empty(const struct iovec iov[], unsigned int num_iov)
221{
222 unsigned int i;
223
224 for (i = 0; i < num_iov; i++)
225 if (iov[i].iov_len)
226 return false;
227 return true;
228}
229
230/* Take len bytes from the front of this iovec. */
231static void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
232{
233 unsigned int i;
234
235 for (i = 0; i < num_iov; i++) {
236 unsigned int used;
237
238 used = iov[i].iov_len < len ? iov[i].iov_len : len;
239 iov[i].iov_base += used;
240 iov[i].iov_len -= used;
241 len -= used;
242 }
243 assert(len == 0);
244}
245
246/* The device virtqueue descriptors are followed by feature bitmasks. */
247static u8 *get_feature_bits(struct device *dev)
248{
249 return (u8 *)(dev->desc + 1)
250 + dev->num_vq * sizeof(struct lguest_vqconfig);
251}
252
253/*L:100
254 * The Launcher code itself takes us out into userspace, that scary place where
255 * pointers run wild and free! Unfortunately, like most userspace programs,
256 * it's quite boring (which is why everyone likes to hack on the kernel!).
257 * Perhaps if you make up an Lguest Drinking Game at this point, it will get
258 * you through this section. Or, maybe not.
259 *
260 * The Launcher sets up a big chunk of memory to be the Guest's "physical"
261 * memory and stores it in "guest_base". In other words, Guest physical ==
262 * Launcher virtual with an offset.
263 *
264 * This can be tough to get your head around, but usually it just means that we
265 * use these trivial conversion functions when the Guest gives us its
266 * "physical" addresses:
267 */
268static void *from_guest_phys(unsigned long addr)
269{
270 return guest_base + addr;
271}
272
273static unsigned long to_guest_phys(const void *addr)
274{
275 return (addr - guest_base);
276}
277
278/*L:130
279 * Loading the Kernel.
280 *
281 * We start with couple of simple helper routines. open_or_die() avoids
282 * error-checking code cluttering the callers:
283 */
284static int open_or_die(const char *name, int flags)
285{
286 int fd = open(name, flags);
287 if (fd < 0)
288 err(1, "Failed to open %s", name);
289 return fd;
290}
291
292/* map_zeroed_pages() takes a number of pages. */
293static void *map_zeroed_pages(unsigned int num)
294{
295 int fd = open_or_die("/dev/zero", O_RDONLY);
296 void *addr;
297
298 /*
299 * We use a private mapping (ie. if we write to the page, it will be
300 * copied). We allocate an extra two pages PROT_NONE to act as guard
301 * pages against read/write attempts that exceed allocated space.
302 */
303 addr = mmap(NULL, getpagesize() * (num+2),
304 PROT_NONE, MAP_PRIVATE, fd, 0);
305
306 if (addr == MAP_FAILED)
307 err(1, "Mmapping %u pages of /dev/zero", num);
308
309 if (mprotect(addr + getpagesize(), getpagesize() * num,
310 PROT_READ|PROT_WRITE) == -1)
311 err(1, "mprotect rw %u pages failed", num);
312
313 /*
314 * One neat mmap feature is that you can close the fd, and it
315 * stays mapped.
316 */
317 close(fd);
318
319 /* Return address after PROT_NONE page */
320 return addr + getpagesize();
321}
322
323/* Get some more pages for a device. */
324static void *get_pages(unsigned int num)
325{
326 void *addr = from_guest_phys(guest_limit);
327
328 guest_limit += num * getpagesize();
329 if (guest_limit > guest_max)
330 errx(1, "Not enough memory for devices");
331 return addr;
332}
333
334/*
335 * This routine is used to load the kernel or initrd. It tries mmap, but if
336 * that fails (Plan 9's kernel file isn't nicely aligned on page boundaries),
337 * it falls back to reading the memory in.
338 */
339static void map_at(int fd, void *addr, unsigned long offset, unsigned long len)
340{
341 ssize_t r;
342
343 /*
344 * We map writable even though for some segments are marked read-only.
345 * The kernel really wants to be writable: it patches its own
346 * instructions.
347 *
348 * MAP_PRIVATE means that the page won't be copied until a write is
349 * done to it. This allows us to share untouched memory between
350 * Guests.
351 */
352 if (mmap(addr, len, PROT_READ|PROT_WRITE,
353 MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED)
354 return;
355
356 /* pread does a seek and a read in one shot: saves a few lines. */
357 r = pread(fd, addr, len, offset);
358 if (r != len)
359 err(1, "Reading offset %lu len %lu gave %zi", offset, len, r);
360}
361
362/*
363 * This routine takes an open vmlinux image, which is in ELF, and maps it into
364 * the Guest memory. ELF = Embedded Linking Format, which is the format used
365 * by all modern binaries on Linux including the kernel.
366 *
367 * The ELF headers give *two* addresses: a physical address, and a virtual
368 * address. We use the physical address; the Guest will map itself to the
369 * virtual address.
370 *
371 * We return the starting address.
372 */
373static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
374{
375 Elf32_Phdr phdr[ehdr->e_phnum];
376 unsigned int i;
377
378 /*
379 * Sanity checks on the main ELF header: an x86 executable with a
380 * reasonable number of correctly-sized program headers.
381 */
382 if (ehdr->e_type != ET_EXEC
383 || ehdr->e_machine != EM_386
384 || ehdr->e_phentsize != sizeof(Elf32_Phdr)
385 || ehdr->e_phnum < 1 || ehdr->e_phnum > 65536U/sizeof(Elf32_Phdr))
386 errx(1, "Malformed elf header");
387
388 /*
389 * An ELF executable contains an ELF header and a number of "program"
390 * headers which indicate which parts ("segments") of the program to
391 * load where.
392 */
393
394 /* We read in all the program headers at once: */
395 if (lseek(elf_fd, ehdr->e_phoff, SEEK_SET) < 0)
396 err(1, "Seeking to program headers");
397 if (read(elf_fd, phdr, sizeof(phdr)) != sizeof(phdr))
398 err(1, "Reading program headers");
399
400 /*
401 * Try all the headers: there are usually only three. A read-only one,
402 * a read-write one, and a "note" section which we don't load.
403 */
404 for (i = 0; i < ehdr->e_phnum; i++) {
405 /* If this isn't a loadable segment, we ignore it */
406 if (phdr[i].p_type != PT_LOAD)
407 continue;
408
409 verbose("Section %i: size %i addr %p\n",
410 i, phdr[i].p_memsz, (void *)phdr[i].p_paddr);
411
412 /* We map this section of the file at its physical address. */
413 map_at(elf_fd, from_guest_phys(phdr[i].p_paddr),
414 phdr[i].p_offset, phdr[i].p_filesz);
415 }
416
417 /* The entry point is given in the ELF header. */
418 return ehdr->e_entry;
419}
420
421/*L:150
422 * A bzImage, unlike an ELF file, is not meant to be loaded. You're supposed
423 * to jump into it and it will unpack itself. We used to have to perform some
424 * hairy magic because the unpacking code scared me.
425 *
426 * Fortunately, Jeremy Fitzhardinge convinced me it wasn't that hard and wrote
427 * a small patch to jump over the tricky bits in the Guest, so now we just read
428 * the funky header so we know where in the file to load, and away we go!
429 */
430static unsigned long load_bzimage(int fd)
431{
432 struct boot_params boot;
433 int r;
434 /* Modern bzImages get loaded at 1M. */
435 void *p = from_guest_phys(0x100000);
436
437 /*
438 * Go back to the start of the file and read the header. It should be
439 * a Linux boot header (see Documentation/x86/boot.txt)
440 */
441 lseek(fd, 0, SEEK_SET);
442 read(fd, &boot, sizeof(boot));
443
444 /* Inside the setup_hdr, we expect the magic "HdrS" */
445 if (memcmp(&boot.hdr.header, "HdrS", 4) != 0)
446 errx(1, "This doesn't look like a bzImage to me");
447
448 /* Skip over the extra sectors of the header. */
449 lseek(fd, (boot.hdr.setup_sects+1) * 512, SEEK_SET);
450
451 /* Now read everything into memory. in nice big chunks. */
452 while ((r = read(fd, p, 65536)) > 0)
453 p += r;
454
455 /* Finally, code32_start tells us where to enter the kernel. */
456 return boot.hdr.code32_start;
457}
458
459/*L:140
460 * Loading the kernel is easy when it's a "vmlinux", but most kernels
461 * come wrapped up in the self-decompressing "bzImage" format. With a little
462 * work, we can load those, too.
463 */
464static unsigned long load_kernel(int fd)
465{
466 Elf32_Ehdr hdr;
467
468 /* Read in the first few bytes. */
469 if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
470 err(1, "Reading kernel");
471
472 /* If it's an ELF file, it starts with "\177ELF" */
473 if (memcmp(hdr.e_ident, ELFMAG, SELFMAG) == 0)
474 return map_elf(fd, &hdr);
475
476 /* Otherwise we assume it's a bzImage, and try to load it. */
477 return load_bzimage(fd);
478}
479
480/*
481 * This is a trivial little helper to align pages. Andi Kleen hated it because
482 * it calls getpagesize() twice: "it's dumb code."
483 *
484 * Kernel guys get really het up about optimization, even when it's not
485 * necessary. I leave this code as a reaction against that.
486 */
487static inline unsigned long page_align(unsigned long addr)
488{
489 /* Add upwards and truncate downwards. */
490 return ((addr + getpagesize()-1) & ~(getpagesize()-1));
491}
492
493/*L:180
494 * An "initial ram disk" is a disk image loaded into memory along with the
495 * kernel which the kernel can use to boot from without needing any drivers.
496 * Most distributions now use this as standard: the initrd contains the code to
497 * load the appropriate driver modules for the current machine.
498 *
499 * Importantly, James Morris works for RedHat, and Fedora uses initrds for its
500 * kernels. He sent me this (and tells me when I break it).
501 */
502static unsigned long load_initrd(const char *name, unsigned long mem)
503{
504 int ifd;
505 struct stat st;
506 unsigned long len;
507
508 ifd = open_or_die(name, O_RDONLY);
509 /* fstat() is needed to get the file size. */
510 if (fstat(ifd, &st) < 0)
511 err(1, "fstat() on initrd '%s'", name);
512
513 /*
514 * We map the initrd at the top of memory, but mmap wants it to be
515 * page-aligned, so we round the size up for that.
516 */
517 len = page_align(st.st_size);
518 map_at(ifd, from_guest_phys(mem - len), 0, st.st_size);
519 /*
520 * Once a file is mapped, you can close the file descriptor. It's a
521 * little odd, but quite useful.
522 */
523 close(ifd);
524 verbose("mapped initrd %s size=%lu @ %p\n", name, len, (void*)mem-len);
525
526 /* We return the initrd size. */
527 return len;
528}
529/*:*/
530
531/*
532 * Simple routine to roll all the commandline arguments together with spaces
533 * between them.
534 */
535static void concat(char *dst, char *args[])
536{
537 unsigned int i, len = 0;
538
539 for (i = 0; args[i]; i++) {
540 if (i) {
541 strcat(dst+len, " ");
542 len++;
543 }
544 strcpy(dst+len, args[i]);
545 len += strlen(args[i]);
546 }
547 /* In case it's empty. */
548 dst[len] = '\0';
549}
550
551/*L:185
552 * This is where we actually tell the kernel to initialize the Guest. We
553 * saw the arguments it expects when we looked at initialize() in lguest_user.c:
554 * the base of Guest "physical" memory, the top physical page to allow and the
555 * entry point for the Guest.
556 */
557static void tell_kernel(unsigned long start)
558{
559 unsigned long args[] = { LHREQ_INITIALIZE,
560 (unsigned long)guest_base,
561 guest_limit / getpagesize(), start };
562 verbose("Guest: %p - %p (%#lx)\n",
563 guest_base, guest_base + guest_limit, guest_limit);
564 lguest_fd = open_or_die("/dev/lguest", O_RDWR);
565 if (write(lguest_fd, args, sizeof(args)) < 0)
566 err(1, "Writing to /dev/lguest");
567}
568/*:*/
569
570/*L:200
571 * Device Handling.
572 *
573 * When the Guest gives us a buffer, it sends an array of addresses and sizes.
574 * We need to make sure it's not trying to reach into the Launcher itself, so
575 * we have a convenient routine which checks it and exits with an error message
576 * if something funny is going on:
577 */
578static void *_check_pointer(unsigned long addr, unsigned int size,
579 unsigned int line)
580{
581 /*
582 * Check if the requested address and size exceeds the allocated memory,
583 * or addr + size wraps around.
584 */
585 if ((addr + size) > guest_limit || (addr + size) < addr)
586 errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr);
587 /*
588 * We return a pointer for the caller's convenience, now we know it's
589 * safe to use.
590 */
591 return from_guest_phys(addr);
592}
593/* A macro which transparently hands the line number to the real function. */
594#define check_pointer(addr,size) _check_pointer(addr, size, __LINE__)
595
596/*
597 * Each buffer in the virtqueues is actually a chain of descriptors. This
598 * function returns the next descriptor in the chain, or vq->vring.num if we're
599 * at the end.
600 */
601static unsigned next_desc(struct vring_desc *desc,
602 unsigned int i, unsigned int max)
603{
604 unsigned int next;
605
606 /* If this descriptor says it doesn't chain, we're done. */
607 if (!(desc[i].flags & VRING_DESC_F_NEXT))
608 return max;
609
610 /* Check they're not leading us off end of descriptors. */
611 next = desc[i].next;
612 /* Make sure compiler knows to grab that: we don't want it changing! */
613 wmb();
614
615 if (next >= max)
616 errx(1, "Desc next is %u", next);
617
618 return next;
619}
620
621/*
622 * This actually sends the interrupt for this virtqueue, if we've used a
623 * buffer.
624 */
625static void trigger_irq(struct virtqueue *vq)
626{
627 unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
628
629 /* Don't inform them if nothing used. */
630 if (!vq->pending_used)
631 return;
632 vq->pending_used = 0;
633
634 /* If they don't want an interrupt, don't send one... */
635 if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) {
636 return;
637 }
638
639 /* Send the Guest an interrupt tell them we used something up. */
640 if (write(lguest_fd, buf, sizeof(buf)) != 0)
641 err(1, "Triggering irq %i", vq->config.irq);
642}
643
644/*
645 * This looks in the virtqueue for the first available buffer, and converts
646 * it to an iovec for convenient access. Since descriptors consist of some
647 * number of output then some number of input descriptors, it's actually two
648 * iovecs, but we pack them into one and note how many of each there were.
649 *
650 * This function waits if necessary, and returns the descriptor number found.
651 */
652static unsigned wait_for_vq_desc(struct virtqueue *vq,
653 struct iovec iov[],
654 unsigned int *out_num, unsigned int *in_num)
655{
656 unsigned int i, head, max;
657 struct vring_desc *desc;
658 u16 last_avail = lg_last_avail(vq);
659
660 /* There's nothing available? */
661 while (last_avail == vq->vring.avail->idx) {
662 u64 event;
663
664 /*
665 * Since we're about to sleep, now is a good time to tell the
666 * Guest about what we've used up to now.
667 */
668 trigger_irq(vq);
669
670 /* OK, now we need to know about added descriptors. */
671 vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
672
673 /*
674 * They could have slipped one in as we were doing that: make
675 * sure it's written, then check again.
676 */
677 mb();
678 if (last_avail != vq->vring.avail->idx) {
679 vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
680 break;
681 }
682
683 /* Nothing new? Wait for eventfd to tell us they refilled. */
684 if (read(vq->eventfd, &event, sizeof(event)) != sizeof(event))
685 errx(1, "Event read failed?");
686
687 /* We don't need to be notified again. */
688 vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
689 }
690
691 /* Check it isn't doing very strange things with descriptor numbers. */
692 if ((u16)(vq->vring.avail->idx - last_avail) > vq->vring.num)
693 errx(1, "Guest moved used index from %u to %u",
694 last_avail, vq->vring.avail->idx);
695
696 /*
697 * Grab the next descriptor number they're advertising, and increment
698 * the index we've seen.
699 */
700 head = vq->vring.avail->ring[last_avail % vq->vring.num];
701 lg_last_avail(vq)++;
702
703 /* If their number is silly, that's a fatal mistake. */
704 if (head >= vq->vring.num)
705 errx(1, "Guest says index %u is available", head);
706
707 /* When we start there are none of either input nor output. */
708 *out_num = *in_num = 0;
709
710 max = vq->vring.num;
711 desc = vq->vring.desc;
712 i = head;
713
714 /*
715 * If this is an indirect entry, then this buffer contains a descriptor
716 * table which we handle as if it's any normal descriptor chain.
717 */
718 if (desc[i].flags & VRING_DESC_F_INDIRECT) {
719 if (desc[i].len % sizeof(struct vring_desc))
720 errx(1, "Invalid size for indirect buffer table");
721
722 max = desc[i].len / sizeof(struct vring_desc);
723 desc = check_pointer(desc[i].addr, desc[i].len);
724 i = 0;
725 }
726
727 do {
728 /* Grab the first descriptor, and check it's OK. */
729 iov[*out_num + *in_num].iov_len = desc[i].len;
730 iov[*out_num + *in_num].iov_base
731 = check_pointer(desc[i].addr, desc[i].len);
732 /* If this is an input descriptor, increment that count. */
733 if (desc[i].flags & VRING_DESC_F_WRITE)
734 (*in_num)++;
735 else {
736 /*
737 * If it's an output descriptor, they're all supposed
738 * to come before any input descriptors.
739 */
740 if (*in_num)
741 errx(1, "Descriptor has out after in");
742 (*out_num)++;
743 }
744
745 /* If we've got too many, that implies a descriptor loop. */
746 if (*out_num + *in_num > max)
747 errx(1, "Looped descriptor");
748 } while ((i = next_desc(desc, i, max)) != max);
749
750 return head;
751}
752
753/*
754 * After we've used one of their buffers, we tell the Guest about it. Sometime
755 * later we'll want to send them an interrupt using trigger_irq(); note that
756 * wait_for_vq_desc() does that for us if it has to wait.
757 */
758static void add_used(struct virtqueue *vq, unsigned int head, int len)
759{
760 struct vring_used_elem *used;
761
762 /*
763 * The virtqueue contains a ring of used buffers. Get a pointer to the
764 * next entry in that used ring.
765 */
766 used = &vq->vring.used->ring[vq->vring.used->idx % vq->vring.num];
767 used->id = head;
768 used->len = len;
769 /* Make sure buffer is written before we update index. */
770 wmb();
771 vq->vring.used->idx++;
772 vq->pending_used++;
773}
774
775/* And here's the combo meal deal. Supersize me! */
776static void add_used_and_trigger(struct virtqueue *vq, unsigned head, int len)
777{
778 add_used(vq, head, len);
779 trigger_irq(vq);
780}
781
782/*
783 * The Console
784 *
785 * We associate some data with the console for our exit hack.
786 */
787struct console_abort {
788 /* How many times have they hit ^C? */
789 int count;
790 /* When did they start? */
791 struct timeval start;
792};
793
794/* This is the routine which handles console input (ie. stdin). */
795static void console_input(struct virtqueue *vq)
796{
797 int len;
798 unsigned int head, in_num, out_num;
799 struct console_abort *abort = vq->dev->priv;
800 struct iovec iov[vq->vring.num];
801
802 /* Make sure there's a descriptor available. */
803 head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
804 if (out_num)
805 errx(1, "Output buffers in console in queue?");
806
807 /* Read into it. This is where we usually wait. */
808 len = readv(STDIN_FILENO, iov, in_num);
809 if (len <= 0) {
810 /* Ran out of input? */
811 warnx("Failed to get console input, ignoring console.");
812 /*
813 * For simplicity, dying threads kill the whole Launcher. So
814 * just nap here.
815 */
816 for (;;)
817 pause();
818 }
819
820 /* Tell the Guest we used a buffer. */
821 add_used_and_trigger(vq, head, len);
822
823 /*
824 * Three ^C within one second? Exit.
825 *
826 * This is such a hack, but works surprisingly well. Each ^C has to
827 * be in a buffer by itself, so they can't be too fast. But we check
828 * that we get three within about a second, so they can't be too
829 * slow.
830 */
831 if (len != 1 || ((char *)iov[0].iov_base)[0] != 3) {
832 abort->count = 0;
833 return;
834 }
835
836 abort->count++;
837 if (abort->count == 1)
838 gettimeofday(&abort->start, NULL);
839 else if (abort->count == 3) {
840 struct timeval now;
841 gettimeofday(&now, NULL);
842 /* Kill all Launcher processes with SIGINT, like normal ^C */
843 if (now.tv_sec <= abort->start.tv_sec+1)
844 kill(0, SIGINT);
845 abort->count = 0;
846 }
847}
848
849/* This is the routine which handles console output (ie. stdout). */
850static void console_output(struct virtqueue *vq)
851{
852 unsigned int head, out, in;
853 struct iovec iov[vq->vring.num];
854
855 /* We usually wait in here, for the Guest to give us something. */
856 head = wait_for_vq_desc(vq, iov, &out, &in);
857 if (in)
858 errx(1, "Input buffers in console output queue?");
859
860 /* writev can return a partial write, so we loop here. */
861 while (!iov_empty(iov, out)) {
862 int len = writev(STDOUT_FILENO, iov, out);
863 if (len <= 0) {
864 warn("Write to stdout gave %i (%d)", len, errno);
865 break;
866 }
867 iov_consume(iov, out, len);
868 }
869
870 /*
871 * We're finished with that buffer: if we're going to sleep,
872 * wait_for_vq_desc() will prod the Guest with an interrupt.
873 */
874 add_used(vq, head, 0);
875}
876
877/*
878 * The Network
879 *
880 * Handling output for network is also simple: we get all the output buffers
881 * and write them to /dev/net/tun.
882 */
883struct net_info {
884 int tunfd;
885};
886
887static void net_output(struct virtqueue *vq)
888{
889 struct net_info *net_info = vq->dev->priv;
890 unsigned int head, out, in;
891 struct iovec iov[vq->vring.num];
892
893 /* We usually wait in here for the Guest to give us a packet. */
894 head = wait_for_vq_desc(vq, iov, &out, &in);
895 if (in)
896 errx(1, "Input buffers in net output queue?");
897 /*
898 * Send the whole thing through to /dev/net/tun. It expects the exact
899 * same format: what a coincidence!
900 */
901 if (writev(net_info->tunfd, iov, out) < 0)
902 warnx("Write to tun failed (%d)?", errno);
903
904 /*
905 * Done with that one; wait_for_vq_desc() will send the interrupt if
906 * all packets are processed.
907 */
908 add_used(vq, head, 0);
909}
910
911/*
912 * Handling network input is a bit trickier, because I've tried to optimize it.
913 *
914 * First we have a helper routine which tells is if from this file descriptor
915 * (ie. the /dev/net/tun device) will block:
916 */
917static bool will_block(int fd)
918{
919 fd_set fdset;
920 struct timeval zero = { 0, 0 };
921 FD_ZERO(&fdset);
922 FD_SET(fd, &fdset);
923 return select(fd+1, &fdset, NULL, NULL, &zero) != 1;
924}
925
926/*
927 * This handles packets coming in from the tun device to our Guest. Like all
928 * service routines, it gets called again as soon as it returns, so you don't
929 * see a while(1) loop here.
930 */
931static void net_input(struct virtqueue *vq)
932{
933 int len;
934 unsigned int head, out, in;
935 struct iovec iov[vq->vring.num];
936 struct net_info *net_info = vq->dev->priv;
937
938 /*
939 * Get a descriptor to write an incoming packet into. This will also
940 * send an interrupt if they're out of descriptors.
941 */
942 head = wait_for_vq_desc(vq, iov, &out, &in);
943 if (out)
944 errx(1, "Output buffers in net input queue?");
945
946 /*
947 * If it looks like we'll block reading from the tun device, send them
948 * an interrupt.
949 */
950 if (vq->pending_used && will_block(net_info->tunfd))
951 trigger_irq(vq);
952
953 /*
954 * Read in the packet. This is where we normally wait (when there's no
955 * incoming network traffic).
956 */
957 len = readv(net_info->tunfd, iov, in);
958 if (len <= 0)
959 warn("Failed to read from tun (%d).", errno);
960
961 /*
962 * Mark that packet buffer as used, but don't interrupt here. We want
963 * to wait until we've done as much work as we can.
964 */
965 add_used(vq, head, len);
966}
967/*:*/
968
969/* This is the helper to create threads: run the service routine in a loop. */
970static int do_thread(void *_vq)
971{
972 struct virtqueue *vq = _vq;
973
974 for (;;)
975 vq->service(vq);
976 return 0;
977}
978
979/*
980 * When a child dies, we kill our entire process group with SIGTERM. This
981 * also has the side effect that the shell restores the console for us!
982 */
983static void kill_launcher(int signal)
984{
985 kill(0, SIGTERM);
986}
987
988static void reset_device(struct device *dev)
989{
990 struct virtqueue *vq;
991
992 verbose("Resetting device %s\n", dev->name);
993
994 /* Clear any features they've acked. */
995 memset(get_feature_bits(dev) + dev->feature_len, 0, dev->feature_len);
996
997 /* We're going to be explicitly killing threads, so ignore them. */
998 signal(SIGCHLD, SIG_IGN);
999
1000 /* Zero out the virtqueues, get rid of their threads */
1001 for (vq = dev->vq; vq; vq = vq->next) {
1002 if (vq->thread != (pid_t)-1) {
1003 kill(vq->thread, SIGTERM);
1004 waitpid(vq->thread, NULL, 0);
1005 vq->thread = (pid_t)-1;
1006 }
1007 memset(vq->vring.desc, 0,
1008 vring_size(vq->config.num, LGUEST_VRING_ALIGN));
1009 lg_last_avail(vq) = 0;
1010 }
1011 dev->running = false;
1012
1013 /* Now we care if threads die. */
1014 signal(SIGCHLD, (void *)kill_launcher);
1015}
1016
1017/*L:216
1018 * This actually creates the thread which services the virtqueue for a device.
1019 */
1020static void create_thread(struct virtqueue *vq)
1021{
1022 /*
1023 * Create stack for thread. Since the stack grows upwards, we point
1024 * the stack pointer to the end of this region.
1025 */
1026 char *stack = malloc(32768);
1027 unsigned long args[] = { LHREQ_EVENTFD,
1028 vq->config.pfn*getpagesize(), 0 };
1029
1030 /* Create a zero-initialized eventfd. */
1031 vq->eventfd = eventfd(0, 0);
1032 if (vq->eventfd < 0)
1033 err(1, "Creating eventfd");
1034 args[2] = vq->eventfd;
1035
1036 /*
1037 * Attach an eventfd to this virtqueue: it will go off when the Guest
1038 * does an LHCALL_NOTIFY for this vq.
1039 */
1040 if (write(lguest_fd, &args, sizeof(args)) != 0)
1041 err(1, "Attaching eventfd");
1042
1043 /*
1044 * CLONE_VM: because it has to access the Guest memory, and SIGCHLD so
1045 * we get a signal if it dies.
1046 */
1047 vq->thread = clone(do_thread, stack + 32768, CLONE_VM | SIGCHLD, vq);
1048 if (vq->thread == (pid_t)-1)
1049 err(1, "Creating clone");
1050
1051 /* We close our local copy now the child has it. */
1052 close(vq->eventfd);
1053}
1054
1055static void start_device(struct device *dev)
1056{
1057 unsigned int i;
1058 struct virtqueue *vq;
1059
1060 verbose("Device %s OK: offered", dev->name);
1061 for (i = 0; i < dev->feature_len; i++)
1062 verbose(" %02x", get_feature_bits(dev)[i]);
1063 verbose(", accepted");
1064 for (i = 0; i < dev->feature_len; i++)
1065 verbose(" %02x", get_feature_bits(dev)
1066 [dev->feature_len+i]);
1067
1068 for (vq = dev->vq; vq; vq = vq->next) {
1069 if (vq->service)
1070 create_thread(vq);
1071 }
1072 dev->running = true;
1073}
1074
1075static void cleanup_devices(void)
1076{
1077 struct device *dev;
1078
1079 for (dev = devices.dev; dev; dev = dev->next)
1080 reset_device(dev);
1081
1082 /* If we saved off the original terminal settings, restore them now. */
1083 if (orig_term.c_lflag & (ISIG|ICANON|ECHO))
1084 tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
1085}
1086
1087/* When the Guest tells us they updated the status field, we handle it. */
1088static void update_device_status(struct device *dev)
1089{
1090 /* A zero status is a reset, otherwise it's a set of flags. */
1091 if (dev->desc->status == 0)
1092 reset_device(dev);
1093 else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
1094 warnx("Device %s configuration FAILED", dev->name);
1095 if (dev->running)
1096 reset_device(dev);
1097 } else {
1098 if (dev->running)
1099 err(1, "Device %s features finalized twice", dev->name);
1100 start_device(dev);
1101 }
1102}
1103
1104/*L:215
1105 * This is the generic routine we call when the Guest uses LHCALL_NOTIFY. In
1106 * particular, it's used to notify us of device status changes during boot.
1107 */
1108static void handle_output(unsigned long addr)
1109{
1110 struct device *i;
1111
1112 /* Check each device. */
1113 for (i = devices.dev; i; i = i->next) {
1114 struct virtqueue *vq;
1115
1116 /*
1117 * Notifications to device descriptors mean they updated the
1118 * device status.
1119 */
1120 if (from_guest_phys(addr) == i->desc) {
1121 update_device_status(i);
1122 return;
1123 }
1124
1125 /* Devices should not be used before features are finalized. */
1126 for (vq = i->vq; vq; vq = vq->next) {
1127 if (addr != vq->config.pfn*getpagesize())
1128 continue;
1129 errx(1, "Notification on %s before setup!", i->name);
1130 }
1131 }
1132
1133 /*
1134 * Early console write is done using notify on a nul-terminated string
1135 * in Guest memory. It's also great for hacking debugging messages
1136 * into a Guest.
1137 */
1138 if (addr >= guest_limit)
1139 errx(1, "Bad NOTIFY %#lx", addr);
1140
1141 write(STDOUT_FILENO, from_guest_phys(addr),
1142 strnlen(from_guest_phys(addr), guest_limit - addr));
1143}
1144
1145/*L:190
1146 * Device Setup
1147 *
1148 * All devices need a descriptor so the Guest knows it exists, and a "struct
1149 * device" so the Launcher can keep track of it. We have common helper
1150 * routines to allocate and manage them.
1151 */
1152
1153/*
1154 * The layout of the device page is a "struct lguest_device_desc" followed by a
1155 * number of virtqueue descriptors, then two sets of feature bits, then an
1156 * array of configuration bytes. This routine returns the configuration
1157 * pointer.
1158 */
1159static u8 *device_config(const struct device *dev)
1160{
1161 return (void *)(dev->desc + 1)
1162 + dev->num_vq * sizeof(struct lguest_vqconfig)
1163 + dev->feature_len * 2;
1164}
1165
1166/*
1167 * This routine allocates a new "struct lguest_device_desc" from descriptor
1168 * table page just above the Guest's normal memory. It returns a pointer to
1169 * that descriptor.
1170 */
1171static struct lguest_device_desc *new_dev_desc(u16 type)
1172{
1173 struct lguest_device_desc d = { .type = type };
1174 void *p;
1175
1176 /* Figure out where the next device config is, based on the last one. */
1177 if (devices.lastdev)
1178 p = device_config(devices.lastdev)
1179 + devices.lastdev->desc->config_len;
1180 else
1181 p = devices.descpage;
1182
1183 /* We only have one page for all the descriptors. */
1184 if (p + sizeof(d) > (void *)devices.descpage + getpagesize())
1185 errx(1, "Too many devices");
1186
1187 /* p might not be aligned, so we memcpy in. */
1188 return memcpy(p, &d, sizeof(d));
1189}
1190
1191/*
1192 * Each device descriptor is followed by the description of its virtqueues. We
1193 * specify how many descriptors the virtqueue is to have.
1194 */
1195static void add_virtqueue(struct device *dev, unsigned int num_descs,
1196 void (*service)(struct virtqueue *))
1197{
1198 unsigned int pages;
1199 struct virtqueue **i, *vq = malloc(sizeof(*vq));
1200 void *p;
1201
1202 /* First we need some memory for this virtqueue. */
1203 pages = (vring_size(num_descs, LGUEST_VRING_ALIGN) + getpagesize() - 1)
1204 / getpagesize();
1205 p = get_pages(pages);
1206
1207 /* Initialize the virtqueue */
1208 vq->next = NULL;
1209 vq->last_avail_idx = 0;
1210 vq->dev = dev;
1211
1212 /*
1213 * This is the routine the service thread will run, and its Process ID
1214 * once it's running.
1215 */
1216 vq->service = service;
1217 vq->thread = (pid_t)-1;
1218
1219 /* Initialize the configuration. */
1220 vq->config.num = num_descs;
1221 vq->config.irq = devices.next_irq++;
1222 vq->config.pfn = to_guest_phys(p) / getpagesize();
1223
1224 /* Initialize the vring. */
1225 vring_init(&vq->vring, num_descs, p, LGUEST_VRING_ALIGN);
1226
1227 /*
1228 * Append virtqueue to this device's descriptor. We use
1229 * device_config() to get the end of the device's current virtqueues;
1230 * we check that we haven't added any config or feature information
1231 * yet, otherwise we'd be overwriting them.
1232 */
1233 assert(dev->desc->config_len == 0 && dev->desc->feature_len == 0);
1234 memcpy(device_config(dev), &vq->config, sizeof(vq->config));
1235 dev->num_vq++;
1236 dev->desc->num_vq++;
1237
1238 verbose("Virtqueue page %#lx\n", to_guest_phys(p));
1239
1240 /*
1241 * Add to tail of list, so dev->vq is first vq, dev->vq->next is
1242 * second.
1243 */
1244 for (i = &dev->vq; *i; i = &(*i)->next);
1245 *i = vq;
1246}
1247
1248/*
1249 * The first half of the feature bitmask is for us to advertise features. The
1250 * second half is for the Guest to accept features.
1251 */
1252static void add_feature(struct device *dev, unsigned bit)
1253{
1254 u8 *features = get_feature_bits(dev);
1255
1256 /* We can't extend the feature bits once we've added config bytes */
1257 if (dev->desc->feature_len <= bit / CHAR_BIT) {
1258 assert(dev->desc->config_len == 0);
1259 dev->feature_len = dev->desc->feature_len = (bit/CHAR_BIT) + 1;
1260 }
1261
1262 features[bit / CHAR_BIT] |= (1 << (bit % CHAR_BIT));
1263}
1264
1265/*
1266 * This routine sets the configuration fields for an existing device's
1267 * descriptor. It only works for the last device, but that's OK because that's
1268 * how we use it.
1269 */
1270static void set_config(struct device *dev, unsigned len, const void *conf)
1271{
1272 /* Check we haven't overflowed our single page. */
1273 if (device_config(dev) + len > devices.descpage + getpagesize())
1274 errx(1, "Too many devices");
1275
1276 /* Copy in the config information, and store the length. */
1277 memcpy(device_config(dev), conf, len);
1278 dev->desc->config_len = len;
1279
1280 /* Size must fit in config_len field (8 bits)! */
1281 assert(dev->desc->config_len == len);
1282}
1283
1284/*
1285 * This routine does all the creation and setup of a new device, including
1286 * calling new_dev_desc() to allocate the descriptor and device memory. We
1287 * don't actually start the service threads until later.
1288 *
1289 * See what I mean about userspace being boring?
1290 */
1291static struct device *new_device(const char *name, u16 type)
1292{
1293 struct device *dev = malloc(sizeof(*dev));
1294
1295 /* Now we populate the fields one at a time. */
1296 dev->desc = new_dev_desc(type);
1297 dev->name = name;
1298 dev->vq = NULL;
1299 dev->feature_len = 0;
1300 dev->num_vq = 0;
1301 dev->running = false;
1302
1303 /*
1304 * Append to device list. Prepending to a single-linked list is
1305 * easier, but the user expects the devices to be arranged on the bus
1306 * in command-line order. The first network device on the command line
1307 * is eth0, the first block device /dev/vda, etc.
1308 */
1309 if (devices.lastdev)
1310 devices.lastdev->next = dev;
1311 else
1312 devices.dev = dev;
1313 devices.lastdev = dev;
1314
1315 return dev;
1316}
1317
1318/*
1319 * Our first setup routine is the console. It's a fairly simple device, but
1320 * UNIX tty handling makes it uglier than it could be.
1321 */
1322static void setup_console(void)
1323{
1324 struct device *dev;
1325
1326 /* If we can save the initial standard input settings... */
1327 if (tcgetattr(STDIN_FILENO, &orig_term) == 0) {
1328 struct termios term = orig_term;
1329 /*
1330 * Then we turn off echo, line buffering and ^C etc: We want a
1331 * raw input stream to the Guest.
1332 */
1333 term.c_lflag &= ~(ISIG|ICANON|ECHO);
1334 tcsetattr(STDIN_FILENO, TCSANOW, &term);
1335 }
1336
1337 dev = new_device("console", VIRTIO_ID_CONSOLE);
1338
1339 /* We store the console state in dev->priv, and initialize it. */
1340 dev->priv = malloc(sizeof(struct console_abort));
1341 ((struct console_abort *)dev->priv)->count = 0;
1342
1343 /*
1344 * The console needs two virtqueues: the input then the output. When
1345 * they put something the input queue, we make sure we're listening to
1346 * stdin. When they put something in the output queue, we write it to
1347 * stdout.
1348 */
1349 add_virtqueue(dev, VIRTQUEUE_NUM, console_input);
1350 add_virtqueue(dev, VIRTQUEUE_NUM, console_output);
1351
1352 verbose("device %u: console\n", ++devices.device_num);
1353}
1354/*:*/
1355
1356/*M:010
1357 * Inter-guest networking is an interesting area. Simplest is to have a
1358 * --sharenet=<name> option which opens or creates a named pipe. This can be
1359 * used to send packets to another guest in a 1:1 manner.
1360 *
1361 * More sophisticated is to use one of the tools developed for project like UML
1362 * to do networking.
1363 *
1364 * Faster is to do virtio bonding in kernel. Doing this 1:1 would be
1365 * completely generic ("here's my vring, attach to your vring") and would work
1366 * for any traffic. Of course, namespace and permissions issues need to be
1367 * dealt with. A more sophisticated "multi-channel" virtio_net.c could hide
1368 * multiple inter-guest channels behind one interface, although it would
1369 * require some manner of hotplugging new virtio channels.
1370 *
1371 * Finally, we could use a virtio network switch in the kernel, ie. vhost.
1372:*/
1373
1374static u32 str2ip(const char *ipaddr)
1375{
1376 unsigned int b[4];
1377
1378 if (sscanf(ipaddr, "%u.%u.%u.%u", &b[0], &b[1], &b[2], &b[3]) != 4)
1379 errx(1, "Failed to parse IP address '%s'", ipaddr);
1380 return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
1381}
1382
1383static void str2mac(const char *macaddr, unsigned char mac[6])
1384{
1385 unsigned int m[6];
1386 if (sscanf(macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
1387 &m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) != 6)
1388 errx(1, "Failed to parse mac address '%s'", macaddr);
1389 mac[0] = m[0];
1390 mac[1] = m[1];
1391 mac[2] = m[2];
1392 mac[3] = m[3];
1393 mac[4] = m[4];
1394 mac[5] = m[5];
1395}
1396
1397/*
1398 * This code is "adapted" from libbridge: it attaches the Host end of the
1399 * network device to the bridge device specified by the command line.
1400 *
1401 * This is yet another James Morris contribution (I'm an IP-level guy, so I
1402 * dislike bridging), and I just try not to break it.
1403 */
1404static void add_to_bridge(int fd, const char *if_name, const char *br_name)
1405{
1406 int ifidx;
1407 struct ifreq ifr;
1408
1409 if (!*br_name)
1410 errx(1, "must specify bridge name");
1411
1412 ifidx = if_nametoindex(if_name);
1413 if (!ifidx)
1414 errx(1, "interface %s does not exist!", if_name);
1415
1416 strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
1417 ifr.ifr_name[IFNAMSIZ-1] = '\0';
1418 ifr.ifr_ifindex = ifidx;
1419 if (ioctl(fd, SIOCBRADDIF, &ifr) < 0)
1420 err(1, "can't add %s to bridge %s", if_name, br_name);
1421}
1422
1423/*
1424 * This sets up the Host end of the network device with an IP address, brings
1425 * it up so packets will flow, the copies the MAC address into the hwaddr
1426 * pointer.
1427 */
1428static void configure_device(int fd, const char *tapif, u32 ipaddr)
1429{
1430 struct ifreq ifr;
1431 struct sockaddr_in sin;
1432
1433 memset(&ifr, 0, sizeof(ifr));
1434 strcpy(ifr.ifr_name, tapif);
1435
1436 /* Don't read these incantations. Just cut & paste them like I did! */
1437 sin.sin_family = AF_INET;
1438 sin.sin_addr.s_addr = htonl(ipaddr);
1439 memcpy(&ifr.ifr_addr, &sin, sizeof(sin));
1440 if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
1441 err(1, "Setting %s interface address", tapif);
1442 ifr.ifr_flags = IFF_UP;
1443 if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
1444 err(1, "Bringing interface %s up", tapif);
1445}
1446
1447static int get_tun_device(char tapif[IFNAMSIZ])
1448{
1449 struct ifreq ifr;
1450 int netfd;
1451
1452 /* Start with this zeroed. Messy but sure. */
1453 memset(&ifr, 0, sizeof(ifr));
1454
1455 /*
1456 * We open the /dev/net/tun device and tell it we want a tap device. A
1457 * tap device is like a tun device, only somehow different. To tell
1458 * the truth, I completely blundered my way through this code, but it
1459 * works now!
1460 */
1461 netfd = open_or_die("/dev/net/tun", O_RDWR);
1462 ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
1463 strcpy(ifr.ifr_name, "tap%d");
1464 if (ioctl(netfd, TUNSETIFF, &ifr) != 0)
1465 err(1, "configuring /dev/net/tun");
1466
1467 if (ioctl(netfd, TUNSETOFFLOAD,
1468 TUN_F_CSUM|TUN_F_TSO4|TUN_F_TSO6|TUN_F_TSO_ECN) != 0)
1469 err(1, "Could not set features for tun device");
1470
1471 /*
1472 * We don't need checksums calculated for packets coming in this
1473 * device: trust us!
1474 */
1475 ioctl(netfd, TUNSETNOCSUM, 1);
1476
1477 memcpy(tapif, ifr.ifr_name, IFNAMSIZ);
1478 return netfd;
1479}
1480
1481/*L:195
1482 * Our network is a Host<->Guest network. This can either use bridging or
1483 * routing, but the principle is the same: it uses the "tun" device to inject
1484 * packets into the Host as if they came in from a normal network card. We
1485 * just shunt packets between the Guest and the tun device.
1486 */
1487static void setup_tun_net(char *arg)
1488{
1489 struct device *dev;
1490 struct net_info *net_info = malloc(sizeof(*net_info));
1491 int ipfd;
1492 u32 ip = INADDR_ANY;
1493 bool bridging = false;
1494 char tapif[IFNAMSIZ], *p;
1495 struct virtio_net_config conf;
1496
1497 net_info->tunfd = get_tun_device(tapif);
1498
1499 /* First we create a new network device. */
1500 dev = new_device("net", VIRTIO_ID_NET);
1501 dev->priv = net_info;
1502
1503 /* Network devices need a recv and a send queue, just like console. */
1504 add_virtqueue(dev, VIRTQUEUE_NUM, net_input);
1505 add_virtqueue(dev, VIRTQUEUE_NUM, net_output);
1506
1507 /*
1508 * We need a socket to perform the magic network ioctls to bring up the
1509 * tap interface, connect to the bridge etc. Any socket will do!
1510 */
1511 ipfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
1512 if (ipfd < 0)
1513 err(1, "opening IP socket");
1514
1515 /* If the command line was --tunnet=bridge:<name> do bridging. */
1516 if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) {
1517 arg += strlen(BRIDGE_PFX);
1518 bridging = true;
1519 }
1520
1521 /* A mac address may follow the bridge name or IP address */
1522 p = strchr(arg, ':');
1523 if (p) {
1524 str2mac(p+1, conf.mac);
1525 add_feature(dev, VIRTIO_NET_F_MAC);
1526 *p = '\0';
1527 }
1528
1529 /* arg is now either an IP address or a bridge name */
1530 if (bridging)
1531 add_to_bridge(ipfd, tapif, arg);
1532 else
1533 ip = str2ip(arg);
1534
1535 /* Set up the tun device. */
1536 configure_device(ipfd, tapif, ip);
1537
1538 /* Expect Guest to handle everything except UFO */
1539 add_feature(dev, VIRTIO_NET_F_CSUM);
1540 add_feature(dev, VIRTIO_NET_F_GUEST_CSUM);
1541 add_feature(dev, VIRTIO_NET_F_GUEST_TSO4);
1542 add_feature(dev, VIRTIO_NET_F_GUEST_TSO6);
1543 add_feature(dev, VIRTIO_NET_F_GUEST_ECN);
1544 add_feature(dev, VIRTIO_NET_F_HOST_TSO4);
1545 add_feature(dev, VIRTIO_NET_F_HOST_TSO6);
1546 add_feature(dev, VIRTIO_NET_F_HOST_ECN);
1547 /* We handle indirect ring entries */
1548 add_feature(dev, VIRTIO_RING_F_INDIRECT_DESC);
1549 set_config(dev, sizeof(conf), &conf);
1550
1551 /* We don't need the socket any more; setup is done. */
1552 close(ipfd);
1553
1554 devices.device_num++;
1555
1556 if (bridging)
1557 verbose("device %u: tun %s attached to bridge: %s\n",
1558 devices.device_num, tapif, arg);
1559 else
1560 verbose("device %u: tun %s: %s\n",
1561 devices.device_num, tapif, arg);
1562}
1563/*:*/
1564
1565/* This hangs off device->priv. */
1566struct vblk_info {
1567 /* The size of the file. */
1568 off64_t len;
1569
1570 /* The file descriptor for the file. */
1571 int fd;
1572
1573};
1574
1575/*L:210
1576 * The Disk
1577 *
1578 * The disk only has one virtqueue, so it only has one thread. It is really
1579 * simple: the Guest asks for a block number and we read or write that position
1580 * in the file.
1581 *
1582 * Before we serviced each virtqueue in a separate thread, that was unacceptably
1583 * slow: the Guest waits until the read is finished before running anything
1584 * else, even if it could have been doing useful work.
1585 *
1586 * We could have used async I/O, except it's reputed to suck so hard that
1587 * characters actually go missing from your code when you try to use it.
1588 */
1589static void blk_request(struct virtqueue *vq)
1590{
1591 struct vblk_info *vblk = vq->dev->priv;
1592 unsigned int head, out_num, in_num, wlen;
1593 int ret;
1594 u8 *in;
1595 struct virtio_blk_outhdr *out;
1596 struct iovec iov[vq->vring.num];
1597 off64_t off;
1598
1599 /*
1600 * Get the next request, where we normally wait. It triggers the
1601 * interrupt to acknowledge previously serviced requests (if any).
1602 */
1603 head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
1604
1605 /*
1606 * Every block request should contain at least one output buffer
1607 * (detailing the location on disk and the type of request) and one
1608 * input buffer (to hold the result).
1609 */
1610 if (out_num == 0 || in_num == 0)
1611 errx(1, "Bad virtblk cmd %u out=%u in=%u",
1612 head, out_num, in_num);
1613
1614 out = convert(&iov[0], struct virtio_blk_outhdr);
1615 in = convert(&iov[out_num+in_num-1], u8);
1616 /*
1617 * For historical reasons, block operations are expressed in 512 byte
1618 * "sectors".
1619 */
1620 off = out->sector * 512;
1621
1622 /*
1623 * In general the virtio block driver is allowed to try SCSI commands.
1624 * It'd be nice if we supported eject, for example, but we don't.
1625 */
1626 if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
1627 fprintf(stderr, "Scsi commands unsupported\n");
1628 *in = VIRTIO_BLK_S_UNSUPP;
1629 wlen = sizeof(*in);
1630 } else if (out->type & VIRTIO_BLK_T_OUT) {
1631 /*
1632 * Write
1633 *
1634 * Move to the right location in the block file. This can fail
1635 * if they try to write past end.
1636 */
1637 if (lseek64(vblk->fd, off, SEEK_SET) != off)
1638 err(1, "Bad seek to sector %llu", out->sector);
1639
1640 ret = writev(vblk->fd, iov+1, out_num-1);
1641 verbose("WRITE to sector %llu: %i\n", out->sector, ret);
1642
1643 /*
1644 * Grr... Now we know how long the descriptor they sent was, we
1645 * make sure they didn't try to write over the end of the block
1646 * file (possibly extending it).
1647 */
1648 if (ret > 0 && off + ret > vblk->len) {
1649 /* Trim it back to the correct length */
1650 ftruncate64(vblk->fd, vblk->len);
1651 /* Die, bad Guest, die. */
1652 errx(1, "Write past end %llu+%u", off, ret);
1653 }
1654
1655 wlen = sizeof(*in);
1656 *in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
1657 } else if (out->type & VIRTIO_BLK_T_FLUSH) {
1658 /* Flush */
1659 ret = fdatasync(vblk->fd);
1660 verbose("FLUSH fdatasync: %i\n", ret);
1661 wlen = sizeof(*in);
1662 *in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
1663 } else {
1664 /*
1665 * Read
1666 *
1667 * Move to the right location in the block file. This can fail
1668 * if they try to read past end.
1669 */
1670 if (lseek64(vblk->fd, off, SEEK_SET) != off)
1671 err(1, "Bad seek to sector %llu", out->sector);
1672
1673 ret = readv(vblk->fd, iov+1, in_num-1);
1674 verbose("READ from sector %llu: %i\n", out->sector, ret);
1675 if (ret >= 0) {
1676 wlen = sizeof(*in) + ret;
1677 *in = VIRTIO_BLK_S_OK;
1678 } else {
1679 wlen = sizeof(*in);
1680 *in = VIRTIO_BLK_S_IOERR;
1681 }
1682 }
1683
1684 /* Finished that request. */
1685 add_used(vq, head, wlen);
1686}
1687
1688/*L:198 This actually sets up a virtual block device. */
1689static void setup_block_file(const char *filename)
1690{
1691 struct device *dev;
1692 struct vblk_info *vblk;
1693 struct virtio_blk_config conf;
1694
1695 /* Creat the device. */
1696 dev = new_device("block", VIRTIO_ID_BLOCK);
1697
1698 /* The device has one virtqueue, where the Guest places requests. */
1699 add_virtqueue(dev, VIRTQUEUE_NUM, blk_request);
1700
1701 /* Allocate the room for our own bookkeeping */
1702 vblk = dev->priv = malloc(sizeof(*vblk));
1703
1704 /* First we open the file and store the length. */
1705 vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE);
1706 vblk->len = lseek64(vblk->fd, 0, SEEK_END);
1707
1708 /* We support FLUSH. */
1709 add_feature(dev, VIRTIO_BLK_F_FLUSH);
1710
1711 /* Tell Guest how many sectors this device has. */
1712 conf.capacity = cpu_to_le64(vblk->len / 512);
1713
1714 /*
1715 * Tell Guest not to put in too many descriptors at once: two are used
1716 * for the in and out elements.
1717 */
1718 add_feature(dev, VIRTIO_BLK_F_SEG_MAX);
1719 conf.seg_max = cpu_to_le32(VIRTQUEUE_NUM - 2);
1720
1721 /* Don't try to put whole struct: we have 8 bit limit. */
1722 set_config(dev, offsetof(struct virtio_blk_config, geometry), &conf);
1723
1724 verbose("device %u: virtblock %llu sectors\n",
1725 ++devices.device_num, le64_to_cpu(conf.capacity));
1726}
1727
1728/*L:211
1729 * Our random number generator device reads from /dev/random into the Guest's
1730 * input buffers. The usual case is that the Guest doesn't want random numbers
1731 * and so has no buffers although /dev/random is still readable, whereas
1732 * console is the reverse.
1733 *
1734 * The same logic applies, however.
1735 */
1736struct rng_info {
1737 int rfd;
1738};
1739
1740static void rng_input(struct virtqueue *vq)
1741{
1742 int len;
1743 unsigned int head, in_num, out_num, totlen = 0;
1744 struct rng_info *rng_info = vq->dev->priv;
1745 struct iovec iov[vq->vring.num];
1746
1747 /* First we need a buffer from the Guests's virtqueue. */
1748 head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
1749 if (out_num)
1750 errx(1, "Output buffers in rng?");
1751
1752 /*
1753 * Just like the console write, we loop to cover the whole iovec.
1754 * In this case, short reads actually happen quite a bit.
1755 */
1756 while (!iov_empty(iov, in_num)) {
1757 len = readv(rng_info->rfd, iov, in_num);
1758 if (len <= 0)
1759 err(1, "Read from /dev/random gave %i", len);
1760 iov_consume(iov, in_num, len);
1761 totlen += len;
1762 }
1763
1764 /* Tell the Guest about the new input. */
1765 add_used(vq, head, totlen);
1766}
1767
1768/*L:199
1769 * This creates a "hardware" random number device for the Guest.
1770 */
1771static void setup_rng(void)
1772{
1773 struct device *dev;
1774 struct rng_info *rng_info = malloc(sizeof(*rng_info));
1775
1776 /* Our device's privat info simply contains the /dev/random fd. */
1777 rng_info->rfd = open_or_die("/dev/random", O_RDONLY);
1778
1779 /* Create the new device. */
1780 dev = new_device("rng", VIRTIO_ID_RNG);
1781 dev->priv = rng_info;
1782
1783 /* The device has one virtqueue, where the Guest places inbufs. */
1784 add_virtqueue(dev, VIRTQUEUE_NUM, rng_input);
1785
1786 verbose("device %u: rng\n", devices.device_num++);
1787}
1788/* That's the end of device setup. */
1789
1790/*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */
1791static void __attribute__((noreturn)) restart_guest(void)
1792{
1793 unsigned int i;
1794
1795 /*
1796 * Since we don't track all open fds, we simply close everything beyond
1797 * stderr.
1798 */
1799 for (i = 3; i < FD_SETSIZE; i++)
1800 close(i);
1801
1802 /* Reset all the devices (kills all threads). */
1803 cleanup_devices();
1804
1805 execv(main_args[0], main_args);
1806 err(1, "Could not exec %s", main_args[0]);
1807}
1808
1809/*L:220
1810 * Finally we reach the core of the Launcher which runs the Guest, serves
1811 * its input and output, and finally, lays it to rest.
1812 */
1813static void __attribute__((noreturn)) run_guest(void)
1814{
1815 for (;;) {
1816 unsigned long notify_addr;
1817 int readval;
1818
1819 /* We read from the /dev/lguest device to run the Guest. */
1820 readval = pread(lguest_fd, &notify_addr,
1821 sizeof(notify_addr), cpu_id);
1822
1823 /* One unsigned long means the Guest did HCALL_NOTIFY */
1824 if (readval == sizeof(notify_addr)) {
1825 verbose("Notify on address %#lx\n", notify_addr);
1826 handle_output(notify_addr);
1827 /* ENOENT means the Guest died. Reading tells us why. */
1828 } else if (errno == ENOENT) {
1829 char reason[1024] = { 0 };
1830 pread(lguest_fd, reason, sizeof(reason)-1, cpu_id);
1831 errx(1, "%s", reason);
1832 /* ERESTART means that we need to reboot the guest */
1833 } else if (errno == ERESTART) {
1834 restart_guest();
1835 /* Anything else means a bug or incompatible change. */
1836 } else
1837 err(1, "Running guest failed");
1838 }
1839}
1840/*L:240
1841 * This is the end of the Launcher. The good news: we are over halfway
1842 * through! The bad news: the most fiendish part of the code still lies ahead
1843 * of us.
1844 *
1845 * Are you ready? Take a deep breath and join me in the core of the Host, in
1846 * "make Host".
1847:*/
1848
1849static struct option opts[] = {
1850 { "verbose", 0, NULL, 'v' },
1851 { "tunnet", 1, NULL, 't' },
1852 { "block", 1, NULL, 'b' },
1853 { "rng", 0, NULL, 'r' },
1854 { "initrd", 1, NULL, 'i' },
1855 { "username", 1, NULL, 'u' },
1856 { "chroot", 1, NULL, 'c' },
1857 { NULL },
1858};
1859static void usage(void)
1860{
1861 errx(1, "Usage: lguest [--verbose] "
1862 "[--tunnet=(<ipaddr>:<macaddr>|bridge:<bridgename>:<macaddr>)\n"
1863 "|--block=<filename>|--initrd=<filename>]...\n"
1864 "<mem-in-mb> vmlinux [args...]");
1865}
1866
1867/*L:105 The main routine is where the real work begins: */
1868int main(int argc, char *argv[])
1869{
1870 /* Memory, code startpoint and size of the (optional) initrd. */
1871 unsigned long mem = 0, start, initrd_size = 0;
1872 /* Two temporaries. */
1873 int i, c;
1874 /* The boot information for the Guest. */
1875 struct boot_params *boot;
1876 /* If they specify an initrd file to load. */
1877 const char *initrd_name = NULL;
1878
1879 /* Password structure for initgroups/setres[gu]id */
1880 struct passwd *user_details = NULL;
1881
1882 /* Directory to chroot to */
1883 char *chroot_path = NULL;
1884
1885 /* Save the args: we "reboot" by execing ourselves again. */
1886 main_args = argv;
1887
1888 /*
1889 * First we initialize the device list. We keep a pointer to the last
1890 * device, and the next interrupt number to use for devices (1:
1891 * remember that 0 is used by the timer).
1892 */
1893 devices.lastdev = NULL;
1894 devices.next_irq = 1;
1895
1896 /* We're CPU 0. In fact, that's the only CPU possible right now. */
1897 cpu_id = 0;
1898
1899 /*
1900 * We need to know how much memory so we can set up the device
1901 * descriptor and memory pages for the devices as we parse the command
1902 * line. So we quickly look through the arguments to find the amount
1903 * of memory now.
1904 */
1905 for (i = 1; i < argc; i++) {
1906 if (argv[i][0] != '-') {
1907 mem = atoi(argv[i]) * 1024 * 1024;
1908 /*
1909 * We start by mapping anonymous pages over all of
1910 * guest-physical memory range. This fills it with 0,
1911 * and ensures that the Guest won't be killed when it
1912 * tries to access it.
1913 */
1914 guest_base = map_zeroed_pages(mem / getpagesize()
1915 + DEVICE_PAGES);
1916 guest_limit = mem;
1917 guest_max = mem + DEVICE_PAGES*getpagesize();
1918 devices.descpage = get_pages(1);
1919 break;
1920 }
1921 }
1922
1923 /* The options are fairly straight-forward */
1924 while ((c = getopt_long(argc, argv, "v", opts, NULL)) != EOF) {
1925 switch (c) {
1926 case 'v':
1927 verbose = true;
1928 break;
1929 case 't':
1930 setup_tun_net(optarg);
1931 break;
1932 case 'b':
1933 setup_block_file(optarg);
1934 break;
1935 case 'r':
1936 setup_rng();
1937 break;
1938 case 'i':
1939 initrd_name = optarg;
1940 break;
1941 case 'u':
1942 user_details = getpwnam(optarg);
1943 if (!user_details)
1944 err(1, "getpwnam failed, incorrect username?");
1945 break;
1946 case 'c':
1947 chroot_path = optarg;
1948 break;
1949 default:
1950 warnx("Unknown argument %s", argv[optind]);
1951 usage();
1952 }
1953 }
1954 /*
1955 * After the other arguments we expect memory and kernel image name,
1956 * followed by command line arguments for the kernel.
1957 */
1958 if (optind + 2 > argc)
1959 usage();
1960
1961 verbose("Guest base is at %p\n", guest_base);
1962
1963 /* We always have a console device */
1964 setup_console();
1965
1966 /* Now we load the kernel */
1967 start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));
1968
1969 /* Boot information is stashed at physical address 0 */
1970 boot = from_guest_phys(0);
1971
1972 /* Map the initrd image if requested (at top of physical memory) */
1973 if (initrd_name) {
1974 initrd_size = load_initrd(initrd_name, mem);
1975 /*
1976 * These are the location in the Linux boot header where the
1977 * start and size of the initrd are expected to be found.
1978 */
1979 boot->hdr.ramdisk_image = mem - initrd_size;
1980 boot->hdr.ramdisk_size = initrd_size;
1981 /* The bootloader type 0xFF means "unknown"; that's OK. */
1982 boot->hdr.type_of_loader = 0xFF;
1983 }
1984
1985 /*
1986 * The Linux boot header contains an "E820" memory map: ours is a
1987 * simple, single region.
1988 */
1989 boot->e820_entries = 1;
1990 boot->e820_map[0] = ((struct e820entry) { 0, mem, E820_RAM });
1991 /*
1992 * The boot header contains a command line pointer: we put the command
1993 * line after the boot header.
1994 */
1995 boot->hdr.cmd_line_ptr = to_guest_phys(boot + 1);
1996 /* We use a simple helper to copy the arguments separated by spaces. */
1997 concat((char *)(boot + 1), argv+optind+2);
1998
1999 /* Set kernel alignment to 16M (CONFIG_PHYSICAL_ALIGN) */
2000 boot->hdr.kernel_alignment = 0x1000000;
2001
2002 /* Boot protocol version: 2.07 supports the fields for lguest. */
2003 boot->hdr.version = 0x207;
2004
2005 /* The hardware_subarch value of "1" tells the Guest it's an lguest. */
2006 boot->hdr.hardware_subarch = 1;
2007
2008 /* Tell the entry path not to try to reload segment registers. */
2009 boot->hdr.loadflags |= KEEP_SEGMENTS;
2010
2011 /* We tell the kernel to initialize the Guest. */
2012 tell_kernel(start);
2013
2014 /* Ensure that we terminate if a device-servicing child dies. */
2015 signal(SIGCHLD, kill_launcher);
2016
2017 /* If we exit via err(), this kills all the threads, restores tty. */
2018 atexit(cleanup_devices);
2019
2020 /* If requested, chroot to a directory */
2021 if (chroot_path) {
2022 if (chroot(chroot_path) != 0)
2023 err(1, "chroot(\"%s\") failed", chroot_path);
2024
2025 if (chdir("/") != 0)
2026 err(1, "chdir(\"/\") failed");
2027
2028 verbose("chroot done\n");
2029 }
2030
2031 /* If requested, drop privileges */
2032 if (user_details) {
2033 uid_t u;
2034 gid_t g;
2035
2036 u = user_details->pw_uid;
2037 g = user_details->pw_gid;
2038
2039 if (initgroups(user_details->pw_name, g) != 0)
2040 err(1, "initgroups failed");
2041
2042 if (setresgid(g, g, g) != 0)
2043 err(1, "setresgid failed");
2044
2045 if (setresuid(u, u, u) != 0)
2046 err(1, "setresuid failed");
2047
2048 verbose("Dropping privileges completed\n");
2049 }
2050
2051 /* Finally, run the Guest. This doesn't return. */
2052 run_guest();
2053}
2054/*:*/
2055
2056/*M:999
2057 * Mastery is done: you now know everything I do.
2058 *
2059 * But surely you have seen code, features and bugs in your wanderings which
2060 * you now yearn to attack? That is the real game, and I look forward to you
2061 * patching and forking lguest into the Your-Name-Here-visor.
2062 *
2063 * Farewell, and good coding!
2064 * Rusty Russell.
2065 */
diff --git a/tools/lguest/lguest.txt b/tools/lguest/lguest.txt
new file mode 100644
index 000000000000..bff0c554485d
--- /dev/null
+++ b/tools/lguest/lguest.txt
@@ -0,0 +1,129 @@
1 __
2 (___()'`; Rusty's Remarkably Unreliable Guide to Lguest
3 /, /` - or, A Young Coder's Illustrated Hypervisor
4 \\"--\\ http://lguest.ozlabs.org
5
6Lguest is designed to be a minimal 32-bit x86 hypervisor for the Linux kernel,
7for Linux developers and users to experiment with virtualization with the
8minimum of complexity. Nonetheless, it should have sufficient features to
9make it useful for specific tasks, and, of course, you are encouraged to fork
10and enhance it (see drivers/lguest/README).
11
12Features:
13
14- Kernel module which runs in a normal kernel.
15- Simple I/O model for communication.
16- Simple program to create new guests.
17- Logo contains cute puppies: http://lguest.ozlabs.org
18
19Developer features:
20
21- Fun to hack on.
22- No ABI: being tied to a specific kernel anyway, you can change anything.
23- Many opportunities for improvement or feature implementation.
24
25Running Lguest:
26
27- The easiest way to run lguest is to use same kernel as guest and host.
28 You can configure them differently, but usually it's easiest not to.
29
30 You will need to configure your kernel with the following options:
31
32 "General setup":
33 "Prompt for development and/or incomplete code/drivers" = Y
34 (CONFIG_EXPERIMENTAL=y)
35
36 "Processor type and features":
37 "Paravirtualized guest support" = Y
38 "Lguest guest support" = Y
39 "High Memory Support" = off/4GB
40 "Alignment value to which kernel should be aligned" = 0x100000
41 (CONFIG_PARAVIRT=y, CONFIG_LGUEST_GUEST=y, CONFIG_HIGHMEM64G=n and
42 CONFIG_PHYSICAL_ALIGN=0x100000)
43
44 "Device Drivers":
45 "Block devices"
46 "Virtio block driver (EXPERIMENTAL)" = M/Y
47 "Network device support"
48 "Universal TUN/TAP device driver support" = M/Y
49 "Virtio network driver (EXPERIMENTAL)" = M/Y
50 (CONFIG_VIRTIO_BLK=m, CONFIG_VIRTIO_NET=m and CONFIG_TUN=m)
51
52 "Virtualization"
53 "Linux hypervisor example code" = M/Y
54 (CONFIG_LGUEST=m)
55
56- A tool called "lguest" is available in this directory: type "make"
57 to build it. If you didn't build your kernel in-tree, use "make
58 O=<builddir>".
59
60- Create or find a root disk image. There are several useful ones
61 around, such as the xm-test tiny root image at
62 http://xm-test.xensource.com/ramdisks/initrd-1.1-i386.img
63
64 For more serious work, I usually use a distribution ISO image and
65 install it under qemu, then make multiple copies:
66
67 dd if=/dev/zero of=rootfile bs=1M count=2048
68 qemu -cdrom image.iso -hda rootfile -net user -net nic -boot d
69
70 Make sure that you install a getty on /dev/hvc0 if you want to log in on the
71 console!
72
73- "modprobe lg" if you built it as a module.
74
75- Run an lguest as root:
76
77 Documentation/virtual/lguest/lguest 64 vmlinux --tunnet=192.168.19.1 \
78 --block=rootfile root=/dev/vda
79
80 Explanation:
81 64: the amount of memory to use, in MB.
82
83 vmlinux: the kernel image found in the top of your build directory. You
84 can also use a standard bzImage.
85
86 --tunnet=192.168.19.1: configures a "tap" device for networking with this
87 IP address.
88
89 --block=rootfile: a file or block device which becomes /dev/vda
90 inside the guest.
91
92 root=/dev/vda: this (and anything else on the command line) are
93 kernel boot parameters.
94
95- Configuring networking. I usually have the host masquerade, using
96 "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE" and "echo 1 >
97 /proc/sys/net/ipv4/ip_forward". In this example, I would configure
98 eth0 inside the guest at 192.168.19.2.
99
100 Another method is to bridge the tap device to an external interface
101 using --tunnet=bridge:<bridgename>, and perhaps run dhcp on the guest
102 to obtain an IP address. The bridge needs to be configured first:
103 this option simply adds the tap interface to it.
104
105 A simple example on my system:
106
107 ifconfig eth0 0.0.0.0
108 brctl addbr lg0
109 ifconfig lg0 up
110 brctl addif lg0 eth0
111 dhclient lg0
112
113 Then use --tunnet=bridge:lg0 when launching the guest.
114
115 See:
116
117 http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge
118
119 for general information on how to get bridging to work.
120
121- Random number generation. Using the --rng option will provide a
122 /dev/hwrng in the guest that will read from the host's /dev/random.
123 Use this option in conjunction with rng-tools (see ../hw_random.txt)
124 to provide entropy to the guest kernel's /dev/random.
125
126There is a helpful mailing list at http://ozlabs.org/mailman/listinfo/lguest
127
128Good luck!
129Rusty Russell rusty@rustcorp.com.au.
diff --git a/tools/nfsd/inject_fault.sh b/tools/nfsd/inject_fault.sh
new file mode 100755
index 000000000000..06a399ac8b2f
--- /dev/null
+++ b/tools/nfsd/inject_fault.sh
@@ -0,0 +1,49 @@
1#!/bin/bash
2#
3# Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com>
4#
5# Script for easier NFSD fault injection
6
7# Check that debugfs has been mounted
8DEBUGFS=`cat /proc/mounts | grep debugfs`
9if [ "$DEBUGFS" == "" ]; then
10 echo "debugfs does not appear to be mounted!"
11 echo "Please mount debugfs and try again"
12 exit 1
13fi
14
15# Check that the fault injection directory exists
16DEBUGDIR=`echo $DEBUGFS | awk '{print $2}'`/nfsd
17if [ ! -d "$DEBUGDIR" ]; then
18 echo "$DEBUGDIR does not exist"
19 echo "Check that your .config selects CONFIG_NFSD_FAULT_INJECTION"
20 exit 1
21fi
22
23function help()
24{
25 echo "Usage $0 injection_type [count]"
26 echo ""
27 echo "Injection types are:"
28 ls $DEBUGDIR
29 exit 1
30}
31
32if [ $# == 0 ]; then
33 help
34elif [ ! -f $DEBUGDIR/$1 ]; then
35 help
36elif [ $# != 2 ]; then
37 COUNT=0
38else
39 COUNT=$2
40fi
41
42BEFORE=`mktemp`
43AFTER=`mktemp`
44dmesg > $BEFORE
45echo $COUNT > $DEBUGDIR/$1
46dmesg > $AFTER
47# Capture lines that only exist in the $AFTER file
48diff $BEFORE $AFTER | grep ">"
49rm -f $BEFORE $AFTER
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 4626a398836a..ca600e09c8d4 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -1,3 +1,10 @@
1OUTPUT := ./
2ifeq ("$(origin O)", "command line")
3 ifneq ($(O),)
4 OUTPUT := $(O)/
5 endif
6endif
7
1MAN1_TXT= \ 8MAN1_TXT= \
2 $(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \ 9 $(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \
3 $(wildcard perf-*.txt)) \ 10 $(wildcard perf-*.txt)) \
@@ -6,10 +13,11 @@ MAN5_TXT=
6MAN7_TXT= 13MAN7_TXT=
7 14
8MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) 15MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
9MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) 16_MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
10MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT)) 17_MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT))
11 18
12DOC_HTML=$(MAN_HTML) 19MAN_XML=$(addprefix $(OUTPUT),$(_MAN_XML))
20MAN_HTML=$(addprefix $(OUTPUT),$(_MAN_HTML))
13 21
14ARTICLES = 22ARTICLES =
15# with their own formatting rules. 23# with their own formatting rules.
@@ -18,11 +26,17 @@ API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technica
18SP_ARTICLES += $(API_DOCS) 26SP_ARTICLES += $(API_DOCS)
19SP_ARTICLES += technical/api-index 27SP_ARTICLES += technical/api-index
20 28
21DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) 29_DOC_HTML = $(_MAN_HTML)
30_DOC_HTML+=$(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES))
31DOC_HTML=$(addprefix $(OUTPUT),$(_DOC_HTML))
22 32
23DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) 33_DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT))
24DOC_MAN5=$(patsubst %.txt,%.5,$(MAN5_TXT)) 34_DOC_MAN5=$(patsubst %.txt,%.5,$(MAN5_TXT))
25DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) 35_DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
36
37DOC_MAN1=$(addprefix $(OUTPUT),$(_DOC_MAN1))
38DOC_MAN5=$(addprefix $(OUTPUT),$(_DOC_MAN5))
39DOC_MAN7=$(addprefix $(OUTPUT),$(_DOC_MAN7))
26 40
27# Make the path relative to DESTDIR, not prefix 41# Make the path relative to DESTDIR, not prefix
28ifndef DESTDIR 42ifndef DESTDIR
@@ -150,9 +164,9 @@ man1: $(DOC_MAN1)
150man5: $(DOC_MAN5) 164man5: $(DOC_MAN5)
151man7: $(DOC_MAN7) 165man7: $(DOC_MAN7)
152 166
153info: perf.info perfman.info 167info: $(OUTPUT)perf.info $(OUTPUT)perfman.info
154 168
155pdf: user-manual.pdf 169pdf: $(OUTPUT)user-manual.pdf
156 170
157install: install-man 171install: install-man
158 172
@@ -166,7 +180,7 @@ install-man: man
166 180
167install-info: info 181install-info: info
168 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir) 182 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir)
169 $(INSTALL) -m 644 perf.info perfman.info $(DESTDIR)$(infodir) 183 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir)
170 if test -r $(DESTDIR)$(infodir)/dir; then \ 184 if test -r $(DESTDIR)$(infodir)/dir; then \
171 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\ 185 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\
172 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\ 186 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\
@@ -176,7 +190,7 @@ install-info: info
176 190
177install-pdf: pdf 191install-pdf: pdf
178 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir) 192 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir)
179 $(INSTALL) -m 644 user-manual.pdf $(DESTDIR)$(pdfdir) 193 $(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir)
180 194
181#install-html: html 195#install-html: html
182# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) 196# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
@@ -189,14 +203,14 @@ install-pdf: pdf
189# 203#
190# Determine "include::" file references in asciidoc files. 204# Determine "include::" file references in asciidoc files.
191# 205#
192doc.dep : $(wildcard *.txt) build-docdep.perl 206$(OUTPUT)doc.dep : $(wildcard *.txt) build-docdep.perl
193 $(QUIET_GEN)$(RM) $@+ $@ && \ 207 $(QUIET_GEN)$(RM) $@+ $@ && \
194 $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \ 208 $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
195 mv $@+ $@ 209 mv $@+ $@
196 210
197-include doc.dep 211-include $(OUPTUT)doc.dep
198 212
199cmds_txt = cmds-ancillaryinterrogators.txt \ 213_cmds_txt = cmds-ancillaryinterrogators.txt \
200 cmds-ancillarymanipulators.txt \ 214 cmds-ancillarymanipulators.txt \
201 cmds-mainporcelain.txt \ 215 cmds-mainporcelain.txt \
202 cmds-plumbinginterrogators.txt \ 216 cmds-plumbinginterrogators.txt \
@@ -205,32 +219,36 @@ cmds_txt = cmds-ancillaryinterrogators.txt \
205 cmds-synchelpers.txt \ 219 cmds-synchelpers.txt \
206 cmds-purehelpers.txt \ 220 cmds-purehelpers.txt \
207 cmds-foreignscminterface.txt 221 cmds-foreignscminterface.txt
222cmds_txt=$(addprefix $(OUTPUT),$(_cmds_txt))
208 223
209$(cmds_txt): cmd-list.made 224$(cmds_txt): $(OUTPUT)cmd-list.made
210 225
211cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) 226$(OUTPUT)cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
212 $(QUIET_GEN)$(RM) $@ && \ 227 $(QUIET_GEN)$(RM) $@ && \
213 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \ 228 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
214 date >$@ 229 date >$@
215 230
216clean: 231clean:
217 $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7 232 $(RM) $(MAN_XML) $(addsuffix +,$(MAN_XML))
218 $(RM) *.texi *.texi+ *.texi++ perf.info perfman.info 233 $(RM) $(MAN_HTML) $(addsuffix +,$(MAN_HTML))
219 $(RM) howto-index.txt howto/*.html doc.dep 234 $(RM) $(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7)
220 $(RM) technical/api-*.html technical/api-index.txt 235 $(RM) $(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++
221 $(RM) $(cmds_txt) *.made 236 $(RM) $(OUTPUT)perf.info $(OUTPUT)perfman.info
222 237 $(RM) $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep
223$(MAN_HTML): %.html : %.txt 238 $(RM) $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt
239 $(RM) $(cmds_txt) $(OUTPUT)*.made
240
241$(MAN_HTML): $(OUTPUT)%.html : %.txt
224 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 242 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
225 $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \ 243 $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
226 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \ 244 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \
227 mv $@+ $@ 245 mv $@+ $@
228 246
229%.1 %.5 %.7 : %.xml 247$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml
230 $(QUIET_XMLTO)$(RM) $@ && \ 248 $(QUIET_XMLTO)$(RM) $@ && \
231 xmlto -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< 249 xmlto -o $(OUTPUT) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
232 250
233%.xml : %.txt 251$(OUTPUT)%.xml : %.txt
234 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 252 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
235 $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ 253 $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
236 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \ 254 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \
@@ -239,25 +257,25 @@ $(MAN_HTML): %.html : %.txt
239XSLT = docbook.xsl 257XSLT = docbook.xsl
240XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css 258XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css
241 259
242user-manual.html: user-manual.xml 260$(OUTPUT)user-manual.html: $(OUTPUT)user-manual.xml
243 $(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $< 261 $(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
244 262
245perf.info: user-manual.texi 263$(OUTPUT)perf.info: $(OUTPUT)user-manual.texi
246 $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ user-manual.texi 264 $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ $(OUTPUT)user-manual.texi
247 265
248user-manual.texi: user-manual.xml 266$(OUTPUT)user-manual.texi: $(OUTPUT)user-manual.xml
249 $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ 267 $(QUIET_DB2TEXI)$(RM) $@+ $@ && \
250 $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \ 268 $(DOCBOOK2X_TEXI) $(OUTPUT)user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \
251 $(PERL_PATH) fix-texi.perl <$@++ >$@+ && \ 269 $(PERL_PATH) fix-texi.perl <$@++ >$@+ && \
252 rm $@++ && \ 270 rm $@++ && \
253 mv $@+ $@ 271 mv $@+ $@
254 272
255user-manual.pdf: user-manual.xml 273$(OUTPUT)user-manual.pdf: $(OUTPUT)user-manual.xml
256 $(QUIET_DBLATEX)$(RM) $@+ $@ && \ 274 $(QUIET_DBLATEX)$(RM) $@+ $@ && \
257 $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< && \ 275 $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< && \
258 mv $@+ $@ 276 mv $@+ $@
259 277
260perfman.texi: $(MAN_XML) cat-texi.perl 278$(OUTPUT)perfman.texi: $(MAN_XML) cat-texi.perl
261 $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ 279 $(QUIET_DB2TEXI)$(RM) $@+ $@ && \
262 ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \ 280 ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \
263 --to-stdout $(xml) &&) true) > $@++ && \ 281 --to-stdout $(xml) &&) true) > $@++ && \
@@ -265,7 +283,7 @@ perfman.texi: $(MAN_XML) cat-texi.perl
265 rm $@++ && \ 283 rm $@++ && \
266 mv $@+ $@ 284 mv $@+ $@
267 285
268perfman.info: perfman.texi 286$(OUTPUT)perfman.info: $(OUTPUT)perfman.texi
269 $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi 287 $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi
270 288
271$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml 289$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 7a527f7e9da9..ddc22525228d 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -21,6 +21,8 @@ EVENT MODIFIERS
21Events can optionally have a modifer by appending a colon and one or 21Events can optionally have a modifer by appending a colon and one or
22more modifiers. Modifiers allow the user to restrict when events are 22more modifiers. Modifiers allow the user to restrict when events are
23counted with 'u' for user-space, 'k' for kernel, 'h' for hypervisor. 23counted with 'u' for user-space, 'k' for kernel, 'h' for hypervisor.
24Additional modifiers are 'G' for guest counting (in KVM guests) and 'H'
25for host counting (not in KVM guests).
24 26
25The 'p' modifier can be used for specifying how precise the instruction 27The 'p' modifier can be used for specifying how precise the instruction
26address should be. The 'p' modifier is currently only implemented for 28address should be. The 'p' modifier is currently only implemented for
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index d6b2a4f2108b..c7f5f55634ac 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -8,7 +8,7 @@ perf-lock - Analyze lock events
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf lock' {record|report|trace} 11'perf lock' {record|report|script|info}
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
@@ -20,10 +20,13 @@ and statistics with this 'perf lock' command.
20 produces the file "perf.data" which contains tracing 20 produces the file "perf.data" which contains tracing
21 results of lock events. 21 results of lock events.
22 22
23 'perf lock trace' shows raw lock events.
24
25 'perf lock report' reports statistical data. 23 'perf lock report' reports statistical data.
26 24
25 'perf lock script' shows raw lock events.
26
27 'perf lock info' shows metadata like threads or addresses
28 of lock instances.
29
27COMMON OPTIONS 30COMMON OPTIONS
28-------------- 31--------------
29 32
@@ -47,6 +50,17 @@ REPORT OPTIONS
47 Sorting key. Possible values: acquired (default), contended, 50 Sorting key. Possible values: acquired (default), contended,
48 wait_total, wait_max, wait_min. 51 wait_total, wait_max, wait_min.
49 52
53INFO OPTIONS
54------------
55
56-t::
57--threads::
58 dump thread list in perf.data
59
60-m::
61--map::
62 dump map of lock instances (address:name table)
63
50SEE ALSO 64SEE ALSO
51-------- 65--------
52linkperf:perf[1] 66linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 2937f7e14bb7..a1386b2fff00 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -52,11 +52,15 @@ OPTIONS
52 52
53-p:: 53-p::
54--pid=:: 54--pid=::
55 Record events on existing process ID. 55 Record events on existing process ID (comma separated list).
56 56
57-t:: 57-t::
58--tid=:: 58--tid=::
59 Record events on existing thread ID. 59 Record events on existing thread ID (comma separated list).
60
61-u::
62--uid=::
63 Record events in threads owned by uid. Name or number.
60 64
61-r:: 65-r::
62--realtime=:: 66--realtime=::
@@ -148,6 +152,36 @@ an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must ha
148corresponding events, i.e., they always refer to events defined earlier on the command 152corresponding events, i.e., they always refer to events defined earlier on the command
149line. 153line.
150 154
155-b::
156--branch-any::
157Enable taken branch stack sampling. Any type of taken branch may be sampled.
158This is a shortcut for --branch-filter any. See --branch-filter for more infos.
159
160-j::
161--branch-filter::
162Enable taken branch stack sampling. Each sample captures a series of consecutive
163taken branches. The number of branches captured with each sample depends on the
164underlying hardware, the type of branches of interest, and the executed code.
165It is possible to select the types of branches captured by enabling filters. The
166following filters are defined:
167
168 - any: any type of branches
169 - any_call: any function call or system call
170 - any_ret: any function return or system call return
171 - any_ind: any indirect branch
172 - u: only when the branch target is at the user level
173 - k: only when the branch target is in the kernel
174 - hv: only when the target is at the hypervisor level
175
176+
177The option requires at least one branch type among any, any_call, any_ret, ind_call.
178The privilege levels may be ommitted, in which case, the privilege levels of the associated
179event are applied to the branch filter. Both kernel (k) and hypervisor (hv) privilege
180levels are subject to permissions. When sampling on multiple events, branch stack sampling
181is enabled for all the sampling events. The sampled branch type is the same for all events.
182The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
183Note that this feature may not be available on all processors.
184
151SEE ALSO 185SEE ALSO
152-------- 186--------
153linkperf:perf-stat[1], linkperf:perf-list[1] 187linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 9b430e98712e..2d89f02719b5 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -48,6 +48,9 @@ OPTIONS
48 Only consider these symbols. CSV that understands 48 Only consider these symbols. CSV that understands
49 file://filename entries. 49 file://filename entries.
50 50
51--symbol-filter=::
52 Only show symbols that match (partially) with this filter.
53
51-U:: 54-U::
52--hide-unresolved:: 55--hide-unresolved::
53 Only display entries resolved to a symbol. 56 Only display entries resolved to a symbol.
@@ -110,6 +113,8 @@ OPTIONS
110 requires a tty, if one is not present, as when piping to other 113 requires a tty, if one is not present, as when piping to other
111 commands, the stdio interface is used. 114 commands, the stdio interface is used.
112 115
116--gtk:: Use the GTK2 interface.
117
113-k:: 118-k::
114--vmlinux=<file>:: 119--vmlinux=<file>::
115 vmlinux pathname 120 vmlinux pathname
@@ -153,6 +158,16 @@ OPTIONS
153 information which may be very large and thus may clutter the display. 158 information which may be very large and thus may clutter the display.
154 It currently includes: cpu and numa topology of the host system. 159 It currently includes: cpu and numa topology of the host system.
155 160
161-b::
162--branch-stack::
163 Use the addresses of sampled taken branches instead of the instruction
164 address to build the histograms. To generate meaningful output, the
165 perf.data file must have been obtained using perf record -b or
166 perf record --branch-filter xxx where xxx is a branch filter option.
167 perf report is able to auto-detect whether a perf.data file contains
168 branch stacks and it will automatically switch to the branch view mode,
169 unless --no-branch-stack is used.
170
156SEE ALSO 171SEE ALSO
157-------- 172--------
158linkperf:perf-stat[1], linkperf:perf-annotate[1] 173linkperf:perf-stat[1], linkperf:perf-annotate[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 2f6cef43da25..e9cbfcddfa3f 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,7 +115,7 @@ OPTIONS
115-f:: 115-f::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr. 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff.
119 Field list can be prepended with the type, trace, sw or hw, 119 Field list can be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies. 120 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -200,6 +200,9 @@ OPTIONS
200 It currently includes: cpu and numa topology of the host system. 200 It currently includes: cpu and numa topology of the host system.
201 It can only be used with the perf script report mode. 201 It can only be used with the perf script report mode.
202 202
203--show-kernel-path::
204 Try to resolve the path of [kernel.kallsyms]
205
203SEE ALSO 206SEE ALSO
204-------- 207--------
205linkperf:perf-record[1], linkperf:perf-script-perl[1], 208linkperf: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 8966b9ab2014..2fa173b51970 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -35,11 +35,11 @@ OPTIONS
35 child tasks do not inherit counters 35 child tasks do not inherit counters
36-p:: 36-p::
37--pid=<pid>:: 37--pid=<pid>::
38 stat events on existing process id 38 stat events on existing process id (comma separated list)
39 39
40-t:: 40-t::
41--tid=<tid>:: 41--tid=<tid>::
42 stat events on existing thread id 42 stat events on existing thread id (comma separated list)
43 43
44 44
45-a:: 45-a::
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index b1a5bbbfebef..4a5680cb242e 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -72,11 +72,15 @@ Default is to monitor all CPUS.
72 72
73-p <pid>:: 73-p <pid>::
74--pid=<pid>:: 74--pid=<pid>::
75 Profile events on existing Process ID. 75 Profile events on existing Process ID (comma separated list).
76 76
77-t <tid>:: 77-t <tid>::
78--tid=<tid>:: 78--tid=<tid>::
79 Profile events on existing thread ID. 79 Profile events on existing thread ID (comma separated list).
80
81-u::
82--uid=::
83 Record events in threads owned by uid. Name or number.
80 84
81-r <priority>:: 85-r <priority>::
82--realtime=<priority>:: 86--realtime=<priority>::
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index c12659d8cb26..5476bc0a1eac 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,4 +1,5 @@
1tools/perf 1tools/perf
2include/linux/const.h
2include/linux/perf_event.h 3include/linux/perf_event.h
3include/linux/rbtree.h 4include/linux/rbtree.h
4include/linux/list.h 5include/linux/list.h
@@ -8,6 +9,7 @@ lib/rbtree.c
8include/linux/swab.h 9include/linux/swab.h
9arch/*/include/asm/unistd*.h 10arch/*/include/asm/unistd*.h
10arch/*/lib/memcpy*.S 11arch/*/lib/memcpy*.S
12arch/*/lib/memset*.S
11include/linux/poison.h 13include/linux/poison.h
12include/linux/magic.h 14include/linux/magic.h
13include/linux/hw_breakpoint.h 15include/linux/hw_breakpoint.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index ac86d67b636e..820371f10d1b 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -15,6 +15,16 @@ endif
15 15
16# Define V to have a more verbose compile. 16# Define V to have a more verbose compile.
17# 17#
18# Define O to save output files in a separate directory.
19#
20# Define ARCH as name of target architecture if you want cross-builds.
21#
22# Define CROSS_COMPILE as prefix name of compiler if you want cross-builds.
23#
24# Define NO_LIBPERL to disable perl script extension.
25#
26# Define NO_LIBPYTHON to disable python script extension.
27#
18# Define PYTHON to point to the python binary if the default 28# Define PYTHON to point to the python binary if the default
19# `python' is not correct; for example: PYTHON=python2 29# `python' is not correct; for example: PYTHON=python2
20# 30#
@@ -32,6 +42,10 @@ endif
32# Define NO_DWARF if you do not want debug-info analysis feature at all. 42# Define NO_DWARF if you do not want debug-info analysis feature at all.
33# 43#
34# Define WERROR=0 to disable treating any warnings as errors. 44# Define WERROR=0 to disable treating any warnings as errors.
45#
46# Define NO_NEWT if you do not want TUI support.
47#
48# Define NO_DEMANGLE if you do not want C++ symbol demangling.
35 49
36$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE 50$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
37 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) 51 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
@@ -61,7 +75,7 @@ ifeq ($(ARCH),x86_64)
61 ifeq (${IS_X86_64}, 1) 75 ifeq (${IS_X86_64}, 1)
62 RAW_ARCH := x86_64 76 RAW_ARCH := x86_64
63 ARCH_CFLAGS := -DARCH_X86_64 77 ARCH_CFLAGS := -DARCH_X86_64
64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S 78 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
65 endif 79 endif
66endif 80endif
67 81
@@ -104,7 +118,7 @@ endif
104 118
105CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 119CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
106EXTLIBS = -lpthread -lrt -lelf -lm 120EXTLIBS = -lpthread -lrt -lelf -lm
107ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 121ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
108ALL_LDFLAGS = $(LDFLAGS) 122ALL_LDFLAGS = $(LDFLAGS)
109STRIP ?= strip 123STRIP ?= strip
110 124
@@ -168,10 +182,7 @@ endif
168 182
169### --- END CONFIGURATION SECTION --- 183### --- END CONFIGURATION SECTION ---
170 184
171# Those must not be GNU-specific; they are shared with perl/ which may 185BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
172# be built by a different compiler. (Note that this is an artifact now
173# but it still might be nice to keep that distinction.)
174BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include
175BASIC_LDFLAGS = 186BASIC_LDFLAGS =
176 187
177# Guard against environment variables 188# Guard against environment variables
@@ -186,7 +197,10 @@ SCRIPT_SH += perf-archive.sh
186grep-libs = $(filter -l%,$(1)) 197grep-libs = $(filter -l%,$(1))
187strip-libs = $(filter-out -l%,$(1)) 198strip-libs = $(filter-out -l%,$(1))
188 199
189$(OUTPUT)python/perf.so: $(PYRF_OBJS) 200PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
201PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
202
203$(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
190 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 204 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
191 --quiet build_ext; \ 205 --quiet build_ext; \
192 mkdir -p $(OUTPUT)python && \ 206 mkdir -p $(OUTPUT)python && \
@@ -220,6 +234,25 @@ endif
220 234
221export PERL_PATH 235export PERL_PATH
222 236
237FLEX = $(CROSS_COMPILE)flex
238BISON= $(CROSS_COMPILE)bison
239
240event-parser:
241 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c
242 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
243
244$(OUTPUT)util/parse-events-flex.c: event-parser
245$(OUTPUT)util/parse-events-bison.c: event-parser
246
247pmu-parser:
248 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c
249 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
250
251$(OUTPUT)util/pmu-flex.c: pmu-parser
252$(OUTPUT)util/pmu-bison.c: pmu-parser
253
254$(OUTPUT)util/parse-events.o: event-parser pmu-parser
255
223LIB_FILE=$(OUTPUT)libperf.a 256LIB_FILE=$(OUTPUT)libperf.a
224 257
225LIB_H += ../../include/linux/perf_event.h 258LIB_H += ../../include/linux/perf_event.h
@@ -235,7 +268,7 @@ LIB_H += util/include/linux/const.h
235LIB_H += util/include/linux/ctype.h 268LIB_H += util/include/linux/ctype.h
236LIB_H += util/include/linux/kernel.h 269LIB_H += util/include/linux/kernel.h
237LIB_H += util/include/linux/list.h 270LIB_H += util/include/linux/list.h
238LIB_H += util/include/linux/module.h 271LIB_H += util/include/linux/export.h
239LIB_H += util/include/linux/poison.h 272LIB_H += util/include/linux/poison.h
240LIB_H += util/include/linux/prefetch.h 273LIB_H += util/include/linux/prefetch.h
241LIB_H += util/include/linux/rbtree.h 274LIB_H += util/include/linux/rbtree.h
@@ -252,6 +285,8 @@ LIB_H += util/include/asm/uaccess.h
252LIB_H += util/include/dwarf-regs.h 285LIB_H += util/include/dwarf-regs.h
253LIB_H += util/include/asm/dwarf2.h 286LIB_H += util/include/asm/dwarf2.h
254LIB_H += util/include/asm/cpufeature.h 287LIB_H += util/include/asm/cpufeature.h
288LIB_H += util/include/asm/unistd_32.h
289LIB_H += util/include/asm/unistd_64.h
255LIB_H += perf.h 290LIB_H += perf.h
256LIB_H += util/annotate.h 291LIB_H += util/annotate.h
257LIB_H += util/cache.h 292LIB_H += util/cache.h
@@ -259,6 +294,8 @@ LIB_H += util/callchain.h
259LIB_H += util/build-id.h 294LIB_H += util/build-id.h
260LIB_H += util/debug.h 295LIB_H += util/debug.h
261LIB_H += util/debugfs.h 296LIB_H += util/debugfs.h
297LIB_H += util/sysfs.h
298LIB_H += util/pmu.h
262LIB_H += util/event.h 299LIB_H += util/event.h
263LIB_H += util/evsel.h 300LIB_H += util/evsel.h
264LIB_H += util/evlist.h 301LIB_H += util/evlist.h
@@ -305,6 +342,8 @@ LIB_OBJS += $(OUTPUT)util/build-id.o
305LIB_OBJS += $(OUTPUT)util/config.o 342LIB_OBJS += $(OUTPUT)util/config.o
306LIB_OBJS += $(OUTPUT)util/ctype.o 343LIB_OBJS += $(OUTPUT)util/ctype.o
307LIB_OBJS += $(OUTPUT)util/debugfs.o 344LIB_OBJS += $(OUTPUT)util/debugfs.o
345LIB_OBJS += $(OUTPUT)util/sysfs.o
346LIB_OBJS += $(OUTPUT)util/pmu.o
308LIB_OBJS += $(OUTPUT)util/environment.o 347LIB_OBJS += $(OUTPUT)util/environment.o
309LIB_OBJS += $(OUTPUT)util/event.o 348LIB_OBJS += $(OUTPUT)util/event.o
310LIB_OBJS += $(OUTPUT)util/evlist.o 349LIB_OBJS += $(OUTPUT)util/evlist.o
@@ -341,6 +380,10 @@ LIB_OBJS += $(OUTPUT)util/session.o
341LIB_OBJS += $(OUTPUT)util/thread.o 380LIB_OBJS += $(OUTPUT)util/thread.o
342LIB_OBJS += $(OUTPUT)util/thread_map.o 381LIB_OBJS += $(OUTPUT)util/thread_map.o
343LIB_OBJS += $(OUTPUT)util/trace-event-parse.o 382LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
383LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
384LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
385LIB_OBJS += $(OUTPUT)util/pmu-flex.o
386LIB_OBJS += $(OUTPUT)util/pmu-bison.o
344LIB_OBJS += $(OUTPUT)util/trace-event-read.o 387LIB_OBJS += $(OUTPUT)util/trace-event-read.o
345LIB_OBJS += $(OUTPUT)util/trace-event-info.o 388LIB_OBJS += $(OUTPUT)util/trace-event-info.o
346LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o 389LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
@@ -362,8 +405,10 @@ BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
362BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o 405BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
363ifeq ($(RAW_ARCH),x86_64) 406ifeq ($(RAW_ARCH),x86_64)
364BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o 407BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
408BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
365endif 409endif
366BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 410BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
411BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
367 412
368BUILTIN_OBJS += $(OUTPUT)builtin-diff.o 413BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
369BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o 414BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
@@ -481,6 +526,20 @@ else
481 endif 526 endif
482endif 527endif
483 528
529ifdef NO_GTK2
530 BASIC_CFLAGS += -DNO_GTK2
531else
532 FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0)
533 ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
534 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
535 BASIC_CFLAGS += -DNO_GTK2_SUPPORT
536 else
537 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
538 EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
539 LIB_OBJS += $(OUTPUT)util/gtk/browser.o
540 endif
541endif
542
484ifdef NO_LIBPERL 543ifdef NO_LIBPERL
485 BASIC_CFLAGS += -DNO_LIBPERL 544 BASIC_CFLAGS += -DNO_LIBPERL
486else 545else
@@ -627,6 +686,8 @@ ifndef V
627 QUIET_LINK = @echo ' ' LINK $@; 686 QUIET_LINK = @echo ' ' LINK $@;
628 QUIET_MKDIR = @echo ' ' MKDIR $@; 687 QUIET_MKDIR = @echo ' ' MKDIR $@;
629 QUIET_GEN = @echo ' ' GEN $@; 688 QUIET_GEN = @echo ' ' GEN $@;
689 QUIET_FLEX = @echo ' ' FLEX $@;
690 QUIET_BISON = @echo ' ' BISON $@;
630endif 691endif
631endif 692endif
632 693
@@ -707,12 +768,28 @@ $(OUTPUT)perf.o perf.spec \
707 $(SCRIPTS) \ 768 $(SCRIPTS) \
708 : $(OUTPUT)PERF-VERSION-FILE 769 : $(OUTPUT)PERF-VERSION-FILE
709 770
771.SUFFIXES:
772.SUFFIXES: .o .c .S .s
773
774# These two need to be here so that when O= is not used they take precedence
775# over the general rule for .o
776
777$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
778 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $<
779
780$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
781 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $<
782
710$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS 783$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
711 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 784 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
785$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
786 $(QUIET_CC)$(CC) -o $@ -E $(ALL_CFLAGS) $<
712$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS 787$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
713 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< 788 $(QUIET_CC)$(CC) -o $@ -S $(ALL_CFLAGS) $<
714$(OUTPUT)%.o: %.S 789$(OUTPUT)%.o: %.S
715 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 790 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
791$(OUTPUT)%.s: %.S
792 $(QUIET_CC)$(CC) -o $@ -E $(ALL_CFLAGS) $<
716 793
717$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS 794$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
718 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ 795 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
@@ -775,6 +852,8 @@ help:
775 @echo ' html - make html documentation' 852 @echo ' html - make html documentation'
776 @echo ' info - make GNU info documentation (access with info <foo>)' 853 @echo ' info - make GNU info documentation (access with info <foo>)'
777 @echo ' pdf - make pdf documentation' 854 @echo ' pdf - make pdf documentation'
855 @echo ' event-parser - make event parser code'
856 @echo ' pmu-parser - make pmu format parser code'
778 @echo ' TAGS - use etags to make tag information for source browsing' 857 @echo ' TAGS - use etags to make tag information for source browsing'
779 @echo ' tags - use ctags to make tag information for source browsing' 858 @echo ' tags - use ctags to make tag information for source browsing'
780 @echo ' cscope - use cscope to make interactive browsing database' 859 @echo ' cscope - use cscope to make interactive browsing database'
@@ -795,7 +874,6 @@ help:
795 @echo ' quick-install-html - install the html documentation quickly' 874 @echo ' quick-install-html - install the html documentation quickly'
796 @echo '' 875 @echo ''
797 @echo 'Perf maintainer targets:' 876 @echo 'Perf maintainer targets:'
798 @echo ' distclean - alias to clean'
799 @echo ' clean - clean all binary objects and build output' 877 @echo ' clean - clean all binary objects and build output'
800 878
801doc: 879doc:
@@ -912,6 +990,7 @@ clean:
912 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* 990 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
913 $(MAKE) -C Documentation/ clean 991 $(MAKE) -C Documentation/ clean
914 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS 992 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
993 $(RM) $(OUTPUT)util/*-{bison,flex}*
915 $(python-clean) 994 $(python-clean)
916 995
917.PHONY: all install clean strip 996.PHONY: all install clean strip
diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c
index eba80c292945..2f7073d107fd 100644
--- a/tools/perf/arch/powerpc/util/header.c
+++ b/tools/perf/arch/powerpc/util/header.c
@@ -25,7 +25,7 @@ get_cpuid(char *buffer, size_t sz)
25 25
26 pvr = mfspr(SPRN_PVR); 26 pvr = mfspr(SPRN_PVR);
27 27
28 nb = snprintf(buffer, sz, "%lu,%lu$", PVR_VER(pvr), PVR_REV(pvr)); 28 nb = scnprintf(buffer, sz, "%lu,%lu$", PVR_VER(pvr), PVR_REV(pvr));
29 29
30 /* look for end marker to ensure the entire data fit */ 30 /* look for end marker to ensure the entire data fit */
31 if (strchr(buffer, '$')) { 31 if (strchr(buffer, '$')) {
diff --git a/tools/perf/arch/x86/util/header.c b/tools/perf/arch/x86/util/header.c
index f94006068d2b..146d12a1cec0 100644
--- a/tools/perf/arch/x86/util/header.c
+++ b/tools/perf/arch/x86/util/header.c
@@ -48,7 +48,7 @@ get_cpuid(char *buffer, size_t sz)
48 if (family >= 0x6) 48 if (family >= 0x6)
49 model += ((a >> 16) & 0xf) << 4; 49 model += ((a >> 16) & 0xf) << 4;
50 } 50 }
51 nb = snprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step); 51 nb = scnprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step);
52 52
53 /* look for end marker to ensure the entire data fit */ 53 /* look for end marker to ensure the entire data fit */
54 if (strchr(buffer, '$')) { 54 if (strchr(buffer, '$')) {
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index f7781c6267c0..a09bece6dad2 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -4,6 +4,7 @@
4extern int bench_sched_messaging(int argc, const char **argv, const char *prefix); 4extern int bench_sched_messaging(int argc, const char **argv, const char *prefix);
5extern int bench_sched_pipe(int argc, const char **argv, const char *prefix); 5extern int bench_sched_pipe(int argc, const char **argv, const char *prefix);
6extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used); 6extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used);
7extern int bench_mem_memset(int argc, const char **argv, const char *prefix);
7 8
8#define BENCH_FORMAT_DEFAULT_STR "default" 9#define BENCH_FORMAT_DEFAULT_STR "default"
9#define BENCH_FORMAT_DEFAULT 0 10#define BENCH_FORMAT_DEFAULT 0
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
index d588b87696fc..d66ab799b35f 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
@@ -2,3 +2,11 @@
2MEMCPY_FN(__memcpy, 2MEMCPY_FN(__memcpy,
3 "x86-64-unrolled", 3 "x86-64-unrolled",
4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S") 4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S")
5
6MEMCPY_FN(memcpy_c,
7 "x86-64-movsq",
8 "movsq-based memcpy() in arch/x86/lib/memcpy_64.S")
9
10MEMCPY_FN(memcpy_c_e,
11 "x86-64-movsb",
12 "movsb-based memcpy() in arch/x86/lib/memcpy_64.S")
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index a57b66e853c2..fcd9cf00600a 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -1,2 +1,12 @@
1 1#define memcpy MEMCPY /* don't hide glibc's memcpy() */
2#define altinstr_replacement text
3#define globl p2align 4; .globl
4#define Lmemcpy_c globl memcpy_c; memcpy_c
5#define Lmemcpy_c_e globl memcpy_c_e; memcpy_c_e
2#include "../../../arch/x86/lib/memcpy_64.S" 6#include "../../../arch/x86/lib/memcpy_64.S"
7/*
8 * We need to provide note.GNU-stack section, saying that we want
9 * NOT executable stack. Otherwise the final linking will assume that
10 * the ELF stack should not be restricted at all and set it RWX.
11 */
12.section .note.GNU-stack,"",@progbits
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index db82021f4b91..71557225bf92 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -5,7 +5,6 @@
5 * 5 *
6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
7 */ 7 */
8#include <ctype.h>
9 8
10#include "../perf.h" 9#include "../perf.h"
11#include "../util/util.h" 10#include "../util/util.h"
@@ -24,6 +23,7 @@
24 23
25static const char *length_str = "1MB"; 24static const char *length_str = "1MB";
26static const char *routine = "default"; 25static const char *routine = "default";
26static int iterations = 1;
27static bool use_clock; 27static bool use_clock;
28static int clock_fd; 28static int clock_fd;
29static bool only_prefault; 29static bool only_prefault;
@@ -35,6 +35,8 @@ static const struct option options[] = {
35 "available unit: B, MB, GB (upper and lower)"), 35 "available unit: B, MB, GB (upper and lower)"),
36 OPT_STRING('r', "routine", &routine, "default", 36 OPT_STRING('r', "routine", &routine, "default",
37 "Specify routine to copy"), 37 "Specify routine to copy"),
38 OPT_INTEGER('i', "iterations", &iterations,
39 "repeat memcpy() invocation this number of times"),
38 OPT_BOOLEAN('c', "clock", &use_clock, 40 OPT_BOOLEAN('c', "clock", &use_clock,
39 "Use CPU clock for measuring"), 41 "Use CPU clock for measuring"),
40 OPT_BOOLEAN('o', "only-prefault", &only_prefault, 42 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
@@ -121,6 +123,7 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
121{ 123{
122 u64 clock_start = 0ULL, clock_end = 0ULL; 124 u64 clock_start = 0ULL, clock_end = 0ULL;
123 void *src = NULL, *dst = NULL; 125 void *src = NULL, *dst = NULL;
126 int i;
124 127
125 alloc_mem(&src, &dst, len); 128 alloc_mem(&src, &dst, len);
126 129
@@ -128,7 +131,8 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
128 fn(dst, src, len); 131 fn(dst, src, len);
129 132
130 clock_start = get_clock(); 133 clock_start = get_clock();
131 fn(dst, src, len); 134 for (i = 0; i < iterations; ++i)
135 fn(dst, src, len);
132 clock_end = get_clock(); 136 clock_end = get_clock();
133 137
134 free(src); 138 free(src);
@@ -140,6 +144,7 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
140{ 144{
141 struct timeval tv_start, tv_end, tv_diff; 145 struct timeval tv_start, tv_end, tv_diff;
142 void *src = NULL, *dst = NULL; 146 void *src = NULL, *dst = NULL;
147 int i;
143 148
144 alloc_mem(&src, &dst, len); 149 alloc_mem(&src, &dst, len);
145 150
@@ -147,7 +152,8 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
147 fn(dst, src, len); 152 fn(dst, src, len);
148 153
149 BUG_ON(gettimeofday(&tv_start, NULL)); 154 BUG_ON(gettimeofday(&tv_start, NULL));
150 fn(dst, src, len); 155 for (i = 0; i < iterations; ++i)
156 fn(dst, src, len);
151 BUG_ON(gettimeofday(&tv_end, NULL)); 157 BUG_ON(gettimeofday(&tv_end, NULL));
152 158
153 timersub(&tv_end, &tv_start, &tv_diff); 159 timersub(&tv_end, &tv_start, &tv_diff);
diff --git a/tools/perf/bench/mem-memset-arch.h b/tools/perf/bench/mem-memset-arch.h
new file mode 100644
index 000000000000..a040fa77665b
--- /dev/null
+++ b/tools/perf/bench/mem-memset-arch.h
@@ -0,0 +1,12 @@
1
2#ifdef ARCH_X86_64
3
4#define MEMSET_FN(fn, name, desc) \
5 extern void *fn(void *, int, size_t);
6
7#include "mem-memset-x86-64-asm-def.h"
8
9#undef MEMSET_FN
10
11#endif
12
diff --git a/tools/perf/bench/mem-memset-x86-64-asm-def.h b/tools/perf/bench/mem-memset-x86-64-asm-def.h
new file mode 100644
index 000000000000..a71dff97c1f5
--- /dev/null
+++ b/tools/perf/bench/mem-memset-x86-64-asm-def.h
@@ -0,0 +1,12 @@
1
2MEMSET_FN(__memset,
3 "x86-64-unrolled",
4 "unrolled memset() in arch/x86/lib/memset_64.S")
5
6MEMSET_FN(memset_c,
7 "x86-64-stosq",
8 "movsq-based memset() in arch/x86/lib/memset_64.S")
9
10MEMSET_FN(memset_c_e,
11 "x86-64-stosb",
12 "movsb-based memset() in arch/x86/lib/memset_64.S")
diff --git a/tools/perf/bench/mem-memset-x86-64-asm.S b/tools/perf/bench/mem-memset-x86-64-asm.S
new file mode 100644
index 000000000000..9e5af89ed13a
--- /dev/null
+++ b/tools/perf/bench/mem-memset-x86-64-asm.S
@@ -0,0 +1,13 @@
1#define memset MEMSET /* don't hide glibc's memset() */
2#define altinstr_replacement text
3#define globl p2align 4; .globl
4#define Lmemset_c globl memset_c; memset_c
5#define Lmemset_c_e globl memset_c_e; memset_c_e
6#include "../../../arch/x86/lib/memset_64.S"
7
8/*
9 * We need to provide note.GNU-stack section, saying that we want
10 * NOT executable stack. Otherwise the final linking will assume that
11 * the ELF stack should not be restricted at all and set it RWX.
12 */
13.section .note.GNU-stack,"",@progbits
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
new file mode 100644
index 000000000000..e9079185bd72
--- /dev/null
+++ b/tools/perf/bench/mem-memset.c
@@ -0,0 +1,297 @@
1/*
2 * mem-memset.c
3 *
4 * memset: Simple memory set in various ways
5 *
6 * Trivial clone of mem-memcpy.c.
7 */
8
9#include "../perf.h"
10#include "../util/util.h"
11#include "../util/parse-options.h"
12#include "../util/header.h"
13#include "bench.h"
14#include "mem-memset-arch.h"
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <sys/time.h>
20#include <errno.h>
21
22#define K 1024
23
24static const char *length_str = "1MB";
25static const char *routine = "default";
26static int iterations = 1;
27static bool use_clock;
28static int clock_fd;
29static bool only_prefault;
30static bool no_prefault;
31
32static const struct option options[] = {
33 OPT_STRING('l', "length", &length_str, "1MB",
34 "Specify length of memory to copy. "
35 "available unit: B, MB, GB (upper and lower)"),
36 OPT_STRING('r', "routine", &routine, "default",
37 "Specify routine to copy"),
38 OPT_INTEGER('i', "iterations", &iterations,
39 "repeat memset() invocation this number of times"),
40 OPT_BOOLEAN('c', "clock", &use_clock,
41 "Use CPU clock for measuring"),
42 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
43 "Show only the result with page faults before memset()"),
44 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
45 "Show only the result without page faults before memset()"),
46 OPT_END()
47};
48
49typedef void *(*memset_t)(void *, int, size_t);
50
51struct routine {
52 const char *name;
53 const char *desc;
54 memset_t fn;
55};
56
57static const struct routine routines[] = {
58 { "default",
59 "Default memset() provided by glibc",
60 memset },
61#ifdef ARCH_X86_64
62
63#define MEMSET_FN(fn, name, desc) { name, desc, fn },
64#include "mem-memset-x86-64-asm-def.h"
65#undef MEMSET_FN
66
67#endif
68
69 { NULL,
70 NULL,
71 NULL }
72};
73
74static const char * const bench_mem_memset_usage[] = {
75 "perf bench mem memset <options>",
76 NULL
77};
78
79static struct perf_event_attr clock_attr = {
80 .type = PERF_TYPE_HARDWARE,
81 .config = PERF_COUNT_HW_CPU_CYCLES
82};
83
84static void init_clock(void)
85{
86 clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
87
88 if (clock_fd < 0 && errno == ENOSYS)
89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
90 else
91 BUG_ON(clock_fd < 0);
92}
93
94static u64 get_clock(void)
95{
96 int ret;
97 u64 clk;
98
99 ret = read(clock_fd, &clk, sizeof(u64));
100 BUG_ON(ret != sizeof(u64));
101
102 return clk;
103}
104
105static double timeval2double(struct timeval *ts)
106{
107 return (double)ts->tv_sec +
108 (double)ts->tv_usec / (double)1000000;
109}
110
111static void alloc_mem(void **dst, size_t length)
112{
113 *dst = zalloc(length);
114 if (!dst)
115 die("memory allocation failed - maybe length is too large?\n");
116}
117
118static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
119{
120 u64 clock_start = 0ULL, clock_end = 0ULL;
121 void *dst = NULL;
122 int i;
123
124 alloc_mem(&dst, len);
125
126 if (prefault)
127 fn(dst, -1, len);
128
129 clock_start = get_clock();
130 for (i = 0; i < iterations; ++i)
131 fn(dst, i, len);
132 clock_end = get_clock();
133
134 free(dst);
135 return clock_end - clock_start;
136}
137
138static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
139{
140 struct timeval tv_start, tv_end, tv_diff;
141 void *dst = NULL;
142 int i;
143
144 alloc_mem(&dst, len);
145
146 if (prefault)
147 fn(dst, -1, len);
148
149 BUG_ON(gettimeofday(&tv_start, NULL));
150 for (i = 0; i < iterations; ++i)
151 fn(dst, i, len);
152 BUG_ON(gettimeofday(&tv_end, NULL));
153
154 timersub(&tv_end, &tv_start, &tv_diff);
155
156 free(dst);
157 return (double)((double)len / timeval2double(&tv_diff));
158}
159
160#define pf (no_prefault ? 0 : 1)
161
162#define print_bps(x) do { \
163 if (x < K) \
164 printf(" %14lf B/Sec", x); \
165 else if (x < K * K) \
166 printf(" %14lfd KB/Sec", x / K); \
167 else if (x < K * K * K) \
168 printf(" %14lf MB/Sec", x / K / K); \
169 else \
170 printf(" %14lf GB/Sec", x / K / K / K); \
171 } while (0)
172
173int bench_mem_memset(int argc, const char **argv,
174 const char *prefix __used)
175{
176 int i;
177 size_t len;
178 double result_bps[2];
179 u64 result_clock[2];
180
181 argc = parse_options(argc, argv, options,
182 bench_mem_memset_usage, 0);
183
184 if (use_clock)
185 init_clock();
186
187 len = (size_t)perf_atoll((char *)length_str);
188
189 result_clock[0] = result_clock[1] = 0ULL;
190 result_bps[0] = result_bps[1] = 0.0;
191
192 if ((s64)len <= 0) {
193 fprintf(stderr, "Invalid length:%s\n", length_str);
194 return 1;
195 }
196
197 /* same to without specifying either of prefault and no-prefault */
198 if (only_prefault && no_prefault)
199 only_prefault = no_prefault = false;
200
201 for (i = 0; routines[i].name; i++) {
202 if (!strcmp(routines[i].name, routine))
203 break;
204 }
205 if (!routines[i].name) {
206 printf("Unknown routine:%s\n", routine);
207 printf("Available routines...\n");
208 for (i = 0; routines[i].name; i++) {
209 printf("\t%s ... %s\n",
210 routines[i].name, routines[i].desc);
211 }
212 return 1;
213 }
214
215 if (bench_format == BENCH_FORMAT_DEFAULT)
216 printf("# Copying %s Bytes ...\n\n", length_str);
217
218 if (!only_prefault && !no_prefault) {
219 /* show both of results */
220 if (use_clock) {
221 result_clock[0] =
222 do_memset_clock(routines[i].fn, len, false);
223 result_clock[1] =
224 do_memset_clock(routines[i].fn, len, true);
225 } else {
226 result_bps[0] =
227 do_memset_gettimeofday(routines[i].fn,
228 len, false);
229 result_bps[1] =
230 do_memset_gettimeofday(routines[i].fn,
231 len, true);
232 }
233 } else {
234 if (use_clock) {
235 result_clock[pf] =
236 do_memset_clock(routines[i].fn,
237 len, only_prefault);
238 } else {
239 result_bps[pf] =
240 do_memset_gettimeofday(routines[i].fn,
241 len, only_prefault);
242 }
243 }
244
245 switch (bench_format) {
246 case BENCH_FORMAT_DEFAULT:
247 if (!only_prefault && !no_prefault) {
248 if (use_clock) {
249 printf(" %14lf Clock/Byte\n",
250 (double)result_clock[0]
251 / (double)len);
252 printf(" %14lf Clock/Byte (with prefault)\n ",
253 (double)result_clock[1]
254 / (double)len);
255 } else {
256 print_bps(result_bps[0]);
257 printf("\n");
258 print_bps(result_bps[1]);
259 printf(" (with prefault)\n");
260 }
261 } else {
262 if (use_clock) {
263 printf(" %14lf Clock/Byte",
264 (double)result_clock[pf]
265 / (double)len);
266 } else
267 print_bps(result_bps[pf]);
268
269 printf("%s\n", only_prefault ? " (with prefault)" : "");
270 }
271 break;
272 case BENCH_FORMAT_SIMPLE:
273 if (!only_prefault && !no_prefault) {
274 if (use_clock) {
275 printf("%lf %lf\n",
276 (double)result_clock[0] / (double)len,
277 (double)result_clock[1] / (double)len);
278 } else {
279 printf("%lf %lf\n",
280 result_bps[0], result_bps[1]);
281 }
282 } else {
283 if (use_clock) {
284 printf("%lf\n", (double)result_clock[pf]
285 / (double)len);
286 } else
287 printf("%lf\n", result_bps[pf]);
288 }
289 break;
290 default:
291 /* reaching this means there's some disaster: */
292 die("unknown format: %d\n", bench_format);
293 break;
294 }
295
296 return 0;
297}
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 214ba7f9f577..806e0a286634 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -235,7 +235,7 @@ out_delete:
235} 235}
236 236
237static const char * const annotate_usage[] = { 237static const char * const annotate_usage[] = {
238 "perf annotate [<options>] <command>", 238 "perf annotate [<options>]",
239 NULL 239 NULL
240}; 240};
241 241
@@ -313,10 +313,5 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
313 annotate.sym_hist_filter = argv[0]; 313 annotate.sym_hist_filter = argv[0];
314 } 314 }
315 315
316 if (field_sep && *field_sep == '.') {
317 pr_err("'.' is the only non valid --field-separator argument\n");
318 return -1;
319 }
320
321 return __cmd_annotate(&annotate); 316 return __cmd_annotate(&annotate);
322} 317}
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index fcb96269852a..b0e74ab2d7a2 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -52,6 +52,9 @@ static struct bench_suite mem_suites[] = {
52 { "memcpy", 52 { "memcpy",
53 "Simple memory copy in various ways", 53 "Simple memory copy in various ways",
54 bench_mem_memcpy }, 54 bench_mem_memcpy },
55 { "memset",
56 "Simple memory set in various ways",
57 bench_mem_memset },
55 suite_all, 58 suite_all,
56 { NULL, 59 { NULL,
57 NULL, 60 NULL,
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 4f19513d7dda..d29d350fb2b7 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -24,6 +24,11 @@ static char diff__default_sort_order[] = "dso,symbol";
24static bool force; 24static bool force;
25static bool show_displacement; 25static bool show_displacement;
26 26
27struct perf_diff {
28 struct perf_tool tool;
29 struct perf_session *session;
30};
31
27static int hists__add_entry(struct hists *self, 32static int hists__add_entry(struct hists *self,
28 struct addr_location *al, u64 period) 33 struct addr_location *al, u64 period)
29{ 34{
@@ -32,12 +37,14 @@ static int hists__add_entry(struct hists *self,
32 return -ENOMEM; 37 return -ENOMEM;
33} 38}
34 39
35static int diff__process_sample_event(struct perf_tool *tool __used, 40static int diff__process_sample_event(struct perf_tool *tool,
36 union perf_event *event, 41 union perf_event *event,
37 struct perf_sample *sample, 42 struct perf_sample *sample,
38 struct perf_evsel *evsel __used, 43 struct perf_evsel *evsel __used,
39 struct machine *machine) 44 struct machine *machine)
40{ 45{
46 struct perf_diff *_diff = container_of(tool, struct perf_diff, tool);
47 struct perf_session *session = _diff->session;
41 struct addr_location al; 48 struct addr_location al;
42 49
43 if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) { 50 if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) {
@@ -49,24 +56,26 @@ static int diff__process_sample_event(struct perf_tool *tool __used,
49 if (al.filtered || al.sym == NULL) 56 if (al.filtered || al.sym == NULL)
50 return 0; 57 return 0;
51 58
52 if (hists__add_entry(&evsel->hists, &al, sample->period)) { 59 if (hists__add_entry(&session->hists, &al, sample->period)) {
53 pr_warning("problem incrementing symbol period, skipping event\n"); 60 pr_warning("problem incrementing symbol period, skipping event\n");
54 return -1; 61 return -1;
55 } 62 }
56 63
57 evsel->hists.stats.total_period += sample->period; 64 session->hists.stats.total_period += sample->period;
58 return 0; 65 return 0;
59} 66}
60 67
61static struct perf_tool perf_diff = { 68static struct perf_diff diff = {
62 .sample = diff__process_sample_event, 69 .tool = {
63 .mmap = perf_event__process_mmap, 70 .sample = diff__process_sample_event,
64 .comm = perf_event__process_comm, 71 .mmap = perf_event__process_mmap,
65 .exit = perf_event__process_task, 72 .comm = perf_event__process_comm,
66 .fork = perf_event__process_task, 73 .exit = perf_event__process_task,
67 .lost = perf_event__process_lost, 74 .fork = perf_event__process_task,
68 .ordered_samples = true, 75 .lost = perf_event__process_lost,
69 .ordering_requires_timestamps = true, 76 .ordered_samples = true,
77 .ordering_requires_timestamps = true,
78 },
70}; 79};
71 80
72static void perf_session__insert_hist_entry_by_name(struct rb_root *root, 81static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
@@ -107,12 +116,6 @@ static void hists__resort_entries(struct hists *self)
107 self->entries = tmp; 116 self->entries = tmp;
108} 117}
109 118
110static void hists__set_positions(struct hists *self)
111{
112 hists__output_resort(self);
113 hists__resort_entries(self);
114}
115
116static struct hist_entry *hists__find_entry(struct hists *self, 119static struct hist_entry *hists__find_entry(struct hists *self,
117 struct hist_entry *he) 120 struct hist_entry *he)
118{ 121{
@@ -146,30 +149,37 @@ static void hists__match(struct hists *older, struct hists *newer)
146static int __cmd_diff(void) 149static int __cmd_diff(void)
147{ 150{
148 int ret, i; 151 int ret, i;
152#define older (session[0])
153#define newer (session[1])
149 struct perf_session *session[2]; 154 struct perf_session *session[2];
150 155
151 session[0] = perf_session__new(input_old, O_RDONLY, force, false, &perf_diff); 156 older = perf_session__new(input_old, O_RDONLY, force, false,
152 session[1] = perf_session__new(input_new, O_RDONLY, force, false, &perf_diff); 157 &diff.tool);
158 newer = perf_session__new(input_new, O_RDONLY, force, false,
159 &diff.tool);
153 if (session[0] == NULL || session[1] == NULL) 160 if (session[0] == NULL || session[1] == NULL)
154 return -ENOMEM; 161 return -ENOMEM;
155 162
156 for (i = 0; i < 2; ++i) { 163 for (i = 0; i < 2; ++i) {
157 ret = perf_session__process_events(session[i], &perf_diff); 164 diff.session = session[i];
165 ret = perf_session__process_events(session[i], &diff.tool);
158 if (ret) 166 if (ret)
159 goto out_delete; 167 goto out_delete;
168 hists__output_resort(&session[i]->hists);
160 } 169 }
161 170
162 hists__output_resort(&session[1]->hists);
163 if (show_displacement) 171 if (show_displacement)
164 hists__set_positions(&session[0]->hists); 172 hists__resort_entries(&older->hists);
165 173
166 hists__match(&session[0]->hists, &session[1]->hists); 174 hists__match(&older->hists, &newer->hists);
167 hists__fprintf(&session[1]->hists, &session[0]->hists, 175 hists__fprintf(&newer->hists, &older->hists,
168 show_displacement, true, 0, 0, stdout); 176 show_displacement, true, 0, 0, stdout);
169out_delete: 177out_delete:
170 for (i = 0; i < 2; ++i) 178 for (i = 0; i < 2; ++i)
171 perf_session__delete(session[i]); 179 perf_session__delete(session[i]);
172 return ret; 180 return ret;
181#undef older
182#undef newer
173} 183}
174 184
175static const char * const diff_usage[] = { 185static const char * const diff_usage[] = {
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index fe1ad8f21961..39104c0beea3 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -108,7 +108,9 @@ static void setup_cpunode_map(void)
108 continue; 108 continue;
109 cpunode_map[cpu] = mem; 109 cpunode_map[cpu] = mem;
110 } 110 }
111 closedir(dir2);
111 } 112 }
113 closedir(dir1);
112} 114}
113 115
114static void insert_alloc_stat(unsigned long call_site, unsigned long ptr, 116static void insert_alloc_stat(unsigned long call_site, unsigned long ptr,
@@ -645,6 +647,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
645 break; 647 break;
646 if (sort_dimension__add(tok, sort_list) < 0) { 648 if (sort_dimension__add(tok, sort_list) < 0) {
647 error("Unknown --sort key: '%s'", tok); 649 error("Unknown --sort key: '%s'", tok);
650 free(str);
648 return -1; 651 return -1;
649 } 652 }
650 } 653 }
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 032324a76b87..9fc6e0fa3dce 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -22,9 +22,6 @@
22static const char *file_name; 22static const char *file_name;
23static char name_buffer[256]; 23static char name_buffer[256];
24 24
25bool perf_host = 1;
26bool perf_guest;
27
28static const char * const kvm_usage[] = { 25static const char * const kvm_usage[] = {
29 "perf kvm [<options>] {top|record|report|diff|buildid-list}", 26 "perf kvm [<options>] {top|record|report|diff|buildid-list}",
30 NULL 27 NULL
@@ -107,7 +104,8 @@ static int __cmd_buildid_list(int argc, const char **argv)
107 104
108int cmd_kvm(int argc, const char **argv, const char *prefix __used) 105int cmd_kvm(int argc, const char **argv, const char *prefix __used)
109{ 106{
110 perf_host = perf_guest = 0; 107 perf_host = 0;
108 perf_guest = 1;
111 109
112 argc = parse_options(argc, argv, kvm_options, kvm_usage, 110 argc = parse_options(argc, argv, kvm_options, kvm_usage,
113 PARSE_OPT_STOP_AT_NON_OPTION); 111 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 2296c391d0f5..12c814838993 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -922,12 +922,12 @@ static const struct option info_options[] = {
922 OPT_BOOLEAN('t', "threads", &info_threads, 922 OPT_BOOLEAN('t', "threads", &info_threads,
923 "dump thread list in perf.data"), 923 "dump thread list in perf.data"),
924 OPT_BOOLEAN('m', "map", &info_map, 924 OPT_BOOLEAN('m', "map", &info_map,
925 "map of lock instances (name:address table)"), 925 "map of lock instances (address:name table)"),
926 OPT_END() 926 OPT_END()
927}; 927};
928 928
929static const char * const lock_usage[] = { 929static const char * const lock_usage[] = {
930 "perf lock [<options>] {record|trace|report}", 930 "perf lock [<options>] {record|report|script|info}",
931 NULL 931 NULL
932}; 932};
933 933
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 59d43abfbfec..4935c09dd5b5 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -20,7 +20,6 @@
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * 21 *
22 */ 22 */
23#define _GNU_SOURCE
24#include <sys/utsname.h> 23#include <sys/utsname.h>
25#include <sys/types.h> 24#include <sys/types.h>
26#include <sys/stat.h> 25#include <sys/stat.h>
@@ -31,7 +30,6 @@
31#include <stdlib.h> 30#include <stdlib.h>
32#include <string.h> 31#include <string.h>
33 32
34#undef _GNU_SOURCE
35#include "perf.h" 33#include "perf.h"
36#include "builtin.h" 34#include "builtin.h"
37#include "util/util.h" 35#include "util/util.h"
@@ -60,7 +58,7 @@ static struct {
60 struct perf_probe_event events[MAX_PROBES]; 58 struct perf_probe_event events[MAX_PROBES];
61 struct strlist *dellist; 59 struct strlist *dellist;
62 struct line_range line_range; 60 struct line_range line_range;
63 const char *target_module; 61 const char *target;
64 int max_probe_points; 62 int max_probe_points;
65 struct strfilter *filter; 63 struct strfilter *filter;
66} params; 64} params;
@@ -248,7 +246,7 @@ static const struct option options[] = {
248 "file", "vmlinux pathname"), 246 "file", "vmlinux pathname"),
249 OPT_STRING('s', "source", &symbol_conf.source_prefix, 247 OPT_STRING('s', "source", &symbol_conf.source_prefix,
250 "directory", "path to kernel source"), 248 "directory", "path to kernel source"),
251 OPT_STRING('m', "module", &params.target_module, 249 OPT_STRING('m', "module", &params.target,
252 "modname|path", 250 "modname|path",
253 "target module name (for online) or path (for offline)"), 251 "target module name (for online) or path (for offline)"),
254#endif 252#endif
@@ -335,7 +333,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
335 if (!params.filter) 333 if (!params.filter)
336 params.filter = strfilter__new(DEFAULT_FUNC_FILTER, 334 params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
337 NULL); 335 NULL);
338 ret = show_available_funcs(params.target_module, 336 ret = show_available_funcs(params.target,
339 params.filter); 337 params.filter);
340 strfilter__delete(params.filter); 338 strfilter__delete(params.filter);
341 if (ret < 0) 339 if (ret < 0)
@@ -356,7 +354,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
356 usage_with_options(probe_usage, options); 354 usage_with_options(probe_usage, options);
357 } 355 }
358 356
359 ret = show_line_range(&params.line_range, params.target_module); 357 ret = show_line_range(&params.line_range, params.target);
360 if (ret < 0) 358 if (ret < 0)
361 pr_err(" Error: Failed to show lines. (%d)\n", ret); 359 pr_err(" Error: Failed to show lines. (%d)\n", ret);
362 return ret; 360 return ret;
@@ -373,7 +371,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
373 371
374 ret = show_available_vars(params.events, params.nevents, 372 ret = show_available_vars(params.events, params.nevents,
375 params.max_probe_points, 373 params.max_probe_points,
376 params.target_module, 374 params.target,
377 params.filter, 375 params.filter,
378 params.show_ext_vars); 376 params.show_ext_vars);
379 strfilter__delete(params.filter); 377 strfilter__delete(params.filter);
@@ -395,7 +393,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
395 if (params.nevents) { 393 if (params.nevents) {
396 ret = add_perf_probe_events(params.events, params.nevents, 394 ret = add_perf_probe_events(params.events, params.nevents,
397 params.max_probe_points, 395 params.max_probe_points,
398 params.target_module, 396 params.target,
399 params.force_add); 397 params.force_add);
400 if (ret < 0) { 398 if (ret < 0) {
401 pr_err(" Error: Failed to add events. (%d)\n", ret); 399 pr_err(" Error: Failed to add events. (%d)\n", ret);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0abfb18b911f..be4e1eee782e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -44,6 +44,7 @@ struct perf_record {
44 struct perf_evlist *evlist; 44 struct perf_evlist *evlist;
45 struct perf_session *session; 45 struct perf_session *session;
46 const char *progname; 46 const char *progname;
47 const char *uid_str;
47 int output; 48 int output;
48 unsigned int page_size; 49 unsigned int page_size;
49 int realtime_prio; 50 int realtime_prio;
@@ -204,8 +205,11 @@ static void perf_record__open(struct perf_record *rec)
204 205
205 if (opts->group && pos != first) 206 if (opts->group && pos != first)
206 group_fd = first->fd; 207 group_fd = first->fd;
208fallback_missing_features:
209 if (opts->exclude_guest_missing)
210 attr->exclude_guest = attr->exclude_host = 0;
207retry_sample_id: 211retry_sample_id:
208 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0; 212 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
209try_again: 213try_again:
210 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, 214 if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
211 opts->group, group_fd) < 0) { 215 opts->group, group_fd) < 0) {
@@ -217,15 +221,23 @@ try_again:
217 } else if (err == ENODEV && opts->cpu_list) { 221 } else if (err == ENODEV && opts->cpu_list) {
218 die("No such device - did you specify" 222 die("No such device - did you specify"
219 " an out-of-range profile CPU?\n"); 223 " an out-of-range profile CPU?\n");
220 } else if (err == EINVAL && opts->sample_id_all_avail) { 224 } else if (err == EINVAL) {
221 /* 225 if (!opts->exclude_guest_missing &&
222 * Old kernel, no attr->sample_id_type_all field 226 (attr->exclude_guest || attr->exclude_host)) {
223 */ 227 pr_debug("Old kernel, cannot exclude "
224 opts->sample_id_all_avail = false; 228 "guest or host samples.\n");
225 if (!opts->sample_time && !opts->raw_samples && !time_needed) 229 opts->exclude_guest_missing = true;
226 attr->sample_type &= ~PERF_SAMPLE_TIME; 230 goto fallback_missing_features;
227 231 } else if (!opts->sample_id_all_missing) {
228 goto retry_sample_id; 232 /*
233 * Old kernel, no attr->sample_id_type_all field
234 */
235 opts->sample_id_all_missing = true;
236 if (!opts->sample_time && !opts->raw_samples && !time_needed)
237 attr->sample_type &= ~PERF_SAMPLE_TIME;
238
239 goto retry_sample_id;
240 }
229 } 241 }
230 242
231 /* 243 /*
@@ -385,7 +397,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
385{ 397{
386 struct stat st; 398 struct stat st;
387 int flags; 399 int flags;
388 int err, output; 400 int err, output, feat;
389 unsigned long waking = 0; 401 unsigned long waking = 0;
390 const bool forks = argc > 0; 402 const bool forks = argc > 0;
391 struct machine *machine; 403 struct machine *machine;
@@ -452,8 +464,17 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
452 464
453 rec->session = session; 465 rec->session = session;
454 466
455 if (!rec->no_buildid) 467 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
456 perf_header__set_feat(&session->header, HEADER_BUILD_ID); 468 perf_header__set_feat(&session->header, feat);
469
470 if (rec->no_buildid)
471 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
472
473 if (!have_tracepoints(&evsel_list->entries))
474 perf_header__clear_feat(&session->header, HEADER_TRACE_INFO);
475
476 if (!rec->opts.branch_stack)
477 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
457 478
458 if (!rec->file_new) { 479 if (!rec->file_new) {
459 err = perf_session__read_header(session, output); 480 err = perf_session__read_header(session, output);
@@ -461,22 +482,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
461 goto out_delete_session; 482 goto out_delete_session;
462 } 483 }
463 484
464 if (have_tracepoints(&evsel_list->entries))
465 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
466
467 perf_header__set_feat(&session->header, HEADER_HOSTNAME);
468 perf_header__set_feat(&session->header, HEADER_OSRELEASE);
469 perf_header__set_feat(&session->header, HEADER_ARCH);
470 perf_header__set_feat(&session->header, HEADER_CPUDESC);
471 perf_header__set_feat(&session->header, HEADER_NRCPUS);
472 perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
473 perf_header__set_feat(&session->header, HEADER_CMDLINE);
474 perf_header__set_feat(&session->header, HEADER_VERSION);
475 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
476 perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
477 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
478 perf_header__set_feat(&session->header, HEADER_CPUID);
479
480 if (forks) { 485 if (forks) {
481 err = perf_evlist__prepare_workload(evsel_list, opts, argv); 486 err = perf_evlist__prepare_workload(evsel_list, opts, argv);
482 if (err < 0) { 487 if (err < 0) {
@@ -503,9 +508,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
503 return err; 508 return err;
504 } 509 }
505 510
506 if (!!rec->no_buildid 511 if (!rec->no_buildid
507 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 512 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
508 pr_err("Couldn't generating buildids. " 513 pr_err("Couldn't generate buildids. "
509 "Use --no-buildid to profile anyway.\n"); 514 "Use --no-buildid to profile anyway.\n");
510 return -1; 515 return -1;
511 } 516 }
@@ -636,6 +641,90 @@ out_delete_session:
636 return err; 641 return err;
637} 642}
638 643
644#define BRANCH_OPT(n, m) \
645 { .name = n, .mode = (m) }
646
647#define BRANCH_END { .name = NULL }
648
649struct branch_mode {
650 const char *name;
651 int mode;
652};
653
654static const struct branch_mode branch_modes[] = {
655 BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
656 BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
657 BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
658 BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
659 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
660 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
661 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
662 BRANCH_END
663};
664
665static int
666parse_branch_stack(const struct option *opt, const char *str, int unset)
667{
668#define ONLY_PLM \
669 (PERF_SAMPLE_BRANCH_USER |\
670 PERF_SAMPLE_BRANCH_KERNEL |\
671 PERF_SAMPLE_BRANCH_HV)
672
673 uint64_t *mode = (uint64_t *)opt->value;
674 const struct branch_mode *br;
675 char *s, *os = NULL, *p;
676 int ret = -1;
677
678 if (unset)
679 return 0;
680
681 /*
682 * cannot set it twice, -b + --branch-filter for instance
683 */
684 if (*mode)
685 return -1;
686
687 /* str may be NULL in case no arg is passed to -b */
688 if (str) {
689 /* because str is read-only */
690 s = os = strdup(str);
691 if (!s)
692 return -1;
693
694 for (;;) {
695 p = strchr(s, ',');
696 if (p)
697 *p = '\0';
698
699 for (br = branch_modes; br->name; br++) {
700 if (!strcasecmp(s, br->name))
701 break;
702 }
703 if (!br->name) {
704 ui__warning("unknown branch filter %s,"
705 " check man page\n", s);
706 goto error;
707 }
708
709 *mode |= br->mode;
710
711 if (!p)
712 break;
713
714 s = p + 1;
715 }
716 }
717 ret = 0;
718
719 /* default to any branch */
720 if ((*mode & ~ONLY_PLM) == 0) {
721 *mode = PERF_SAMPLE_BRANCH_ANY;
722 }
723error:
724 free(os);
725 return ret;
726}
727
639static const char * const record_usage[] = { 728static const char * const record_usage[] = {
640 "perf record [<options>] [<command>]", 729 "perf record [<options>] [<command>]",
641 "perf record [<options>] -- <command> [<options>]", 730 "perf record [<options>] -- <command> [<options>]",
@@ -654,13 +743,10 @@ static const char * const record_usage[] = {
654 */ 743 */
655static struct perf_record record = { 744static struct perf_record record = {
656 .opts = { 745 .opts = {
657 .target_pid = -1,
658 .target_tid = -1,
659 .mmap_pages = UINT_MAX, 746 .mmap_pages = UINT_MAX,
660 .user_freq = UINT_MAX, 747 .user_freq = UINT_MAX,
661 .user_interval = ULLONG_MAX, 748 .user_interval = ULLONG_MAX,
662 .freq = 1000, 749 .freq = 1000,
663 .sample_id_all_avail = true,
664 }, 750 },
665 .write_mode = WRITE_FORCE, 751 .write_mode = WRITE_FORCE,
666 .file_new = true, 752 .file_new = true,
@@ -679,9 +765,9 @@ const struct option record_options[] = {
679 parse_events_option), 765 parse_events_option),
680 OPT_CALLBACK(0, "filter", &record.evlist, "filter", 766 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
681 "event filter", parse_filter), 767 "event filter", parse_filter),
682 OPT_INTEGER('p', "pid", &record.opts.target_pid, 768 OPT_STRING('p', "pid", &record.opts.target_pid, "pid",
683 "record events on existing process id"), 769 "record events on existing process id"),
684 OPT_INTEGER('t', "tid", &record.opts.target_tid, 770 OPT_STRING('t', "tid", &record.opts.target_tid, "tid",
685 "record events on existing thread id"), 771 "record events on existing thread id"),
686 OPT_INTEGER('r', "realtime", &record.realtime_prio, 772 OPT_INTEGER('r', "realtime", &record.realtime_prio,
687 "collect data with this RT SCHED_FIFO priority"), 773 "collect data with this RT SCHED_FIFO priority"),
@@ -727,6 +813,15 @@ const struct option record_options[] = {
727 OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 813 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
728 "monitor event in cgroup name only", 814 "monitor event in cgroup name only",
729 parse_cgroups), 815 parse_cgroups),
816 OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),
817
818 OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
819 "branch any", "sample any taken branches",
820 parse_branch_stack),
821
822 OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
823 "branch filter mask", "branch stack filter modes",
824 parse_branch_stack),
730 OPT_END() 825 OPT_END()
731}; 826};
732 827
@@ -747,8 +842,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
747 842
748 argc = parse_options(argc, argv, record_options, record_usage, 843 argc = parse_options(argc, argv, record_options, record_usage,
749 PARSE_OPT_STOP_AT_NON_OPTION); 844 PARSE_OPT_STOP_AT_NON_OPTION);
750 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 && 845 if (!argc && !rec->opts.target_pid && !rec->opts.target_tid &&
751 !rec->opts.system_wide && !rec->opts.cpu_list) 846 !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str)
752 usage_with_options(record_usage, record_options); 847 usage_with_options(record_usage, record_options);
753 848
754 if (rec->force && rec->append_file) { 849 if (rec->force && rec->append_file) {
@@ -788,11 +883,17 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
788 goto out_symbol_exit; 883 goto out_symbol_exit;
789 } 884 }
790 885
791 if (rec->opts.target_pid != -1) 886 rec->opts.uid = parse_target_uid(rec->uid_str, rec->opts.target_tid,
887 rec->opts.target_pid);
888 if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1)
889 goto out_free_fd;
890
891 if (rec->opts.target_pid)
792 rec->opts.target_tid = rec->opts.target_pid; 892 rec->opts.target_tid = rec->opts.target_pid;
793 893
794 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 894 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
795 rec->opts.target_tid, rec->opts.cpu_list) < 0) 895 rec->opts.target_tid, rec->opts.uid,
896 rec->opts.cpu_list) < 0)
796 usage_with_options(record_usage, record_options); 897 usage_with_options(record_usage, record_options);
797 898
798 list_for_each_entry(pos, &evsel_list->entries, node) { 899 list_for_each_entry(pos, &evsel_list->entries, node) {
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 25d34d483e49..2e317438980b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -40,7 +40,7 @@ struct perf_report {
40 struct perf_tool tool; 40 struct perf_tool tool;
41 struct perf_session *session; 41 struct perf_session *session;
42 char const *input_name; 42 char const *input_name;
43 bool force, use_tui, use_stdio; 43 bool force, use_tui, use_gtk, use_stdio;
44 bool hide_unresolved; 44 bool hide_unresolved;
45 bool dont_use_callchains; 45 bool dont_use_callchains;
46 bool show_full_info; 46 bool show_full_info;
@@ -50,9 +50,86 @@ struct perf_report {
50 const char *pretty_printing_style; 50 const char *pretty_printing_style;
51 symbol_filter_t annotate_init; 51 symbol_filter_t annotate_init;
52 const char *cpu_list; 52 const char *cpu_list;
53 const char *symbol_filter_str;
53 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 54 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
54}; 55};
55 56
57static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
58 struct addr_location *al,
59 struct perf_sample *sample,
60 struct perf_evsel *evsel,
61 struct machine *machine)
62{
63 struct perf_report *rep = container_of(tool, struct perf_report, tool);
64 struct symbol *parent = NULL;
65 int err = 0;
66 unsigned i;
67 struct hist_entry *he;
68 struct branch_info *bi, *bx;
69
70 if ((sort__has_parent || symbol_conf.use_callchain)
71 && sample->callchain) {
72 err = machine__resolve_callchain(machine, evsel, al->thread,
73 sample->callchain, &parent);
74 if (err)
75 return err;
76 }
77
78 bi = machine__resolve_bstack(machine, al->thread,
79 sample->branch_stack);
80 if (!bi)
81 return -ENOMEM;
82
83 for (i = 0; i < sample->branch_stack->nr; i++) {
84 if (rep->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym))
85 continue;
86 /*
87 * The report shows the percentage of total branches captured
88 * and not events sampled. Thus we use a pseudo period of 1.
89 */
90 he = __hists__add_branch_entry(&evsel->hists, al, parent,
91 &bi[i], 1);
92 if (he) {
93 struct annotation *notes;
94 err = -ENOMEM;
95 bx = he->branch_info;
96 if (bx->from.sym && use_browser > 0) {
97 notes = symbol__annotation(bx->from.sym);
98 if (!notes->src
99 && symbol__alloc_hist(bx->from.sym) < 0)
100 goto out;
101
102 err = symbol__inc_addr_samples(bx->from.sym,
103 bx->from.map,
104 evsel->idx,
105 bx->from.al_addr);
106 if (err)
107 goto out;
108 }
109
110 if (bx->to.sym && use_browser > 0) {
111 notes = symbol__annotation(bx->to.sym);
112 if (!notes->src
113 && symbol__alloc_hist(bx->to.sym) < 0)
114 goto out;
115
116 err = symbol__inc_addr_samples(bx->to.sym,
117 bx->to.map,
118 evsel->idx,
119 bx->to.al_addr);
120 if (err)
121 goto out;
122 }
123 evsel->hists.stats.total_period += 1;
124 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
125 err = 0;
126 } else
127 return -ENOMEM;
128 }
129out:
130 return err;
131}
132
56static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, 133static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
57 struct addr_location *al, 134 struct addr_location *al,
58 struct perf_sample *sample, 135 struct perf_sample *sample,
@@ -126,14 +203,21 @@ static int process_sample_event(struct perf_tool *tool,
126 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) 203 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
127 return 0; 204 return 0;
128 205
129 if (al.map != NULL) 206 if (sort__branch_mode == 1) {
130 al.map->dso->hit = 1; 207 if (perf_report__add_branch_hist_entry(tool, &al, sample,
208 evsel, machine)) {
209 pr_debug("problem adding lbr entry, skipping event\n");
210 return -1;
211 }
212 } else {
213 if (al.map != NULL)
214 al.map->dso->hit = 1;
131 215
132 if (perf_evsel__add_hist_entry(evsel, &al, sample, machine)) { 216 if (perf_evsel__add_hist_entry(evsel, &al, sample, machine)) {
133 pr_debug("problem incrementing symbol period, skipping event\n"); 217 pr_debug("problem incrementing symbol period, skipping event\n");
134 return -1; 218 return -1;
219 }
135 } 220 }
136
137 return 0; 221 return 0;
138} 222}
139 223
@@ -188,6 +272,15 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
188 } 272 }
189 } 273 }
190 274
275 if (sort__branch_mode == 1) {
276 if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
277 fprintf(stderr, "selected -b but no branch data."
278 " Did you call perf record without"
279 " -b?\n");
280 return -1;
281 }
282 }
283
191 return 0; 284 return 0;
192} 285}
193 286
@@ -246,7 +339,7 @@ static int __cmd_report(struct perf_report *rep)
246{ 339{
247 int ret = -EINVAL; 340 int ret = -EINVAL;
248 u64 nr_samples; 341 u64 nr_samples;
249 struct perf_session *session; 342 struct perf_session *session = rep->session;
250 struct perf_evsel *pos; 343 struct perf_evsel *pos;
251 struct map *kernel_map; 344 struct map *kernel_map;
252 struct kmap *kernel_kmap; 345 struct kmap *kernel_kmap;
@@ -254,13 +347,6 @@ static int __cmd_report(struct perf_report *rep)
254 347
255 signal(SIGINT, sig_handler); 348 signal(SIGINT, sig_handler);
256 349
257 session = perf_session__new(rep->input_name, O_RDONLY,
258 rep->force, false, &rep->tool);
259 if (session == NULL)
260 return -ENOMEM;
261
262 rep->session = session;
263
264 if (rep->cpu_list) { 350 if (rep->cpu_list) {
265 ret = perf_session__cpu_bitmap(session, rep->cpu_list, 351 ret = perf_session__cpu_bitmap(session, rep->cpu_list,
266 rep->cpu_bitmap); 352 rep->cpu_bitmap);
@@ -315,6 +401,9 @@ static int __cmd_report(struct perf_report *rep)
315 list_for_each_entry(pos, &session->evlist->entries, node) { 401 list_for_each_entry(pos, &session->evlist->entries, node) {
316 struct hists *hists = &pos->hists; 402 struct hists *hists = &pos->hists;
317 403
404 if (pos->idx == 0)
405 hists->symbol_filter_str = rep->symbol_filter_str;
406
318 hists__collapse_resort(hists); 407 hists__collapse_resort(hists);
319 hists__output_resort(hists); 408 hists__output_resort(hists);
320 nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE]; 409 nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
@@ -326,8 +415,13 @@ static int __cmd_report(struct perf_report *rep)
326 } 415 }
327 416
328 if (use_browser > 0) { 417 if (use_browser > 0) {
329 perf_evlist__tui_browse_hists(session->evlist, help, 418 if (use_browser == 1) {
330 NULL, NULL, 0); 419 perf_evlist__tui_browse_hists(session->evlist, help,
420 NULL, NULL, 0);
421 } else if (use_browser == 2) {
422 perf_evlist__gtk_browse_hists(session->evlist, help,
423 NULL, NULL, 0);
424 }
331 } else 425 } else
332 perf_evlist__tty_browse_hists(session->evlist, rep, help); 426 perf_evlist__tty_browse_hists(session->evlist, rep, help);
333 427
@@ -427,9 +521,19 @@ setup:
427 return 0; 521 return 0;
428} 522}
429 523
524static int
525parse_branch_mode(const struct option *opt __used, const char *str __used, int unset)
526{
527 sort__branch_mode = !unset;
528 return 0;
529}
530
430int cmd_report(int argc, const char **argv, const char *prefix __used) 531int cmd_report(int argc, const char **argv, const char *prefix __used)
431{ 532{
533 struct perf_session *session;
432 struct stat st; 534 struct stat st;
535 bool has_br_stack = false;
536 int ret = -1;
433 char callchain_default_opt[] = "fractal,0.5,callee"; 537 char callchain_default_opt[] = "fractal,0.5,callee";
434 const char * const report_usage[] = { 538 const char * const report_usage[] = {
435 "perf report [<options>]", 539 "perf report [<options>]",
@@ -474,10 +578,12 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
474 OPT_STRING(0, "pretty", &report.pretty_printing_style, "key", 578 OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
475 "pretty printing style key: normal raw"), 579 "pretty printing style key: normal raw"),
476 OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"), 580 OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
581 OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
477 OPT_BOOLEAN(0, "stdio", &report.use_stdio, 582 OPT_BOOLEAN(0, "stdio", &report.use_stdio,
478 "Use the stdio interface"), 583 "Use the stdio interface"),
479 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 584 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
480 "sort by key(s): pid, comm, dso, symbol, parent"), 585 "sort by key(s): pid, comm, dso, symbol, parent, dso_to,"
586 " dso_from, symbol_to, symbol_from, mispredict"),
481 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 587 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
482 "Show sample percentage for different cpu modes"), 588 "Show sample percentage for different cpu modes"),
483 OPT_STRING('p', "parent", &parent_pattern, "regex", 589 OPT_STRING('p', "parent", &parent_pattern, "regex",
@@ -495,6 +601,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
495 "only consider symbols in these comms"), 601 "only consider symbols in these comms"),
496 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 602 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
497 "only consider these symbols"), 603 "only consider these symbols"),
604 OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
605 "only show symbols that (partially) match with this filter"),
498 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str, 606 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
499 "width[,width...]", 607 "width[,width...]",
500 "don't try to adjust column width, use these fixed values"), 608 "don't try to adjust column width, use these fixed values"),
@@ -517,6 +625,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
517 "Specify disassembler style (e.g. -M intel for intel syntax)"), 625 "Specify disassembler style (e.g. -M intel for intel syntax)"),
518 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 626 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
519 "Show a column with the sum of periods"), 627 "Show a column with the sum of periods"),
628 OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "",
629 "use branch records for histogram filling", parse_branch_mode),
520 OPT_END() 630 OPT_END()
521 }; 631 };
522 632
@@ -526,6 +636,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
526 use_browser = 0; 636 use_browser = 0;
527 else if (report.use_tui) 637 else if (report.use_tui)
528 use_browser = 1; 638 use_browser = 1;
639 else if (report.use_gtk)
640 use_browser = 2;
529 641
530 if (report.inverted_callchain) 642 if (report.inverted_callchain)
531 callchain_param.order = ORDER_CALLER; 643 callchain_param.order = ORDER_CALLER;
@@ -536,11 +648,39 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
536 else 648 else
537 report.input_name = "perf.data"; 649 report.input_name = "perf.data";
538 } 650 }
651 session = perf_session__new(report.input_name, O_RDONLY,
652 report.force, false, &report.tool);
653 if (session == NULL)
654 return -ENOMEM;
539 655
540 if (strcmp(report.input_name, "-") != 0) 656 report.session = session;
541 setup_browser(true); 657
542 else 658 has_br_stack = perf_header__has_feat(&session->header,
659 HEADER_BRANCH_STACK);
660
661 if (sort__branch_mode == -1 && has_br_stack)
662 sort__branch_mode = 1;
663
664 /* sort__branch_mode could be 0 if --no-branch-stack */
665 if (sort__branch_mode == 1) {
666 /*
667 * if no sort_order is provided, then specify
668 * branch-mode specific order
669 */
670 if (sort_order == default_sort_order)
671 sort_order = "comm,dso_from,symbol_from,"
672 "dso_to,symbol_to";
673
674 }
675
676 if (strcmp(report.input_name, "-") != 0) {
677 if (report.use_gtk)
678 perf_gtk_setup_browser(argc, argv, true);
679 else
680 setup_browser(true);
681 } else {
543 use_browser = 0; 682 use_browser = 0;
683 }
544 684
545 /* 685 /*
546 * Only in the newt browser we are doing integrated annotation, 686 * Only in the newt browser we are doing integrated annotation,
@@ -568,13 +708,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
568 } 708 }
569 709
570 if (symbol__init() < 0) 710 if (symbol__init() < 0)
571 return -1; 711 goto error;
572 712
573 setup_sorting(report_usage, options); 713 setup_sorting(report_usage, options);
574 714
575 if (parent_pattern != default_parent_pattern) { 715 if (parent_pattern != default_parent_pattern) {
576 if (sort_dimension__add("parent") < 0) 716 if (sort_dimension__add("parent") < 0)
577 return -1; 717 goto error;
578 718
579 /* 719 /*
580 * Only show the parent fields if we explicitly 720 * Only show the parent fields if we explicitly
@@ -586,15 +726,31 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
586 } else 726 } else
587 symbol_conf.exclude_other = false; 727 symbol_conf.exclude_other = false;
588 728
589 /* 729 if (argc) {
590 * Any (unrecognized) arguments left? 730 /*
591 */ 731 * Special case: if there's an argument left then assume that
592 if (argc) 732 * it's a symbol filter:
593 usage_with_options(report_usage, options); 733 */
734 if (argc > 1)
735 usage_with_options(report_usage, options);
736
737 report.symbol_filter_str = argv[0];
738 }
594 739
595 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
596 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout); 740 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
597 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
598 741
599 return __cmd_report(&report); 742 if (sort__branch_mode == 1) {
743 sort_entry__setup_elide(&sort_dso_from, symbol_conf.dso_from_list, "dso_from", stdout);
744 sort_entry__setup_elide(&sort_dso_to, symbol_conf.dso_to_list, "dso_to", stdout);
745 sort_entry__setup_elide(&sort_sym_from, symbol_conf.sym_from_list, "sym_from", stdout);
746 sort_entry__setup_elide(&sort_sym_to, symbol_conf.sym_to_list, "sym_to", stdout);
747 } else {
748 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
749 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
750 }
751
752 ret = __cmd_report(&report);
753error:
754 perf_session__delete(session);
755 return ret;
600} 756}
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index fb8b5f83b4a0..1cad3af4bf4c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -17,6 +17,7 @@
17#include "util/debug.h" 17#include "util/debug.h"
18 18
19#include <sys/prctl.h> 19#include <sys/prctl.h>
20#include <sys/resource.h>
20 21
21#include <semaphore.h> 22#include <semaphore.h>
22#include <pthread.h> 23#include <pthread.h>
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index fd1909afcfd6..d4ce733b9eba 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -40,6 +40,7 @@ enum perf_output_field {
40 PERF_OUTPUT_SYM = 1U << 8, 40 PERF_OUTPUT_SYM = 1U << 8,
41 PERF_OUTPUT_DSO = 1U << 9, 41 PERF_OUTPUT_DSO = 1U << 9,
42 PERF_OUTPUT_ADDR = 1U << 10, 42 PERF_OUTPUT_ADDR = 1U << 10,
43 PERF_OUTPUT_SYMOFFSET = 1U << 11,
43}; 44};
44 45
45struct output_option { 46struct output_option {
@@ -57,6 +58,7 @@ struct output_option {
57 {.str = "sym", .field = PERF_OUTPUT_SYM}, 58 {.str = "sym", .field = PERF_OUTPUT_SYM},
58 {.str = "dso", .field = PERF_OUTPUT_DSO}, 59 {.str = "dso", .field = PERF_OUTPUT_DSO},
59 {.str = "addr", .field = PERF_OUTPUT_ADDR}, 60 {.str = "addr", .field = PERF_OUTPUT_ADDR},
61 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
60}; 62};
61 63
62/* default set to maintain compatibility with current format */ 64/* default set to maintain compatibility with current format */
@@ -193,6 +195,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
193 "to symbols.\n"); 195 "to symbols.\n");
194 return -EINVAL; 196 return -EINVAL;
195 } 197 }
198 if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) {
199 pr_err("Display of offsets requested but symbol is not"
200 "selected.\n");
201 return -EINVAL;
202 }
196 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 203 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
197 pr_err("Display of DSO requested but neither sample IP nor " 204 pr_err("Display of DSO requested but neither sample IP nor "
198 "sample address\nis selected. Hence, no addresses to convert " 205 "sample address\nis selected. Hence, no addresses to convert "
@@ -300,10 +307,17 @@ static void print_sample_start(struct perf_sample *sample,
300 } else 307 } else
301 evname = __event_name(attr->type, attr->config); 308 evname = __event_name(attr->type, attr->config);
302 309
303 printf("%s: ", evname ? evname : "(unknown)"); 310 printf("%s: ", evname ? evname : "[unknown]");
304 } 311 }
305} 312}
306 313
314static bool is_bts_event(struct perf_event_attr *attr)
315{
316 return ((attr->type == PERF_TYPE_HARDWARE) &&
317 (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
318 (attr->sample_period == 1));
319}
320
307static bool sample_addr_correlates_sym(struct perf_event_attr *attr) 321static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
308{ 322{
309 if ((attr->type == PERF_TYPE_SOFTWARE) && 323 if ((attr->type == PERF_TYPE_SOFTWARE) &&
@@ -312,6 +326,9 @@ static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
312 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))) 326 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
313 return true; 327 return true;
314 328
329 if (is_bts_event(attr))
330 return true;
331
315 return false; 332 return false;
316} 333}
317 334
@@ -323,7 +340,6 @@ static void print_sample_addr(union perf_event *event,
323{ 340{
324 struct addr_location al; 341 struct addr_location al;
325 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 342 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
326 const char *symname, *dsoname;
327 343
328 printf("%16" PRIx64, sample->addr); 344 printf("%16" PRIx64, sample->addr);
329 345
@@ -343,22 +359,46 @@ static void print_sample_addr(union perf_event *event,
343 al.sym = map__find_symbol(al.map, al.addr, NULL); 359 al.sym = map__find_symbol(al.map, al.addr, NULL);
344 360
345 if (PRINT_FIELD(SYM)) { 361 if (PRINT_FIELD(SYM)) {
346 if (al.sym && al.sym->name) 362 printf(" ");
347 symname = al.sym->name; 363 if (PRINT_FIELD(SYMOFFSET))
364 symbol__fprintf_symname_offs(al.sym, &al, stdout);
348 else 365 else
349 symname = ""; 366 symbol__fprintf_symname(al.sym, stdout);
350
351 printf(" %16s", symname);
352 } 367 }
353 368
354 if (PRINT_FIELD(DSO)) { 369 if (PRINT_FIELD(DSO)) {
355 if (al.map && al.map->dso && al.map->dso->name) 370 printf(" (");
356 dsoname = al.map->dso->name; 371 map__fprintf_dsoname(al.map, stdout);
357 else 372 printf(")");
358 dsoname = ""; 373 }
374}
359 375
360 printf(" (%s)", dsoname); 376static void print_sample_bts(union perf_event *event,
377 struct perf_sample *sample,
378 struct perf_evsel *evsel,
379 struct machine *machine,
380 struct thread *thread)
381{
382 struct perf_event_attr *attr = &evsel->attr;
383
384 /* print branch_from information */
385 if (PRINT_FIELD(IP)) {
386 if (!symbol_conf.use_callchain)
387 printf(" ");
388 else
389 printf("\n");
390 perf_event__print_ip(event, sample, machine, evsel,
391 PRINT_FIELD(SYM), PRINT_FIELD(DSO),
392 PRINT_FIELD(SYMOFFSET));
361 } 393 }
394
395 printf(" => ");
396
397 /* print branch_to information */
398 if (PRINT_FIELD(ADDR))
399 print_sample_addr(event, sample, machine, thread, attr);
400
401 printf("\n");
362} 402}
363 403
364static void process_event(union perf_event *event __unused, 404static void process_event(union perf_event *event __unused,
@@ -374,6 +414,11 @@ static void process_event(union perf_event *event __unused,
374 414
375 print_sample_start(sample, thread, attr); 415 print_sample_start(sample, thread, attr);
376 416
417 if (is_bts_event(attr)) {
418 print_sample_bts(event, sample, evsel, machine, thread);
419 return;
420 }
421
377 if (PRINT_FIELD(TRACE)) 422 if (PRINT_FIELD(TRACE))
378 print_trace_event(sample->cpu, sample->raw_data, 423 print_trace_event(sample->cpu, sample->raw_data,
379 sample->raw_size); 424 sample->raw_size);
@@ -387,7 +432,8 @@ static void process_event(union perf_event *event __unused,
387 else 432 else
388 printf("\n"); 433 printf("\n");
389 perf_event__print_ip(event, sample, machine, evsel, 434 perf_event__print_ip(event, sample, machine, evsel,
390 PRINT_FIELD(SYM), PRINT_FIELD(DSO)); 435 PRINT_FIELD(SYM), PRINT_FIELD(DSO),
436 PRINT_FIELD(SYMOFFSET));
391 } 437 }
392 438
393 printf("\n"); 439 printf("\n");
@@ -1018,13 +1064,17 @@ static char *get_script_path(const char *script_root, const char *suffix)
1018 __script_root = get_script_root(&script_dirent, suffix); 1064 __script_root = get_script_root(&script_dirent, suffix);
1019 if (__script_root && !strcmp(script_root, __script_root)) { 1065 if (__script_root && !strcmp(script_root, __script_root)) {
1020 free(__script_root); 1066 free(__script_root);
1067 closedir(lang_dir);
1068 closedir(scripts_dir);
1021 snprintf(script_path, MAXPATHLEN, "%s/%s", 1069 snprintf(script_path, MAXPATHLEN, "%s/%s",
1022 lang_path, script_dirent.d_name); 1070 lang_path, script_dirent.d_name);
1023 return strdup(script_path); 1071 return strdup(script_path);
1024 } 1072 }
1025 free(__script_root); 1073 free(__script_root);
1026 } 1074 }
1075 closedir(lang_dir);
1027 } 1076 }
1077 closedir(scripts_dir);
1028 1078
1029 return NULL; 1079 return NULL;
1030} 1080}
@@ -1093,7 +1143,10 @@ static const struct option options[] = {
1093 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1143 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1094 "Look for files with symbols relative to this directory"), 1144 "Look for files with symbols relative to this directory"),
1095 OPT_CALLBACK('f', "fields", NULL, "str", 1145 OPT_CALLBACK('f', "fields", NULL, "str",
1096 "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", 1146 "comma separated output fields prepend with 'type:'. "
1147 "Valid types: hw,sw,trace,raw. "
1148 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1149 "addr,symoff",
1097 parse_output_fields), 1150 parse_output_fields),
1098 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1151 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1099 "system-wide collection from all CPUs"), 1152 "system-wide collection from all CPUs"),
@@ -1102,6 +1155,9 @@ static const struct option options[] = {
1102 "only display events for these comms"), 1155 "only display events for these comms"),
1103 OPT_BOOLEAN('I', "show-info", &show_full_info, 1156 OPT_BOOLEAN('I', "show-info", &show_full_info,
1104 "display extended information from perf.data file"), 1157 "display extended information from perf.data file"),
1158 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
1159 "Show the path of [kernel.kallsyms]"),
1160
1105 OPT_END() 1161 OPT_END()
1106}; 1162};
1107 1163
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f5d2a63eba66..c941bb640f49 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -182,8 +182,8 @@ static int run_count = 1;
182static bool no_inherit = false; 182static bool no_inherit = false;
183static bool scale = true; 183static bool scale = true;
184static bool no_aggr = false; 184static bool no_aggr = false;
185static pid_t target_pid = -1; 185static const char *target_pid;
186static pid_t target_tid = -1; 186static const char *target_tid;
187static pid_t child_pid = -1; 187static pid_t child_pid = -1;
188static bool null_run = false; 188static bool null_run = false;
189static int detailed_run = 0; 189static int detailed_run = 0;
@@ -296,7 +296,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
296 if (system_wide) 296 if (system_wide)
297 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, 297 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
298 group, group_fd); 298 group, group_fd);
299 if (target_pid == -1 && target_tid == -1) { 299 if (!target_pid && !target_tid && (!group || evsel == first)) {
300 attr->disabled = 1; 300 attr->disabled = 1;
301 attr->enable_on_exec = 1; 301 attr->enable_on_exec = 1;
302 } 302 }
@@ -446,7 +446,7 @@ static int run_perf_stat(int argc __used, const char **argv)
446 exit(-1); 446 exit(-1);
447 } 447 }
448 448
449 if (target_tid == -1 && target_pid == -1 && !system_wide) 449 if (!target_tid && !target_pid && !system_wide)
450 evsel_list->threads->map[0] = child_pid; 450 evsel_list->threads->map[0] = child_pid;
451 451
452 /* 452 /*
@@ -576,6 +576,8 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
576 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 576 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
577 fprintf(output, " # %8.3f CPUs utilized ", 577 fprintf(output, " # %8.3f CPUs utilized ",
578 avg / avg_stats(&walltime_nsecs_stats)); 578 avg / avg_stats(&walltime_nsecs_stats));
579 else
580 fprintf(output, " ");
579} 581}
580 582
581/* used for get_ratio_color() */ 583/* used for get_ratio_color() */
@@ -844,12 +846,18 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
844 846
845 fprintf(output, " # %8.3f GHz ", ratio); 847 fprintf(output, " # %8.3f GHz ", ratio);
846 } else if (runtime_nsecs_stats[cpu].n != 0) { 848 } else if (runtime_nsecs_stats[cpu].n != 0) {
849 char unit = 'M';
850
847 total = avg_stats(&runtime_nsecs_stats[cpu]); 851 total = avg_stats(&runtime_nsecs_stats[cpu]);
848 852
849 if (total) 853 if (total)
850 ratio = 1000.0 * avg / total; 854 ratio = 1000.0 * avg / total;
855 if (ratio < 0.001) {
856 ratio *= 1000;
857 unit = 'K';
858 }
851 859
852 fprintf(output, " # %8.3f M/sec ", ratio); 860 fprintf(output, " # %8.3f %c/sec ", ratio, unit);
853 } else { 861 } else {
854 fprintf(output, " "); 862 fprintf(output, " ");
855 } 863 }
@@ -960,14 +968,14 @@ static void print_stat(int argc, const char **argv)
960 if (!csv_output) { 968 if (!csv_output) {
961 fprintf(output, "\n"); 969 fprintf(output, "\n");
962 fprintf(output, " Performance counter stats for "); 970 fprintf(output, " Performance counter stats for ");
963 if(target_pid == -1 && target_tid == -1) { 971 if (!target_pid && !target_tid) {
964 fprintf(output, "\'%s", argv[0]); 972 fprintf(output, "\'%s", argv[0]);
965 for (i = 1; i < argc; i++) 973 for (i = 1; i < argc; i++)
966 fprintf(output, " %s", argv[i]); 974 fprintf(output, " %s", argv[i]);
967 } else if (target_pid != -1) 975 } else if (target_pid)
968 fprintf(output, "process id \'%d", target_pid); 976 fprintf(output, "process id \'%s", target_pid);
969 else 977 else
970 fprintf(output, "thread id \'%d", target_tid); 978 fprintf(output, "thread id \'%s", target_tid);
971 979
972 fprintf(output, "\'"); 980 fprintf(output, "\'");
973 if (run_count > 1) 981 if (run_count > 1)
@@ -1041,10 +1049,10 @@ static const struct option options[] = {
1041 "event filter", parse_filter), 1049 "event filter", parse_filter),
1042 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 1050 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1043 "child tasks do not inherit counters"), 1051 "child tasks do not inherit counters"),
1044 OPT_INTEGER('p', "pid", &target_pid, 1052 OPT_STRING('p', "pid", &target_pid, "pid",
1045 "stat events on existing process id"), 1053 "stat events on existing process id"),
1046 OPT_INTEGER('t', "tid", &target_tid, 1054 OPT_STRING('t', "tid", &target_tid, "tid",
1047 "stat events on existing thread id"), 1055 "stat events on existing thread id"),
1048 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1056 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1049 "system-wide collection from all CPUs"), 1057 "system-wide collection from all CPUs"),
1050 OPT_BOOLEAN('g', "group", &group, 1058 OPT_BOOLEAN('g', "group", &group,
@@ -1182,7 +1190,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1182 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1190 } else if (big_num_opt == 0) /* User passed --no-big-num */
1183 big_num = false; 1191 big_num = false;
1184 1192
1185 if (!argc && target_pid == -1 && target_tid == -1) 1193 if (!argc && !target_pid && !target_tid)
1186 usage_with_options(stat_usage, options); 1194 usage_with_options(stat_usage, options);
1187 if (run_count <= 0) 1195 if (run_count <= 0)
1188 usage_with_options(stat_usage, options); 1196 usage_with_options(stat_usage, options);
@@ -1198,10 +1206,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1198 if (add_default_attributes()) 1206 if (add_default_attributes())
1199 goto out; 1207 goto out;
1200 1208
1201 if (target_pid != -1) 1209 if (target_pid)
1202 target_tid = target_pid; 1210 target_tid = target_pid;
1203 1211
1204 evsel_list->threads = thread_map__new(target_pid, target_tid); 1212 evsel_list->threads = thread_map__new_str(target_pid,
1213 target_tid, UINT_MAX);
1205 if (evsel_list->threads == NULL) { 1214 if (evsel_list->threads == NULL) {
1206 pr_err("Problems finding threads of monitor\n"); 1215 pr_err("Problems finding threads of monitor\n");
1207 usage_with_options(stat_usage, options); 1216 usage_with_options(stat_usage, options);
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 2b9a7f497a20..1c5b9801ac61 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -13,8 +13,11 @@
13#include "util/parse-events.h" 13#include "util/parse-events.h"
14#include "util/symbol.h" 14#include "util/symbol.h"
15#include "util/thread_map.h" 15#include "util/thread_map.h"
16#include "util/pmu.h"
16#include "../../include/linux/hw_breakpoint.h" 17#include "../../include/linux/hw_breakpoint.h"
17 18
19#include <sys/mman.h>
20
18static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) 21static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym)
19{ 22{
20 bool *visited = symbol__priv(sym); 23 bool *visited = symbol__priv(sym);
@@ -276,7 +279,7 @@ static int test__open_syscall_event(void)
276 return -1; 279 return -1;
277 } 280 }
278 281
279 threads = thread_map__new(-1, getpid()); 282 threads = thread_map__new(-1, getpid(), UINT_MAX);
280 if (threads == NULL) { 283 if (threads == NULL) {
281 pr_debug("thread_map__new\n"); 284 pr_debug("thread_map__new\n");
282 return -1; 285 return -1;
@@ -342,7 +345,7 @@ static int test__open_syscall_event_on_all_cpus(void)
342 return -1; 345 return -1;
343 } 346 }
344 347
345 threads = thread_map__new(-1, getpid()); 348 threads = thread_map__new(-1, getpid(), UINT_MAX);
346 if (threads == NULL) { 349 if (threads == NULL) {
347 pr_debug("thread_map__new\n"); 350 pr_debug("thread_map__new\n");
348 return -1; 351 return -1;
@@ -490,7 +493,7 @@ static int test__basic_mmap(void)
490 expected_nr_events[i] = random() % 257; 493 expected_nr_events[i] = random() % 257;
491 } 494 }
492 495
493 threads = thread_map__new(-1, getpid()); 496 threads = thread_map__new(-1, getpid(), UINT_MAX);
494 if (threads == NULL) { 497 if (threads == NULL) {
495 pr_debug("thread_map__new\n"); 498 pr_debug("thread_map__new\n");
496 return -1; 499 return -1;
@@ -648,7 +651,7 @@ static int test__checkevent_raw(struct perf_evlist *evlist)
648 651
649 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 652 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
650 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 653 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
651 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); 654 TEST_ASSERT_VAL("wrong config", 0x1a == evsel->attr.config);
652 return 0; 655 return 0;
653} 656}
654 657
@@ -675,6 +678,24 @@ static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
675 return 0; 678 return 0;
676} 679}
677 680
681static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist)
682{
683 struct perf_evsel *evsel = list_entry(evlist->entries.next,
684 struct perf_evsel, node);
685
686 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
687 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
688 TEST_ASSERT_VAL("wrong config",
689 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
690 TEST_ASSERT_VAL("wrong period",
691 100000 == evsel->attr.sample_period);
692 TEST_ASSERT_VAL("wrong config1",
693 0 == evsel->attr.config1);
694 TEST_ASSERT_VAL("wrong config2",
695 1 == evsel->attr.config2);
696 return 0;
697}
698
678static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) 699static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
679{ 700{
680 struct perf_evsel *evsel = list_entry(evlist->entries.next, 701 struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -856,6 +877,115 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
856 return test__checkevent_genhw(evlist); 877 return test__checkevent_genhw(evlist);
857} 878}
858 879
880static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
881{
882 struct perf_evsel *evsel = list_entry(evlist->entries.next,
883 struct perf_evsel, node);
884
885 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
886 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
887 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
888 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
889
890 return test__checkevent_breakpoint(evlist);
891}
892
893static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
894{
895 struct perf_evsel *evsel = list_entry(evlist->entries.next,
896 struct perf_evsel, node);
897
898 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
899 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
900 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
901 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
902
903 return test__checkevent_breakpoint_x(evlist);
904}
905
906static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
907{
908 struct perf_evsel *evsel = list_entry(evlist->entries.next,
909 struct perf_evsel, node);
910
911 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
912 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
913 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
914 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
915
916 return test__checkevent_breakpoint_r(evlist);
917}
918
919static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
920{
921 struct perf_evsel *evsel = list_entry(evlist->entries.next,
922 struct perf_evsel, node);
923
924 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
925 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
926 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
927 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
928
929 return test__checkevent_breakpoint_w(evlist);
930}
931
932static int test__checkevent_pmu(struct perf_evlist *evlist)
933{
934
935 struct perf_evsel *evsel = list_entry(evlist->entries.next,
936 struct perf_evsel, node);
937
938 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
939 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
940 TEST_ASSERT_VAL("wrong config", 10 == evsel->attr.config);
941 TEST_ASSERT_VAL("wrong config1", 1 == evsel->attr.config1);
942 TEST_ASSERT_VAL("wrong config2", 3 == evsel->attr.config2);
943 TEST_ASSERT_VAL("wrong period", 1000 == evsel->attr.sample_period);
944
945 return 0;
946}
947
948static int test__checkevent_list(struct perf_evlist *evlist)
949{
950 struct perf_evsel *evsel;
951
952 TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
953
954 /* r1 */
955 evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
956 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
957 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
958 TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1);
959 TEST_ASSERT_VAL("wrong config2", 0 == evsel->attr.config2);
960 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
961 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
962 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
963 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
964
965 /* syscalls:sys_enter_open:k */
966 evsel = list_entry(evsel->node.next, struct perf_evsel, node);
967 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
968 TEST_ASSERT_VAL("wrong sample_type",
969 (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
970 evsel->attr.sample_type);
971 TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
972 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
973 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
974 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
975 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
976
977 /* 1:1:hp */
978 evsel = list_entry(evsel->node.next, struct perf_evsel, node);
979 TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
980 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
981 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
982 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
983 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
984 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
985
986 return 0;
987}
988
859static struct test__event_st { 989static struct test__event_st {
860 const char *name; 990 const char *name;
861 __u32 type; 991 __u32 type;
@@ -870,7 +1000,7 @@ static struct test__event_st {
870 .check = test__checkevent_tracepoint_multi, 1000 .check = test__checkevent_tracepoint_multi,
871 }, 1001 },
872 { 1002 {
873 .name = "r1", 1003 .name = "r1a",
874 .check = test__checkevent_raw, 1004 .check = test__checkevent_raw,
875 }, 1005 },
876 { 1006 {
@@ -882,6 +1012,10 @@ static struct test__event_st {
882 .check = test__checkevent_symbolic_name, 1012 .check = test__checkevent_symbolic_name,
883 }, 1013 },
884 { 1014 {
1015 .name = "cycles/period=100000,config2/",
1016 .check = test__checkevent_symbolic_name_config,
1017 },
1018 {
885 .name = "faults", 1019 .name = "faults",
886 .check = test__checkevent_symbolic_alias, 1020 .check = test__checkevent_symbolic_alias,
887 }, 1021 },
@@ -914,7 +1048,7 @@ static struct test__event_st {
914 .check = test__checkevent_tracepoint_multi_modifier, 1048 .check = test__checkevent_tracepoint_multi_modifier,
915 }, 1049 },
916 { 1050 {
917 .name = "r1:kp", 1051 .name = "r1a:kp",
918 .check = test__checkevent_raw_modifier, 1052 .check = test__checkevent_raw_modifier,
919 }, 1053 },
920 { 1054 {
@@ -933,6 +1067,30 @@ static struct test__event_st {
933 .name = "L1-dcache-load-miss:kp", 1067 .name = "L1-dcache-load-miss:kp",
934 .check = test__checkevent_genhw_modifier, 1068 .check = test__checkevent_genhw_modifier,
935 }, 1069 },
1070 {
1071 .name = "mem:0:u",
1072 .check = test__checkevent_breakpoint_modifier,
1073 },
1074 {
1075 .name = "mem:0:x:k",
1076 .check = test__checkevent_breakpoint_x_modifier,
1077 },
1078 {
1079 .name = "mem:0:r:hp",
1080 .check = test__checkevent_breakpoint_r_modifier,
1081 },
1082 {
1083 .name = "mem:0:w:up",
1084 .check = test__checkevent_breakpoint_w_modifier,
1085 },
1086 {
1087 .name = "cpu/config=10,config1,config2=3,period=1000/u",
1088 .check = test__checkevent_pmu,
1089 },
1090 {
1091 .name = "r1,syscalls:sys_enter_open:k,1:1:hp",
1092 .check = test__checkevent_list,
1093 },
936}; 1094};
937 1095
938#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st)) 1096#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
@@ -958,10 +1116,9 @@ static int test__parse_events(void)
958 } 1116 }
959 1117
960 ret = e->check(evlist); 1118 ret = e->check(evlist);
1119 perf_evlist__delete(evlist);
961 if (ret) 1120 if (ret)
962 break; 1121 break;
963
964 perf_evlist__delete(evlist);
965 } 1122 }
966 1123
967 return ret; 1124 return ret;
@@ -1008,12 +1165,9 @@ realloc:
1008static int test__PERF_RECORD(void) 1165static int test__PERF_RECORD(void)
1009{ 1166{
1010 struct perf_record_opts opts = { 1167 struct perf_record_opts opts = {
1011 .target_pid = -1,
1012 .target_tid = -1,
1013 .no_delay = true, 1168 .no_delay = true,
1014 .freq = 10, 1169 .freq = 10,
1015 .mmap_pages = 256, 1170 .mmap_pages = 256,
1016 .sample_id_all_avail = true,
1017 }; 1171 };
1018 cpu_set_t *cpu_mask = NULL; 1172 cpu_set_t *cpu_mask = NULL;
1019 size_t cpu_mask_size = 0; 1173 size_t cpu_mask_size = 0;
@@ -1054,7 +1208,7 @@ static int test__PERF_RECORD(void)
1054 * we're monitoring, the one forked there. 1208 * we're monitoring, the one forked there.
1055 */ 1209 */
1056 err = perf_evlist__create_maps(evlist, opts.target_pid, 1210 err = perf_evlist__create_maps(evlist, opts.target_pid,
1057 opts.target_tid, opts.cpu_list); 1211 opts.target_tid, UINT_MAX, opts.cpu_list);
1058 if (err < 0) { 1212 if (err < 0) {
1059 pr_debug("Not enough memory to create thread/cpu maps\n"); 1213 pr_debug("Not enough memory to create thread/cpu maps\n");
1060 goto out_delete_evlist; 1214 goto out_delete_evlist;
@@ -1296,6 +1450,178 @@ out:
1296 return (err < 0 || errs > 0) ? -1 : 0; 1450 return (err < 0 || errs > 0) ? -1 : 0;
1297} 1451}
1298 1452
1453
1454#if defined(__x86_64__) || defined(__i386__)
1455
1456#define barrier() asm volatile("" ::: "memory")
1457
1458static u64 rdpmc(unsigned int counter)
1459{
1460 unsigned int low, high;
1461
1462 asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
1463
1464 return low | ((u64)high) << 32;
1465}
1466
1467static u64 rdtsc(void)
1468{
1469 unsigned int low, high;
1470
1471 asm volatile("rdtsc" : "=a" (low), "=d" (high));
1472
1473 return low | ((u64)high) << 32;
1474}
1475
1476static u64 mmap_read_self(void *addr)
1477{
1478 struct perf_event_mmap_page *pc = addr;
1479 u32 seq, idx, time_mult = 0, time_shift = 0;
1480 u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
1481
1482 do {
1483 seq = pc->lock;
1484 barrier();
1485
1486 enabled = pc->time_enabled;
1487 running = pc->time_running;
1488
1489 if (enabled != running) {
1490 cyc = rdtsc();
1491 time_mult = pc->time_mult;
1492 time_shift = pc->time_shift;
1493 time_offset = pc->time_offset;
1494 }
1495
1496 idx = pc->index;
1497 count = pc->offset;
1498 if (idx)
1499 count += rdpmc(idx - 1);
1500
1501 barrier();
1502 } while (pc->lock != seq);
1503
1504 if (enabled != running) {
1505 u64 quot, rem;
1506
1507 quot = (cyc >> time_shift);
1508 rem = cyc & ((1 << time_shift) - 1);
1509 delta = time_offset + quot * time_mult +
1510 ((rem * time_mult) >> time_shift);
1511
1512 enabled += delta;
1513 if (idx)
1514 running += delta;
1515
1516 quot = count / running;
1517 rem = count % running;
1518 count = quot * enabled + (rem * enabled) / running;
1519 }
1520
1521 return count;
1522}
1523
1524/*
1525 * If the RDPMC instruction faults then signal this back to the test parent task:
1526 */
1527static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used)
1528{
1529 exit(-1);
1530}
1531
1532static int __test__rdpmc(void)
1533{
1534 long page_size = sysconf(_SC_PAGE_SIZE);
1535 volatile int tmp = 0;
1536 u64 i, loops = 1000;
1537 int n;
1538 int fd;
1539 void *addr;
1540 struct perf_event_attr attr = {
1541 .type = PERF_TYPE_HARDWARE,
1542 .config = PERF_COUNT_HW_INSTRUCTIONS,
1543 .exclude_kernel = 1,
1544 };
1545 u64 delta_sum = 0;
1546 struct sigaction sa;
1547
1548 sigfillset(&sa.sa_mask);
1549 sa.sa_sigaction = segfault_handler;
1550 sigaction(SIGSEGV, &sa, NULL);
1551
1552 fprintf(stderr, "\n\n");
1553
1554 fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
1555 if (fd < 0) {
1556 die("Error: sys_perf_event_open() syscall returned "
1557 "with %d (%s)\n", fd, strerror(errno));
1558 }
1559
1560 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
1561 if (addr == (void *)(-1)) {
1562 die("Error: mmap() syscall returned "
1563 "with (%s)\n", strerror(errno));
1564 }
1565
1566 for (n = 0; n < 6; n++) {
1567 u64 stamp, now, delta;
1568
1569 stamp = mmap_read_self(addr);
1570
1571 for (i = 0; i < loops; i++)
1572 tmp++;
1573
1574 now = mmap_read_self(addr);
1575 loops *= 10;
1576
1577 delta = now - stamp;
1578 fprintf(stderr, "%14d: %14Lu\n", n, (long long)delta);
1579
1580 delta_sum += delta;
1581 }
1582
1583 munmap(addr, page_size);
1584 close(fd);
1585
1586 fprintf(stderr, " ");
1587
1588 if (!delta_sum)
1589 return -1;
1590
1591 return 0;
1592}
1593
1594static int test__rdpmc(void)
1595{
1596 int status = 0;
1597 int wret = 0;
1598 int ret;
1599 int pid;
1600
1601 pid = fork();
1602 if (pid < 0)
1603 return -1;
1604
1605 if (!pid) {
1606 ret = __test__rdpmc();
1607
1608 exit(ret);
1609 }
1610
1611 wret = waitpid(pid, &status, 0);
1612 if (wret < 0 || status)
1613 return -1;
1614
1615 return 0;
1616}
1617
1618#endif
1619
1620static int test__perf_pmu(void)
1621{
1622 return perf_pmu__test();
1623}
1624
1299static struct test { 1625static struct test {
1300 const char *desc; 1626 const char *desc;
1301 int (*func)(void); 1627 int (*func)(void);
@@ -1320,11 +1646,21 @@ static struct test {
1320 .desc = "parse events tests", 1646 .desc = "parse events tests",
1321 .func = test__parse_events, 1647 .func = test__parse_events,
1322 }, 1648 },
1649#if defined(__x86_64__) || defined(__i386__)
1650 {
1651 .desc = "x86 rdpmc test",
1652 .func = test__rdpmc,
1653 },
1654#endif
1323 { 1655 {
1324 .desc = "Validate PERF_RECORD_* events & perf_sample fields", 1656 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
1325 .func = test__PERF_RECORD, 1657 .func = test__PERF_RECORD,
1326 }, 1658 },
1327 { 1659 {
1660 .desc = "Test perf pmu format parsing",
1661 .func = test__perf_pmu,
1662 },
1663 {
1328 .func = NULL, 1664 .func = NULL,
1329 }, 1665 },
1330}; 1666};
@@ -1396,7 +1732,7 @@ int cmd_test(int argc, const char **argv, const char *prefix __used)
1396 NULL, 1732 NULL,
1397 }; 1733 };
1398 const struct option test_options[] = { 1734 const struct option test_options[] = {
1399 OPT_INTEGER('v', "verbose", &verbose, 1735 OPT_INCR('v', "verbose", &verbose,
1400 "be more verbose (show symbol address, etc)"), 1736 "be more verbose (show symbol address, etc)"),
1401 OPT_END() 1737 OPT_END()
1402 }; 1738 };
@@ -1412,7 +1748,5 @@ int cmd_test(int argc, const char **argv, const char *prefix __used)
1412 if (symbol__init() < 0) 1748 if (symbol__init() < 0)
1413 return -1; 1749 return -1;
1414 1750
1415 setup_pager();
1416
1417 return __cmd_test(argc, argv); 1751 return __cmd_test(argc, argv);
1418} 1752}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 4f81eeb99875..e3c63aef8efc 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -64,7 +64,6 @@
64#include <linux/unistd.h> 64#include <linux/unistd.h>
65#include <linux/types.h> 65#include <linux/types.h>
66 66
67
68void get_term_dimensions(struct winsize *ws) 67void get_term_dimensions(struct winsize *ws)
69{ 68{
70 char *s = getenv("LINES"); 69 char *s = getenv("LINES");
@@ -89,8 +88,6 @@ void get_term_dimensions(struct winsize *ws)
89 88
90static void perf_top__update_print_entries(struct perf_top *top) 89static void perf_top__update_print_entries(struct perf_top *top)
91{ 90{
92 top->print_entries = top->winsize.ws_row;
93
94 if (top->print_entries > 9) 91 if (top->print_entries > 9)
95 top->print_entries -= 9; 92 top->print_entries -= 9;
96} 93}
@@ -100,6 +97,13 @@ static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *ar
100 struct perf_top *top = arg; 97 struct perf_top *top = arg;
101 98
102 get_term_dimensions(&top->winsize); 99 get_term_dimensions(&top->winsize);
100 if (!top->print_entries
101 || (top->print_entries+4) > top->winsize.ws_row) {
102 top->print_entries = top->winsize.ws_row;
103 } else {
104 top->print_entries += 4;
105 top->winsize.ws_row = top->print_entries;
106 }
103 perf_top__update_print_entries(top); 107 perf_top__update_print_entries(top);
104} 108}
105 109
@@ -235,7 +239,6 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
235 if (he == NULL) 239 if (he == NULL)
236 return NULL; 240 return NULL;
237 241
238 evsel->hists.stats.total_period += sample->period;
239 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 242 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
240 return he; 243 return he;
241} 244}
@@ -454,8 +457,10 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
454 }; 457 };
455 perf_top__sig_winch(SIGWINCH, NULL, top); 458 perf_top__sig_winch(SIGWINCH, NULL, top);
456 sigaction(SIGWINCH, &act, NULL); 459 sigaction(SIGWINCH, &act, NULL);
457 } else 460 } else {
461 perf_top__sig_winch(SIGWINCH, NULL, top);
458 signal(SIGWINCH, SIG_DFL); 462 signal(SIGWINCH, SIG_DFL);
463 }
459 break; 464 break;
460 case 'E': 465 case 'E':
461 if (top->evlist->nr_entries > 1) { 466 if (top->evlist->nr_entries > 1) {
@@ -538,10 +543,20 @@ static void perf_top__sort_new_samples(void *arg)
538 543
539static void *display_thread_tui(void *arg) 544static void *display_thread_tui(void *arg)
540{ 545{
546 struct perf_evsel *pos;
541 struct perf_top *top = arg; 547 struct perf_top *top = arg;
542 const char *help = "For a higher level overview, try: perf top --sort comm,dso"; 548 const char *help = "For a higher level overview, try: perf top --sort comm,dso";
543 549
544 perf_top__sort_new_samples(top); 550 perf_top__sort_new_samples(top);
551
552 /*
553 * Initialize the uid_filter_str, in the future the TUI will allow
554 * Zooming in/out UIDs. For now juse use whatever the user passed
555 * via --uid.
556 */
557 list_for_each_entry(pos, &top->evlist->entries, node)
558 pos->hists.uid_filter_str = top->uid_str;
559
545 perf_evlist__tui_browse_hists(top->evlist, help, 560 perf_evlist__tui_browse_hists(top->evlist, help,
546 perf_top__sort_new_samples, 561 perf_top__sort_new_samples,
547 top, top->delay_secs); 562 top, top->delay_secs);
@@ -662,6 +677,12 @@ static void perf_event__process_sample(struct perf_tool *tool,
662 return; 677 return;
663 } 678 }
664 679
680 if (!machine) {
681 pr_err("%u unprocessable samples recorded.",
682 top->session->hists.stats.nr_unprocessable_samples++);
683 return;
684 }
685
665 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) 686 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
666 top->exact_samples++; 687 top->exact_samples++;
667 688
@@ -851,8 +872,11 @@ static void perf_top__start_counters(struct perf_top *top)
851 attr->mmap = 1; 872 attr->mmap = 1;
852 attr->comm = 1; 873 attr->comm = 1;
853 attr->inherit = top->inherit; 874 attr->inherit = top->inherit;
875fallback_missing_features:
876 if (top->exclude_guest_missing)
877 attr->exclude_guest = attr->exclude_host = 0;
854retry_sample_id: 878retry_sample_id:
855 attr->sample_id_all = top->sample_id_all_avail ? 1 : 0; 879 attr->sample_id_all = top->sample_id_all_missing ? 0 : 1;
856try_again: 880try_again:
857 if (perf_evsel__open(counter, top->evlist->cpus, 881 if (perf_evsel__open(counter, top->evlist->cpus,
858 top->evlist->threads, top->group, 882 top->evlist->threads, top->group,
@@ -862,12 +886,20 @@ try_again:
862 if (err == EPERM || err == EACCES) { 886 if (err == EPERM || err == EACCES) {
863 ui__error_paranoid(); 887 ui__error_paranoid();
864 goto out_err; 888 goto out_err;
865 } else if (err == EINVAL && top->sample_id_all_avail) { 889 } else if (err == EINVAL) {
866 /* 890 if (!top->exclude_guest_missing &&
867 * Old kernel, no attr->sample_id_type_all field 891 (attr->exclude_guest || attr->exclude_host)) {
868 */ 892 pr_debug("Old kernel, cannot exclude "
869 top->sample_id_all_avail = false; 893 "guest or host samples.\n");
870 goto retry_sample_id; 894 top->exclude_guest_missing = true;
895 goto fallback_missing_features;
896 } else if (!top->sample_id_all_missing) {
897 /*
898 * Old kernel, no attr->sample_id_type_all field
899 */
900 top->sample_id_all_missing = true;
901 goto retry_sample_id;
902 }
871 } 903 }
872 /* 904 /*
873 * If it's cycles then fall back to hrtimer 905 * If it's cycles then fall back to hrtimer
@@ -889,6 +921,10 @@ try_again:
889 ui__warning("The %s event is not supported.\n", 921 ui__warning("The %s event is not supported.\n",
890 event_name(counter)); 922 event_name(counter));
891 goto out_err; 923 goto out_err;
924 } else if (err == EMFILE) {
925 ui__warning("Too many events are opened.\n"
926 "Try again after reducing the number of events\n");
927 goto out_err;
892 } 928 }
893 929
894 ui__warning("The sys_perf_event_open() syscall " 930 ui__warning("The sys_perf_event_open() syscall "
@@ -946,7 +982,7 @@ static int __cmd_top(struct perf_top *top)
946 if (ret) 982 if (ret)
947 goto out_delete; 983 goto out_delete;
948 984
949 if (top->target_tid != -1) 985 if (top->target_tid || top->uid != UINT_MAX)
950 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 986 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
951 perf_event__process, 987 perf_event__process,
952 &top->session->host_machine); 988 &top->session->host_machine);
@@ -1084,10 +1120,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1084 struct perf_top top = { 1120 struct perf_top top = {
1085 .count_filter = 5, 1121 .count_filter = 5,
1086 .delay_secs = 2, 1122 .delay_secs = 2,
1087 .target_pid = -1, 1123 .uid = UINT_MAX,
1088 .target_tid = -1,
1089 .freq = 1000, /* 1 KHz */ 1124 .freq = 1000, /* 1 KHz */
1090 .sample_id_all_avail = true,
1091 .mmap_pages = 128, 1125 .mmap_pages = 128,
1092 .sym_pcnt_filter = 5, 1126 .sym_pcnt_filter = 5,
1093 }; 1127 };
@@ -1098,9 +1132,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1098 parse_events_option), 1132 parse_events_option),
1099 OPT_INTEGER('c', "count", &top.default_interval, 1133 OPT_INTEGER('c', "count", &top.default_interval,
1100 "event period to sample"), 1134 "event period to sample"),
1101 OPT_INTEGER('p', "pid", &top.target_pid, 1135 OPT_STRING('p', "pid", &top.target_pid, "pid",
1102 "profile events on existing process id"), 1136 "profile events on existing process id"),
1103 OPT_INTEGER('t', "tid", &top.target_tid, 1137 OPT_STRING('t', "tid", &top.target_tid, "tid",
1104 "profile events on existing thread id"), 1138 "profile events on existing thread id"),
1105 OPT_BOOLEAN('a', "all-cpus", &top.system_wide, 1139 OPT_BOOLEAN('a', "all-cpus", &top.system_wide,
1106 "system-wide collection from all CPUs"), 1140 "system-wide collection from all CPUs"),
@@ -1159,6 +1193,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1159 "Display raw encoding of assembly instructions (default)"), 1193 "Display raw encoding of assembly instructions (default)"),
1160 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1194 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1161 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1195 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1196 OPT_STRING('u', "uid", &top.uid_str, "user", "user to profile"),
1162 OPT_END() 1197 OPT_END()
1163 }; 1198 };
1164 1199
@@ -1184,18 +1219,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1184 1219
1185 setup_browser(false); 1220 setup_browser(false);
1186 1221
1222 top.uid = parse_target_uid(top.uid_str, top.target_tid, top.target_pid);
1223 if (top.uid_str != NULL && top.uid == UINT_MAX - 1)
1224 goto out_delete_evlist;
1225
1187 /* CPU and PID are mutually exclusive */ 1226 /* CPU and PID are mutually exclusive */
1188 if (top.target_tid > 0 && top.cpu_list) { 1227 if (top.target_tid && top.cpu_list) {
1189 printf("WARNING: PID switch overriding CPU\n"); 1228 printf("WARNING: PID switch overriding CPU\n");
1190 sleep(1); 1229 sleep(1);
1191 top.cpu_list = NULL; 1230 top.cpu_list = NULL;
1192 } 1231 }
1193 1232
1194 if (top.target_pid != -1) 1233 if (top.target_pid)
1195 top.target_tid = top.target_pid; 1234 top.target_tid = top.target_pid;
1196 1235
1197 if (perf_evlist__create_maps(top.evlist, top.target_pid, 1236 if (perf_evlist__create_maps(top.evlist, top.target_pid,
1198 top.target_tid, top.cpu_list) < 0) 1237 top.target_tid, top.uid, top.cpu_list) < 0)
1199 usage_with_options(top_usage, options); 1238 usage_with_options(top_usage, options);
1200 1239
1201 if (!top.evlist->nr_entries && 1240 if (!top.evlist->nr_entries &&
@@ -1259,6 +1298,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1259 1298
1260 status = __cmd_top(&top); 1299 status = __cmd_top(&top);
1261 1300
1301out_delete_evlist:
1262 perf_evlist__delete(top.evlist); 1302 perf_evlist__delete(top.evlist);
1263 1303
1264 return status; 1304 return status;
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index 6170fd2531b5..d9084e03ce56 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -65,6 +65,21 @@ int main(void)
65endef 65endef
66endif 66endif
67 67
68ifndef NO_GTK2
69define SOURCE_GTK2
70#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
71#include <gtk/gtk.h>
72#pragma GCC diagnostic error \"-Wstrict-prototypes\"
73
74int main(int argc, char *argv[])
75{
76 gtk_init(&argc, &argv);
77
78 return 0;
79}
80endef
81endif
82
68ifndef NO_LIBPERL 83ifndef NO_LIBPERL
69define SOURCE_PERL_EMBED 84define SOURCE_PERL_EMBED
70#include <EXTERN.h> 85#include <EXTERN.h>
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 64f8bee31ced..89e3355ab173 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -10,6 +10,9 @@ void get_term_dimensions(struct winsize *ws);
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#define CPUINFO_PROC "model name"
13#ifndef __NR_perf_event_open
14# define __NR_perf_event_open 336
15#endif
13#endif 16#endif
14 17
15#if defined(__x86_64__) 18#if defined(__x86_64__)
@@ -17,6 +20,9 @@ void get_term_dimensions(struct winsize *ws);
17#define rmb() asm volatile("lfence" ::: "memory") 20#define rmb() asm volatile("lfence" ::: "memory")
18#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 21#define cpu_relax() asm volatile("rep; nop" ::: "memory");
19#define CPUINFO_PROC "model name" 22#define CPUINFO_PROC "model name"
23#ifndef __NR_perf_event_open
24# define __NR_perf_event_open 298
25#endif
20#endif 26#endif
21 27
22#ifdef __powerpc__ 28#ifdef __powerpc__
@@ -167,7 +173,6 @@ sys_perf_event_open(struct perf_event_attr *attr,
167 pid_t pid, int cpu, int group_fd, 173 pid_t pid, int cpu, int group_fd,
168 unsigned long flags) 174 unsigned long flags)
169{ 175{
170 attr->size = sizeof(*attr);
171 return syscall(__NR_perf_event_open, attr, pid, cpu, 176 return syscall(__NR_perf_event_open, attr, pid, cpu,
172 group_fd, flags); 177 group_fd, flags);
173} 178}
@@ -180,14 +185,32 @@ struct ip_callchain {
180 u64 ips[0]; 185 u64 ips[0];
181}; 186};
182 187
188struct branch_flags {
189 u64 mispred:1;
190 u64 predicted:1;
191 u64 reserved:62;
192};
193
194struct branch_entry {
195 u64 from;
196 u64 to;
197 struct branch_flags flags;
198};
199
200struct branch_stack {
201 u64 nr;
202 struct branch_entry entries[0];
203};
204
183extern bool perf_host, perf_guest; 205extern bool perf_host, perf_guest;
184extern const char perf_version_string[]; 206extern const char perf_version_string[];
185 207
186void pthread__unblock_sigwinch(void); 208void pthread__unblock_sigwinch(void);
187 209
188struct perf_record_opts { 210struct perf_record_opts {
189 pid_t target_pid; 211 const char *target_pid;
190 pid_t target_tid; 212 const char *target_tid;
213 uid_t uid;
191 bool call_graph; 214 bool call_graph;
192 bool group; 215 bool group;
193 bool inherit_stat; 216 bool inherit_stat;
@@ -198,12 +221,14 @@ struct perf_record_opts {
198 bool raw_samples; 221 bool raw_samples;
199 bool sample_address; 222 bool sample_address;
200 bool sample_time; 223 bool sample_time;
201 bool sample_id_all_avail; 224 bool sample_id_all_missing;
225 bool exclude_guest_missing;
202 bool system_wide; 226 bool system_wide;
203 bool period; 227 bool period;
204 unsigned int freq; 228 unsigned int freq;
205 unsigned int mmap_pages; 229 unsigned int mmap_pages;
206 unsigned int user_freq; 230 unsigned int user_freq;
231 int branch_stack;
207 u64 default_interval; 232 u64 default_interval;
208 u64 user_interval; 233 u64 user_interval;
209 const char *cpu_list; 234 const char *cpu_list;
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
index df638c438a9f..b11cca584238 100755
--- a/tools/perf/python/twatch.py
+++ b/tools/perf/python/twatch.py
@@ -19,7 +19,7 @@ def main():
19 cpus = perf.cpu_map() 19 cpus = perf.cpu_map()
20 threads = perf.thread_map() 20 threads = perf.thread_map()
21 evsel = perf.evsel(task = 1, comm = 1, mmap = 0, 21 evsel = perf.evsel(task = 1, comm = 1, mmap = 0,
22 wakeup_events = 1, sample_period = 1, 22 wakeup_events = 1, watermark = 1,
23 sample_id_all = 1, 23 sample_id_all = 1,
24 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID) 24 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID)
25 evsel.open(cpus = cpus, threads = threads); 25 evsel.open(cpus = cpus, threads = threads);
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 011ed2676604..199f69ec656f 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -28,8 +28,8 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym)
28int symbol__alloc_hist(struct symbol *sym) 28int symbol__alloc_hist(struct symbol *sym)
29{ 29{
30 struct annotation *notes = symbol__annotation(sym); 30 struct annotation *notes = symbol__annotation(sym);
31 size_t sizeof_sym_hist = (sizeof(struct sym_hist) + 31 const size_t size = sym->end - sym->start + 1;
32 (sym->end - sym->start) * sizeof(u64)); 32 size_t sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64));
33 33
34 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); 34 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
35 if (notes->src == NULL) 35 if (notes->src == NULL)
@@ -64,7 +64,7 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
64 64
65 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 65 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
66 66
67 if (addr >= sym->end) 67 if (addr > sym->end)
68 return 0; 68 return 0;
69 69
70 offset = addr - sym->start; 70 offset = addr - sym->start;
@@ -315,7 +315,7 @@ fallback:
315 "Please use:\n\n" 315 "Please use:\n\n"
316 " perf buildid-cache -av vmlinux\n\n" 316 " perf buildid-cache -av vmlinux\n\n"
317 "or:\n\n" 317 "or:\n\n"
318 " --vmlinux vmlinux", 318 " --vmlinux vmlinux\n",
319 sym->name, build_id_msg ?: ""); 319 sym->name, build_id_msg ?: "");
320 goto out_free_filename; 320 goto out_free_filename;
321 } 321 }
@@ -408,7 +408,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
408 if (!notes->src->lines) 408 if (!notes->src->lines)
409 return -1; 409 return -1;
410 410
411 start = map->unmap_ip(map, sym->start); 411 start = map__rip_2objdump(map, sym->start);
412 412
413 for (i = 0; i < len; i++) { 413 for (i = 0; i < len; i++) {
414 char *path = NULL; 414 char *path = NULL;
diff --git a/tools/perf/util/bitmap.c b/tools/perf/util/bitmap.c
index 5e230acae1e9..0a1adc1111fd 100644
--- a/tools/perf/util/bitmap.c
+++ b/tools/perf/util/bitmap.c
@@ -19,3 +19,13 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)
19 19
20 return w; 20 return w;
21} 21}
22
23void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
24 const unsigned long *bitmap2, int bits)
25{
26 int k;
27 int nr = BITS_TO_LONGS(bits);
28
29 for (k = 0; k < nr; k++)
30 dst[k] = bitmap1[k] | bitmap2[k];
31}
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index fc5e5a09d5b9..8dd224df3e54 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -45,6 +45,18 @@ void setup_browser(bool fallback_to_pager);
45void exit_browser(bool wait_for_ok); 45void exit_browser(bool wait_for_ok);
46#endif 46#endif
47 47
48#ifdef NO_GTK2_SUPPORT
49static inline void perf_gtk_setup_browser(int argc __used, const char *argv[] __used, bool fallback_to_pager)
50{
51 if (fallback_to_pager)
52 setup_pager();
53}
54static inline void perf_gtk_exit_browser(bool wait_for_ok __used) {}
55#else
56void perf_gtk_setup_browser(int argc, const char *argv[], bool fallback_to_pager);
57void perf_gtk_exit_browser(bool wait_for_ok);
58#endif
59
48char *alias_lookup(const char *alias); 60char *alias_lookup(const char *alias);
49int split_cmdline(char *cmdline, const char ***argv); 61int split_cmdline(char *cmdline, const char ***argv);
50 62
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 521c38a79190..11e46da17bbb 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -1,3 +1,4 @@
1#include <linux/kernel.h>
1#include "cache.h" 2#include "cache.h"
2#include "color.h" 3#include "color.h"
3 4
@@ -182,12 +183,12 @@ static int __color_vsnprintf(char *bf, size_t size, const char *color,
182 } 183 }
183 184
184 if (perf_use_color_default && *color) 185 if (perf_use_color_default && *color)
185 r += snprintf(bf, size, "%s", color); 186 r += scnprintf(bf, size, "%s", color);
186 r += vsnprintf(bf + r, size - r, fmt, args); 187 r += vscnprintf(bf + r, size - r, fmt, args);
187 if (perf_use_color_default && *color) 188 if (perf_use_color_default && *color)
188 r += snprintf(bf + r, size - r, "%s", PERF_COLOR_RESET); 189 r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
189 if (trail) 190 if (trail)
190 r += snprintf(bf + r, size - r, "%s", trail); 191 r += scnprintf(bf + r, size - r, "%s", trail);
191 return r; 192 return r;
192} 193}
193 194
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 6893eec693ab..adc72f09914d 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -166,6 +166,17 @@ out:
166 return cpus; 166 return cpus;
167} 167}
168 168
169size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
170{
171 int i;
172 size_t printed = fprintf(fp, "%d cpu%s: ",
173 map->nr, map->nr > 1 ? "s" : "");
174 for (i = 0; i < map->nr; ++i)
175 printed += fprintf(fp, "%s%d", i ? ", " : "", map->map[i]);
176
177 return printed + fprintf(fp, "\n");
178}
179
169struct cpu_map *cpu_map__dummy_new(void) 180struct cpu_map *cpu_map__dummy_new(void)
170{ 181{
171 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int)); 182 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 072c0a374794..c41518573c6a 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -1,6 +1,8 @@
1#ifndef __PERF_CPUMAP_H 1#ifndef __PERF_CPUMAP_H
2#define __PERF_CPUMAP_H 2#define __PERF_CPUMAP_H
3 3
4#include <stdio.h>
5
4struct cpu_map { 6struct cpu_map {
5 int nr; 7 int nr;
6 int map[]; 8 int map[];
@@ -10,4 +12,6 @@ struct cpu_map *cpu_map__new(const char *cpu_list);
10struct cpu_map *cpu_map__dummy_new(void); 12struct cpu_map *cpu_map__dummy_new(void);
11void cpu_map__delete(struct cpu_map *map); 13void cpu_map__delete(struct cpu_map *map);
12 14
15size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
16
13#endif /* __PERF_CPUMAP_H */ 17#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c
index 35073621e5de..aada3ac5e891 100644
--- a/tools/perf/util/ctype.c
+++ b/tools/perf/util/ctype.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * No surprises, and works with signed and unsigned chars. 4 * No surprises, and works with signed and unsigned chars.
5 */ 5 */
6#include "cache.h" 6#include "util.h"
7 7
8enum { 8enum {
9 S = GIT_SPACE, 9 S = GIT_SPACE,
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
index ffc35e748e89..dd8b19319c03 100644
--- a/tools/perf/util/debugfs.c
+++ b/tools/perf/util/debugfs.c
@@ -15,32 +15,6 @@ static const char *debugfs_known_mountpoints[] = {
15 0, 15 0,
16}; 16};
17 17
18/* use this to force a umount */
19void debugfs_force_cleanup(void)
20{
21 debugfs_find_mountpoint();
22 debugfs_premounted = 0;
23 debugfs_umount();
24}
25
26/* construct a full path to a debugfs element */
27int debugfs_make_path(const char *element, char *buffer, int size)
28{
29 int len;
30
31 if (strlen(debugfs_mountpoint) == 0) {
32 buffer[0] = '\0';
33 return -1;
34 }
35
36 len = strlen(debugfs_mountpoint) + strlen(element) + 1;
37 if (len >= size)
38 return len+1;
39
40 snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element);
41 return 0;
42}
43
44static int debugfs_found; 18static int debugfs_found;
45 19
46/* find the path to the mounted debugfs */ 20/* find the path to the mounted debugfs */
@@ -97,17 +71,6 @@ int debugfs_valid_mountpoint(const char *debugfs)
97 return 0; 71 return 0;
98} 72}
99 73
100
101int debugfs_valid_entry(const char *path)
102{
103 struct stat st;
104
105 if (stat(path, &st))
106 return -errno;
107
108 return 0;
109}
110
111static void debugfs_set_tracing_events_path(const char *mountpoint) 74static void debugfs_set_tracing_events_path(const char *mountpoint)
112{ 75{
113 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 76 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
@@ -149,107 +112,3 @@ void debugfs_set_path(const char *mountpoint)
149 snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint); 112 snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint);
150 debugfs_set_tracing_events_path(mountpoint); 113 debugfs_set_tracing_events_path(mountpoint);
151} 114}
152
153/* umount the debugfs */
154
155int debugfs_umount(void)
156{
157 char umountcmd[128];
158 int ret;
159
160 /* if it was already mounted, leave it */
161 if (debugfs_premounted)
162 return 0;
163
164 /* make sure it's a valid mount point */
165 ret = debugfs_valid_mountpoint(debugfs_mountpoint);
166 if (ret)
167 return ret;
168
169 snprintf(umountcmd, sizeof(umountcmd),
170 "/bin/umount %s", debugfs_mountpoint);
171 return system(umountcmd);
172}
173
174int debugfs_write(const char *entry, const char *value)
175{
176 char path[PATH_MAX + 1];
177 int ret, count;
178 int fd;
179
180 /* construct the path */
181 snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
182
183 /* verify that it exists */
184 ret = debugfs_valid_entry(path);
185 if (ret)
186 return ret;
187
188 /* get how many chars we're going to write */
189 count = strlen(value);
190
191 /* open the debugfs entry */
192 fd = open(path, O_RDWR);
193 if (fd < 0)
194 return -errno;
195
196 while (count > 0) {
197 /* write it */
198 ret = write(fd, value, count);
199 if (ret <= 0) {
200 if (ret == EAGAIN)
201 continue;
202 close(fd);
203 return -errno;
204 }
205 count -= ret;
206 }
207
208 /* close it */
209 close(fd);
210
211 /* return success */
212 return 0;
213}
214
215/*
216 * read a debugfs entry
217 * returns the number of chars read or a negative errno
218 */
219int debugfs_read(const char *entry, char *buffer, size_t size)
220{
221 char path[PATH_MAX + 1];
222 int ret;
223 int fd;
224
225 /* construct the path */
226 snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
227
228 /* verify that it exists */
229 ret = debugfs_valid_entry(path);
230 if (ret)
231 return ret;
232
233 /* open the debugfs entry */
234 fd = open(path, O_RDONLY);
235 if (fd < 0)
236 return -errno;
237
238 do {
239 /* read it */
240 ret = read(fd, buffer, size);
241 if (ret == 0) {
242 close(fd);
243 return EOF;
244 }
245 } while (ret < 0 && errno == EAGAIN);
246
247 /* close it */
248 close(fd);
249
250 /* make *sure* there's a null character at the end */
251 buffer[ret] = '\0';
252
253 /* return the number of chars read */
254 return ret;
255}
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
index 4a878f735eb0..68f3e87ec57f 100644
--- a/tools/perf/util/debugfs.h
+++ b/tools/perf/util/debugfs.h
@@ -3,14 +3,8 @@
3 3
4const char *debugfs_find_mountpoint(void); 4const char *debugfs_find_mountpoint(void);
5int debugfs_valid_mountpoint(const char *debugfs); 5int debugfs_valid_mountpoint(const char *debugfs);
6int debugfs_valid_entry(const char *path);
7char *debugfs_mount(const char *mountpoint); 6char *debugfs_mount(const char *mountpoint);
8int debugfs_umount(void);
9void debugfs_set_path(const char *mountpoint); 7void debugfs_set_path(const char *mountpoint);
10int debugfs_write(const char *entry, const char *value);
11int debugfs_read(const char *entry, char *buffer, size_t size);
12void debugfs_force_cleanup(void);
13int debugfs_make_path(const char *element, char *buffer, int size);
14 8
15extern char debugfs_mountpoint[]; 9extern char debugfs_mountpoint[];
16extern char tracing_events_path[]; 10extern char tracing_events_path[];
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 73ddaf06b8e7..2a6f33cd888c 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -74,6 +74,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
74 if (size >= len) 74 if (size >= len)
75 size = len - 1; 75 size = len - 1;
76 memcpy(comm, name, size); 76 memcpy(comm, name, size);
77 comm[size] = '\0';
77 78
78 } else if (memcmp(bf, "Tgid:", 5) == 0) { 79 } else if (memcmp(bf, "Tgid:", 5) == 0) {
79 char *tgids = bf + 5; 80 char *tgids = bf + 5;
@@ -554,7 +555,7 @@ static int perf_event__process_kernel_mmap(struct perf_tool *tool __used,
554 555
555 is_kernel_mmap = memcmp(event->mmap.filename, 556 is_kernel_mmap = memcmp(event->mmap.filename,
556 kmmap_prefix, 557 kmmap_prefix,
557 strlen(kmmap_prefix)) == 0; 558 strlen(kmmap_prefix) - 1) == 0;
558 if (event->mmap.filename[0] == '/' || 559 if (event->mmap.filename[0] == '/' ||
559 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 560 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
560 561
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index cbdeaad9c5e5..1b197280c621 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -81,6 +81,7 @@ struct perf_sample {
81 u32 raw_size; 81 u32 raw_size;
82 void *raw_data; 82 void *raw_data;
83 struct ip_callchain *callchain; 83 struct ip_callchain *callchain;
84 struct branch_stack *branch_stack;
84}; 85};
85 86
86#define BUILD_ID_SIZE 20 87#define BUILD_ID_SIZE 20
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index fa1837088ca8..1986d8051bd1 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -51,13 +51,15 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
51void perf_evlist__config_attrs(struct perf_evlist *evlist, 51void perf_evlist__config_attrs(struct perf_evlist *evlist,
52 struct perf_record_opts *opts) 52 struct perf_record_opts *opts)
53{ 53{
54 struct perf_evsel *evsel; 54 struct perf_evsel *evsel, *first;
55 55
56 if (evlist->cpus->map[0] < 0) 56 if (evlist->cpus->map[0] < 0)
57 opts->no_inherit = true; 57 opts->no_inherit = true;
58 58
59 first = list_entry(evlist->entries.next, struct perf_evsel, node);
60
59 list_for_each_entry(evsel, &evlist->entries, node) { 61 list_for_each_entry(evsel, &evlist->entries, node) {
60 perf_evsel__config(evsel, opts); 62 perf_evsel__config(evsel, opts, first);
61 63
62 if (evlist->nr_entries > 1) 64 if (evlist->nr_entries > 1)
63 evsel->attr.sample_type |= PERF_SAMPLE_ID; 65 evsel->attr.sample_type |= PERF_SAMPLE_ID;
@@ -97,9 +99,9 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
97 ++evlist->nr_entries; 99 ++evlist->nr_entries;
98} 100}
99 101
100static void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 102void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
101 struct list_head *list, 103 struct list_head *list,
102 int nr_entries) 104 int nr_entries)
103{ 105{
104 list_splice_tail(list, &evlist->entries); 106 list_splice_tail(list, &evlist->entries);
105 evlist->nr_entries += nr_entries; 107 evlist->nr_entries += nr_entries;
@@ -111,8 +113,11 @@ int perf_evlist__add_default(struct perf_evlist *evlist)
111 .type = PERF_TYPE_HARDWARE, 113 .type = PERF_TYPE_HARDWARE,
112 .config = PERF_COUNT_HW_CPU_CYCLES, 114 .config = PERF_COUNT_HW_CPU_CYCLES,
113 }; 115 };
114 struct perf_evsel *evsel = perf_evsel__new(&attr, 0); 116 struct perf_evsel *evsel;
115 117
118 event_attr_init(&attr);
119
120 evsel = perf_evsel__new(&attr, 0);
116 if (evsel == NULL) 121 if (evsel == NULL)
117 goto error; 122 goto error;
118 123
@@ -346,6 +351,10 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
346 hlist_for_each_entry(sid, pos, head, node) 351 hlist_for_each_entry(sid, pos, head, node)
347 if (sid->id == id) 352 if (sid->id == id)
348 return sid->evsel; 353 return sid->evsel;
354
355 if (!perf_evlist__sample_id_all(evlist))
356 return list_entry(evlist->entries.next, struct perf_evsel, node);
357
349 return NULL; 358 return NULL;
350} 359}
351 360
@@ -590,15 +599,15 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
590 return perf_evlist__mmap_per_cpu(evlist, prot, mask); 599 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
591} 600}
592 601
593int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, 602int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid,
594 pid_t target_tid, const char *cpu_list) 603 const char *target_tid, uid_t uid, const char *cpu_list)
595{ 604{
596 evlist->threads = thread_map__new(target_pid, target_tid); 605 evlist->threads = thread_map__new_str(target_pid, target_tid, uid);
597 606
598 if (evlist->threads == NULL) 607 if (evlist->threads == NULL)
599 return -1; 608 return -1;
600 609
601 if (cpu_list == NULL && target_tid != -1) 610 if (uid != UINT_MAX || (cpu_list == NULL && target_tid))
602 evlist->cpus = cpu_map__dummy_new(); 611 evlist->cpus = cpu_map__dummy_new();
603 else 612 else
604 evlist->cpus = cpu_map__new(cpu_list); 613 evlist->cpus = cpu_map__new(cpu_list);
@@ -758,6 +767,7 @@ out_err:
758 list_for_each_entry_reverse(evsel, &evlist->entries, node) 767 list_for_each_entry_reverse(evsel, &evlist->entries, node)
759 perf_evsel__close(evsel, ncpus, nthreads); 768 perf_evsel__close(evsel, ncpus, nthreads);
760 769
770 errno = -err;
761 return err; 771 return err;
762} 772}
763 773
@@ -817,7 +827,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
817 exit(-1); 827 exit(-1);
818 } 828 }
819 829
820 if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1) 830 if (!opts->system_wide && !opts->target_tid && !opts->target_pid)
821 evlist->threads->map[0] = evlist->workload.pid; 831 evlist->threads->map[0] = evlist->workload.pid;
822 832
823 close(child_ready_pipe[1]); 833 close(child_ready_pipe[1]);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 8922aeed0467..21f1c9e57f13 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -106,8 +106,8 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
106 evlist->threads = threads; 106 evlist->threads = threads;
107} 107}
108 108
109int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, 109int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid,
110 pid_t target_tid, const char *cpu_list); 110 const char *tid, uid_t uid, const char *cpu_list);
111void perf_evlist__delete_maps(struct perf_evlist *evlist); 111void perf_evlist__delete_maps(struct perf_evlist *evlist);
112int perf_evlist__set_filters(struct perf_evlist *evlist); 112int perf_evlist__set_filters(struct perf_evlist *evlist);
113 113
@@ -117,4 +117,9 @@ u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
117 117
118bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); 118bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
119bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); 119bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
120
121void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
122 struct list_head *list,
123 int nr_entries);
124
120#endif /* __PERF_EVLIST_H */ 125#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 667f3b78bb2c..8c13dbcb84b9 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -34,7 +34,7 @@ int __perf_evsel__sample_size(u64 sample_type)
34 return size; 34 return size;
35} 35}
36 36
37static void hists__init(struct hists *hists) 37void hists__init(struct hists *hists)
38{ 38{
39 memset(hists, 0, sizeof(*hists)); 39 memset(hists, 0, sizeof(*hists));
40 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; 40 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
@@ -63,12 +63,13 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
63 return evsel; 63 return evsel;
64} 64}
65 65
66void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts) 66void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
67 struct perf_evsel *first)
67{ 68{
68 struct perf_event_attr *attr = &evsel->attr; 69 struct perf_event_attr *attr = &evsel->attr;
69 int track = !evsel->idx; /* only the first counter needs these */ 70 int track = !evsel->idx; /* only the first counter needs these */
70 71
71 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0; 72 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
72 attr->inherit = !opts->no_inherit; 73 attr->inherit = !opts->no_inherit;
73 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 74 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
74 PERF_FORMAT_TOTAL_TIME_RUNNING | 75 PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -111,7 +112,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
111 if (opts->period) 112 if (opts->period)
112 attr->sample_type |= PERF_SAMPLE_PERIOD; 113 attr->sample_type |= PERF_SAMPLE_PERIOD;
113 114
114 if (opts->sample_id_all_avail && 115 if (!opts->sample_id_all_missing &&
115 (opts->sample_time || opts->system_wide || 116 (opts->sample_time || opts->system_wide ||
116 !opts->no_inherit || opts->cpu_list)) 117 !opts->no_inherit || opts->cpu_list))
117 attr->sample_type |= PERF_SAMPLE_TIME; 118 attr->sample_type |= PERF_SAMPLE_TIME;
@@ -126,11 +127,16 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
126 attr->watermark = 0; 127 attr->watermark = 0;
127 attr->wakeup_events = 1; 128 attr->wakeup_events = 1;
128 } 129 }
130 if (opts->branch_stack) {
131 attr->sample_type |= PERF_SAMPLE_BRANCH_STACK;
132 attr->branch_sample_type = opts->branch_stack;
133 }
129 134
130 attr->mmap = track; 135 attr->mmap = track;
131 attr->comm = track; 136 attr->comm = track;
132 137
133 if (opts->target_pid == -1 && opts->target_tid == -1 && !opts->system_wide) { 138 if (!opts->target_pid && !opts->target_tid && !opts->system_wide &&
139 (!opts->group || evsel == first)) {
134 attr->disabled = 1; 140 attr->disabled = 1;
135 attr->enable_on_exec = 1; 141 attr->enable_on_exec = 1;
136 } 142 }
@@ -463,6 +469,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
463 memset(data, 0, sizeof(*data)); 469 memset(data, 0, sizeof(*data));
464 data->cpu = data->pid = data->tid = -1; 470 data->cpu = data->pid = data->tid = -1;
465 data->stream_id = data->id = data->time = -1ULL; 471 data->stream_id = data->id = data->time = -1ULL;
472 data->period = 1;
466 473
467 if (event->header.type != PERF_RECORD_SAMPLE) { 474 if (event->header.type != PERF_RECORD_SAMPLE) {
468 if (!sample_id_all) 475 if (!sample_id_all)
@@ -535,7 +542,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
535 } 542 }
536 543
537 if (type & PERF_SAMPLE_READ) { 544 if (type & PERF_SAMPLE_READ) {
538 fprintf(stderr, "PERF_SAMPLE_READ is unsuported for now\n"); 545 fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n");
539 return -1; 546 return -1;
540 } 547 }
541 548
@@ -573,8 +580,20 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
573 return -EFAULT; 580 return -EFAULT;
574 581
575 data->raw_data = (void *) pdata; 582 data->raw_data = (void *) pdata;
583
584 array = (void *)array + data->raw_size + sizeof(u32);
576 } 585 }
577 586
587 if (type & PERF_SAMPLE_BRANCH_STACK) {
588 u64 sz;
589
590 data->branch_stack = (struct branch_stack *)array;
591 array++; /* nr */
592
593 sz = data->branch_stack->nr * sizeof(struct branch_entry);
594 sz /= sizeof(u64);
595 array += sz;
596 }
578 return 0; 597 return 0;
579} 598}
580 599
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 326b8e4d5035..3d6b3e4cb66b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -80,7 +80,8 @@ void perf_evsel__exit(struct perf_evsel *evsel);
80void perf_evsel__delete(struct perf_evsel *evsel); 80void perf_evsel__delete(struct perf_evsel *evsel);
81 81
82void perf_evsel__config(struct perf_evsel *evsel, 82void perf_evsel__config(struct perf_evsel *evsel,
83 struct perf_record_opts *opts); 83 struct perf_record_opts *opts,
84 struct perf_evsel *first);
84 85
85int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 86int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
86int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 87int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
@@ -169,4 +170,6 @@ static inline int perf_evsel__sample_size(struct perf_evsel *evsel)
169 return __perf_evsel__sample_size(evsel->attr.sample_type); 170 return __perf_evsel__sample_size(evsel->attr.sample_type);
170} 171}
171 172
173void hists__init(struct hists *hists);
174
172#endif /* __PERF_EVSEL_H */ 175#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/gtk/browser.c b/tools/perf/util/gtk/browser.c
new file mode 100644
index 000000000000..258352a2356c
--- /dev/null
+++ b/tools/perf/util/gtk/browser.c
@@ -0,0 +1,189 @@
1#include "../evlist.h"
2#include "../cache.h"
3#include "../evsel.h"
4#include "../sort.h"
5#include "../hist.h"
6#include "gtk.h"
7
8#include <signal.h>
9
10#define MAX_COLUMNS 32
11
12void perf_gtk_setup_browser(int argc, const char *argv[],
13 bool fallback_to_pager __used)
14{
15 gtk_init(&argc, (char ***)&argv);
16}
17
18void perf_gtk_exit_browser(bool wait_for_ok __used)
19{
20 gtk_main_quit();
21}
22
23static void perf_gtk_signal(int sig)
24{
25 psignal(sig, "perf");
26 gtk_main_quit();
27}
28
29static void perf_gtk_resize_window(GtkWidget *window)
30{
31 GdkRectangle rect;
32 GdkScreen *screen;
33 int monitor;
34 int height;
35 int width;
36
37 screen = gtk_widget_get_screen(window);
38
39 monitor = gdk_screen_get_monitor_at_window(screen, window->window);
40
41 gdk_screen_get_monitor_geometry(screen, monitor, &rect);
42
43 width = rect.width * 3 / 4;
44 height = rect.height * 3 / 4;
45
46 gtk_window_resize(GTK_WINDOW(window), width, height);
47}
48
49static void perf_gtk_show_hists(GtkWidget *window, struct hists *hists)
50{
51 GType col_types[MAX_COLUMNS];
52 GtkCellRenderer *renderer;
53 struct sort_entry *se;
54 GtkListStore *store;
55 struct rb_node *nd;
56 u64 total_period;
57 GtkWidget *view;
58 int col_idx;
59 int nr_cols;
60
61 nr_cols = 0;
62
63 /* The percentage column */
64 col_types[nr_cols++] = G_TYPE_STRING;
65
66 list_for_each_entry(se, &hist_entry__sort_list, list) {
67 if (se->elide)
68 continue;
69
70 col_types[nr_cols++] = G_TYPE_STRING;
71 }
72
73 store = gtk_list_store_newv(nr_cols, col_types);
74
75 view = gtk_tree_view_new();
76
77 renderer = gtk_cell_renderer_text_new();
78
79 col_idx = 0;
80
81 /* The percentage column */
82 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
83 -1, "Overhead (%)",
84 renderer, "text",
85 col_idx++, NULL);
86
87 list_for_each_entry(se, &hist_entry__sort_list, list) {
88 if (se->elide)
89 continue;
90
91 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
92 -1, se->se_header,
93 renderer, "text",
94 col_idx++, NULL);
95 }
96
97 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
98
99 g_object_unref(GTK_TREE_MODEL(store));
100
101 total_period = hists->stats.total_period;
102
103 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
104 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
105 GtkTreeIter iter;
106 double percent;
107 char s[512];
108
109 if (h->filtered)
110 continue;
111
112 gtk_list_store_append(store, &iter);
113
114 col_idx = 0;
115
116 percent = (h->period * 100.0) / total_period;
117
118 snprintf(s, ARRAY_SIZE(s), "%.2f", percent);
119
120 gtk_list_store_set(store, &iter, col_idx++, s, -1);
121
122 list_for_each_entry(se, &hist_entry__sort_list, list) {
123 if (se->elide)
124 continue;
125
126 se->se_snprintf(h, s, ARRAY_SIZE(s),
127 hists__col_len(hists, se->se_width_idx));
128
129 gtk_list_store_set(store, &iter, col_idx++, s, -1);
130 }
131 }
132
133 gtk_container_add(GTK_CONTAINER(window), view);
134}
135
136int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
137 const char *help __used,
138 void (*timer) (void *arg)__used,
139 void *arg __used, int delay_secs __used)
140{
141 struct perf_evsel *pos;
142 GtkWidget *notebook;
143 GtkWidget *window;
144
145 signal(SIGSEGV, perf_gtk_signal);
146 signal(SIGFPE, perf_gtk_signal);
147 signal(SIGINT, perf_gtk_signal);
148 signal(SIGQUIT, perf_gtk_signal);
149 signal(SIGTERM, perf_gtk_signal);
150
151 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
152
153 gtk_window_set_title(GTK_WINDOW(window), "perf report");
154
155 g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
156
157 notebook = gtk_notebook_new();
158
159 list_for_each_entry(pos, &evlist->entries, node) {
160 struct hists *hists = &pos->hists;
161 const char *evname = event_name(pos);
162 GtkWidget *scrolled_window;
163 GtkWidget *tab_label;
164
165 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
166
167 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
168 GTK_POLICY_AUTOMATIC,
169 GTK_POLICY_AUTOMATIC);
170
171 perf_gtk_show_hists(scrolled_window, hists);
172
173 tab_label = gtk_label_new(evname);
174
175 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
176 }
177
178 gtk_container_add(GTK_CONTAINER(window), notebook);
179
180 gtk_widget_show_all(window);
181
182 perf_gtk_resize_window(window);
183
184 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
185
186 gtk_main();
187
188 return 0;
189}
diff --git a/tools/perf/util/gtk/gtk.h b/tools/perf/util/gtk/gtk.h
new file mode 100644
index 000000000000..75177ee04032
--- /dev/null
+++ b/tools/perf/util/gtk/gtk.h
@@ -0,0 +1,8 @@
1#ifndef _PERF_GTK_H_
2#define _PERF_GTK_H_ 1
3
4#pragma GCC diagnostic ignored "-Wstrict-prototypes"
5#include <gtk/gtk.h>
6#pragma GCC diagnostic error "-Wstrict-prototypes"
7
8#endif /* _PERF_GTK_H_ */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3e7e0b09c12c..4c7c2d73251f 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -63,9 +63,20 @@ char *perf_header__find_event(u64 id)
63 return NULL; 63 return NULL;
64} 64}
65 65
66static const char *__perf_magic = "PERFFILE"; 66/*
67 * magic2 = "PERFILE2"
68 * must be a numerical value to let the endianness
69 * determine the memory layout. That way we are able
70 * to detect endianness when reading the perf.data file
71 * back.
72 *
73 * we check for legacy (PERFFILE) format.
74 */
75static const char *__perf_magic1 = "PERFFILE";
76static const u64 __perf_magic2 = 0x32454c4946524550ULL;
77static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;
67 78
68#define PERF_MAGIC (*(u64 *)__perf_magic) 79#define PERF_MAGIC __perf_magic2
69 80
70struct perf_file_attr { 81struct perf_file_attr {
71 struct perf_event_attr attr; 82 struct perf_event_attr attr;
@@ -280,7 +291,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
280 if (realname == NULL || filename == NULL || linkname == NULL) 291 if (realname == NULL || filename == NULL || linkname == NULL)
281 goto out_free; 292 goto out_free;
282 293
283 len = snprintf(filename, size, "%s%s%s", 294 len = scnprintf(filename, size, "%s%s%s",
284 debugdir, is_kallsyms ? "/" : "", realname); 295 debugdir, is_kallsyms ? "/" : "", realname);
285 if (mkdir_p(filename, 0755)) 296 if (mkdir_p(filename, 0755))
286 goto out_free; 297 goto out_free;
@@ -295,7 +306,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
295 goto out_free; 306 goto out_free;
296 } 307 }
297 308
298 len = snprintf(linkname, size, "%s/.build-id/%.2s", 309 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
299 debugdir, sbuild_id); 310 debugdir, sbuild_id);
300 311
301 if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) 312 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
@@ -1012,6 +1023,12 @@ write_it:
1012 return do_write_string(fd, buffer); 1023 return do_write_string(fd, buffer);
1013} 1024}
1014 1025
1026static int write_branch_stack(int fd __used, struct perf_header *h __used,
1027 struct perf_evlist *evlist __used)
1028{
1029 return 0;
1030}
1031
1015static void print_hostname(struct perf_header *ph, int fd, FILE *fp) 1032static void print_hostname(struct perf_header *ph, int fd, FILE *fp)
1016{ 1033{
1017 char *str = do_read_string(fd, ph); 1034 char *str = do_read_string(fd, ph);
@@ -1133,8 +1150,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1133 uint64_t id; 1150 uint64_t id;
1134 void *buf = NULL; 1151 void *buf = NULL;
1135 char *str; 1152 char *str;
1136 u32 nre, sz, nr, i, j, msz; 1153 u32 nre, sz, nr, i, j;
1137 int ret; 1154 ssize_t ret;
1155 size_t msz;
1138 1156
1139 /* number of events */ 1157 /* number of events */
1140 ret = read(fd, &nre, sizeof(nre)); 1158 ret = read(fd, &nre, sizeof(nre));
@@ -1151,15 +1169,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1151 if (ph->needs_swap) 1169 if (ph->needs_swap)
1152 sz = bswap_32(sz); 1170 sz = bswap_32(sz);
1153 1171
1154 /*
1155 * ensure it is at least to our ABI rev
1156 */
1157 if (sz < (u32)sizeof(attr))
1158 goto error;
1159
1160 memset(&attr, 0, sizeof(attr)); 1172 memset(&attr, 0, sizeof(attr));
1161 1173
1162 /* read entire region to sync up to next field */ 1174 /* buffer to hold on file attr struct */
1163 buf = malloc(sz); 1175 buf = malloc(sz);
1164 if (!buf) 1176 if (!buf)
1165 goto error; 1177 goto error;
@@ -1170,6 +1182,10 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1170 1182
1171 for (i = 0 ; i < nre; i++) { 1183 for (i = 0 ; i < nre; i++) {
1172 1184
1185 /*
1186 * must read entire on-file attr struct to
1187 * sync up with layout.
1188 */
1173 ret = read(fd, buf, sz); 1189 ret = read(fd, buf, sz);
1174 if (ret != (ssize_t)sz) 1190 if (ret != (ssize_t)sz)
1175 goto error; 1191 goto error;
@@ -1305,25 +1321,204 @@ static void print_cpuid(struct perf_header *ph, int fd, FILE *fp)
1305 free(str); 1321 free(str);
1306} 1322}
1307 1323
1324static void print_branch_stack(struct perf_header *ph __used, int fd __used,
1325 FILE *fp)
1326{
1327 fprintf(fp, "# contains samples with branch stack\n");
1328}
1329
1330static int __event_process_build_id(struct build_id_event *bev,
1331 char *filename,
1332 struct perf_session *session)
1333{
1334 int err = -1;
1335 struct list_head *head;
1336 struct machine *machine;
1337 u16 misc;
1338 struct dso *dso;
1339 enum dso_kernel_type dso_type;
1340
1341 machine = perf_session__findnew_machine(session, bev->pid);
1342 if (!machine)
1343 goto out;
1344
1345 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1346
1347 switch (misc) {
1348 case PERF_RECORD_MISC_KERNEL:
1349 dso_type = DSO_TYPE_KERNEL;
1350 head = &machine->kernel_dsos;
1351 break;
1352 case PERF_RECORD_MISC_GUEST_KERNEL:
1353 dso_type = DSO_TYPE_GUEST_KERNEL;
1354 head = &machine->kernel_dsos;
1355 break;
1356 case PERF_RECORD_MISC_USER:
1357 case PERF_RECORD_MISC_GUEST_USER:
1358 dso_type = DSO_TYPE_USER;
1359 head = &machine->user_dsos;
1360 break;
1361 default:
1362 goto out;
1363 }
1364
1365 dso = __dsos__findnew(head, filename);
1366 if (dso != NULL) {
1367 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1368
1369 dso__set_build_id(dso, &bev->build_id);
1370
1371 if (filename[0] == '[')
1372 dso->kernel = dso_type;
1373
1374 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1375 sbuild_id);
1376 pr_debug("build id event received for %s: %s\n",
1377 dso->long_name, sbuild_id);
1378 }
1379
1380 err = 0;
1381out:
1382 return err;
1383}
1384
1385static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1386 int input, u64 offset, u64 size)
1387{
1388 struct perf_session *session = container_of(header, struct perf_session, header);
1389 struct {
1390 struct perf_event_header header;
1391 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
1392 char filename[0];
1393 } old_bev;
1394 struct build_id_event bev;
1395 char filename[PATH_MAX];
1396 u64 limit = offset + size;
1397
1398 while (offset < limit) {
1399 ssize_t len;
1400
1401 if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
1402 return -1;
1403
1404 if (header->needs_swap)
1405 perf_event_header__bswap(&old_bev.header);
1406
1407 len = old_bev.header.size - sizeof(old_bev);
1408 if (read(input, filename, len) != len)
1409 return -1;
1410
1411 bev.header = old_bev.header;
1412
1413 /*
1414 * As the pid is the missing value, we need to fill
1415 * it properly. The header.misc value give us nice hint.
1416 */
1417 bev.pid = HOST_KERNEL_ID;
1418 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1419 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1420 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1421
1422 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
1423 __event_process_build_id(&bev, filename, session);
1424
1425 offset += bev.header.size;
1426 }
1427
1428 return 0;
1429}
1430
1431static int perf_header__read_build_ids(struct perf_header *header,
1432 int input, u64 offset, u64 size)
1433{
1434 struct perf_session *session = container_of(header, struct perf_session, header);
1435 struct build_id_event bev;
1436 char filename[PATH_MAX];
1437 u64 limit = offset + size, orig_offset = offset;
1438 int err = -1;
1439
1440 while (offset < limit) {
1441 ssize_t len;
1442
1443 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
1444 goto out;
1445
1446 if (header->needs_swap)
1447 perf_event_header__bswap(&bev.header);
1448
1449 len = bev.header.size - sizeof(bev);
1450 if (read(input, filename, len) != len)
1451 goto out;
1452 /*
1453 * The a1645ce1 changeset:
1454 *
1455 * "perf: 'perf kvm' tool for monitoring guest performance from host"
1456 *
1457 * Added a field to struct build_id_event that broke the file
1458 * format.
1459 *
1460 * Since the kernel build-id is the first entry, process the
1461 * table using the old format if the well known
1462 * '[kernel.kallsyms]' string for the kernel build-id has the
1463 * first 4 characters chopped off (where the pid_t sits).
1464 */
1465 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
1466 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
1467 return -1;
1468 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
1469 }
1470
1471 __event_process_build_id(&bev, filename, session);
1472
1473 offset += bev.header.size;
1474 }
1475 err = 0;
1476out:
1477 return err;
1478}
1479
1480static int process_trace_info(struct perf_file_section *section __unused,
1481 struct perf_header *ph __unused,
1482 int feat __unused, int fd)
1483{
1484 trace_report(fd, false);
1485 return 0;
1486}
1487
1488static int process_build_id(struct perf_file_section *section,
1489 struct perf_header *ph,
1490 int feat __unused, int fd)
1491{
1492 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1493 pr_debug("Failed to read buildids, continuing...\n");
1494 return 0;
1495}
1496
1308struct feature_ops { 1497struct feature_ops {
1309 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1498 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1310 void (*print)(struct perf_header *h, int fd, FILE *fp); 1499 void (*print)(struct perf_header *h, int fd, FILE *fp);
1500 int (*process)(struct perf_file_section *section,
1501 struct perf_header *h, int feat, int fd);
1311 const char *name; 1502 const char *name;
1312 bool full_only; 1503 bool full_only;
1313}; 1504};
1314 1505
1315#define FEAT_OPA(n, func) \ 1506#define FEAT_OPA(n, func) \
1316 [n] = { .name = #n, .write = write_##func, .print = print_##func } 1507 [n] = { .name = #n, .write = write_##func, .print = print_##func }
1508#define FEAT_OPP(n, func) \
1509 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
1510 .process = process_##func }
1317#define FEAT_OPF(n, func) \ 1511#define FEAT_OPF(n, func) \
1318 [n] = { .name = #n, .write = write_##func, .print = print_##func, .full_only = true } 1512 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
1513 .full_only = true }
1319 1514
1320/* feature_ops not implemented: */ 1515/* feature_ops not implemented: */
1321#define print_trace_info NULL 1516#define print_trace_info NULL
1322#define print_build_id NULL 1517#define print_build_id NULL
1323 1518
1324static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { 1519static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1325 FEAT_OPA(HEADER_TRACE_INFO, trace_info), 1520 FEAT_OPP(HEADER_TRACE_INFO, trace_info),
1326 FEAT_OPA(HEADER_BUILD_ID, build_id), 1521 FEAT_OPP(HEADER_BUILD_ID, build_id),
1327 FEAT_OPA(HEADER_HOSTNAME, hostname), 1522 FEAT_OPA(HEADER_HOSTNAME, hostname),
1328 FEAT_OPA(HEADER_OSRELEASE, osrelease), 1523 FEAT_OPA(HEADER_OSRELEASE, osrelease),
1329 FEAT_OPA(HEADER_VERSION, version), 1524 FEAT_OPA(HEADER_VERSION, version),
@@ -1336,6 +1531,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1336 FEAT_OPA(HEADER_CMDLINE, cmdline), 1531 FEAT_OPA(HEADER_CMDLINE, cmdline),
1337 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), 1532 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
1338 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), 1533 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
1534 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
1339}; 1535};
1340 1536
1341struct header_print_data { 1537struct header_print_data {
@@ -1620,24 +1816,128 @@ out_free:
1620 return err; 1816 return err;
1621} 1817}
1622 1818
1819static const int attr_file_abi_sizes[] = {
1820 [0] = PERF_ATTR_SIZE_VER0,
1821 [1] = PERF_ATTR_SIZE_VER1,
1822 0,
1823};
1824
1825/*
1826 * In the legacy file format, the magic number is not used to encode endianness.
1827 * hdr_sz was used to encode endianness. But given that hdr_sz can vary based
1828 * on ABI revisions, we need to try all combinations for all endianness to
1829 * detect the endianness.
1830 */
1831static int try_all_file_abis(uint64_t hdr_sz, struct perf_header *ph)
1832{
1833 uint64_t ref_size, attr_size;
1834 int i;
1835
1836 for (i = 0 ; attr_file_abi_sizes[i]; i++) {
1837 ref_size = attr_file_abi_sizes[i]
1838 + sizeof(struct perf_file_section);
1839 if (hdr_sz != ref_size) {
1840 attr_size = bswap_64(hdr_sz);
1841 if (attr_size != ref_size)
1842 continue;
1843
1844 ph->needs_swap = true;
1845 }
1846 pr_debug("ABI%d perf.data file detected, need_swap=%d\n",
1847 i,
1848 ph->needs_swap);
1849 return 0;
1850 }
1851 /* could not determine endianness */
1852 return -1;
1853}
1854
1855#define PERF_PIPE_HDR_VER0 16
1856
1857static const size_t attr_pipe_abi_sizes[] = {
1858 [0] = PERF_PIPE_HDR_VER0,
1859 0,
1860};
1861
1862/*
1863 * In the legacy pipe format, there is an implicit assumption that endiannesss
1864 * between host recording the samples, and host parsing the samples is the
1865 * same. This is not always the case given that the pipe output may always be
1866 * redirected into a file and analyzed on a different machine with possibly a
1867 * different endianness and perf_event ABI revsions in the perf tool itself.
1868 */
1869static int try_all_pipe_abis(uint64_t hdr_sz, struct perf_header *ph)
1870{
1871 u64 attr_size;
1872 int i;
1873
1874 for (i = 0 ; attr_pipe_abi_sizes[i]; i++) {
1875 if (hdr_sz != attr_pipe_abi_sizes[i]) {
1876 attr_size = bswap_64(hdr_sz);
1877 if (attr_size != hdr_sz)
1878 continue;
1879
1880 ph->needs_swap = true;
1881 }
1882 pr_debug("Pipe ABI%d perf.data file detected\n", i);
1883 return 0;
1884 }
1885 return -1;
1886}
1887
1888static int check_magic_endian(u64 magic, uint64_t hdr_sz,
1889 bool is_pipe, struct perf_header *ph)
1890{
1891 int ret;
1892
1893 /* check for legacy format */
1894 ret = memcmp(&magic, __perf_magic1, sizeof(magic));
1895 if (ret == 0) {
1896 pr_debug("legacy perf.data format\n");
1897 if (is_pipe)
1898 return try_all_pipe_abis(hdr_sz, ph);
1899
1900 return try_all_file_abis(hdr_sz, ph);
1901 }
1902 /*
1903 * the new magic number serves two purposes:
1904 * - unique number to identify actual perf.data files
1905 * - encode endianness of file
1906 */
1907
1908 /* check magic number with one endianness */
1909 if (magic == __perf_magic2)
1910 return 0;
1911
1912 /* check magic number with opposite endianness */
1913 if (magic != __perf_magic2_sw)
1914 return -1;
1915
1916 ph->needs_swap = true;
1917
1918 return 0;
1919}
1920
1623int perf_file_header__read(struct perf_file_header *header, 1921int perf_file_header__read(struct perf_file_header *header,
1624 struct perf_header *ph, int fd) 1922 struct perf_header *ph, int fd)
1625{ 1923{
1924 int ret;
1925
1626 lseek(fd, 0, SEEK_SET); 1926 lseek(fd, 0, SEEK_SET);
1627 1927
1628 if (readn(fd, header, sizeof(*header)) <= 0 || 1928 ret = readn(fd, header, sizeof(*header));
1629 memcmp(&header->magic, __perf_magic, sizeof(header->magic))) 1929 if (ret <= 0)
1630 return -1; 1930 return -1;
1631 1931
1632 if (header->attr_size != sizeof(struct perf_file_attr)) { 1932 if (check_magic_endian(header->magic,
1633 u64 attr_size = bswap_64(header->attr_size); 1933 header->attr_size, false, ph) < 0) {
1634 1934 pr_debug("magic/endian check failed\n");
1635 if (attr_size != sizeof(struct perf_file_attr)) 1935 return -1;
1636 return -1; 1936 }
1637 1937
1938 if (ph->needs_swap) {
1638 mem_bswap_64(header, offsetof(struct perf_file_header, 1939 mem_bswap_64(header, offsetof(struct perf_file_header,
1639 adds_features)); 1940 adds_features));
1640 ph->needs_swap = true;
1641 } 1941 }
1642 1942
1643 if (header->size != sizeof(*header)) { 1943 if (header->size != sizeof(*header)) {
@@ -1689,156 +1989,6 @@ int perf_file_header__read(struct perf_file_header *header,
1689 return 0; 1989 return 0;
1690} 1990}
1691 1991
1692static int __event_process_build_id(struct build_id_event *bev,
1693 char *filename,
1694 struct perf_session *session)
1695{
1696 int err = -1;
1697 struct list_head *head;
1698 struct machine *machine;
1699 u16 misc;
1700 struct dso *dso;
1701 enum dso_kernel_type dso_type;
1702
1703 machine = perf_session__findnew_machine(session, bev->pid);
1704 if (!machine)
1705 goto out;
1706
1707 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1708
1709 switch (misc) {
1710 case PERF_RECORD_MISC_KERNEL:
1711 dso_type = DSO_TYPE_KERNEL;
1712 head = &machine->kernel_dsos;
1713 break;
1714 case PERF_RECORD_MISC_GUEST_KERNEL:
1715 dso_type = DSO_TYPE_GUEST_KERNEL;
1716 head = &machine->kernel_dsos;
1717 break;
1718 case PERF_RECORD_MISC_USER:
1719 case PERF_RECORD_MISC_GUEST_USER:
1720 dso_type = DSO_TYPE_USER;
1721 head = &machine->user_dsos;
1722 break;
1723 default:
1724 goto out;
1725 }
1726
1727 dso = __dsos__findnew(head, filename);
1728 if (dso != NULL) {
1729 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1730
1731 dso__set_build_id(dso, &bev->build_id);
1732
1733 if (filename[0] == '[')
1734 dso->kernel = dso_type;
1735
1736 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1737 sbuild_id);
1738 pr_debug("build id event received for %s: %s\n",
1739 dso->long_name, sbuild_id);
1740 }
1741
1742 err = 0;
1743out:
1744 return err;
1745}
1746
1747static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1748 int input, u64 offset, u64 size)
1749{
1750 struct perf_session *session = container_of(header, struct perf_session, header);
1751 struct {
1752 struct perf_event_header header;
1753 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
1754 char filename[0];
1755 } old_bev;
1756 struct build_id_event bev;
1757 char filename[PATH_MAX];
1758 u64 limit = offset + size;
1759
1760 while (offset < limit) {
1761 ssize_t len;
1762
1763 if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
1764 return -1;
1765
1766 if (header->needs_swap)
1767 perf_event_header__bswap(&old_bev.header);
1768
1769 len = old_bev.header.size - sizeof(old_bev);
1770 if (read(input, filename, len) != len)
1771 return -1;
1772
1773 bev.header = old_bev.header;
1774
1775 /*
1776 * As the pid is the missing value, we need to fill
1777 * it properly. The header.misc value give us nice hint.
1778 */
1779 bev.pid = HOST_KERNEL_ID;
1780 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1781 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1782 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1783
1784 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
1785 __event_process_build_id(&bev, filename, session);
1786
1787 offset += bev.header.size;
1788 }
1789
1790 return 0;
1791}
1792
1793static int perf_header__read_build_ids(struct perf_header *header,
1794 int input, u64 offset, u64 size)
1795{
1796 struct perf_session *session = container_of(header, struct perf_session, header);
1797 struct build_id_event bev;
1798 char filename[PATH_MAX];
1799 u64 limit = offset + size, orig_offset = offset;
1800 int err = -1;
1801
1802 while (offset < limit) {
1803 ssize_t len;
1804
1805 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
1806 goto out;
1807
1808 if (header->needs_swap)
1809 perf_event_header__bswap(&bev.header);
1810
1811 len = bev.header.size - sizeof(bev);
1812 if (read(input, filename, len) != len)
1813 goto out;
1814 /*
1815 * The a1645ce1 changeset:
1816 *
1817 * "perf: 'perf kvm' tool for monitoring guest performance from host"
1818 *
1819 * Added a field to struct build_id_event that broke the file
1820 * format.
1821 *
1822 * Since the kernel build-id is the first entry, process the
1823 * table using the old format if the well known
1824 * '[kernel.kallsyms]' string for the kernel build-id has the
1825 * first 4 characters chopped off (where the pid_t sits).
1826 */
1827 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
1828 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
1829 return -1;
1830 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
1831 }
1832
1833 __event_process_build_id(&bev, filename, session);
1834
1835 offset += bev.header.size;
1836 }
1837 err = 0;
1838out:
1839 return err;
1840}
1841
1842static int perf_file_section__process(struct perf_file_section *section, 1992static int perf_file_section__process(struct perf_file_section *section,
1843 struct perf_header *ph, 1993 struct perf_header *ph,
1844 int feat, int fd, void *data __used) 1994 int feat, int fd, void *data __used)
@@ -1854,40 +2004,32 @@ static int perf_file_section__process(struct perf_file_section *section,
1854 return 0; 2004 return 0;
1855 } 2005 }
1856 2006
1857 switch (feat) { 2007 if (!feat_ops[feat].process)
1858 case HEADER_TRACE_INFO: 2008 return 0;
1859 trace_report(fd, false);
1860 break;
1861 case HEADER_BUILD_ID:
1862 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1863 pr_debug("Failed to read buildids, continuing...\n");
1864 break;
1865 default:
1866 break;
1867 }
1868 2009
1869 return 0; 2010 return feat_ops[feat].process(section, ph, feat, fd);
1870} 2011}
1871 2012
1872static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 2013static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
1873 struct perf_header *ph, int fd, 2014 struct perf_header *ph, int fd,
1874 bool repipe) 2015 bool repipe)
1875{ 2016{
1876 if (readn(fd, header, sizeof(*header)) <= 0 || 2017 int ret;
1877 memcmp(&header->magic, __perf_magic, sizeof(header->magic)))
1878 return -1;
1879 2018
1880 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0) 2019 ret = readn(fd, header, sizeof(*header));
2020 if (ret <= 0)
1881 return -1; 2021 return -1;
1882 2022
1883 if (header->size != sizeof(*header)) { 2023 if (check_magic_endian(header->magic, header->size, true, ph) < 0) {
1884 u64 size = bswap_64(header->size); 2024 pr_debug("endian/magic failed\n");
2025 return -1;
2026 }
1885 2027
1886 if (size != sizeof(*header)) 2028 if (ph->needs_swap)
1887 return -1; 2029 header->size = bswap_64(header->size);
1888 2030
1889 ph->needs_swap = true; 2031 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0)
1890 } 2032 return -1;
1891 2033
1892 return 0; 2034 return 0;
1893} 2035}
@@ -1908,6 +2050,52 @@ static int perf_header__read_pipe(struct perf_session *session, int fd)
1908 return 0; 2050 return 0;
1909} 2051}
1910 2052
2053static int read_attr(int fd, struct perf_header *ph,
2054 struct perf_file_attr *f_attr)
2055{
2056 struct perf_event_attr *attr = &f_attr->attr;
2057 size_t sz, left;
2058 size_t our_sz = sizeof(f_attr->attr);
2059 int ret;
2060
2061 memset(f_attr, 0, sizeof(*f_attr));
2062
2063 /* read minimal guaranteed structure */
2064 ret = readn(fd, attr, PERF_ATTR_SIZE_VER0);
2065 if (ret <= 0) {
2066 pr_debug("cannot read %d bytes of header attr\n",
2067 PERF_ATTR_SIZE_VER0);
2068 return -1;
2069 }
2070
2071 /* on file perf_event_attr size */
2072 sz = attr->size;
2073
2074 if (ph->needs_swap)
2075 sz = bswap_32(sz);
2076
2077 if (sz == 0) {
2078 /* assume ABI0 */
2079 sz = PERF_ATTR_SIZE_VER0;
2080 } else if (sz > our_sz) {
2081 pr_debug("file uses a more recent and unsupported ABI"
2082 " (%zu bytes extra)\n", sz - our_sz);
2083 return -1;
2084 }
2085 /* what we have not yet read and that we know about */
2086 left = sz - PERF_ATTR_SIZE_VER0;
2087 if (left) {
2088 void *ptr = attr;
2089 ptr += PERF_ATTR_SIZE_VER0;
2090
2091 ret = readn(fd, ptr, left);
2092 }
2093 /* read perf_file_section, ids are read in caller */
2094 ret = readn(fd, &f_attr->ids, sizeof(f_attr->ids));
2095
2096 return ret <= 0 ? -1 : 0;
2097}
2098
1911int perf_session__read_header(struct perf_session *session, int fd) 2099int perf_session__read_header(struct perf_session *session, int fd)
1912{ 2100{
1913 struct perf_header *header = &session->header; 2101 struct perf_header *header = &session->header;
@@ -1923,19 +2111,17 @@ int perf_session__read_header(struct perf_session *session, int fd)
1923 if (session->fd_pipe) 2111 if (session->fd_pipe)
1924 return perf_header__read_pipe(session, fd); 2112 return perf_header__read_pipe(session, fd);
1925 2113
1926 if (perf_file_header__read(&f_header, header, fd) < 0) { 2114 if (perf_file_header__read(&f_header, header, fd) < 0)
1927 pr_debug("incompatible file format\n");
1928 return -EINVAL; 2115 return -EINVAL;
1929 }
1930 2116
1931 nr_attrs = f_header.attrs.size / sizeof(f_attr); 2117 nr_attrs = f_header.attrs.size / f_header.attr_size;
1932 lseek(fd, f_header.attrs.offset, SEEK_SET); 2118 lseek(fd, f_header.attrs.offset, SEEK_SET);
1933 2119
1934 for (i = 0; i < nr_attrs; i++) { 2120 for (i = 0; i < nr_attrs; i++) {
1935 struct perf_evsel *evsel; 2121 struct perf_evsel *evsel;
1936 off_t tmp; 2122 off_t tmp;
1937 2123
1938 if (readn(fd, &f_attr, sizeof(f_attr)) <= 0) 2124 if (read_attr(fd, header, &f_attr) < 0)
1939 goto out_errno; 2125 goto out_errno;
1940 2126
1941 if (header->needs_swap) 2127 if (header->needs_swap)
@@ -2105,7 +2291,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool,
2105 strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); 2291 strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
2106 2292
2107 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; 2293 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
2108 size = strlen(name); 2294 size = strlen(ev.event_type.event_type.name);
2109 size = ALIGN(size, sizeof(u64)); 2295 size = ALIGN(size, sizeof(u64));
2110 ev.event_type.header.size = sizeof(ev.event_type) - 2296 ev.event_type.header.size = sizeof(ev.event_type) -
2111 (sizeof(ev.event_type.event_type.name) - size); 2297 (sizeof(ev.event_type.event_type.name) - size);
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index ac4ec956024e..21a6be09c129 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -11,6 +11,7 @@
11 11
12enum { 12enum {
13 HEADER_RESERVED = 0, /* always cleared */ 13 HEADER_RESERVED = 0, /* always cleared */
14 HEADER_FIRST_FEATURE = 1,
14 HEADER_TRACE_INFO = 1, 15 HEADER_TRACE_INFO = 1,
15 HEADER_BUILD_ID, 16 HEADER_BUILD_ID,
16 17
@@ -26,7 +27,7 @@ enum {
26 HEADER_EVENT_DESC, 27 HEADER_EVENT_DESC,
27 HEADER_CPU_TOPOLOGY, 28 HEADER_CPU_TOPOLOGY,
28 HEADER_NUMA_TOPOLOGY, 29 HEADER_NUMA_TOPOLOGY,
29 30 HEADER_BRANCH_STACK,
30 HEADER_LAST_FEATURE, 31 HEADER_LAST_FEATURE,
31 HEADER_FEAT_BITS = 256, 32 HEADER_FEAT_BITS = 256,
32}; 33};
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index abef2703cd24..2ec4b60aff6c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -10,11 +10,14 @@ static bool hists__filter_entry_by_dso(struct hists *hists,
10 struct hist_entry *he); 10 struct hist_entry *he);
11static bool hists__filter_entry_by_thread(struct hists *hists, 11static bool hists__filter_entry_by_thread(struct hists *hists,
12 struct hist_entry *he); 12 struct hist_entry *he);
13static bool hists__filter_entry_by_symbol(struct hists *hists,
14 struct hist_entry *he);
13 15
14enum hist_filter { 16enum hist_filter {
15 HIST_FILTER__DSO, 17 HIST_FILTER__DSO,
16 HIST_FILTER__THREAD, 18 HIST_FILTER__THREAD,
17 HIST_FILTER__PARENT, 19 HIST_FILTER__PARENT,
20 HIST_FILTER__SYMBOL,
18}; 21};
19 22
20struct callchain_param callchain_param = { 23struct callchain_param callchain_param = {
@@ -50,21 +53,25 @@ static void hists__reset_col_len(struct hists *hists)
50 hists__set_col_len(hists, col, 0); 53 hists__set_col_len(hists, col, 0);
51} 54}
52 55
56static void hists__set_unres_dso_col_len(struct hists *hists, int dso)
57{
58 const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
59
60 if (hists__col_len(hists, dso) < unresolved_col_width &&
61 !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
62 !symbol_conf.dso_list)
63 hists__set_col_len(hists, dso, unresolved_col_width);
64}
65
53static void hists__calc_col_len(struct hists *hists, struct hist_entry *h) 66static void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
54{ 67{
68 const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
55 u16 len; 69 u16 len;
56 70
57 if (h->ms.sym) 71 if (h->ms.sym)
58 hists__new_col_len(hists, HISTC_SYMBOL, h->ms.sym->namelen); 72 hists__new_col_len(hists, HISTC_SYMBOL, h->ms.sym->namelen + 4);
59 else { 73 else
60 const unsigned int unresolved_col_width = BITS_PER_LONG / 4; 74 hists__set_unres_dso_col_len(hists, HISTC_DSO);
61
62 if (hists__col_len(hists, HISTC_DSO) < unresolved_col_width &&
63 !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
64 !symbol_conf.dso_list)
65 hists__set_col_len(hists, HISTC_DSO,
66 unresolved_col_width);
67 }
68 75
69 len = thread__comm_len(h->thread); 76 len = thread__comm_len(h->thread);
70 if (hists__new_col_len(hists, HISTC_COMM, len)) 77 if (hists__new_col_len(hists, HISTC_COMM, len))
@@ -74,23 +81,54 @@ static void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
74 len = dso__name_len(h->ms.map->dso); 81 len = dso__name_len(h->ms.map->dso);
75 hists__new_col_len(hists, HISTC_DSO, len); 82 hists__new_col_len(hists, HISTC_DSO, len);
76 } 83 }
84
85 if (h->branch_info) {
86 int symlen;
87 /*
88 * +4 accounts for '[x] ' priv level info
89 * +2 account of 0x prefix on raw addresses
90 */
91 if (h->branch_info->from.sym) {
92 symlen = (int)h->branch_info->from.sym->namelen + 4;
93 hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);
94
95 symlen = dso__name_len(h->branch_info->from.map->dso);
96 hists__new_col_len(hists, HISTC_DSO_FROM, symlen);
97 } else {
98 symlen = unresolved_col_width + 4 + 2;
99 hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);
100 hists__set_unres_dso_col_len(hists, HISTC_DSO_FROM);
101 }
102
103 if (h->branch_info->to.sym) {
104 symlen = (int)h->branch_info->to.sym->namelen + 4;
105 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
106
107 symlen = dso__name_len(h->branch_info->to.map->dso);
108 hists__new_col_len(hists, HISTC_DSO_TO, symlen);
109 } else {
110 symlen = unresolved_col_width + 4 + 2;
111 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
112 hists__set_unres_dso_col_len(hists, HISTC_DSO_TO);
113 }
114 }
77} 115}
78 116
79static void hist_entry__add_cpumode_period(struct hist_entry *self, 117static void hist_entry__add_cpumode_period(struct hist_entry *he,
80 unsigned int cpumode, u64 period) 118 unsigned int cpumode, u64 period)
81{ 119{
82 switch (cpumode) { 120 switch (cpumode) {
83 case PERF_RECORD_MISC_KERNEL: 121 case PERF_RECORD_MISC_KERNEL:
84 self->period_sys += period; 122 he->period_sys += period;
85 break; 123 break;
86 case PERF_RECORD_MISC_USER: 124 case PERF_RECORD_MISC_USER:
87 self->period_us += period; 125 he->period_us += period;
88 break; 126 break;
89 case PERF_RECORD_MISC_GUEST_KERNEL: 127 case PERF_RECORD_MISC_GUEST_KERNEL:
90 self->period_guest_sys += period; 128 he->period_guest_sys += period;
91 break; 129 break;
92 case PERF_RECORD_MISC_GUEST_USER: 130 case PERF_RECORD_MISC_GUEST_USER:
93 self->period_guest_us += period; 131 he->period_guest_us += period;
94 break; 132 break;
95 default: 133 default:
96 break; 134 break;
@@ -165,18 +203,18 @@ void hists__decay_entries_threaded(struct hists *hists,
165static struct hist_entry *hist_entry__new(struct hist_entry *template) 203static struct hist_entry *hist_entry__new(struct hist_entry *template)
166{ 204{
167 size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0; 205 size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
168 struct hist_entry *self = malloc(sizeof(*self) + callchain_size); 206 struct hist_entry *he = malloc(sizeof(*he) + callchain_size);
169 207
170 if (self != NULL) { 208 if (he != NULL) {
171 *self = *template; 209 *he = *template;
172 self->nr_events = 1; 210 he->nr_events = 1;
173 if (self->ms.map) 211 if (he->ms.map)
174 self->ms.map->referenced = true; 212 he->ms.map->referenced = true;
175 if (symbol_conf.use_callchain) 213 if (symbol_conf.use_callchain)
176 callchain_init(self->callchain); 214 callchain_init(he->callchain);
177 } 215 }
178 216
179 return self; 217 return he;
180} 218}
181 219
182static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h) 220static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
@@ -195,26 +233,14 @@ static u8 symbol__parent_filter(const struct symbol *parent)
195 return 0; 233 return 0;
196} 234}
197 235
198struct hist_entry *__hists__add_entry(struct hists *hists, 236static struct hist_entry *add_hist_entry(struct hists *hists,
237 struct hist_entry *entry,
199 struct addr_location *al, 238 struct addr_location *al,
200 struct symbol *sym_parent, u64 period) 239 u64 period)
201{ 240{
202 struct rb_node **p; 241 struct rb_node **p;
203 struct rb_node *parent = NULL; 242 struct rb_node *parent = NULL;
204 struct hist_entry *he; 243 struct hist_entry *he;
205 struct hist_entry entry = {
206 .thread = al->thread,
207 .ms = {
208 .map = al->map,
209 .sym = al->sym,
210 },
211 .cpu = al->cpu,
212 .ip = al->addr,
213 .level = al->level,
214 .period = period,
215 .parent = sym_parent,
216 .filtered = symbol__parent_filter(sym_parent),
217 };
218 int cmp; 244 int cmp;
219 245
220 pthread_mutex_lock(&hists->lock); 246 pthread_mutex_lock(&hists->lock);
@@ -225,7 +251,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
225 parent = *p; 251 parent = *p;
226 he = rb_entry(parent, struct hist_entry, rb_node_in); 252 he = rb_entry(parent, struct hist_entry, rb_node_in);
227 253
228 cmp = hist_entry__cmp(&entry, he); 254 cmp = hist_entry__cmp(entry, he);
229 255
230 if (!cmp) { 256 if (!cmp) {
231 he->period += period; 257 he->period += period;
@@ -239,7 +265,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
239 p = &(*p)->rb_right; 265 p = &(*p)->rb_right;
240 } 266 }
241 267
242 he = hist_entry__new(&entry); 268 he = hist_entry__new(entry);
243 if (!he) 269 if (!he)
244 goto out_unlock; 270 goto out_unlock;
245 271
@@ -252,6 +278,51 @@ out_unlock:
252 return he; 278 return he;
253} 279}
254 280
281struct hist_entry *__hists__add_branch_entry(struct hists *self,
282 struct addr_location *al,
283 struct symbol *sym_parent,
284 struct branch_info *bi,
285 u64 period)
286{
287 struct hist_entry entry = {
288 .thread = al->thread,
289 .ms = {
290 .map = bi->to.map,
291 .sym = bi->to.sym,
292 },
293 .cpu = al->cpu,
294 .ip = bi->to.addr,
295 .level = al->level,
296 .period = period,
297 .parent = sym_parent,
298 .filtered = symbol__parent_filter(sym_parent),
299 .branch_info = bi,
300 };
301
302 return add_hist_entry(self, &entry, al, period);
303}
304
305struct hist_entry *__hists__add_entry(struct hists *self,
306 struct addr_location *al,
307 struct symbol *sym_parent, u64 period)
308{
309 struct hist_entry entry = {
310 .thread = al->thread,
311 .ms = {
312 .map = al->map,
313 .sym = al->sym,
314 },
315 .cpu = al->cpu,
316 .ip = al->addr,
317 .level = al->level,
318 .period = period,
319 .parent = sym_parent,
320 .filtered = symbol__parent_filter(sym_parent),
321 };
322
323 return add_hist_entry(self, &entry, al, period);
324}
325
255int64_t 326int64_t
256hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) 327hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
257{ 328{
@@ -352,6 +423,7 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
352{ 423{
353 hists__filter_entry_by_dso(hists, he); 424 hists__filter_entry_by_dso(hists, he);
354 hists__filter_entry_by_thread(hists, he); 425 hists__filter_entry_by_thread(hists, he);
426 hists__filter_entry_by_symbol(hists, he);
355} 427}
356 428
357static void __hists__collapse_resort(struct hists *hists, bool threaded) 429static void __hists__collapse_resort(struct hists *hists, bool threaded)
@@ -535,7 +607,7 @@ static void init_rem_hits(void)
535 rem_hits.ms.sym = rem_sq_bracket; 607 rem_hits.ms.sym = rem_sq_bracket;
536} 608}
537 609
538static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, 610static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
539 u64 total_samples, int depth, 611 u64 total_samples, int depth,
540 int depth_mask, int left_margin) 612 int depth_mask, int left_margin)
541{ 613{
@@ -543,21 +615,16 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
543 struct callchain_node *child; 615 struct callchain_node *child;
544 struct callchain_list *chain; 616 struct callchain_list *chain;
545 int new_depth_mask = depth_mask; 617 int new_depth_mask = depth_mask;
546 u64 new_total;
547 u64 remaining; 618 u64 remaining;
548 size_t ret = 0; 619 size_t ret = 0;
549 int i; 620 int i;
550 uint entries_printed = 0; 621 uint entries_printed = 0;
551 622
552 if (callchain_param.mode == CHAIN_GRAPH_REL) 623 remaining = total_samples;
553 new_total = self->children_hit;
554 else
555 new_total = total_samples;
556
557 remaining = new_total;
558 624
559 node = rb_first(&self->rb_root); 625 node = rb_first(root);
560 while (node) { 626 while (node) {
627 u64 new_total;
561 u64 cumul; 628 u64 cumul;
562 629
563 child = rb_entry(node, struct callchain_node, rb_node); 630 child = rb_entry(node, struct callchain_node, rb_node);
@@ -585,11 +652,17 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
585 list_for_each_entry(chain, &child->val, list) { 652 list_for_each_entry(chain, &child->val, list) {
586 ret += ipchain__fprintf_graph(fp, chain, depth, 653 ret += ipchain__fprintf_graph(fp, chain, depth,
587 new_depth_mask, i++, 654 new_depth_mask, i++,
588 new_total, 655 total_samples,
589 cumul, 656 cumul,
590 left_margin); 657 left_margin);
591 } 658 }
592 ret += __callchain__fprintf_graph(fp, child, new_total, 659
660 if (callchain_param.mode == CHAIN_GRAPH_REL)
661 new_total = child->children_hit;
662 else
663 new_total = total_samples;
664
665 ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total,
593 depth + 1, 666 depth + 1,
594 new_depth_mask | (1 << depth), 667 new_depth_mask | (1 << depth),
595 left_margin); 668 left_margin);
@@ -599,61 +672,75 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
599 } 672 }
600 673
601 if (callchain_param.mode == CHAIN_GRAPH_REL && 674 if (callchain_param.mode == CHAIN_GRAPH_REL &&
602 remaining && remaining != new_total) { 675 remaining && remaining != total_samples) {
603 676
604 if (!rem_sq_bracket) 677 if (!rem_sq_bracket)
605 return ret; 678 return ret;
606 679
607 new_depth_mask &= ~(1 << (depth - 1)); 680 new_depth_mask &= ~(1 << (depth - 1));
608
609 ret += ipchain__fprintf_graph(fp, &rem_hits, depth, 681 ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
610 new_depth_mask, 0, new_total, 682 new_depth_mask, 0, total_samples,
611 remaining, left_margin); 683 remaining, left_margin);
612 } 684 }
613 685
614 return ret; 686 return ret;
615} 687}
616 688
617static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, 689static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
618 u64 total_samples, int left_margin) 690 u64 total_samples, int left_margin)
619{ 691{
692 struct callchain_node *cnode;
620 struct callchain_list *chain; 693 struct callchain_list *chain;
694 u32 entries_printed = 0;
621 bool printed = false; 695 bool printed = false;
696 struct rb_node *node;
622 int i = 0; 697 int i = 0;
623 int ret = 0; 698 int ret;
624 u32 entries_printed = 0;
625
626 list_for_each_entry(chain, &self->val, list) {
627 if (!i++ && sort__first_dimension == SORT_SYM)
628 continue;
629
630 if (!printed) {
631 ret += callchain__fprintf_left_margin(fp, left_margin);
632 ret += fprintf(fp, "|\n");
633 ret += callchain__fprintf_left_margin(fp, left_margin);
634 ret += fprintf(fp, "---");
635
636 left_margin += 3;
637 printed = true;
638 } else
639 ret += callchain__fprintf_left_margin(fp, left_margin);
640 699
641 if (chain->ms.sym) 700 /*
642 ret += fprintf(fp, " %s\n", chain->ms.sym->name); 701 * If have one single callchain root, don't bother printing
643 else 702 * its percentage (100 % in fractal mode and the same percentage
644 ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); 703 * than the hist in graph mode). This also avoid one level of column.
704 */
705 node = rb_first(root);
706 if (node && !rb_next(node)) {
707 cnode = rb_entry(node, struct callchain_node, rb_node);
708 list_for_each_entry(chain, &cnode->val, list) {
709 /*
710 * If we sort by symbol, the first entry is the same than
711 * the symbol. No need to print it otherwise it appears as
712 * displayed twice.
713 */
714 if (!i++ && sort__first_dimension == SORT_SYM)
715 continue;
716 if (!printed) {
717 ret += callchain__fprintf_left_margin(fp, left_margin);
718 ret += fprintf(fp, "|\n");
719 ret += callchain__fprintf_left_margin(fp, left_margin);
720 ret += fprintf(fp, "---");
721 left_margin += 3;
722 printed = true;
723 } else
724 ret += callchain__fprintf_left_margin(fp, left_margin);
725
726 if (chain->ms.sym)
727 ret += fprintf(fp, " %s\n", chain->ms.sym->name);
728 else
729 ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
645 730
646 if (++entries_printed == callchain_param.print_limit) 731 if (++entries_printed == callchain_param.print_limit)
647 break; 732 break;
733 }
734 root = &cnode->rb_root;
648 } 735 }
649 736
650 ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin); 737 return __callchain__fprintf_graph(fp, root, total_samples,
651 738 1, 1, left_margin);
652 return ret;
653} 739}
654 740
655static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self, 741static size_t __callchain__fprintf_flat(FILE *fp,
656 u64 total_samples) 742 struct callchain_node *self,
743 u64 total_samples)
657{ 744{
658 struct callchain_list *chain; 745 struct callchain_list *chain;
659 size_t ret = 0; 746 size_t ret = 0;
@@ -661,7 +748,7 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
661 if (!self) 748 if (!self)
662 return 0; 749 return 0;
663 750
664 ret += callchain__fprintf_flat(fp, self->parent, total_samples); 751 ret += __callchain__fprintf_flat(fp, self->parent, total_samples);
665 752
666 753
667 list_for_each_entry(chain, &self->val, list) { 754 list_for_each_entry(chain, &self->val, list) {
@@ -677,43 +764,58 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
677 return ret; 764 return ret;
678} 765}
679 766
680static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, 767static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self,
681 u64 total_samples, int left_margin) 768 u64 total_samples)
682{ 769{
683 struct rb_node *rb_node;
684 struct callchain_node *chain;
685 size_t ret = 0; 770 size_t ret = 0;
686 u32 entries_printed = 0; 771 u32 entries_printed = 0;
772 struct rb_node *rb_node;
773 struct callchain_node *chain;
687 774
688 rb_node = rb_first(&self->sorted_chain); 775 rb_node = rb_first(self);
689 while (rb_node) { 776 while (rb_node) {
690 double percent; 777 double percent;
691 778
692 chain = rb_entry(rb_node, struct callchain_node, rb_node); 779 chain = rb_entry(rb_node, struct callchain_node, rb_node);
693 percent = chain->hit * 100.0 / total_samples; 780 percent = chain->hit * 100.0 / total_samples;
694 switch (callchain_param.mode) { 781
695 case CHAIN_FLAT: 782 ret = percent_color_fprintf(fp, " %6.2f%%\n", percent);
696 ret += percent_color_fprintf(fp, " %6.2f%%\n", 783 ret += __callchain__fprintf_flat(fp, chain, total_samples);
697 percent);
698 ret += callchain__fprintf_flat(fp, chain, total_samples);
699 break;
700 case CHAIN_GRAPH_ABS: /* Falldown */
701 case CHAIN_GRAPH_REL:
702 ret += callchain__fprintf_graph(fp, chain, total_samples,
703 left_margin);
704 case CHAIN_NONE:
705 default:
706 break;
707 }
708 ret += fprintf(fp, "\n"); 784 ret += fprintf(fp, "\n");
709 if (++entries_printed == callchain_param.print_limit) 785 if (++entries_printed == callchain_param.print_limit)
710 break; 786 break;
787
711 rb_node = rb_next(rb_node); 788 rb_node = rb_next(rb_node);
712 } 789 }
713 790
714 return ret; 791 return ret;
715} 792}
716 793
794static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
795 u64 total_samples, int left_margin,
796 FILE *fp)
797{
798 switch (callchain_param.mode) {
799 case CHAIN_GRAPH_REL:
800 return callchain__fprintf_graph(fp, &he->sorted_chain, he->period,
801 left_margin);
802 break;
803 case CHAIN_GRAPH_ABS:
804 return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples,
805 left_margin);
806 break;
807 case CHAIN_FLAT:
808 return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples);
809 break;
810 case CHAIN_NONE:
811 break;
812 default:
813 pr_err("Bad callchain mode\n");
814 }
815
816 return 0;
817}
818
717void hists__output_recalc_col_len(struct hists *hists, int max_rows) 819void hists__output_recalc_col_len(struct hists *hists, int max_rows)
718{ 820{
719 struct rb_node *next = rb_first(&hists->entries); 821 struct rb_node *next = rb_first(&hists->entries);
@@ -730,35 +832,35 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows)
730 } 832 }
731} 833}
732 834
733static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s, 835static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s,
734 size_t size, struct hists *pair_hists, 836 size_t size, struct hists *pair_hists,
735 bool show_displacement, long displacement, 837 bool show_displacement, long displacement,
736 bool color, u64 session_total) 838 bool color, u64 total_period)
737{ 839{
738 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; 840 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
739 u64 nr_events; 841 u64 nr_events;
740 const char *sep = symbol_conf.field_sep; 842 const char *sep = symbol_conf.field_sep;
741 int ret; 843 int ret;
742 844
743 if (symbol_conf.exclude_other && !self->parent) 845 if (symbol_conf.exclude_other && !he->parent)
744 return 0; 846 return 0;
745 847
746 if (pair_hists) { 848 if (pair_hists) {
747 period = self->pair ? self->pair->period : 0; 849 period = he->pair ? he->pair->period : 0;
748 nr_events = self->pair ? self->pair->nr_events : 0; 850 nr_events = he->pair ? he->pair->nr_events : 0;
749 total = pair_hists->stats.total_period; 851 total = pair_hists->stats.total_period;
750 period_sys = self->pair ? self->pair->period_sys : 0; 852 period_sys = he->pair ? he->pair->period_sys : 0;
751 period_us = self->pair ? self->pair->period_us : 0; 853 period_us = he->pair ? he->pair->period_us : 0;
752 period_guest_sys = self->pair ? self->pair->period_guest_sys : 0; 854 period_guest_sys = he->pair ? he->pair->period_guest_sys : 0;
753 period_guest_us = self->pair ? self->pair->period_guest_us : 0; 855 period_guest_us = he->pair ? he->pair->period_guest_us : 0;
754 } else { 856 } else {
755 period = self->period; 857 period = he->period;
756 nr_events = self->nr_events; 858 nr_events = he->nr_events;
757 total = session_total; 859 total = total_period;
758 period_sys = self->period_sys; 860 period_sys = he->period_sys;
759 period_us = self->period_us; 861 period_us = he->period_us;
760 period_guest_sys = self->period_guest_sys; 862 period_guest_sys = he->period_guest_sys;
761 period_guest_us = self->period_guest_us; 863 period_guest_us = he->period_guest_us;
762 } 864 }
763 865
764 if (total) { 866 if (total) {
@@ -767,7 +869,7 @@ static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s,
767 sep ? "%.2f" : " %6.2f%%", 869 sep ? "%.2f" : " %6.2f%%",
768 (period * 100.0) / total); 870 (period * 100.0) / total);
769 else 871 else
770 ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%", 872 ret = scnprintf(s, size, sep ? "%.2f" : " %6.2f%%",
771 (period * 100.0) / total); 873 (period * 100.0) / total);
772 if (symbol_conf.show_cpu_utilization) { 874 if (symbol_conf.show_cpu_utilization) {
773 ret += percent_color_snprintf(s + ret, size - ret, 875 ret += percent_color_snprintf(s + ret, size - ret,
@@ -790,20 +892,20 @@ static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s,
790 } 892 }
791 } 893 }
792 } else 894 } else
793 ret = snprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period); 895 ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period);
794 896
795 if (symbol_conf.show_nr_samples) { 897 if (symbol_conf.show_nr_samples) {
796 if (sep) 898 if (sep)
797 ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events); 899 ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events);
798 else 900 else
799 ret += snprintf(s + ret, size - ret, "%11" PRIu64, nr_events); 901 ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
800 } 902 }
801 903
802 if (symbol_conf.show_total_period) { 904 if (symbol_conf.show_total_period) {
803 if (sep) 905 if (sep)
804 ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period); 906 ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
805 else 907 else
806 ret += snprintf(s + ret, size - ret, " %12" PRIu64, period); 908 ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period);
807 } 909 }
808 910
809 if (pair_hists) { 911 if (pair_hists) {
@@ -812,31 +914,31 @@ static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s,
812 914
813 if (total > 0) 915 if (total > 0)
814 old_percent = (period * 100.0) / total; 916 old_percent = (period * 100.0) / total;
815 if (session_total > 0) 917 if (total_period > 0)
816 new_percent = (self->period * 100.0) / session_total; 918 new_percent = (he->period * 100.0) / total_period;
817 919
818 diff = new_percent - old_percent; 920 diff = new_percent - old_percent;
819 921
820 if (fabs(diff) >= 0.01) 922 if (fabs(diff) >= 0.01)
821 snprintf(bf, sizeof(bf), "%+4.2F%%", diff); 923 scnprintf(bf, sizeof(bf), "%+4.2F%%", diff);
822 else 924 else
823 snprintf(bf, sizeof(bf), " "); 925 scnprintf(bf, sizeof(bf), " ");
824 926
825 if (sep) 927 if (sep)
826 ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf); 928 ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
827 else 929 else
828 ret += snprintf(s + ret, size - ret, "%11.11s", bf); 930 ret += scnprintf(s + ret, size - ret, "%11.11s", bf);
829 931
830 if (show_displacement) { 932 if (show_displacement) {
831 if (displacement) 933 if (displacement)
832 snprintf(bf, sizeof(bf), "%+4ld", displacement); 934 scnprintf(bf, sizeof(bf), "%+4ld", displacement);
833 else 935 else
834 snprintf(bf, sizeof(bf), " "); 936 scnprintf(bf, sizeof(bf), " ");
835 937
836 if (sep) 938 if (sep)
837 ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf); 939 ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
838 else 940 else
839 ret += snprintf(s + ret, size - ret, "%6.6s", bf); 941 ret += scnprintf(s + ret, size - ret, "%6.6s", bf);
840 } 942 }
841 } 943 }
842 944
@@ -854,7 +956,7 @@ int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
854 if (se->elide) 956 if (se->elide)
855 continue; 957 continue;
856 958
857 ret += snprintf(s + ret, size - ret, "%s", sep ?: " "); 959 ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
858 ret += se->se_snprintf(he, s + ret, size - ret, 960 ret += se->se_snprintf(he, s + ret, size - ret,
859 hists__col_len(hists, se->se_width_idx)); 961 hists__col_len(hists, se->se_width_idx));
860 } 962 }
@@ -862,9 +964,10 @@ int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
862 return ret; 964 return ret;
863} 965}
864 966
865int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists, 967static int hist_entry__fprintf(struct hist_entry *he, size_t size,
866 struct hists *pair_hists, bool show_displacement, 968 struct hists *hists, struct hists *pair_hists,
867 long displacement, FILE *fp, u64 session_total) 969 bool show_displacement, long displacement,
970 u64 total_period, FILE *fp)
868{ 971{
869 char bf[512]; 972 char bf[512];
870 int ret; 973 int ret;
@@ -874,14 +977,14 @@ int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists,
874 977
875 ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists, 978 ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists,
876 show_displacement, displacement, 979 show_displacement, displacement,
877 true, session_total); 980 true, total_period);
878 hist_entry__snprintf(he, bf + ret, size - ret, hists); 981 hist_entry__snprintf(he, bf + ret, size - ret, hists);
879 return fprintf(fp, "%s\n", bf); 982 return fprintf(fp, "%s\n", bf);
880} 983}
881 984
882static size_t hist_entry__fprintf_callchain(struct hist_entry *self, 985static size_t hist_entry__fprintf_callchain(struct hist_entry *he,
883 struct hists *hists, FILE *fp, 986 struct hists *hists,
884 u64 session_total) 987 u64 total_period, FILE *fp)
885{ 988{
886 int left_margin = 0; 989 int left_margin = 0;
887 990
@@ -889,11 +992,10 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self,
889 struct sort_entry *se = list_first_entry(&hist_entry__sort_list, 992 struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
890 typeof(*se), list); 993 typeof(*se), list);
891 left_margin = hists__col_len(hists, se->se_width_idx); 994 left_margin = hists__col_len(hists, se->se_width_idx);
892 left_margin -= thread__comm_len(self->thread); 995 left_margin -= thread__comm_len(he->thread);
893 } 996 }
894 997
895 return hist_entry_callchain__fprintf(fp, self, session_total, 998 return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
896 left_margin);
897} 999}
898 1000
899size_t hists__fprintf(struct hists *hists, struct hists *pair, 1001size_t hists__fprintf(struct hists *hists, struct hists *pair,
@@ -903,6 +1005,7 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
903 struct sort_entry *se; 1005 struct sort_entry *se;
904 struct rb_node *nd; 1006 struct rb_node *nd;
905 size_t ret = 0; 1007 size_t ret = 0;
1008 u64 total_period;
906 unsigned long position = 1; 1009 unsigned long position = 1;
907 long displacement = 0; 1010 long displacement = 0;
908 unsigned int width; 1011 unsigned int width;
@@ -917,20 +1020,6 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
917 1020
918 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead"); 1021 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
919 1022
920 if (symbol_conf.show_nr_samples) {
921 if (sep)
922 fprintf(fp, "%cSamples", *sep);
923 else
924 fputs(" Samples ", fp);
925 }
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
934 if (symbol_conf.show_cpu_utilization) { 1023 if (symbol_conf.show_cpu_utilization) {
935 if (sep) { 1024 if (sep) {
936 ret += fprintf(fp, "%csys", *sep); 1025 ret += fprintf(fp, "%csys", *sep);
@@ -940,8 +1029,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
940 ret += fprintf(fp, "%cguest us", *sep); 1029 ret += fprintf(fp, "%cguest us", *sep);
941 } 1030 }
942 } else { 1031 } else {
943 ret += fprintf(fp, " sys "); 1032 ret += fprintf(fp, " sys ");
944 ret += fprintf(fp, " us "); 1033 ret += fprintf(fp, " us ");
945 if (perf_guest) { 1034 if (perf_guest) {
946 ret += fprintf(fp, " guest sys "); 1035 ret += fprintf(fp, " guest sys ");
947 ret += fprintf(fp, " guest us "); 1036 ret += fprintf(fp, " guest us ");
@@ -949,6 +1038,20 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
949 } 1038 }
950 } 1039 }
951 1040
1041 if (symbol_conf.show_nr_samples) {
1042 if (sep)
1043 fprintf(fp, "%cSamples", *sep);
1044 else
1045 fputs(" Samples ", fp);
1046 }
1047
1048 if (symbol_conf.show_total_period) {
1049 if (sep)
1050 ret += fprintf(fp, "%cPeriod", *sep);
1051 else
1052 ret += fprintf(fp, " Period ");
1053 }
1054
952 if (pair) { 1055 if (pair) {
953 if (sep) 1056 if (sep)
954 ret += fprintf(fp, "%cDelta", *sep); 1057 ret += fprintf(fp, "%cDelta", *sep);
@@ -993,6 +1096,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
993 goto print_entries; 1096 goto print_entries;
994 1097
995 fprintf(fp, "# ........"); 1098 fprintf(fp, "# ........");
1099 if (symbol_conf.show_cpu_utilization)
1100 fprintf(fp, " ....... .......");
996 if (symbol_conf.show_nr_samples) 1101 if (symbol_conf.show_nr_samples)
997 fprintf(fp, " .........."); 1102 fprintf(fp, " ..........");
998 if (symbol_conf.show_total_period) 1103 if (symbol_conf.show_total_period)
@@ -1025,6 +1130,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
1025 goto out; 1130 goto out;
1026 1131
1027print_entries: 1132print_entries:
1133 total_period = hists->stats.total_period;
1134
1028 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 1135 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
1029 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 1136 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
1030 1137
@@ -1040,11 +1147,10 @@ print_entries:
1040 ++position; 1147 ++position;
1041 } 1148 }
1042 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement, 1149 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement,
1043 displacement, fp, hists->stats.total_period); 1150 displacement, total_period, fp);
1044 1151
1045 if (symbol_conf.use_callchain) 1152 if (symbol_conf.use_callchain)
1046 ret += hist_entry__fprintf_callchain(h, hists, fp, 1153 ret += hist_entry__fprintf_callchain(h, hists, total_period, fp);
1047 hists->stats.total_period);
1048 if (max_rows && ++nr_rows >= max_rows) 1154 if (max_rows && ++nr_rows >= max_rows)
1049 goto out; 1155 goto out;
1050 1156
@@ -1174,6 +1280,37 @@ void hists__filter_by_thread(struct hists *hists)
1174 } 1280 }
1175} 1281}
1176 1282
1283static bool hists__filter_entry_by_symbol(struct hists *hists,
1284 struct hist_entry *he)
1285{
1286 if (hists->symbol_filter_str != NULL &&
1287 (!he->ms.sym || strstr(he->ms.sym->name,
1288 hists->symbol_filter_str) == NULL)) {
1289 he->filtered |= (1 << HIST_FILTER__SYMBOL);
1290 return true;
1291 }
1292
1293 return false;
1294}
1295
1296void hists__filter_by_symbol(struct hists *hists)
1297{
1298 struct rb_node *nd;
1299
1300 hists->nr_entries = hists->stats.total_period = 0;
1301 hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
1302 hists__reset_col_len(hists);
1303
1304 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
1305 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
1306
1307 if (hists__filter_entry_by_symbol(hists, h))
1308 continue;
1309
1310 hists__remove_entry_filter(hists, h, HIST_FILTER__SYMBOL);
1311 }
1312}
1313
1177int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) 1314int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
1178{ 1315{
1179 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); 1316 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ff6f9d56ea41..2cae9df40e04 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -32,6 +32,7 @@ struct events_stats {
32 u32 nr_unknown_events; 32 u32 nr_unknown_events;
33 u32 nr_invalid_chains; 33 u32 nr_invalid_chains;
34 u32 nr_unknown_id; 34 u32 nr_unknown_id;
35 u32 nr_unprocessable_samples;
35}; 36};
36 37
37enum hist_column { 38enum hist_column {
@@ -41,6 +42,11 @@ enum hist_column {
41 HISTC_COMM, 42 HISTC_COMM,
42 HISTC_PARENT, 43 HISTC_PARENT,
43 HISTC_CPU, 44 HISTC_CPU,
45 HISTC_MISPREDICT,
46 HISTC_SYMBOL_FROM,
47 HISTC_SYMBOL_TO,
48 HISTC_DSO_FROM,
49 HISTC_DSO_TO,
44 HISTC_NR_COLS, /* Last entry */ 50 HISTC_NR_COLS, /* Last entry */
45}; 51};
46 52
@@ -55,6 +61,8 @@ struct hists {
55 u64 nr_entries; 61 u64 nr_entries;
56 const struct thread *thread_filter; 62 const struct thread *thread_filter;
57 const struct dso *dso_filter; 63 const struct dso *dso_filter;
64 const char *uid_filter_str;
65 const char *symbol_filter_str;
58 pthread_mutex_t lock; 66 pthread_mutex_t lock;
59 struct events_stats stats; 67 struct events_stats stats;
60 u64 event_stream; 68 u64 event_stream;
@@ -66,15 +74,18 @@ struct hists {
66struct hist_entry *__hists__add_entry(struct hists *self, 74struct hist_entry *__hists__add_entry(struct hists *self,
67 struct addr_location *al, 75 struct addr_location *al,
68 struct symbol *parent, u64 period); 76 struct symbol *parent, u64 period);
69extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); 77int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
70extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); 78int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
71int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists,
72 struct hists *pair_hists, bool show_displacement,
73 long displacement, FILE *fp, u64 session_total);
74int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, 79int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size,
75 struct hists *hists); 80 struct hists *hists);
76void hist_entry__free(struct hist_entry *); 81void hist_entry__free(struct hist_entry *);
77 82
83struct hist_entry *__hists__add_branch_entry(struct hists *self,
84 struct addr_location *al,
85 struct symbol *sym_parent,
86 struct branch_info *bi,
87 u64 period);
88
78void hists__output_resort(struct hists *self); 89void hists__output_resort(struct hists *self);
79void hists__output_resort_threaded(struct hists *hists); 90void hists__output_resort_threaded(struct hists *hists);
80void hists__collapse_resort(struct hists *self); 91void hists__collapse_resort(struct hists *self);
@@ -97,6 +108,7 @@ int hist_entry__annotate(struct hist_entry *self, size_t privsize);
97 108
98void hists__filter_by_dso(struct hists *hists); 109void hists__filter_by_dso(struct hists *hists);
99void hists__filter_by_thread(struct hists *hists); 110void hists__filter_by_thread(struct hists *hists);
111void hists__filter_by_symbol(struct hists *hists);
100 112
101u16 hists__col_len(struct hists *self, enum hist_column col); 113u16 hists__col_len(struct hists *self, enum hist_column col);
102void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); 114void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
@@ -135,6 +147,23 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
135 int refresh); 147 int refresh);
136#endif 148#endif
137 149
150#ifdef NO_GTK2_SUPPORT
151static inline
152int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __used,
153 const char *help __used,
154 void(*timer)(void *arg) __used,
155 void *arg __used,
156 int refresh __used)
157{
158 return 0;
159}
160
161#else
162int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
163 void(*timer)(void *arg), void *arg,
164 int refresh);
165#endif
166
138unsigned int hists__sort_list_width(struct hists *self); 167unsigned int hists__sort_list_width(struct hists *self);
139 168
140#endif /* __PERF_HIST_H */ 169#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/include/asm/dwarf2.h b/tools/perf/util/include/asm/dwarf2.h
index bb4198e7837a..afe38199e922 100644
--- a/tools/perf/util/include/asm/dwarf2.h
+++ b/tools/perf/util/include/asm/dwarf2.h
@@ -2,10 +2,12 @@
2#ifndef PERF_DWARF2_H 2#ifndef PERF_DWARF2_H
3#define PERF_DWARF2_H 3#define PERF_DWARF2_H
4 4
5/* dwarf2.h ... dummy header file for including arch/x86/lib/memcpy_64.S */ 5/* dwarf2.h ... dummy header file for including arch/x86/lib/mem{cpy,set}_64.S */
6 6
7#define CFI_STARTPROC 7#define CFI_STARTPROC
8#define CFI_ENDPROC 8#define CFI_ENDPROC
9#define CFI_REMEMBER_STATE
10#define CFI_RESTORE_STATE
9 11
10#endif /* PERF_DWARF2_H */ 12#endif /* PERF_DWARF2_H */
11 13
diff --git a/tools/perf/util/include/asm/unistd_32.h b/tools/perf/util/include/asm/unistd_32.h
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/tools/perf/util/include/asm/unistd_32.h
@@ -0,0 +1 @@
diff --git a/tools/perf/util/include/asm/unistd_64.h b/tools/perf/util/include/asm/unistd_64.h
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/tools/perf/util/include/asm/unistd_64.h
@@ -0,0 +1 @@
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
index eda4416efa0a..bb162e40c76c 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -5,6 +5,8 @@
5#include <linux/bitops.h> 5#include <linux/bitops.h>
6 6
7int __bitmap_weight(const unsigned long *bitmap, int bits); 7int __bitmap_weight(const unsigned long *bitmap, int bits);
8void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
9 const unsigned long *bitmap2, int bits);
8 10
9#define BITMAP_LAST_WORD_MASK(nbits) \ 11#define BITMAP_LAST_WORD_MASK(nbits) \
10( \ 12( \
@@ -32,4 +34,13 @@ static inline int bitmap_weight(const unsigned long *src, int nbits)
32 return __bitmap_weight(src, nbits); 34 return __bitmap_weight(src, nbits);
33} 35}
34 36
37static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
38 const unsigned long *src2, int nbits)
39{
40 if (small_const_nbits(nbits))
41 *dst = *src1 | *src2;
42 else
43 __bitmap_or(dst, src1, src2, nbits);
44}
45
35#endif /* _PERF_BITOPS_H */ 46#endif /* _PERF_BITOPS_H */
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index 62cdee78db7b..f1584833bd22 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -15,7 +15,7 @@
15 (bit) = find_next_bit((addr), (size), (bit) + 1)) 15 (bit) = find_next_bit((addr), (size), (bit) + 1))
16 16
17/* same as for_each_set_bit() but use bit as value to start with */ 17/* same as for_each_set_bit() but use bit as value to start with */
18#define for_each_set_bit_cont(bit, addr, size) \ 18#define for_each_set_bit_from(bit, addr, size) \
19 for ((bit) = find_next_bit((addr), (size), (bit)); \ 19 for ((bit) = find_next_bit((addr), (size), (bit)); \
20 (bit) < (size); \ 20 (bit) < (size); \
21 (bit) = find_next_bit((addr), (size), (bit) + 1)) 21 (bit) = find_next_bit((addr), (size), (bit) + 1))
diff --git a/tools/perf/util/include/linux/module.h b/tools/perf/util/include/linux/export.h
index b43e2dc21e04..b43e2dc21e04 100644
--- a/tools/perf/util/include/linux/module.h
+++ b/tools/perf/util/include/linux/export.h
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 316aa0ab7122..dea6d1c1a954 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -212,6 +212,21 @@ size_t map__fprintf(struct map *self, FILE *fp)
212 self->start, self->end, self->pgoff, self->dso->name); 212 self->start, self->end, self->pgoff, self->dso->name);
213} 213}
214 214
215size_t map__fprintf_dsoname(struct map *map, FILE *fp)
216{
217 const char *dsoname;
218
219 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
220 if (symbol_conf.show_kernel_path && map->dso->long_name)
221 dsoname = map->dso->long_name;
222 else if (map->dso->name)
223 dsoname = map->dso->name;
224 } else
225 dsoname = "[unknown]";
226
227 return fprintf(fp, "%s", dsoname);
228}
229
215/* 230/*
216 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 231 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
217 * map->dso->adjust_symbols==1 for ET_EXEC-like cases. 232 * map->dso->adjust_symbols==1 for ET_EXEC-like cases.
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 2b8017f8a930..b100c20b7f94 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -118,6 +118,7 @@ void map__delete(struct map *self);
118struct map *map__clone(struct map *self); 118struct map *map__clone(struct map *self);
119int map__overlap(struct map *l, struct map *r); 119int map__overlap(struct map *l, struct map *r);
120size_t map__fprintf(struct map *self, FILE *fp); 120size_t map__fprintf(struct map *self, FILE *fp);
121size_t map__fprintf_dsoname(struct map *map, FILE *fp);
121 122
122int map__load(struct map *self, symbol_filter_t filter); 123int map__load(struct map *self, symbol_filter_t filter);
123struct symbol *map__find_symbol(struct map *self, 124struct symbol *map__find_symbol(struct map *self,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 531c283fc0c5..5b3a0ef4e232 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -11,6 +11,10 @@
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include "debugfs.h" 13#include "debugfs.h"
14#include "parse-events-flex.h"
15#include "pmu.h"
16
17#define MAX_NAME_LEN 100
14 18
15struct event_symbol { 19struct event_symbol {
16 u8 type; 20 u8 type;
@@ -19,11 +23,8 @@ struct event_symbol {
19 const char *alias; 23 const char *alias;
20}; 24};
21 25
22enum event_result { 26int parse_events_parse(struct list_head *list, struct list_head *list_tmp,
23 EVT_FAILED, 27 int *idx);
24 EVT_HANDLED,
25 EVT_HANDLED_ALL
26};
27 28
28#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 29#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
29#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 30#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
@@ -165,7 +166,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
165 struct tracepoint_path *path = NULL; 166 struct tracepoint_path *path = NULL;
166 DIR *sys_dir, *evt_dir; 167 DIR *sys_dir, *evt_dir;
167 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 168 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
168 char id_buf[4]; 169 char id_buf[24];
169 int fd; 170 int fd;
170 u64 id; 171 u64 id;
171 char evt_path[MAXPATHLEN]; 172 char evt_path[MAXPATHLEN];
@@ -354,7 +355,24 @@ const char *__event_name(int type, u64 config)
354 return "unknown"; 355 return "unknown";
355} 356}
356 357
357static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size) 358static int add_event(struct list_head *list, int *idx,
359 struct perf_event_attr *attr, char *name)
360{
361 struct perf_evsel *evsel;
362
363 event_attr_init(attr);
364
365 evsel = perf_evsel__new(attr, (*idx)++);
366 if (!evsel)
367 return -ENOMEM;
368
369 list_add_tail(&evsel->node, list);
370
371 evsel->name = strdup(name);
372 return 0;
373}
374
375static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size)
358{ 376{
359 int i, j; 377 int i, j;
360 int n, longest = -1; 378 int n, longest = -1;
@@ -362,58 +380,57 @@ static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int
362 for (i = 0; i < size; i++) { 380 for (i = 0; i < size; i++) {
363 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { 381 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
364 n = strlen(names[i][j]); 382 n = strlen(names[i][j]);
365 if (n > longest && !strncasecmp(*str, names[i][j], n)) 383 if (n > longest && !strncasecmp(str, names[i][j], n))
366 longest = n; 384 longest = n;
367 } 385 }
368 if (longest > 0) { 386 if (longest > 0)
369 *str += longest;
370 return i; 387 return i;
371 }
372 } 388 }
373 389
374 return -1; 390 return -1;
375} 391}
376 392
377static enum event_result 393int parse_events_add_cache(struct list_head *list, int *idx,
378parse_generic_hw_event(const char **str, struct perf_event_attr *attr) 394 char *type, char *op_result1, char *op_result2)
379{ 395{
380 const char *s = *str; 396 struct perf_event_attr attr;
397 char name[MAX_NAME_LEN];
381 int cache_type = -1, cache_op = -1, cache_result = -1; 398 int cache_type = -1, cache_op = -1, cache_result = -1;
399 char *op_result[2] = { op_result1, op_result2 };
400 int i, n;
382 401
383 cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
384 /* 402 /*
385 * No fallback - if we cannot get a clear cache type 403 * No fallback - if we cannot get a clear cache type
386 * then bail out: 404 * then bail out:
387 */ 405 */
406 cache_type = parse_aliases(type, hw_cache,
407 PERF_COUNT_HW_CACHE_MAX);
388 if (cache_type == -1) 408 if (cache_type == -1)
389 return EVT_FAILED; 409 return -EINVAL;
410
411 n = snprintf(name, MAX_NAME_LEN, "%s", type);
412
413 for (i = 0; (i < 2) && (op_result[i]); i++) {
414 char *str = op_result[i];
390 415
391 while ((cache_op == -1 || cache_result == -1) && *s == '-') { 416 snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str);
392 ++s;
393 417
394 if (cache_op == -1) { 418 if (cache_op == -1) {
395 cache_op = parse_aliases(&s, hw_cache_op, 419 cache_op = parse_aliases(str, hw_cache_op,
396 PERF_COUNT_HW_CACHE_OP_MAX); 420 PERF_COUNT_HW_CACHE_OP_MAX);
397 if (cache_op >= 0) { 421 if (cache_op >= 0) {
398 if (!is_cache_op_valid(cache_type, cache_op)) 422 if (!is_cache_op_valid(cache_type, cache_op))
399 return EVT_FAILED; 423 return -EINVAL;
400 continue; 424 continue;
401 } 425 }
402 } 426 }
403 427
404 if (cache_result == -1) { 428 if (cache_result == -1) {
405 cache_result = parse_aliases(&s, hw_cache_result, 429 cache_result = parse_aliases(str, hw_cache_result,
406 PERF_COUNT_HW_CACHE_RESULT_MAX); 430 PERF_COUNT_HW_CACHE_RESULT_MAX);
407 if (cache_result >= 0) 431 if (cache_result >= 0)
408 continue; 432 continue;
409 } 433 }
410
411 /*
412 * Can't parse this as a cache op or result, so back up
413 * to the '-'.
414 */
415 --s;
416 break;
417 } 434 }
418 435
419 /* 436 /*
@@ -428,20 +445,17 @@ parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
428 if (cache_result == -1) 445 if (cache_result == -1)
429 cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 446 cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
430 447
431 attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 448 memset(&attr, 0, sizeof(attr));
432 attr->type = PERF_TYPE_HW_CACHE; 449 attr.config = cache_type | (cache_op << 8) | (cache_result << 16);
433 450 attr.type = PERF_TYPE_HW_CACHE;
434 *str = s; 451 return add_event(list, idx, &attr, name);
435 return EVT_HANDLED;
436} 452}
437 453
438static enum event_result 454static int add_tracepoint(struct list_head *list, int *idx,
439parse_single_tracepoint_event(char *sys_name, 455 char *sys_name, char *evt_name)
440 const char *evt_name,
441 unsigned int evt_length,
442 struct perf_event_attr *attr,
443 const char **strp)
444{ 456{
457 struct perf_event_attr attr;
458 char name[MAX_NAME_LEN];
445 char evt_path[MAXPATHLEN]; 459 char evt_path[MAXPATHLEN];
446 char id_buf[4]; 460 char id_buf[4];
447 u64 id; 461 u64 id;
@@ -452,130 +466,80 @@ parse_single_tracepoint_event(char *sys_name,
452 466
453 fd = open(evt_path, O_RDONLY); 467 fd = open(evt_path, O_RDONLY);
454 if (fd < 0) 468 if (fd < 0)
455 return EVT_FAILED; 469 return -1;
456 470
457 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 471 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
458 close(fd); 472 close(fd);
459 return EVT_FAILED; 473 return -1;
460 } 474 }
461 475
462 close(fd); 476 close(fd);
463 id = atoll(id_buf); 477 id = atoll(id_buf);
464 attr->config = id;
465 attr->type = PERF_TYPE_TRACEPOINT;
466 *strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
467
468 attr->sample_type |= PERF_SAMPLE_RAW;
469 attr->sample_type |= PERF_SAMPLE_TIME;
470 attr->sample_type |= PERF_SAMPLE_CPU;
471 478
472 attr->sample_period = 1; 479 memset(&attr, 0, sizeof(attr));
480 attr.config = id;
481 attr.type = PERF_TYPE_TRACEPOINT;
482 attr.sample_type |= PERF_SAMPLE_RAW;
483 attr.sample_type |= PERF_SAMPLE_TIME;
484 attr.sample_type |= PERF_SAMPLE_CPU;
485 attr.sample_period = 1;
473 486
474 487 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name);
475 return EVT_HANDLED; 488 return add_event(list, idx, &attr, name);
476} 489}
477 490
478/* sys + ':' + event + ':' + flags*/ 491static int add_tracepoint_multi(struct list_head *list, int *idx,
479#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) 492 char *sys_name, char *evt_name)
480static enum event_result
481parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name,
482 const char *evt_exp, char *flags)
483{ 493{
484 char evt_path[MAXPATHLEN]; 494 char evt_path[MAXPATHLEN];
485 struct dirent *evt_ent; 495 struct dirent *evt_ent;
486 DIR *evt_dir; 496 DIR *evt_dir;
497 int ret = 0;
487 498
488 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); 499 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
489 evt_dir = opendir(evt_path); 500 evt_dir = opendir(evt_path);
490
491 if (!evt_dir) { 501 if (!evt_dir) {
492 perror("Can't open event dir"); 502 perror("Can't open event dir");
493 return EVT_FAILED; 503 return -1;
494 } 504 }
495 505
496 while ((evt_ent = readdir(evt_dir))) { 506 while (!ret && (evt_ent = readdir(evt_dir))) {
497 char event_opt[MAX_EVOPT_LEN + 1];
498 int len;
499
500 if (!strcmp(evt_ent->d_name, ".") 507 if (!strcmp(evt_ent->d_name, ".")
501 || !strcmp(evt_ent->d_name, "..") 508 || !strcmp(evt_ent->d_name, "..")
502 || !strcmp(evt_ent->d_name, "enable") 509 || !strcmp(evt_ent->d_name, "enable")
503 || !strcmp(evt_ent->d_name, "filter")) 510 || !strcmp(evt_ent->d_name, "filter"))
504 continue; 511 continue;
505 512
506 if (!strglobmatch(evt_ent->d_name, evt_exp)) 513 if (!strglobmatch(evt_ent->d_name, evt_name))
507 continue; 514 continue;
508 515
509 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name, 516 ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name);
510 evt_ent->d_name, flags ? ":" : "",
511 flags ?: "");
512 if (len < 0)
513 return EVT_FAILED;
514
515 if (parse_events(evlist, event_opt, 0))
516 return EVT_FAILED;
517 } 517 }
518 518
519 return EVT_HANDLED_ALL; 519 return ret;
520} 520}
521 521
522static enum event_result 522int parse_events_add_tracepoint(struct list_head *list, int *idx,
523parse_tracepoint_event(struct perf_evlist *evlist, const char **strp, 523 char *sys, char *event)
524 struct perf_event_attr *attr)
525{ 524{
526 const char *evt_name; 525 int ret;
527 char *flags = NULL, *comma_loc;
528 char sys_name[MAX_EVENT_LENGTH];
529 unsigned int sys_length, evt_length;
530
531 if (debugfs_valid_mountpoint(tracing_events_path))
532 return 0;
533
534 evt_name = strchr(*strp, ':');
535 if (!evt_name)
536 return EVT_FAILED;
537
538 sys_length = evt_name - *strp;
539 if (sys_length >= MAX_EVENT_LENGTH)
540 return 0;
541 526
542 strncpy(sys_name, *strp, sys_length); 527 ret = debugfs_valid_mountpoint(tracing_events_path);
543 sys_name[sys_length] = '\0'; 528 if (ret)
544 evt_name = evt_name + 1; 529 return ret;
545 530
546 comma_loc = strchr(evt_name, ','); 531 return strpbrk(event, "*?") ?
547 if (comma_loc) { 532 add_tracepoint_multi(list, idx, sys, event) :
548 /* take the event name up to the comma */ 533 add_tracepoint(list, idx, sys, event);
549 evt_name = strndup(evt_name, comma_loc - evt_name);
550 }
551 flags = strchr(evt_name, ':');
552 if (flags) {
553 /* split it out: */
554 evt_name = strndup(evt_name, flags - evt_name);
555 flags++;
556 }
557
558 evt_length = strlen(evt_name);
559 if (evt_length >= MAX_EVENT_LENGTH)
560 return EVT_FAILED;
561 if (strpbrk(evt_name, "*?")) {
562 *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
563 return parse_multiple_tracepoint_event(evlist, sys_name,
564 evt_name, flags);
565 } else {
566 return parse_single_tracepoint_event(sys_name, evt_name,
567 evt_length, attr, strp);
568 }
569} 534}
570 535
571static enum event_result 536static int
572parse_breakpoint_type(const char *type, const char **strp, 537parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
573 struct perf_event_attr *attr)
574{ 538{
575 int i; 539 int i;
576 540
577 for (i = 0; i < 3; i++) { 541 for (i = 0; i < 3; i++) {
578 if (!type[i]) 542 if (!type || !type[i])
579 break; 543 break;
580 544
581 switch (type[i]) { 545 switch (type[i]) {
@@ -589,164 +553,146 @@ parse_breakpoint_type(const char *type, const char **strp,
589 attr->bp_type |= HW_BREAKPOINT_X; 553 attr->bp_type |= HW_BREAKPOINT_X;
590 break; 554 break;
591 default: 555 default:
592 return EVT_FAILED; 556 return -EINVAL;
593 } 557 }
594 } 558 }
559
595 if (!attr->bp_type) /* Default */ 560 if (!attr->bp_type) /* Default */
596 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 561 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
597 562
598 *strp = type + i; 563 return 0;
599
600 return EVT_HANDLED;
601} 564}
602 565
603static enum event_result 566int parse_events_add_breakpoint(struct list_head *list, int *idx,
604parse_breakpoint_event(const char **strp, struct perf_event_attr *attr) 567 void *ptr, char *type)
605{ 568{
606 const char *target; 569 struct perf_event_attr attr;
607 const char *type; 570 char name[MAX_NAME_LEN];
608 char *endaddr;
609 u64 addr;
610 enum event_result err;
611
612 target = strchr(*strp, ':');
613 if (!target)
614 return EVT_FAILED;
615
616 if (strncmp(*strp, "mem", target - *strp) != 0)
617 return EVT_FAILED;
618
619 target++;
620
621 addr = strtoull(target, &endaddr, 0);
622 if (target == endaddr)
623 return EVT_FAILED;
624
625 attr->bp_addr = addr;
626 *strp = endaddr;
627 571
628 type = strchr(target, ':'); 572 memset(&attr, 0, sizeof(attr));
573 attr.bp_addr = (unsigned long) ptr;
629 574
630 /* If no type is defined, just rw as default */ 575 if (parse_breakpoint_type(type, &attr))
631 if (!type) { 576 return -EINVAL;
632 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
633 } else {
634 err = parse_breakpoint_type(++type, strp, attr);
635 if (err == EVT_FAILED)
636 return EVT_FAILED;
637 }
638 577
639 /* 578 /*
640 * We should find a nice way to override the access length 579 * We should find a nice way to override the access length
641 * Provide some defaults for now 580 * Provide some defaults for now
642 */ 581 */
643 if (attr->bp_type == HW_BREAKPOINT_X) 582 if (attr.bp_type == HW_BREAKPOINT_X)
644 attr->bp_len = sizeof(long); 583 attr.bp_len = sizeof(long);
645 else 584 else
646 attr->bp_len = HW_BREAKPOINT_LEN_4; 585 attr.bp_len = HW_BREAKPOINT_LEN_4;
647 586
648 attr->type = PERF_TYPE_BREAKPOINT; 587 attr.type = PERF_TYPE_BREAKPOINT;
649 588
650 return EVT_HANDLED; 589 snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw");
590 return add_event(list, idx, &attr, name);
651} 591}
652 592
653static int check_events(const char *str, unsigned int i) 593static int config_term(struct perf_event_attr *attr,
594 struct parse_events__term *term)
654{ 595{
655 int n; 596 switch (term->type) {
597 case PARSE_EVENTS__TERM_TYPE_CONFIG:
598 attr->config = term->val.num;
599 break;
600 case PARSE_EVENTS__TERM_TYPE_CONFIG1:
601 attr->config1 = term->val.num;
602 break;
603 case PARSE_EVENTS__TERM_TYPE_CONFIG2:
604 attr->config2 = term->val.num;
605 break;
606 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
607 attr->sample_period = term->val.num;
608 break;
609 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
610 /*
611 * TODO uncomment when the field is available
612 * attr->branch_sample_type = term->val.num;
613 */
614 break;
615 default:
616 return -EINVAL;
617 }
618 return 0;
619}
656 620
657 n = strlen(event_symbols[i].symbol); 621static int config_attr(struct perf_event_attr *attr,
658 if (!strncasecmp(str, event_symbols[i].symbol, n)) 622 struct list_head *head, int fail)
659 return n; 623{
624 struct parse_events__term *term;
660 625
661 n = strlen(event_symbols[i].alias); 626 list_for_each_entry(term, head, list)
662 if (n) { 627 if (config_term(attr, term) && fail)
663 if (!strncasecmp(str, event_symbols[i].alias, n)) 628 return -EINVAL;
664 return n;
665 }
666 629
667 return 0; 630 return 0;
668} 631}
669 632
670static enum event_result 633int parse_events_add_numeric(struct list_head *list, int *idx,
671parse_symbolic_event(const char **strp, struct perf_event_attr *attr) 634 unsigned long type, unsigned long config,
635 struct list_head *head_config)
672{ 636{
673 const char *str = *strp; 637 struct perf_event_attr attr;
674 unsigned int i; 638
675 int n; 639 memset(&attr, 0, sizeof(attr));
676 640 attr.type = type;
677 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 641 attr.config = config;
678 n = check_events(str, i); 642
679 if (n > 0) { 643 if (head_config &&
680 attr->type = event_symbols[i].type; 644 config_attr(&attr, head_config, 1))
681 attr->config = event_symbols[i].config; 645 return -EINVAL;
682 *strp = str + n; 646
683 return EVT_HANDLED; 647 return add_event(list, idx, &attr,
684 } 648 (char *) __event_name(type, config));
685 }
686 return EVT_FAILED;
687} 649}
688 650
689static enum event_result 651int parse_events_add_pmu(struct list_head *list, int *idx,
690parse_raw_event(const char **strp, struct perf_event_attr *attr) 652 char *name, struct list_head *head_config)
691{ 653{
692 const char *str = *strp; 654 struct perf_event_attr attr;
693 u64 config; 655 struct perf_pmu *pmu;
694 int n; 656
695 657 pmu = perf_pmu__find(name);
696 if (*str != 'r') 658 if (!pmu)
697 return EVT_FAILED; 659 return -EINVAL;
698 n = hex2u64(str + 1, &config); 660
699 if (n > 0) { 661 memset(&attr, 0, sizeof(attr));
700 const char *end = str + n + 1; 662
701 if (*end != '\0' && *end != ',' && *end != ':') 663 /*
702 return EVT_FAILED; 664 * Configure hardcoded terms first, no need to check
703 665 * return value when called with fail == 0 ;)
704 *strp = end; 666 */
705 attr->type = PERF_TYPE_RAW; 667 config_attr(&attr, head_config, 0);
706 attr->config = config; 668
707 return EVT_HANDLED; 669 if (perf_pmu__config(pmu, &attr, head_config))
708 } 670 return -EINVAL;
709 return EVT_FAILED; 671
672 return add_event(list, idx, &attr, (char *) "pmu");
710} 673}
711 674
712static enum event_result 675void parse_events_update_lists(struct list_head *list_event,
713parse_numeric_event(const char **strp, struct perf_event_attr *attr) 676 struct list_head *list_all)
714{ 677{
715 const char *str = *strp; 678 /*
716 char *endp; 679 * Called for single event definition. Update the
717 unsigned long type; 680 * 'all event' list, and reinit the 'signle event'
718 u64 config; 681 * list, for next event definition.
719 682 */
720 type = strtoul(str, &endp, 0); 683 list_splice_tail(list_event, list_all);
721 if (endp > str && type < PERF_TYPE_MAX && *endp == ':') { 684 INIT_LIST_HEAD(list_event);
722 str = endp + 1;
723 config = strtoul(str, &endp, 0);
724 if (endp > str) {
725 attr->type = type;
726 attr->config = config;
727 *strp = endp;
728 return EVT_HANDLED;
729 }
730 }
731 return EVT_FAILED;
732} 685}
733 686
734static int 687int parse_events_modifier(struct list_head *list, char *str)
735parse_event_modifier(const char **strp, struct perf_event_attr *attr)
736{ 688{
737 const char *str = *strp; 689 struct perf_evsel *evsel;
738 int exclude = 0; 690 int exclude = 0, exclude_GH = 0;
739 int eu = 0, ek = 0, eh = 0, precise = 0; 691 int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0;
740 692
741 if (!*str) 693 if (str == NULL)
742 return 0; 694 return 0;
743 695
744 if (*str == ',')
745 return 0;
746
747 if (*str++ != ':')
748 return -1;
749
750 while (*str) { 696 while (*str) {
751 if (*str == 'u') { 697 if (*str == 'u') {
752 if (!exclude) 698 if (!exclude)
@@ -760,6 +706,14 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
760 if (!exclude) 706 if (!exclude)
761 exclude = eu = ek = eh = 1; 707 exclude = eu = ek = eh = 1;
762 eh = 0; 708 eh = 0;
709 } else if (*str == 'G') {
710 if (!exclude_GH)
711 exclude_GH = eG = eH = 1;
712 eG = 0;
713 } else if (*str == 'H') {
714 if (!exclude_GH)
715 exclude_GH = eG = eH = 1;
716 eH = 0;
763 } else if (*str == 'p') { 717 } else if (*str == 'p') {
764 precise++; 718 precise++;
765 } else 719 } else
@@ -767,108 +721,62 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
767 721
768 ++str; 722 ++str;
769 } 723 }
770 if (str < *strp + 2)
771 return -1;
772 724
773 *strp = str; 725 /*
726 * precise ip:
727 *
728 * 0 - SAMPLE_IP can have arbitrary skid
729 * 1 - SAMPLE_IP must have constant skid
730 * 2 - SAMPLE_IP requested to have 0 skid
731 * 3 - SAMPLE_IP must have 0 skid
732 *
733 * See also PERF_RECORD_MISC_EXACT_IP
734 */
735 if (precise > 3)
736 return -EINVAL;
774 737
775 attr->exclude_user = eu; 738 list_for_each_entry(evsel, list, node) {
776 attr->exclude_kernel = ek; 739 evsel->attr.exclude_user = eu;
777 attr->exclude_hv = eh; 740 evsel->attr.exclude_kernel = ek;
778 attr->precise_ip = precise; 741 evsel->attr.exclude_hv = eh;
742 evsel->attr.precise_ip = precise;
743 evsel->attr.exclude_host = eH;
744 evsel->attr.exclude_guest = eG;
745 }
779 746
780 return 0; 747 return 0;
781} 748}
782 749
783/* 750int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
784 * Each event can have multiple symbolic names.
785 * Symbolic names are (almost) exactly matched.
786 */
787static enum event_result
788parse_event_symbols(struct perf_evlist *evlist, const char **str,
789 struct perf_event_attr *attr)
790{ 751{
791 enum event_result ret; 752 LIST_HEAD(list);
792 753 LIST_HEAD(list_tmp);
793 ret = parse_tracepoint_event(evlist, str, attr); 754 YY_BUFFER_STATE buffer;
794 if (ret != EVT_FAILED) 755 int ret, idx = evlist->nr_entries;
795 goto modifier;
796
797 ret = parse_raw_event(str, attr);
798 if (ret != EVT_FAILED)
799 goto modifier;
800 756
801 ret = parse_numeric_event(str, attr); 757 buffer = parse_events__scan_string(str);
802 if (ret != EVT_FAILED)
803 goto modifier;
804 758
805 ret = parse_symbolic_event(str, attr); 759 ret = parse_events_parse(&list, &list_tmp, &idx);
806 if (ret != EVT_FAILED)
807 goto modifier;
808 760
809 ret = parse_generic_hw_event(str, attr); 761 parse_events__flush_buffer(buffer);
810 if (ret != EVT_FAILED) 762 parse_events__delete_buffer(buffer);
811 goto modifier;
812 763
813 ret = parse_breakpoint_event(str, attr); 764 if (!ret) {
814 if (ret != EVT_FAILED) 765 int entries = idx - evlist->nr_entries;
815 goto modifier; 766 perf_evlist__splice_list_tail(evlist, &list, entries);
816 767 return 0;
817 fprintf(stderr, "invalid or unsupported event: '%s'\n", *str);
818 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
819 return EVT_FAILED;
820
821modifier:
822 if (parse_event_modifier(str, attr) < 0) {
823 fprintf(stderr, "invalid event modifier: '%s'\n", *str);
824 fprintf(stderr, "Run 'perf list' for a list of valid events and modifiers\n");
825
826 return EVT_FAILED;
827 } 768 }
828 769
770 /*
771 * There are 2 users - builtin-record and builtin-test objects.
772 * Both call perf_evlist__delete in case of error, so we dont
773 * need to bother.
774 */
775 fprintf(stderr, "invalid or unsupported event: '%s'\n", str);
776 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
829 return ret; 777 return ret;
830} 778}
831 779
832int parse_events(struct perf_evlist *evlist , const char *str, int unset __used)
833{
834 struct perf_event_attr attr;
835 enum event_result ret;
836 const char *ostr;
837
838 for (;;) {
839 ostr = str;
840 memset(&attr, 0, sizeof(attr));
841 ret = parse_event_symbols(evlist, &str, &attr);
842 if (ret == EVT_FAILED)
843 return -1;
844
845 if (!(*str == 0 || *str == ',' || isspace(*str)))
846 return -1;
847
848 if (ret != EVT_HANDLED_ALL) {
849 struct perf_evsel *evsel;
850 evsel = perf_evsel__new(&attr, evlist->nr_entries);
851 if (evsel == NULL)
852 return -1;
853 perf_evlist__add(evlist, evsel);
854
855 evsel->name = calloc(str - ostr + 1, 1);
856 if (!evsel->name)
857 return -1;
858 strncpy(evsel->name, ostr, str - ostr);
859 }
860
861 if (*str == 0)
862 break;
863 if (*str == ',')
864 ++str;
865 while (isspace(*str))
866 ++str;
867 }
868
869 return 0;
870}
871
872int parse_events_option(const struct option *opt, const char *str, 780int parse_events_option(const struct option *opt, const char *str,
873 int unset __used) 781 int unset __used)
874{ 782{
@@ -1041,8 +949,6 @@ int print_hwcache_events(const char *event_glob)
1041 return printed; 949 return printed;
1042} 950}
1043 951
1044#define MAX_NAME_LEN 100
1045
1046/* 952/*
1047 * Print the help text for the event symbols: 953 * Print the help text for the event symbols:
1048 */ 954 */
@@ -1091,8 +997,12 @@ void print_events(const char *event_glob)
1091 997
1092 printf("\n"); 998 printf("\n");
1093 printf(" %-50s [%s]\n", 999 printf(" %-50s [%s]\n",
1094 "rNNN (see 'perf list --help' on how to encode it)", 1000 "rNNN",
1095 event_type_descriptors[PERF_TYPE_RAW]); 1001 event_type_descriptors[PERF_TYPE_RAW]);
1002 printf(" %-50s [%s]\n",
1003 "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
1004 event_type_descriptors[PERF_TYPE_RAW]);
1005 printf(" (see 'perf list --help' on how to encode it)\n");
1096 printf("\n"); 1006 printf("\n");
1097 1007
1098 printf(" %-50s [%s]\n", 1008 printf(" %-50s [%s]\n",
@@ -1102,3 +1012,51 @@ void print_events(const char *event_glob)
1102 1012
1103 print_tracepoint_events(NULL, NULL); 1013 print_tracepoint_events(NULL, NULL);
1104} 1014}
1015
1016int parse_events__is_hardcoded_term(struct parse_events__term *term)
1017{
1018 return term->type <= PARSE_EVENTS__TERM_TYPE_HARDCODED_MAX;
1019}
1020
1021int parse_events__new_term(struct parse_events__term **_term, int type,
1022 char *config, char *str, long num)
1023{
1024 struct parse_events__term *term;
1025
1026 term = zalloc(sizeof(*term));
1027 if (!term)
1028 return -ENOMEM;
1029
1030 INIT_LIST_HEAD(&term->list);
1031 term->type = type;
1032 term->config = config;
1033
1034 switch (type) {
1035 case PARSE_EVENTS__TERM_TYPE_CONFIG:
1036 case PARSE_EVENTS__TERM_TYPE_CONFIG1:
1037 case PARSE_EVENTS__TERM_TYPE_CONFIG2:
1038 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
1039 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
1040 case PARSE_EVENTS__TERM_TYPE_NUM:
1041 term->val.num = num;
1042 break;
1043 case PARSE_EVENTS__TERM_TYPE_STR:
1044 term->val.str = str;
1045 break;
1046 default:
1047 return -EINVAL;
1048 }
1049
1050 *_term = term;
1051 return 0;
1052}
1053
1054void parse_events__free_terms(struct list_head *terms)
1055{
1056 struct parse_events__term *term, *h;
1057
1058 list_for_each_entry_safe(term, h, terms, list)
1059 free(term);
1060
1061 free(terms);
1062}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 7e0cbe75d5f1..ca069f893381 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -33,6 +33,55 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
33 33
34#define EVENTS_HELP_MAX (128*1024) 34#define EVENTS_HELP_MAX (128*1024)
35 35
36enum {
37 PARSE_EVENTS__TERM_TYPE_CONFIG,
38 PARSE_EVENTS__TERM_TYPE_CONFIG1,
39 PARSE_EVENTS__TERM_TYPE_CONFIG2,
40 PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD,
41 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
42 PARSE_EVENTS__TERM_TYPE_NUM,
43 PARSE_EVENTS__TERM_TYPE_STR,
44
45 PARSE_EVENTS__TERM_TYPE_HARDCODED_MAX =
46 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
47};
48
49struct parse_events__term {
50 char *config;
51 union {
52 char *str;
53 long num;
54 } val;
55 int type;
56
57 struct list_head list;
58};
59
60int parse_events__is_hardcoded_term(struct parse_events__term *term);
61int parse_events__new_term(struct parse_events__term **term, int type,
62 char *config, char *str, long num);
63void parse_events__free_terms(struct list_head *terms);
64int parse_events_modifier(struct list_head *list __used, char *str __used);
65int parse_events_add_tracepoint(struct list_head *list, int *idx,
66 char *sys, char *event);
67int parse_events_add_raw(struct perf_evlist *evlist, unsigned long config,
68 unsigned long config1, unsigned long config2,
69 char *mod);
70int parse_events_add_numeric(struct list_head *list, int *idx,
71 unsigned long type, unsigned long config,
72 struct list_head *head_config);
73int parse_events_add_cache(struct list_head *list, int *idx,
74 char *type, char *op_result1, char *op_result2);
75int parse_events_add_breakpoint(struct list_head *list, int *idx,
76 void *ptr, char *type);
77int parse_events_add_pmu(struct list_head *list, int *idx,
78 char *pmu , struct list_head *head_config);
79void parse_events_update_lists(struct list_head *list_event,
80 struct list_head *list_all);
81void parse_events_error(struct list_head *list_all,
82 struct list_head *list_event,
83 int *idx, char const *msg);
84
36void print_events(const char *event_glob); 85void print_events(const char *event_glob);
37void print_events_type(u8 type); 86void print_events_type(u8 type);
38void print_tracepoint_events(const char *subsys_glob, const char *event_glob); 87void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
new file mode 100644
index 000000000000..05d766e3ecb5
--- /dev/null
+++ b/tools/perf/util/parse-events.l
@@ -0,0 +1,127 @@
1
2%option prefix="parse_events_"
3
4%{
5#include <errno.h>
6#include "../perf.h"
7#include "parse-events-bison.h"
8#include "parse-events.h"
9
10static int __value(char *str, int base, int token)
11{
12 long num;
13
14 errno = 0;
15 num = strtoul(str, NULL, base);
16 if (errno)
17 return PE_ERROR;
18
19 parse_events_lval.num = num;
20 return token;
21}
22
23static int value(int base)
24{
25 return __value(parse_events_text, base, PE_VALUE);
26}
27
28static int raw(void)
29{
30 return __value(parse_events_text + 1, 16, PE_RAW);
31}
32
33static int str(int token)
34{
35 parse_events_lval.str = strdup(parse_events_text);
36 return token;
37}
38
39static int sym(int type, int config)
40{
41 parse_events_lval.num = (type << 16) + config;
42 return PE_VALUE_SYM;
43}
44
45static int term(int type)
46{
47 parse_events_lval.num = type;
48 return PE_TERM;
49}
50
51%}
52
53num_dec [0-9]+
54num_hex 0x[a-fA-F0-9]+
55num_raw_hex [a-fA-F0-9]+
56name [a-zA-Z_*?][a-zA-Z0-9_*?]*
57modifier_event [ukhp]{1,5}
58modifier_bp [rwx]
59
60%%
61cpu-cycles|cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
62stalled-cycles-frontend|idle-cycles-frontend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
63stalled-cycles-backend|idle-cycles-backend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
64instructions { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
65cache-references { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
66cache-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
67branch-instructions|branches { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
68branch-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
69bus-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
70ref-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
71cpu-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
72task-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
73page-faults|faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
74minor-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
75major-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
76context-switches|cs { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
77cpu-migrations|migrations { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
78alignment-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
79emulation-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
80
81L1-dcache|l1-d|l1d|L1-data |
82L1-icache|l1-i|l1i|L1-instruction |
83LLC|L2 |
84dTLB|d-tlb|Data-TLB |
85iTLB|i-tlb|Instruction-TLB |
86branch|branches|bpu|btb|bpc |
87node { return str(PE_NAME_CACHE_TYPE); }
88
89load|loads|read |
90store|stores|write |
91prefetch|prefetches |
92speculative-read|speculative-load |
93refs|Reference|ops|access |
94misses|miss { return str(PE_NAME_CACHE_OP_RESULT); }
95
96 /*
97 * These are event config hardcoded term names to be specified
98 * within xxx/.../ syntax. So far we dont clash with other names,
99 * so we can put them here directly. In case the we have a conflict
100 * in future, this needs to go into '//' condition block.
101 */
102config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); }
103config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); }
104config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); }
105period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
106branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
107
108mem: { return PE_PREFIX_MEM; }
109r{num_raw_hex} { return raw(); }
110{num_dec} { return value(10); }
111{num_hex} { return value(16); }
112
113{modifier_event} { return str(PE_MODIFIER_EVENT); }
114{modifier_bp} { return str(PE_MODIFIER_BP); }
115{name} { return str(PE_NAME); }
116"/" { return '/'; }
117- { return '-'; }
118, { return ','; }
119: { return ':'; }
120= { return '='; }
121
122%%
123
124int parse_events_wrap(void)
125{
126 return 1;
127}
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
new file mode 100644
index 000000000000..d9637da7333c
--- /dev/null
+++ b/tools/perf/util/parse-events.y
@@ -0,0 +1,229 @@
1
2%name-prefix "parse_events_"
3%parse-param {struct list_head *list_all}
4%parse-param {struct list_head *list_event}
5%parse-param {int *idx}
6
7%{
8
9#define YYDEBUG 1
10
11#include <linux/compiler.h>
12#include <linux/list.h>
13#include "types.h"
14#include "util.h"
15#include "parse-events.h"
16
17extern int parse_events_lex (void);
18
19#define ABORT_ON(val) \
20do { \
21 if (val) \
22 YYABORT; \
23} while (0)
24
25%}
26
27%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM
28%token PE_NAME
29%token PE_MODIFIER_EVENT PE_MODIFIER_BP
30%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
31%token PE_PREFIX_MEM PE_PREFIX_RAW
32%token PE_ERROR
33%type <num> PE_VALUE
34%type <num> PE_VALUE_SYM
35%type <num> PE_RAW
36%type <num> PE_TERM
37%type <str> PE_NAME
38%type <str> PE_NAME_CACHE_TYPE
39%type <str> PE_NAME_CACHE_OP_RESULT
40%type <str> PE_MODIFIER_EVENT
41%type <str> PE_MODIFIER_BP
42%type <head> event_config
43%type <term> event_term
44
45%union
46{
47 char *str;
48 unsigned long num;
49 struct list_head *head;
50 struct parse_events__term *term;
51}
52%%
53
54events:
55events ',' event | event
56
57event:
58event_def PE_MODIFIER_EVENT
59{
60 /*
61 * Apply modifier on all events added by single event definition
62 * (there could be more events added for multiple tracepoint
63 * definitions via '*?'.
64 */
65 ABORT_ON(parse_events_modifier(list_event, $2));
66 parse_events_update_lists(list_event, list_all);
67}
68|
69event_def
70{
71 parse_events_update_lists(list_event, list_all);
72}
73
74event_def: event_pmu |
75 event_legacy_symbol |
76 event_legacy_cache sep_dc |
77 event_legacy_mem |
78 event_legacy_tracepoint sep_dc |
79 event_legacy_numeric sep_dc |
80 event_legacy_raw sep_dc
81
82event_pmu:
83PE_NAME '/' event_config '/'
84{
85 ABORT_ON(parse_events_add_pmu(list_event, idx, $1, $3));
86 parse_events__free_terms($3);
87}
88
89event_legacy_symbol:
90PE_VALUE_SYM '/' event_config '/'
91{
92 int type = $1 >> 16;
93 int config = $1 & 255;
94
95 ABORT_ON(parse_events_add_numeric(list_event, idx, type, config, $3));
96 parse_events__free_terms($3);
97}
98|
99PE_VALUE_SYM sep_slash_dc
100{
101 int type = $1 >> 16;
102 int config = $1 & 255;
103
104 ABORT_ON(parse_events_add_numeric(list_event, idx, type, config, NULL));
105}
106
107event_legacy_cache:
108PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
109{
110 ABORT_ON(parse_events_add_cache(list_event, idx, $1, $3, $5));
111}
112|
113PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
114{
115 ABORT_ON(parse_events_add_cache(list_event, idx, $1, $3, NULL));
116}
117|
118PE_NAME_CACHE_TYPE
119{
120 ABORT_ON(parse_events_add_cache(list_event, idx, $1, NULL, NULL));
121}
122
123event_legacy_mem:
124PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
125{
126 ABORT_ON(parse_events_add_breakpoint(list_event, idx, (void *) $2, $4));
127}
128|
129PE_PREFIX_MEM PE_VALUE sep_dc
130{
131 ABORT_ON(parse_events_add_breakpoint(list_event, idx, (void *) $2, NULL));
132}
133
134event_legacy_tracepoint:
135PE_NAME ':' PE_NAME
136{
137 ABORT_ON(parse_events_add_tracepoint(list_event, idx, $1, $3));
138}
139
140event_legacy_numeric:
141PE_VALUE ':' PE_VALUE
142{
143 ABORT_ON(parse_events_add_numeric(list_event, idx, $1, $3, NULL));
144}
145
146event_legacy_raw:
147PE_RAW
148{
149 ABORT_ON(parse_events_add_numeric(list_event, idx, PERF_TYPE_RAW, $1, NULL));
150}
151
152event_config:
153event_config ',' event_term
154{
155 struct list_head *head = $1;
156 struct parse_events__term *term = $3;
157
158 ABORT_ON(!head);
159 list_add_tail(&term->list, head);
160 $$ = $1;
161}
162|
163event_term
164{
165 struct list_head *head = malloc(sizeof(*head));
166 struct parse_events__term *term = $1;
167
168 ABORT_ON(!head);
169 INIT_LIST_HEAD(head);
170 list_add_tail(&term->list, head);
171 $$ = head;
172}
173
174event_term:
175PE_NAME '=' PE_NAME
176{
177 struct parse_events__term *term;
178
179 ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_STR,
180 $1, $3, 0));
181 $$ = term;
182}
183|
184PE_NAME '=' PE_VALUE
185{
186 struct parse_events__term *term;
187
188 ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_NUM,
189 $1, NULL, $3));
190 $$ = term;
191}
192|
193PE_NAME
194{
195 struct parse_events__term *term;
196
197 ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_NUM,
198 $1, NULL, 1));
199 $$ = term;
200}
201|
202PE_TERM '=' PE_VALUE
203{
204 struct parse_events__term *term;
205
206 ABORT_ON(parse_events__new_term(&term, $1, NULL, NULL, $3));
207 $$ = term;
208}
209|
210PE_TERM
211{
212 struct parse_events__term *term;
213
214 ABORT_ON(parse_events__new_term(&term, $1, NULL, NULL, 1));
215 $$ = term;
216}
217
218sep_dc: ':' |
219
220sep_slash_dc: '/' | ':' |
221
222%%
223
224void parse_events_error(struct list_head *list_all __used,
225 struct list_head *list_event __used,
226 int *idx __used,
227 char const *msg __used)
228{
229}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
new file mode 100644
index 000000000000..cb08a118e811
--- /dev/null
+++ b/tools/perf/util/pmu.c
@@ -0,0 +1,469 @@
1
2#include <linux/list.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <unistd.h>
6#include <stdio.h>
7#include <dirent.h>
8#include "sysfs.h"
9#include "util.h"
10#include "pmu.h"
11#include "parse-events.h"
12
13int perf_pmu_parse(struct list_head *list, char *name);
14extern FILE *perf_pmu_in;
15
16static LIST_HEAD(pmus);
17
18/*
19 * Parse & process all the sysfs attributes located under
20 * the directory specified in 'dir' parameter.
21 */
22static int pmu_format_parse(char *dir, struct list_head *head)
23{
24 struct dirent *evt_ent;
25 DIR *format_dir;
26 int ret = 0;
27
28 format_dir = opendir(dir);
29 if (!format_dir)
30 return -EINVAL;
31
32 while (!ret && (evt_ent = readdir(format_dir))) {
33 char path[PATH_MAX];
34 char *name = evt_ent->d_name;
35 FILE *file;
36
37 if (!strcmp(name, ".") || !strcmp(name, ".."))
38 continue;
39
40 snprintf(path, PATH_MAX, "%s/%s", dir, name);
41
42 ret = -EINVAL;
43 file = fopen(path, "r");
44 if (!file)
45 break;
46
47 perf_pmu_in = file;
48 ret = perf_pmu_parse(head, name);
49 fclose(file);
50 }
51
52 closedir(format_dir);
53 return ret;
54}
55
56/*
57 * Reading/parsing the default pmu format definition, which should be
58 * located at:
59 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
60 */
61static int pmu_format(char *name, struct list_head *format)
62{
63 struct stat st;
64 char path[PATH_MAX];
65 const char *sysfs;
66
67 sysfs = sysfs_find_mountpoint();
68 if (!sysfs)
69 return -1;
70
71 snprintf(path, PATH_MAX,
72 "%s/bus/event_source/devices/%s/format", sysfs, name);
73
74 if (stat(path, &st) < 0)
75 return -1;
76
77 if (pmu_format_parse(path, format))
78 return -1;
79
80 return 0;
81}
82
83/*
84 * Reading/parsing the default pmu type value, which should be
85 * located at:
86 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
87 */
88static int pmu_type(char *name, __u32 *type)
89{
90 struct stat st;
91 char path[PATH_MAX];
92 const char *sysfs;
93 FILE *file;
94 int ret = 0;
95
96 sysfs = sysfs_find_mountpoint();
97 if (!sysfs)
98 return -1;
99
100 snprintf(path, PATH_MAX,
101 "%s/bus/event_source/devices/%s/type", sysfs, name);
102
103 if (stat(path, &st) < 0)
104 return -1;
105
106 file = fopen(path, "r");
107 if (!file)
108 return -EINVAL;
109
110 if (1 != fscanf(file, "%u", type))
111 ret = -1;
112
113 fclose(file);
114 return ret;
115}
116
117static struct perf_pmu *pmu_lookup(char *name)
118{
119 struct perf_pmu *pmu;
120 LIST_HEAD(format);
121 __u32 type;
122
123 /*
124 * The pmu data we store & need consists of the pmu
125 * type value and format definitions. Load both right
126 * now.
127 */
128 if (pmu_format(name, &format))
129 return NULL;
130
131 if (pmu_type(name, &type))
132 return NULL;
133
134 pmu = zalloc(sizeof(*pmu));
135 if (!pmu)
136 return NULL;
137
138 INIT_LIST_HEAD(&pmu->format);
139 list_splice(&format, &pmu->format);
140 pmu->name = strdup(name);
141 pmu->type = type;
142 return pmu;
143}
144
145static struct perf_pmu *pmu_find(char *name)
146{
147 struct perf_pmu *pmu;
148
149 list_for_each_entry(pmu, &pmus, list)
150 if (!strcmp(pmu->name, name))
151 return pmu;
152
153 return NULL;
154}
155
156struct perf_pmu *perf_pmu__find(char *name)
157{
158 struct perf_pmu *pmu;
159
160 /*
161 * Once PMU is loaded it stays in the list,
162 * so we keep us from multiple reading/parsing
163 * the pmu format definitions.
164 */
165 pmu = pmu_find(name);
166 if (pmu)
167 return pmu;
168
169 return pmu_lookup(name);
170}
171
172static struct perf_pmu__format*
173pmu_find_format(struct list_head *formats, char *name)
174{
175 struct perf_pmu__format *format;
176
177 list_for_each_entry(format, formats, list)
178 if (!strcmp(format->name, name))
179 return format;
180
181 return NULL;
182}
183
184/*
185 * Returns value based on the format definition (format parameter)
186 * and unformated value (value parameter).
187 *
188 * TODO maybe optimize a little ;)
189 */
190static __u64 pmu_format_value(unsigned long *format, __u64 value)
191{
192 unsigned long fbit, vbit;
193 __u64 v = 0;
194
195 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
196
197 if (!test_bit(fbit, format))
198 continue;
199
200 if (!(value & (1llu << vbit++)))
201 continue;
202
203 v |= (1llu << fbit);
204 }
205
206 return v;
207}
208
209/*
210 * Setup one of config[12] attr members based on the
211 * user input data - temr parameter.
212 */
213static int pmu_config_term(struct list_head *formats,
214 struct perf_event_attr *attr,
215 struct parse_events__term *term)
216{
217 struct perf_pmu__format *format;
218 __u64 *vp;
219
220 /*
221 * Support only for hardcoded and numnerial terms.
222 * Hardcoded terms should be already in, so nothing
223 * to be done for them.
224 */
225 if (parse_events__is_hardcoded_term(term))
226 return 0;
227
228 if (term->type != PARSE_EVENTS__TERM_TYPE_NUM)
229 return -EINVAL;
230
231 format = pmu_find_format(formats, term->config);
232 if (!format)
233 return -EINVAL;
234
235 switch (format->value) {
236 case PERF_PMU_FORMAT_VALUE_CONFIG:
237 vp = &attr->config;
238 break;
239 case PERF_PMU_FORMAT_VALUE_CONFIG1:
240 vp = &attr->config1;
241 break;
242 case PERF_PMU_FORMAT_VALUE_CONFIG2:
243 vp = &attr->config2;
244 break;
245 default:
246 return -EINVAL;
247 }
248
249 *vp |= pmu_format_value(format->bits, term->val.num);
250 return 0;
251}
252
253static int pmu_config(struct list_head *formats, struct perf_event_attr *attr,
254 struct list_head *head_terms)
255{
256 struct parse_events__term *term, *h;
257
258 list_for_each_entry_safe(term, h, head_terms, list)
259 if (pmu_config_term(formats, attr, term))
260 return -EINVAL;
261
262 return 0;
263}
264
265/*
266 * Configures event's 'attr' parameter based on the:
267 * 1) users input - specified in terms parameter
268 * 2) pmu format definitions - specified by pmu parameter
269 */
270int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
271 struct list_head *head_terms)
272{
273 attr->type = pmu->type;
274 return pmu_config(&pmu->format, attr, head_terms);
275}
276
277int perf_pmu__new_format(struct list_head *list, char *name,
278 int config, unsigned long *bits)
279{
280 struct perf_pmu__format *format;
281
282 format = zalloc(sizeof(*format));
283 if (!format)
284 return -ENOMEM;
285
286 format->name = strdup(name);
287 format->value = config;
288 memcpy(format->bits, bits, sizeof(format->bits));
289
290 list_add_tail(&format->list, list);
291 return 0;
292}
293
294void perf_pmu__set_format(unsigned long *bits, long from, long to)
295{
296 long b;
297
298 if (!to)
299 to = from;
300
301 memset(bits, 0, BITS_TO_LONGS(PERF_PMU_FORMAT_BITS));
302 for (b = from; b <= to; b++)
303 set_bit(b, bits);
304}
305
306/* Simulated format definitions. */
307static struct test_format {
308 const char *name;
309 const char *value;
310} test_formats[] = {
311 { "krava01", "config:0-1,62-63\n", },
312 { "krava02", "config:10-17\n", },
313 { "krava03", "config:5\n", },
314 { "krava11", "config1:0,2,4,6,8,20-28\n", },
315 { "krava12", "config1:63\n", },
316 { "krava13", "config1:45-47\n", },
317 { "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", },
318 { "krava22", "config2:8,18,48,58\n", },
319 { "krava23", "config2:28-29,38\n", },
320};
321
322#define TEST_FORMATS_CNT (sizeof(test_formats) / sizeof(struct test_format))
323
324/* Simulated users input. */
325static struct parse_events__term test_terms[] = {
326 {
327 .config = (char *) "krava01",
328 .val.num = 15,
329 .type = PARSE_EVENTS__TERM_TYPE_NUM,
330 },
331 {
332 .config = (char *) "krava02",
333 .val.num = 170,
334 .type = PARSE_EVENTS__TERM_TYPE_NUM,
335 },
336 {
337 .config = (char *) "krava03",
338 .val.num = 1,
339 .type = PARSE_EVENTS__TERM_TYPE_NUM,
340 },
341 {
342 .config = (char *) "krava11",
343 .val.num = 27,
344 .type = PARSE_EVENTS__TERM_TYPE_NUM,
345 },
346 {
347 .config = (char *) "krava12",
348 .val.num = 1,
349 .type = PARSE_EVENTS__TERM_TYPE_NUM,
350 },
351 {
352 .config = (char *) "krava13",
353 .val.num = 2,
354 .type = PARSE_EVENTS__TERM_TYPE_NUM,
355 },
356 {
357 .config = (char *) "krava21",
358 .val.num = 119,
359 .type = PARSE_EVENTS__TERM_TYPE_NUM,
360 },
361 {
362 .config = (char *) "krava22",
363 .val.num = 11,
364 .type = PARSE_EVENTS__TERM_TYPE_NUM,
365 },
366 {
367 .config = (char *) "krava23",
368 .val.num = 2,
369 .type = PARSE_EVENTS__TERM_TYPE_NUM,
370 },
371};
372#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term))
373
374/*
375 * Prepare format directory data, exported by kernel
376 * at /sys/bus/event_source/devices/<dev>/format.
377 */
378static char *test_format_dir_get(void)
379{
380 static char dir[PATH_MAX];
381 unsigned int i;
382
383 snprintf(dir, PATH_MAX, "/tmp/perf-pmu-test-format-XXXXXX");
384 if (!mkdtemp(dir))
385 return NULL;
386
387 for (i = 0; i < TEST_FORMATS_CNT; i++) {
388 static char name[PATH_MAX];
389 struct test_format *format = &test_formats[i];
390 FILE *file;
391
392 snprintf(name, PATH_MAX, "%s/%s", dir, format->name);
393
394 file = fopen(name, "w");
395 if (!file)
396 return NULL;
397
398 if (1 != fwrite(format->value, strlen(format->value), 1, file))
399 break;
400
401 fclose(file);
402 }
403
404 return dir;
405}
406
407/* Cleanup format directory. */
408static int test_format_dir_put(char *dir)
409{
410 char buf[PATH_MAX];
411 snprintf(buf, PATH_MAX, "rm -f %s/*\n", dir);
412 if (system(buf))
413 return -1;
414
415 snprintf(buf, PATH_MAX, "rmdir %s\n", dir);
416 return system(buf);
417}
418
419static struct list_head *test_terms_list(void)
420{
421 static LIST_HEAD(terms);
422 unsigned int i;
423
424 for (i = 0; i < TERMS_CNT; i++)
425 list_add_tail(&test_terms[i].list, &terms);
426
427 return &terms;
428}
429
430#undef TERMS_CNT
431
432int perf_pmu__test(void)
433{
434 char *format = test_format_dir_get();
435 LIST_HEAD(formats);
436 struct list_head *terms = test_terms_list();
437 int ret;
438
439 if (!format)
440 return -EINVAL;
441
442 do {
443 struct perf_event_attr attr;
444
445 memset(&attr, 0, sizeof(attr));
446
447 ret = pmu_format_parse(format, &formats);
448 if (ret)
449 break;
450
451 ret = pmu_config(&formats, &attr, terms);
452 if (ret)
453 break;
454
455 ret = -EINVAL;
456
457 if (attr.config != 0xc00000000002a823)
458 break;
459 if (attr.config1 != 0x8000400000000145)
460 break;
461 if (attr.config2 != 0x0400000020041d07)
462 break;
463
464 ret = 0;
465 } while (0);
466
467 test_format_dir_put(format);
468 return ret;
469}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
new file mode 100644
index 000000000000..68c0db965e1f
--- /dev/null
+++ b/tools/perf/util/pmu.h
@@ -0,0 +1,41 @@
1#ifndef __PMU_H
2#define __PMU_H
3
4#include <linux/bitops.h>
5#include "../../../include/linux/perf_event.h"
6
7enum {
8 PERF_PMU_FORMAT_VALUE_CONFIG,
9 PERF_PMU_FORMAT_VALUE_CONFIG1,
10 PERF_PMU_FORMAT_VALUE_CONFIG2,
11};
12
13#define PERF_PMU_FORMAT_BITS 64
14
15struct perf_pmu__format {
16 char *name;
17 int value;
18 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
19 struct list_head list;
20};
21
22struct perf_pmu {
23 char *name;
24 __u32 type;
25 struct list_head format;
26 struct list_head list;
27};
28
29struct perf_pmu *perf_pmu__find(char *name);
30int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
31 struct list_head *head_terms);
32
33int perf_pmu_wrap(void);
34void perf_pmu_error(struct list_head *list, char *name, char const *msg);
35
36int perf_pmu__new_format(struct list_head *list, char *name,
37 int config, unsigned long *bits);
38void perf_pmu__set_format(unsigned long *bits, long from, long to);
39
40int perf_pmu__test(void);
41#endif /* __PMU_H */
diff --git a/tools/perf/util/pmu.l b/tools/perf/util/pmu.l
new file mode 100644
index 000000000000..a15d9fbd7c0e
--- /dev/null
+++ b/tools/perf/util/pmu.l
@@ -0,0 +1,43 @@
1%option prefix="perf_pmu_"
2
3%{
4#include <stdlib.h>
5#include <linux/bitops.h>
6#include "pmu.h"
7#include "pmu-bison.h"
8
9static int value(int base)
10{
11 long num;
12
13 errno = 0;
14 num = strtoul(perf_pmu_text, NULL, base);
15 if (errno)
16 return PP_ERROR;
17
18 perf_pmu_lval.num = num;
19 return PP_VALUE;
20}
21
22%}
23
24num_dec [0-9]+
25
26%%
27
28{num_dec} { return value(10); }
29config { return PP_CONFIG; }
30config1 { return PP_CONFIG1; }
31config2 { return PP_CONFIG2; }
32- { return '-'; }
33: { return ':'; }
34, { return ','; }
35. { ; }
36\n { ; }
37
38%%
39
40int perf_pmu_wrap(void)
41{
42 return 1;
43}
diff --git a/tools/perf/util/pmu.y b/tools/perf/util/pmu.y
new file mode 100644
index 000000000000..20ea77e93169
--- /dev/null
+++ b/tools/perf/util/pmu.y
@@ -0,0 +1,93 @@
1
2%name-prefix "perf_pmu_"
3%parse-param {struct list_head *format}
4%parse-param {char *name}
5
6%{
7
8#include <linux/compiler.h>
9#include <linux/list.h>
10#include <linux/bitmap.h>
11#include <string.h>
12#include "pmu.h"
13
14extern int perf_pmu_lex (void);
15
16#define ABORT_ON(val) \
17do { \
18 if (val) \
19 YYABORT; \
20} while (0)
21
22%}
23
24%token PP_CONFIG PP_CONFIG1 PP_CONFIG2
25%token PP_VALUE PP_ERROR
26%type <num> PP_VALUE
27%type <bits> bit_term
28%type <bits> bits
29
30%union
31{
32 unsigned long num;
33 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
34}
35
36%%
37
38format:
39format format_term
40|
41format_term
42
43format_term:
44PP_CONFIG ':' bits
45{
46 ABORT_ON(perf_pmu__new_format(format, name,
47 PERF_PMU_FORMAT_VALUE_CONFIG,
48 $3));
49}
50|
51PP_CONFIG1 ':' bits
52{
53 ABORT_ON(perf_pmu__new_format(format, name,
54 PERF_PMU_FORMAT_VALUE_CONFIG1,
55 $3));
56}
57|
58PP_CONFIG2 ':' bits
59{
60 ABORT_ON(perf_pmu__new_format(format, name,
61 PERF_PMU_FORMAT_VALUE_CONFIG2,
62 $3));
63}
64
65bits:
66bits ',' bit_term
67{
68 bitmap_or($$, $1, $3, 64);
69}
70|
71bit_term
72{
73 memcpy($$, $1, sizeof($1));
74}
75
76bit_term:
77PP_VALUE '-' PP_VALUE
78{
79 perf_pmu__set_format($$, $1, $3);
80}
81|
82PP_VALUE
83{
84 perf_pmu__set_format($$, $1, 0);
85}
86
87%%
88
89void perf_pmu_error(struct list_head *list __used,
90 char *name __used,
91 char const *msg __used)
92{
93}
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index eb25900e2211..8a8ee64e72d1 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -19,7 +19,6 @@
19 * 19 *
20 */ 20 */
21 21
22#define _GNU_SOURCE
23#include <sys/utsname.h> 22#include <sys/utsname.h>
24#include <sys/types.h> 23#include <sys/types.h>
25#include <sys/stat.h> 24#include <sys/stat.h>
@@ -33,10 +32,8 @@
33#include <limits.h> 32#include <limits.h>
34#include <elf.h> 33#include <elf.h>
35 34
36#undef _GNU_SOURCE
37#include "util.h" 35#include "util.h"
38#include "event.h" 36#include "event.h"
39#include "string.h"
40#include "strlist.h" 37#include "strlist.h"
41#include "debug.h" 38#include "debug.h"
42#include "cache.h" 39#include "cache.h"
@@ -275,10 +272,10 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
275/* Try to find perf_probe_event with debuginfo */ 272/* Try to find perf_probe_event with debuginfo */
276static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 273static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
277 struct probe_trace_event **tevs, 274 struct probe_trace_event **tevs,
278 int max_tevs, const char *module) 275 int max_tevs, const char *target)
279{ 276{
280 bool need_dwarf = perf_probe_event_need_dwarf(pev); 277 bool need_dwarf = perf_probe_event_need_dwarf(pev);
281 struct debuginfo *dinfo = open_debuginfo(module); 278 struct debuginfo *dinfo = open_debuginfo(target);
282 int ntevs, ret = 0; 279 int ntevs, ret = 0;
283 280
284 if (!dinfo) { 281 if (!dinfo) {
@@ -297,9 +294,9 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
297 294
298 if (ntevs > 0) { /* Succeeded to find trace events */ 295 if (ntevs > 0) { /* Succeeded to find trace events */
299 pr_debug("find %d probe_trace_events.\n", ntevs); 296 pr_debug("find %d probe_trace_events.\n", ntevs);
300 if (module) 297 if (target)
301 ret = add_module_to_probe_trace_events(*tevs, ntevs, 298 ret = add_module_to_probe_trace_events(*tevs, ntevs,
302 module); 299 target);
303 return ret < 0 ? ret : ntevs; 300 return ret < 0 ? ret : ntevs;
304 } 301 }
305 302
@@ -1731,7 +1728,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1731 } 1728 }
1732 1729
1733 ret = 0; 1730 ret = 0;
1734 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); 1731 printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
1735 for (i = 0; i < ntevs; i++) { 1732 for (i = 0; i < ntevs; i++) {
1736 tev = &tevs[i]; 1733 tev = &tevs[i];
1737 if (pev->event) 1734 if (pev->event)
@@ -1786,7 +1783,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1786 1783
1787 if (ret >= 0) { 1784 if (ret >= 0) {
1788 /* Show how to use the event. */ 1785 /* Show how to use the event. */
1789 printf("\nYou can now use it on all perf tools, such as:\n\n"); 1786 printf("\nYou can now use it in all perf tools, such as:\n\n");
1790 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 1787 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
1791 tev->event); 1788 tev->event);
1792 } 1789 }
@@ -1798,14 +1795,14 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1798 1795
1799static int convert_to_probe_trace_events(struct perf_probe_event *pev, 1796static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1800 struct probe_trace_event **tevs, 1797 struct probe_trace_event **tevs,
1801 int max_tevs, const char *module) 1798 int max_tevs, const char *target)
1802{ 1799{
1803 struct symbol *sym; 1800 struct symbol *sym;
1804 int ret = 0, i; 1801 int ret = 0, i;
1805 struct probe_trace_event *tev; 1802 struct probe_trace_event *tev;
1806 1803
1807 /* Convert perf_probe_event with debuginfo */ 1804 /* Convert perf_probe_event with debuginfo */
1808 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); 1805 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
1809 if (ret != 0) 1806 if (ret != 0)
1810 return ret; /* Found in debuginfo or got an error */ 1807 return ret; /* Found in debuginfo or got an error */
1811 1808
@@ -1821,8 +1818,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1821 goto error; 1818 goto error;
1822 } 1819 }
1823 1820
1824 if (module) { 1821 if (target) {
1825 tev->point.module = strdup(module); 1822 tev->point.module = strdup(target);
1826 if (tev->point.module == NULL) { 1823 if (tev->point.module == NULL) {
1827 ret = -ENOMEM; 1824 ret = -ENOMEM;
1828 goto error; 1825 goto error;
@@ -1869,6 +1866,12 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1869 tev->point.symbol); 1866 tev->point.symbol);
1870 ret = -ENOENT; 1867 ret = -ENOENT;
1871 goto error; 1868 goto error;
1869 } else if (tev->point.offset > sym->end - sym->start) {
1870 pr_warning("Offset specified is greater than size of %s\n",
1871 tev->point.symbol);
1872 ret = -ENOENT;
1873 goto error;
1874
1872 } 1875 }
1873 1876
1874 return 1; 1877 return 1;
@@ -1886,7 +1889,7 @@ struct __event_package {
1886}; 1889};
1887 1890
1888int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 1891int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1889 int max_tevs, const char *module, bool force_add) 1892 int max_tevs, const char *target, bool force_add)
1890{ 1893{
1891 int i, j, ret; 1894 int i, j, ret;
1892 struct __event_package *pkgs; 1895 struct __event_package *pkgs;
@@ -1909,7 +1912,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1909 ret = convert_to_probe_trace_events(pkgs[i].pev, 1912 ret = convert_to_probe_trace_events(pkgs[i].pev,
1910 &pkgs[i].tevs, 1913 &pkgs[i].tevs,
1911 max_tevs, 1914 max_tevs,
1912 module); 1915 target);
1913 if (ret < 0) 1916 if (ret < 0)
1914 goto end; 1917 goto end;
1915 pkgs[i].ntevs = ret; 1918 pkgs[i].ntevs = ret;
@@ -1961,7 +1964,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
1961 goto error; 1964 goto error;
1962 } 1965 }
1963 1966
1964 printf("Remove event: %s\n", ent->s); 1967 printf("Removed event: %s\n", ent->s);
1965 return 0; 1968 return 0;
1966error: 1969error:
1967 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 1970 pr_warning("Failed to delete event: %s\n", strerror(-ret));
@@ -2065,7 +2068,7 @@ static int filter_available_functions(struct map *map __unused,
2065 return 1; 2068 return 1;
2066} 2069}
2067 2070
2068int show_available_funcs(const char *module, struct strfilter *_filter) 2071int show_available_funcs(const char *target, struct strfilter *_filter)
2069{ 2072{
2070 struct map *map; 2073 struct map *map;
2071 int ret; 2074 int ret;
@@ -2076,9 +2079,9 @@ int show_available_funcs(const char *module, struct strfilter *_filter)
2076 if (ret < 0) 2079 if (ret < 0)
2077 return ret; 2080 return ret;
2078 2081
2079 map = kernel_get_module_map(module); 2082 map = kernel_get_module_map(target);
2080 if (!map) { 2083 if (!map) {
2081 pr_err("Failed to find %s map.\n", (module) ? : "kernel"); 2084 pr_err("Failed to find %s map.\n", (target) ? : "kernel");
2082 return -EINVAL; 2085 return -EINVAL;
2083 } 2086 }
2084 available_func_filter = _filter; 2087 available_func_filter = _filter;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 5d732621a462..d448984ed789 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -30,7 +30,6 @@
30#include <stdlib.h> 30#include <stdlib.h>
31#include <string.h> 31#include <string.h>
32#include <stdarg.h> 32#include <stdarg.h>
33#include <ctype.h>
34#include <dwarf-regs.h> 33#include <dwarf-regs.h>
35 34
36#include <linux/bitops.h> 35#include <linux/bitops.h>
@@ -672,7 +671,7 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
672static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr, 671static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
673 bool retprobe, struct probe_trace_point *tp) 672 bool retprobe, struct probe_trace_point *tp)
674{ 673{
675 Dwarf_Addr eaddr; 674 Dwarf_Addr eaddr, highaddr;
676 const char *name; 675 const char *name;
677 676
678 /* Copy the name of probe point */ 677 /* Copy the name of probe point */
@@ -683,6 +682,16 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
683 dwarf_diename(sp_die)); 682 dwarf_diename(sp_die));
684 return -ENOENT; 683 return -ENOENT;
685 } 684 }
685 if (dwarf_highpc(sp_die, &highaddr) != 0) {
686 pr_warning("Failed to get end address of %s\n",
687 dwarf_diename(sp_die));
688 return -ENOENT;
689 }
690 if (paddr > highaddr) {
691 pr_warning("Offset specified is greater than size of %s\n",
692 dwarf_diename(sp_die));
693 return -EINVAL;
694 }
686 tp->symbol = strdup(name); 695 tp->symbol = strdup(name);
687 if (tp->symbol == NULL) 696 if (tp->symbol == NULL)
688 return -ENOMEM; 697 return -ENOMEM;
@@ -963,10 +972,12 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
963 struct dwarf_callback_param *param = data; 972 struct dwarf_callback_param *param = data;
964 struct probe_finder *pf = param->data; 973 struct probe_finder *pf = param->data;
965 struct perf_probe_point *pp = &pf->pev->point; 974 struct perf_probe_point *pp = &pf->pev->point;
975 Dwarf_Attribute attr;
966 976
967 /* Check tag and diename */ 977 /* Check tag and diename */
968 if (dwarf_tag(sp_die) != DW_TAG_subprogram || 978 if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
969 !die_compare_name(sp_die, pp->function)) 979 !die_compare_name(sp_die, pp->function) ||
980 dwarf_attr(sp_die, DW_AT_declaration, &attr))
970 return DWARF_CB_OK; 981 return DWARF_CB_OK;
971 982
972 /* Check declared file */ 983 /* Check declared file */
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
new file mode 100644
index 000000000000..2884e67ee625
--- /dev/null
+++ b/tools/perf/util/python-ext-sources
@@ -0,0 +1,19 @@
1#
2# List of files needed by perf python extention
3#
4# Each source file must be placed on its own line so that it can be
5# processed by Makefile and util/setup.py accordingly.
6#
7
8util/python.c
9util/ctype.c
10util/evlist.c
11util/evsel.c
12util/cpumap.c
13util/thread_map.c
14util/util.c
15util/xyarray.c
16util/cgroup.c
17util/debugfs.c
18util/strlist.c
19../../lib/rbtree.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 9dd47a4f2596..e03b58a48424 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -425,14 +425,14 @@ struct pyrf_thread_map {
425static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, 425static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
426 PyObject *args, PyObject *kwargs) 426 PyObject *args, PyObject *kwargs)
427{ 427{
428 static char *kwlist[] = { "pid", "tid", NULL }; 428 static char *kwlist[] = { "pid", "tid", "uid", NULL };
429 int pid = -1, tid = -1; 429 int pid = -1, tid = -1, uid = UINT_MAX;
430 430
431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", 431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iii",
432 kwlist, &pid, &tid)) 432 kwlist, &pid, &tid, &uid))
433 return -1; 433 return -1;
434 434
435 pthreads->threads = thread_map__new(pid, tid); 435 pthreads->threads = thread_map__new(pid, tid, uid);
436 if (pthreads->threads == NULL) 436 if (pthreads->threads == NULL)
437 return -1; 437 return -1;
438 return 0; 438 return 0;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 0b2a48783172..c2623c6f9b51 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -24,7 +24,6 @@
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <string.h> 26#include <string.h>
27#include <ctype.h>
28#include <errno.h> 27#include <errno.h>
29 28
30#include "../../perf.h" 29#include "../../perf.h"
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b5ca2558c7bb..9412e3b05f68 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -24,7 +24,7 @@ static int perf_session__open(struct perf_session *self, bool force)
24 self->fd = STDIN_FILENO; 24 self->fd = STDIN_FILENO;
25 25
26 if (perf_session__read_header(self, self->fd) < 0) 26 if (perf_session__read_header(self, self->fd) < 0)
27 pr_err("incompatible file format"); 27 pr_err("incompatible file format (rerun with -v to learn more)");
28 28
29 return 0; 29 return 0;
30 } 30 }
@@ -56,7 +56,7 @@ static int perf_session__open(struct perf_session *self, bool force)
56 } 56 }
57 57
58 if (perf_session__read_header(self, self->fd) < 0) { 58 if (perf_session__read_header(self, self->fd) < 0) {
59 pr_err("incompatible file format"); 59 pr_err("incompatible file format (rerun with -v to learn more)");
60 goto out_close; 60 goto out_close;
61 } 61 }
62 62
@@ -140,6 +140,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,
140 INIT_LIST_HEAD(&self->ordered_samples.sample_cache); 140 INIT_LIST_HEAD(&self->ordered_samples.sample_cache);
141 INIT_LIST_HEAD(&self->ordered_samples.to_free); 141 INIT_LIST_HEAD(&self->ordered_samples.to_free);
142 machine__init(&self->host_machine, "", HOST_KERNEL_ID); 142 machine__init(&self->host_machine, "", HOST_KERNEL_ID);
143 hists__init(&self->hists);
143 144
144 if (mode == O_RDONLY) { 145 if (mode == O_RDONLY) {
145 if (perf_session__open(self, force) < 0) 146 if (perf_session__open(self, force) < 0)
@@ -229,6 +230,64 @@ static bool symbol__match_parent_regex(struct symbol *sym)
229 return 0; 230 return 0;
230} 231}
231 232
233static const u8 cpumodes[] = {
234 PERF_RECORD_MISC_USER,
235 PERF_RECORD_MISC_KERNEL,
236 PERF_RECORD_MISC_GUEST_USER,
237 PERF_RECORD_MISC_GUEST_KERNEL
238};
239#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
240
241static void ip__resolve_ams(struct machine *self, struct thread *thread,
242 struct addr_map_symbol *ams,
243 u64 ip)
244{
245 struct addr_location al;
246 size_t i;
247 u8 m;
248
249 memset(&al, 0, sizeof(al));
250
251 for (i = 0; i < NCPUMODES; i++) {
252 m = cpumodes[i];
253 /*
254 * We cannot use the header.misc hint to determine whether a
255 * branch stack address is user, kernel, guest, hypervisor.
256 * Branches may straddle the kernel/user/hypervisor boundaries.
257 * Thus, we have to try consecutively until we find a match
258 * or else, the symbol is unknown
259 */
260 thread__find_addr_location(thread, self, m, MAP__FUNCTION,
261 ip, &al, NULL);
262 if (al.sym)
263 goto found;
264 }
265found:
266 ams->addr = ip;
267 ams->al_addr = al.addr;
268 ams->sym = al.sym;
269 ams->map = al.map;
270}
271
272struct branch_info *machine__resolve_bstack(struct machine *self,
273 struct thread *thr,
274 struct branch_stack *bs)
275{
276 struct branch_info *bi;
277 unsigned int i;
278
279 bi = calloc(bs->nr, sizeof(struct branch_info));
280 if (!bi)
281 return NULL;
282
283 for (i = 0; i < bs->nr; i++) {
284 ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to);
285 ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from);
286 bi[i].flags = bs->entries[i].flags;
287 }
288 return bi;
289}
290
232int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, 291int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
233 struct thread *thread, 292 struct thread *thread,
234 struct ip_callchain *chain, 293 struct ip_callchain *chain,
@@ -697,6 +756,18 @@ static void callchain__printf(struct perf_sample *sample)
697 i, sample->callchain->ips[i]); 756 i, sample->callchain->ips[i]);
698} 757}
699 758
759static void branch_stack__printf(struct perf_sample *sample)
760{
761 uint64_t i;
762
763 printf("... branch stack: nr:%" PRIu64 "\n", sample->branch_stack->nr);
764
765 for (i = 0; i < sample->branch_stack->nr; i++)
766 printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 "\n",
767 i, sample->branch_stack->entries[i].from,
768 sample->branch_stack->entries[i].to);
769}
770
700static void perf_session__print_tstamp(struct perf_session *session, 771static void perf_session__print_tstamp(struct perf_session *session,
701 union perf_event *event, 772 union perf_event *event,
702 struct perf_sample *sample) 773 struct perf_sample *sample)
@@ -744,6 +815,9 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
744 815
745 if (session->sample_type & PERF_SAMPLE_CALLCHAIN) 816 if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
746 callchain__printf(sample); 817 callchain__printf(sample);
818
819 if (session->sample_type & PERF_SAMPLE_BRANCH_STACK)
820 branch_stack__printf(sample);
747} 821}
748 822
749static struct machine * 823static struct machine *
@@ -796,6 +870,10 @@ static int perf_session_deliver_event(struct perf_session *session,
796 ++session->hists.stats.nr_unknown_id; 870 ++session->hists.stats.nr_unknown_id;
797 return -1; 871 return -1;
798 } 872 }
873 if (machine == NULL) {
874 ++session->hists.stats.nr_unprocessable_samples;
875 return -1;
876 }
799 return tool->sample(tool, event, sample, evsel, machine); 877 return tool->sample(tool, event, sample, evsel, machine);
800 case PERF_RECORD_MMAP: 878 case PERF_RECORD_MMAP:
801 return tool->mmap(tool, event, sample, machine); 879 return tool->mmap(tool, event, sample, machine);
@@ -964,6 +1042,12 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
964 session->hists.stats.nr_invalid_chains, 1042 session->hists.stats.nr_invalid_chains,
965 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]); 1043 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
966 } 1044 }
1045
1046 if (session->hists.stats.nr_unprocessable_samples != 0) {
1047 ui__warning("%u unprocessable samples recorded.\n"
1048 "Do you have a KVM guest running and not using 'perf kvm'?\n",
1049 session->hists.stats.nr_unprocessable_samples);
1050 }
967} 1051}
968 1052
969#define session_done() (*(volatile int *)(&session_done)) 1053#define session_done() (*(volatile int *)(&session_done))
@@ -1293,10 +1377,9 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1293 1377
1294void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 1378void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1295 struct machine *machine, struct perf_evsel *evsel, 1379 struct machine *machine, struct perf_evsel *evsel,
1296 int print_sym, int print_dso) 1380 int print_sym, int print_dso, int print_symoffset)
1297{ 1381{
1298 struct addr_location al; 1382 struct addr_location al;
1299 const char *symname, *dsoname;
1300 struct callchain_cursor *cursor = &evsel->hists.callchain_cursor; 1383 struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
1301 struct callchain_cursor_node *node; 1384 struct callchain_cursor_node *node;
1302 1385
@@ -1324,20 +1407,13 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1324 1407
1325 printf("\t%16" PRIx64, node->ip); 1408 printf("\t%16" PRIx64, node->ip);
1326 if (print_sym) { 1409 if (print_sym) {
1327 if (node->sym && node->sym->name) 1410 printf(" ");
1328 symname = node->sym->name; 1411 symbol__fprintf_symname(node->sym, stdout);
1329 else
1330 symname = "";
1331
1332 printf(" %s", symname);
1333 } 1412 }
1334 if (print_dso) { 1413 if (print_dso) {
1335 if (node->map && node->map->dso && node->map->dso->name) 1414 printf(" (");
1336 dsoname = node->map->dso->name; 1415 map__fprintf_dsoname(al.map, stdout);
1337 else 1416 printf(")");
1338 dsoname = "";
1339
1340 printf(" (%s)", dsoname);
1341 } 1417 }
1342 printf("\n"); 1418 printf("\n");
1343 1419
@@ -1347,21 +1423,18 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1347 } else { 1423 } else {
1348 printf("%16" PRIx64, sample->ip); 1424 printf("%16" PRIx64, sample->ip);
1349 if (print_sym) { 1425 if (print_sym) {
1350 if (al.sym && al.sym->name) 1426 printf(" ");
1351 symname = al.sym->name; 1427 if (print_symoffset)
1428 symbol__fprintf_symname_offs(al.sym, &al,
1429 stdout);
1352 else 1430 else
1353 symname = ""; 1431 symbol__fprintf_symname(al.sym, stdout);
1354
1355 printf(" %s", symname);
1356 } 1432 }
1357 1433
1358 if (print_dso) { 1434 if (print_dso) {
1359 if (al.map && al.map->dso && al.map->dso->name) 1435 printf(" (");
1360 dsoname = al.map->dso->name; 1436 map__fprintf_dsoname(al.map, stdout);
1361 else 1437 printf(")");
1362 dsoname = "";
1363
1364 printf(" (%s)", dsoname);
1365 } 1438 }
1366 } 1439 }
1367} 1440}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 37bc38381fb6..7a5434c00565 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -73,6 +73,10 @@ int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel
73 struct ip_callchain *chain, 73 struct ip_callchain *chain,
74 struct symbol **parent); 74 struct symbol **parent);
75 75
76struct branch_info *machine__resolve_bstack(struct machine *self,
77 struct thread *thread,
78 struct branch_stack *bs);
79
76bool perf_session__has_traces(struct perf_session *self, const char *msg); 80bool perf_session__has_traces(struct perf_session *self, const char *msg);
77 81
78void mem_bswap_64(void *src, int byte_size); 82void mem_bswap_64(void *src, int byte_size);
@@ -147,7 +151,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
147 151
148void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 152void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
149 struct machine *machine, struct perf_evsel *evsel, 153 struct machine *machine, struct perf_evsel *evsel,
150 int print_sym, int print_dso); 154 int print_sym, int print_dso, int print_symoffset);
151 155
152int perf_session__cpu_bitmap(struct perf_session *session, 156int perf_session__cpu_bitmap(struct perf_session *session,
153 const char *cpu_list, unsigned long *cpu_bitmap); 157 const char *cpu_list, unsigned long *cpu_bitmap);
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 36d4c5619575..d0f9f29cf181 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -24,11 +24,11 @@ cflags += getenv('CFLAGS', '').split()
24build_lib = getenv('PYTHON_EXTBUILD_LIB') 24build_lib = getenv('PYTHON_EXTBUILD_LIB')
25build_tmp = getenv('PYTHON_EXTBUILD_TMP') 25build_tmp = getenv('PYTHON_EXTBUILD_TMP')
26 26
27ext_sources = [f.strip() for f in file('util/python-ext-sources')
28 if len(f.strip()) > 0 and f[0] != '#']
29
27perf = Extension('perf', 30perf = Extension('perf',
28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 31 sources = ext_sources,
29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
30 'util/util.c', 'util/xyarray.c', 'util/cgroup.c',
31 'util/debugfs.c'],
32 include_dirs = ['util/include'], 32 include_dirs = ['util/include'],
33 extra_compile_args = cflags, 33 extra_compile_args = cflags,
34 ) 34 )
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 16da30d8d765..a27237430c5f 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -8,6 +8,7 @@ const char default_sort_order[] = "comm,dso,symbol";
8const char *sort_order = default_sort_order; 8const char *sort_order = default_sort_order;
9int sort__need_collapse = 0; 9int sort__need_collapse = 0;
10int sort__has_parent = 0; 10int sort__has_parent = 0;
11int sort__branch_mode = -1; /* -1 = means not set */
11 12
12enum sort_type sort__first_dimension; 13enum sort_type sort__first_dimension;
13 14
@@ -33,6 +34,9 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
33 } 34 }
34 } 35 }
35 va_end(ap); 36 va_end(ap);
37
38 if (n >= (int)size)
39 return size - 1;
36 return n; 40 return n;
37} 41}
38 42
@@ -94,6 +98,26 @@ static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
94 return repsep_snprintf(bf, size, "%*s", width, self->thread->comm); 98 return repsep_snprintf(bf, size, "%*s", width, self->thread->comm);
95} 99}
96 100
101static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
102{
103 struct dso *dso_l = map_l ? map_l->dso : NULL;
104 struct dso *dso_r = map_r ? map_r->dso : NULL;
105 const char *dso_name_l, *dso_name_r;
106
107 if (!dso_l || !dso_r)
108 return cmp_null(dso_l, dso_r);
109
110 if (verbose) {
111 dso_name_l = dso_l->long_name;
112 dso_name_r = dso_r->long_name;
113 } else {
114 dso_name_l = dso_l->short_name;
115 dso_name_r = dso_r->short_name;
116 }
117
118 return strcmp(dso_name_l, dso_name_r);
119}
120
97struct sort_entry sort_comm = { 121struct sort_entry sort_comm = {
98 .se_header = "Command", 122 .se_header = "Command",
99 .se_cmp = sort__comm_cmp, 123 .se_cmp = sort__comm_cmp,
@@ -107,36 +131,74 @@ struct sort_entry sort_comm = {
107static int64_t 131static int64_t
108sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) 132sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
109{ 133{
110 struct dso *dso_l = left->ms.map ? left->ms.map->dso : NULL; 134 return _sort__dso_cmp(left->ms.map, right->ms.map);
111 struct dso *dso_r = right->ms.map ? right->ms.map->dso : NULL; 135}
112 const char *dso_name_l, *dso_name_r;
113 136
114 if (!dso_l || !dso_r)
115 return cmp_null(dso_l, dso_r);
116 137
117 if (verbose) { 138static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r,
118 dso_name_l = dso_l->long_name; 139 u64 ip_l, u64 ip_r)
119 dso_name_r = dso_r->long_name; 140{
120 } else { 141 if (!sym_l || !sym_r)
121 dso_name_l = dso_l->short_name; 142 return cmp_null(sym_l, sym_r);
122 dso_name_r = dso_r->short_name; 143
144 if (sym_l == sym_r)
145 return 0;
146
147 if (sym_l)
148 ip_l = sym_l->start;
149 if (sym_r)
150 ip_r = sym_r->start;
151
152 return (int64_t)(ip_r - ip_l);
153}
154
155static int _hist_entry__dso_snprintf(struct map *map, char *bf,
156 size_t size, unsigned int width)
157{
158 if (map && map->dso) {
159 const char *dso_name = !verbose ? map->dso->short_name :
160 map->dso->long_name;
161 return repsep_snprintf(bf, size, "%-*s", width, dso_name);
123 } 162 }
124 163
125 return strcmp(dso_name_l, dso_name_r); 164 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
126} 165}
127 166
128static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, 167static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
129 size_t size, unsigned int width) 168 size_t size, unsigned int width)
130{ 169{
131 if (self->ms.map && self->ms.map->dso) { 170 return _hist_entry__dso_snprintf(self->ms.map, bf, size, width);
132 const char *dso_name = !verbose ? self->ms.map->dso->short_name : 171}
133 self->ms.map->dso->long_name; 172
134 return repsep_snprintf(bf, size, "%-*s", width, dso_name); 173static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
174 u64 ip, char level, char *bf, size_t size,
175 unsigned int width __used)
176{
177 size_t ret = 0;
178
179 if (verbose) {
180 char o = map ? dso__symtab_origin(map->dso) : '!';
181 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
182 BITS_PER_LONG / 4, ip, o);
135 } 183 }
136 184
137 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); 185 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
186 if (sym)
187 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
188 width - ret,
189 sym->name);
190 else {
191 size_t len = BITS_PER_LONG / 4;
192 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
193 len, ip);
194 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
195 width - ret, "");
196 }
197
198 return ret;
138} 199}
139 200
201
140struct sort_entry sort_dso = { 202struct sort_entry sort_dso = {
141 .se_header = "Shared Object", 203 .se_header = "Shared Object",
142 .se_cmp = sort__dso_cmp, 204 .se_cmp = sort__dso_cmp,
@@ -144,8 +206,14 @@ struct sort_entry sort_dso = {
144 .se_width_idx = HISTC_DSO, 206 .se_width_idx = HISTC_DSO,
145}; 207};
146 208
147/* --sort symbol */ 209static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
210 size_t size, unsigned int width __used)
211{
212 return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip,
213 self->level, bf, size, width);
214}
148 215
216/* --sort symbol */
149static int64_t 217static int64_t
150sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 218sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
151{ 219{
@@ -163,31 +231,7 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
163 ip_l = left->ms.sym->start; 231 ip_l = left->ms.sym->start;
164 ip_r = right->ms.sym->start; 232 ip_r = right->ms.sym->start;
165 233
166 return (int64_t)(ip_r - ip_l); 234 return _sort__sym_cmp(left->ms.sym, right->ms.sym, ip_l, ip_r);
167}
168
169static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
170 size_t size, unsigned int width __used)
171{
172 size_t ret = 0;
173
174 if (verbose) {
175 char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
176 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
177 BITS_PER_LONG / 4, self->ip, o);
178 }
179
180 if (!sort_dso.elide)
181 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level);
182
183 if (self->ms.sym)
184 ret += repsep_snprintf(bf + ret, size - ret, "%s",
185 self->ms.sym->name);
186 else
187 ret += repsep_snprintf(bf + ret, size - ret, "%-#*llx",
188 BITS_PER_LONG / 4, self->ip);
189
190 return ret;
191} 235}
192 236
193struct sort_entry sort_sym = { 237struct sort_entry sort_sym = {
@@ -246,19 +290,155 @@ struct sort_entry sort_cpu = {
246 .se_width_idx = HISTC_CPU, 290 .se_width_idx = HISTC_CPU,
247}; 291};
248 292
293static int64_t
294sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
295{
296 return _sort__dso_cmp(left->branch_info->from.map,
297 right->branch_info->from.map);
298}
299
300static int hist_entry__dso_from_snprintf(struct hist_entry *self, char *bf,
301 size_t size, unsigned int width)
302{
303 return _hist_entry__dso_snprintf(self->branch_info->from.map,
304 bf, size, width);
305}
306
307struct sort_entry sort_dso_from = {
308 .se_header = "Source Shared Object",
309 .se_cmp = sort__dso_from_cmp,
310 .se_snprintf = hist_entry__dso_from_snprintf,
311 .se_width_idx = HISTC_DSO_FROM,
312};
313
314static int64_t
315sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
316{
317 return _sort__dso_cmp(left->branch_info->to.map,
318 right->branch_info->to.map);
319}
320
321static int hist_entry__dso_to_snprintf(struct hist_entry *self, char *bf,
322 size_t size, unsigned int width)
323{
324 return _hist_entry__dso_snprintf(self->branch_info->to.map,
325 bf, size, width);
326}
327
328static int64_t
329sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
330{
331 struct addr_map_symbol *from_l = &left->branch_info->from;
332 struct addr_map_symbol *from_r = &right->branch_info->from;
333
334 if (!from_l->sym && !from_r->sym)
335 return right->level - left->level;
336
337 return _sort__sym_cmp(from_l->sym, from_r->sym, from_l->addr,
338 from_r->addr);
339}
340
341static int64_t
342sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
343{
344 struct addr_map_symbol *to_l = &left->branch_info->to;
345 struct addr_map_symbol *to_r = &right->branch_info->to;
346
347 if (!to_l->sym && !to_r->sym)
348 return right->level - left->level;
349
350 return _sort__sym_cmp(to_l->sym, to_r->sym, to_l->addr, to_r->addr);
351}
352
353static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf,
354 size_t size, unsigned int width __used)
355{
356 struct addr_map_symbol *from = &self->branch_info->from;
357 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
358 self->level, bf, size, width);
359
360}
361
362static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf,
363 size_t size, unsigned int width __used)
364{
365 struct addr_map_symbol *to = &self->branch_info->to;
366 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
367 self->level, bf, size, width);
368
369}
370
371struct sort_entry sort_dso_to = {
372 .se_header = "Target Shared Object",
373 .se_cmp = sort__dso_to_cmp,
374 .se_snprintf = hist_entry__dso_to_snprintf,
375 .se_width_idx = HISTC_DSO_TO,
376};
377
378struct sort_entry sort_sym_from = {
379 .se_header = "Source Symbol",
380 .se_cmp = sort__sym_from_cmp,
381 .se_snprintf = hist_entry__sym_from_snprintf,
382 .se_width_idx = HISTC_SYMBOL_FROM,
383};
384
385struct sort_entry sort_sym_to = {
386 .se_header = "Target Symbol",
387 .se_cmp = sort__sym_to_cmp,
388 .se_snprintf = hist_entry__sym_to_snprintf,
389 .se_width_idx = HISTC_SYMBOL_TO,
390};
391
392static int64_t
393sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
394{
395 const unsigned char mp = left->branch_info->flags.mispred !=
396 right->branch_info->flags.mispred;
397 const unsigned char p = left->branch_info->flags.predicted !=
398 right->branch_info->flags.predicted;
399
400 return mp || p;
401}
402
403static int hist_entry__mispredict_snprintf(struct hist_entry *self, char *bf,
404 size_t size, unsigned int width){
405 static const char *out = "N/A";
406
407 if (self->branch_info->flags.predicted)
408 out = "N";
409 else if (self->branch_info->flags.mispred)
410 out = "Y";
411
412 return repsep_snprintf(bf, size, "%-*s", width, out);
413}
414
415struct sort_entry sort_mispredict = {
416 .se_header = "Branch Mispredicted",
417 .se_cmp = sort__mispredict_cmp,
418 .se_snprintf = hist_entry__mispredict_snprintf,
419 .se_width_idx = HISTC_MISPREDICT,
420};
421
249struct sort_dimension { 422struct sort_dimension {
250 const char *name; 423 const char *name;
251 struct sort_entry *entry; 424 struct sort_entry *entry;
252 int taken; 425 int taken;
253}; 426};
254 427
428#define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
429
255static struct sort_dimension sort_dimensions[] = { 430static struct sort_dimension sort_dimensions[] = {
256 { .name = "pid", .entry = &sort_thread, }, 431 DIM(SORT_PID, "pid", sort_thread),
257 { .name = "comm", .entry = &sort_comm, }, 432 DIM(SORT_COMM, "comm", sort_comm),
258 { .name = "dso", .entry = &sort_dso, }, 433 DIM(SORT_DSO, "dso", sort_dso),
259 { .name = "symbol", .entry = &sort_sym, }, 434 DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
260 { .name = "parent", .entry = &sort_parent, }, 435 DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
261 { .name = "cpu", .entry = &sort_cpu, }, 436 DIM(SORT_SYM, "symbol", sort_sym),
437 DIM(SORT_SYM_TO, "symbol_from", sort_sym_from),
438 DIM(SORT_SYM_FROM, "symbol_to", sort_sym_to),
439 DIM(SORT_PARENT, "parent", sort_parent),
440 DIM(SORT_CPU, "cpu", sort_cpu),
441 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
262}; 442};
263 443
264int sort_dimension__add(const char *tok) 444int sort_dimension__add(const char *tok)
@@ -270,7 +450,6 @@ int sort_dimension__add(const char *tok)
270 450
271 if (strncasecmp(tok, sd->name, strlen(tok))) 451 if (strncasecmp(tok, sd->name, strlen(tok)))
272 continue; 452 continue;
273
274 if (sd->entry == &sort_parent) { 453 if (sd->entry == &sort_parent) {
275 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); 454 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
276 if (ret) { 455 if (ret) {
@@ -302,6 +481,16 @@ int sort_dimension__add(const char *tok)
302 sort__first_dimension = SORT_PARENT; 481 sort__first_dimension = SORT_PARENT;
303 else if (!strcmp(sd->name, "cpu")) 482 else if (!strcmp(sd->name, "cpu"))
304 sort__first_dimension = SORT_CPU; 483 sort__first_dimension = SORT_CPU;
484 else if (!strcmp(sd->name, "symbol_from"))
485 sort__first_dimension = SORT_SYM_FROM;
486 else if (!strcmp(sd->name, "symbol_to"))
487 sort__first_dimension = SORT_SYM_TO;
488 else if (!strcmp(sd->name, "dso_from"))
489 sort__first_dimension = SORT_DSO_FROM;
490 else if (!strcmp(sd->name, "dso_to"))
491 sort__first_dimension = SORT_DSO_TO;
492 else if (!strcmp(sd->name, "mispredict"))
493 sort__first_dimension = SORT_MISPREDICT;
305 } 494 }
306 495
307 list_add_tail(&sd->entry->list, &hist_entry__sort_list); 496 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
@@ -309,7 +498,6 @@ int sort_dimension__add(const char *tok)
309 498
310 return 0; 499 return 0;
311 } 500 }
312
313 return -ESRCH; 501 return -ESRCH;
314} 502}
315 503
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 3f67ae395752..472aa5a63a58 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -31,11 +31,16 @@ extern const char *parent_pattern;
31extern const char default_sort_order[]; 31extern const char default_sort_order[];
32extern int sort__need_collapse; 32extern int sort__need_collapse;
33extern int sort__has_parent; 33extern int sort__has_parent;
34extern int sort__branch_mode;
34extern char *field_sep; 35extern char *field_sep;
35extern struct sort_entry sort_comm; 36extern struct sort_entry sort_comm;
36extern struct sort_entry sort_dso; 37extern struct sort_entry sort_dso;
37extern struct sort_entry sort_sym; 38extern struct sort_entry sort_sym;
38extern struct sort_entry sort_parent; 39extern struct sort_entry sort_parent;
40extern struct sort_entry sort_dso_from;
41extern struct sort_entry sort_dso_to;
42extern struct sort_entry sort_sym_from;
43extern struct sort_entry sort_sym_to;
39extern enum sort_type sort__first_dimension; 44extern enum sort_type sort__first_dimension;
40 45
41/** 46/**
@@ -72,6 +77,7 @@ struct hist_entry {
72 struct hist_entry *pair; 77 struct hist_entry *pair;
73 struct rb_root sorted_chain; 78 struct rb_root sorted_chain;
74 }; 79 };
80 struct branch_info *branch_info;
75 struct callchain_root callchain[0]; 81 struct callchain_root callchain[0];
76}; 82};
77 83
@@ -82,6 +88,11 @@ enum sort_type {
82 SORT_SYM, 88 SORT_SYM,
83 SORT_PARENT, 89 SORT_PARENT,
84 SORT_CPU, 90 SORT_CPU,
91 SORT_DSO_FROM,
92 SORT_DSO_TO,
93 SORT_SYM_FROM,
94 SORT_SYM_TO,
95 SORT_MISPREDICT,
85}; 96};
86 97
87/* 98/*
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 92e068517c1a..2eeb51baf077 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -1,4 +1,5 @@
1#include "cache.h" 1#include "cache.h"
2#include <linux/kernel.h>
2 3
3int prefixcmp(const char *str, const char *prefix) 4int prefixcmp(const char *str, const char *prefix)
4{ 5{
@@ -89,14 +90,14 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
89 if (!strbuf_avail(sb)) 90 if (!strbuf_avail(sb))
90 strbuf_grow(sb, 64); 91 strbuf_grow(sb, 64);
91 va_start(ap, fmt); 92 va_start(ap, fmt);
92 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 93 len = vscnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
93 va_end(ap); 94 va_end(ap);
94 if (len < 0) 95 if (len < 0)
95 die("your vsnprintf is broken"); 96 die("your vscnprintf is broken");
96 if (len > strbuf_avail(sb)) { 97 if (len > strbuf_avail(sb)) {
97 strbuf_grow(sb, len); 98 strbuf_grow(sb, len);
98 va_start(ap, fmt); 99 va_start(ap, fmt);
99 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 100 len = vscnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
100 va_end(ap); 101 va_end(ap);
101 if (len > strbuf_avail(sb)) { 102 if (len > strbuf_avail(sb)) {
102 die("this should not happen, your snprintf is broken"); 103 die("this should not happen, your snprintf is broken");
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 215d50f2042e..c0a028c3ebaf 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,8 +1,5 @@
1#define _GNU_SOURCE
2#include <ctype.h>
3#include <dirent.h> 1#include <dirent.h>
4#include <errno.h> 2#include <errno.h>
5#include <libgen.h>
6#include <stdlib.h> 3#include <stdlib.h>
7#include <stdio.h> 4#include <stdio.h>
8#include <string.h> 5#include <string.h>
@@ -13,6 +10,7 @@
13#include <unistd.h> 10#include <unistd.h>
14#include <inttypes.h> 11#include <inttypes.h>
15#include "build-id.h" 12#include "build-id.h"
13#include "util.h"
16#include "debug.h" 14#include "debug.h"
17#include "symbol.h" 15#include "symbol.h"
18#include "strlist.h" 16#include "strlist.h"
@@ -52,6 +50,8 @@ struct symbol_conf symbol_conf = {
52 50
53int dso__name_len(const struct dso *dso) 51int dso__name_len(const struct dso *dso)
54{ 52{
53 if (!dso)
54 return strlen("[unknown]");
55 if (verbose) 55 if (verbose)
56 return dso->long_name_len; 56 return dso->long_name_len;
57 57
@@ -264,6 +264,28 @@ static size_t symbol__fprintf(struct symbol *sym, FILE *fp)
264 sym->name); 264 sym->name);
265} 265}
266 266
267size_t symbol__fprintf_symname_offs(const struct symbol *sym,
268 const struct addr_location *al, FILE *fp)
269{
270 unsigned long offset;
271 size_t length;
272
273 if (sym && sym->name) {
274 length = fprintf(fp, "%s", sym->name);
275 if (al) {
276 offset = al->addr - sym->start;
277 length += fprintf(fp, "+0x%lx", offset);
278 }
279 return length;
280 } else
281 return fprintf(fp, "[unknown]");
282}
283
284size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
285{
286 return symbol__fprintf_symname_offs(sym, NULL, fp);
287}
288
267void dso__set_long_name(struct dso *dso, char *name) 289void dso__set_long_name(struct dso *dso, char *name)
268{ 290{
269 if (name == NULL) 291 if (name == NULL)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 123c2e14353e..ac49ef208a5f 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -5,6 +5,7 @@
5#include <stdbool.h> 5#include <stdbool.h>
6#include <stdint.h> 6#include <stdint.h>
7#include "map.h" 7#include "map.h"
8#include "../perf.h"
8#include <linux/list.h> 9#include <linux/list.h>
9#include <linux/rbtree.h> 10#include <linux/rbtree.h>
10#include <stdio.h> 11#include <stdio.h>
@@ -70,6 +71,7 @@ struct symbol_conf {
70 unsigned short priv_size; 71 unsigned short priv_size;
71 unsigned short nr_events; 72 unsigned short nr_events;
72 bool try_vmlinux_path, 73 bool try_vmlinux_path,
74 show_kernel_path,
73 use_modules, 75 use_modules,
74 sort_by_name, 76 sort_by_name,
75 show_nr_samples, 77 show_nr_samples,
@@ -95,7 +97,11 @@ struct symbol_conf {
95 *col_width_list_str; 97 *col_width_list_str;
96 struct strlist *dso_list, 98 struct strlist *dso_list,
97 *comm_list, 99 *comm_list,
98 *sym_list; 100 *sym_list,
101 *dso_from_list,
102 *dso_to_list,
103 *sym_from_list,
104 *sym_to_list;
99 const char *symfs; 105 const char *symfs;
100}; 106};
101 107
@@ -119,6 +125,19 @@ struct map_symbol {
119 bool has_children; 125 bool has_children;
120}; 126};
121 127
128struct addr_map_symbol {
129 struct map *map;
130 struct symbol *sym;
131 u64 addr;
132 u64 al_addr;
133};
134
135struct branch_info {
136 struct addr_map_symbol from;
137 struct addr_map_symbol to;
138 struct branch_flags flags;
139};
140
122struct addr_location { 141struct addr_location {
123 struct thread *thread; 142 struct thread *thread;
124 struct map *map; 143 struct map *map;
@@ -241,6 +260,9 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines);
241 260
242int symbol__init(void); 261int symbol__init(void);
243void symbol__exit(void); 262void symbol__exit(void);
263size_t symbol__fprintf_symname_offs(const struct symbol *sym,
264 const struct addr_location *al, FILE *fp);
265size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
244bool symbol_type__is_a(char symbol_type, enum map_type map_type); 266bool symbol_type__is_a(char symbol_type, enum map_type map_type);
245 267
246size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 268size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
diff --git a/tools/perf/util/sysfs.c b/tools/perf/util/sysfs.c
new file mode 100644
index 000000000000..48c6902e749f
--- /dev/null
+++ b/tools/perf/util/sysfs.c
@@ -0,0 +1,60 @@
1
2#include "util.h"
3#include "sysfs.h"
4
5static const char * const sysfs_known_mountpoints[] = {
6 "/sys",
7 0,
8};
9
10static int sysfs_found;
11char sysfs_mountpoint[PATH_MAX];
12
13static int sysfs_valid_mountpoint(const char *sysfs)
14{
15 struct statfs st_fs;
16
17 if (statfs(sysfs, &st_fs) < 0)
18 return -ENOENT;
19 else if (st_fs.f_type != (long) SYSFS_MAGIC)
20 return -ENOENT;
21
22 return 0;
23}
24
25const char *sysfs_find_mountpoint(void)
26{
27 const char * const *ptr;
28 char type[100];
29 FILE *fp;
30
31 if (sysfs_found)
32 return (const char *) sysfs_mountpoint;
33
34 ptr = sysfs_known_mountpoints;
35 while (*ptr) {
36 if (sysfs_valid_mountpoint(*ptr) == 0) {
37 sysfs_found = 1;
38 strcpy(sysfs_mountpoint, *ptr);
39 return sysfs_mountpoint;
40 }
41 ptr++;
42 }
43
44 /* give up and parse /proc/mounts */
45 fp = fopen("/proc/mounts", "r");
46 if (fp == NULL)
47 return NULL;
48
49 while (!sysfs_found &&
50 fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
51 sysfs_mountpoint, type) == 2) {
52
53 if (strcmp(type, "sysfs") == 0)
54 sysfs_found = 1;
55 }
56
57 fclose(fp);
58
59 return sysfs_found ? sysfs_mountpoint : NULL;
60}
diff --git a/tools/perf/util/sysfs.h b/tools/perf/util/sysfs.h
new file mode 100644
index 000000000000..a813b7203938
--- /dev/null
+++ b/tools/perf/util/sysfs.h
@@ -0,0 +1,6 @@
1#ifndef __SYSFS_H__
2#define __SYSFS_H__
3
4const char *sysfs_find_mountpoint(void);
5
6#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index a5df131b77c3..84d9bd782004 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -1,6 +1,13 @@
1#include <dirent.h> 1#include <dirent.h>
2#include <limits.h>
3#include <stdbool.h>
2#include <stdlib.h> 4#include <stdlib.h>
3#include <stdio.h> 5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include "strlist.h"
10#include <string.h>
4#include "thread_map.h" 11#include "thread_map.h"
5 12
6/* Skip "." and ".." directories */ 13/* Skip "." and ".." directories */
@@ -23,7 +30,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
23 sprintf(name, "/proc/%d/task", pid); 30 sprintf(name, "/proc/%d/task", pid);
24 items = scandir(name, &namelist, filter, NULL); 31 items = scandir(name, &namelist, filter, NULL);
25 if (items <= 0) 32 if (items <= 0)
26 return NULL; 33 return NULL;
27 34
28 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); 35 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
29 if (threads != NULL) { 36 if (threads != NULL) {
@@ -51,14 +58,240 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
51 return threads; 58 return threads;
52} 59}
53 60
54struct thread_map *thread_map__new(pid_t pid, pid_t tid) 61struct thread_map *thread_map__new_by_uid(uid_t uid)
62{
63 DIR *proc;
64 int max_threads = 32, items, i;
65 char path[256];
66 struct dirent dirent, *next, **namelist = NULL;
67 struct thread_map *threads = malloc(sizeof(*threads) +
68 max_threads * sizeof(pid_t));
69 if (threads == NULL)
70 goto out;
71
72 proc = opendir("/proc");
73 if (proc == NULL)
74 goto out_free_threads;
75
76 threads->nr = 0;
77
78 while (!readdir_r(proc, &dirent, &next) && next) {
79 char *end;
80 bool grow = false;
81 struct stat st;
82 pid_t pid = strtol(dirent.d_name, &end, 10);
83
84 if (*end) /* only interested in proper numerical dirents */
85 continue;
86
87 snprintf(path, sizeof(path), "/proc/%s", dirent.d_name);
88
89 if (stat(path, &st) != 0)
90 continue;
91
92 if (st.st_uid != uid)
93 continue;
94
95 snprintf(path, sizeof(path), "/proc/%d/task", pid);
96 items = scandir(path, &namelist, filter, NULL);
97 if (items <= 0)
98 goto out_free_closedir;
99
100 while (threads->nr + items >= max_threads) {
101 max_threads *= 2;
102 grow = true;
103 }
104
105 if (grow) {
106 struct thread_map *tmp;
107
108 tmp = realloc(threads, (sizeof(*threads) +
109 max_threads * sizeof(pid_t)));
110 if (tmp == NULL)
111 goto out_free_namelist;
112
113 threads = tmp;
114 }
115
116 for (i = 0; i < items; i++)
117 threads->map[threads->nr + i] = atoi(namelist[i]->d_name);
118
119 for (i = 0; i < items; i++)
120 free(namelist[i]);
121 free(namelist);
122
123 threads->nr += items;
124 }
125
126out_closedir:
127 closedir(proc);
128out:
129 return threads;
130
131out_free_threads:
132 free(threads);
133 return NULL;
134
135out_free_namelist:
136 for (i = 0; i < items; i++)
137 free(namelist[i]);
138 free(namelist);
139
140out_free_closedir:
141 free(threads);
142 threads = NULL;
143 goto out_closedir;
144}
145
146struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
55{ 147{
56 if (pid != -1) 148 if (pid != -1)
57 return thread_map__new_by_pid(pid); 149 return thread_map__new_by_pid(pid);
150
151 if (tid == -1 && uid != UINT_MAX)
152 return thread_map__new_by_uid(uid);
153
58 return thread_map__new_by_tid(tid); 154 return thread_map__new_by_tid(tid);
59} 155}
60 156
157static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
158{
159 struct thread_map *threads = NULL, *nt;
160 char name[256];
161 int items, total_tasks = 0;
162 struct dirent **namelist = NULL;
163 int i, j = 0;
164 pid_t pid, prev_pid = INT_MAX;
165 char *end_ptr;
166 struct str_node *pos;
167 struct strlist *slist = strlist__new(false, pid_str);
168
169 if (!slist)
170 return NULL;
171
172 strlist__for_each(pos, slist) {
173 pid = strtol(pos->s, &end_ptr, 10);
174
175 if (pid == INT_MIN || pid == INT_MAX ||
176 (*end_ptr != '\0' && *end_ptr != ','))
177 goto out_free_threads;
178
179 if (pid == prev_pid)
180 continue;
181
182 sprintf(name, "/proc/%d/task", pid);
183 items = scandir(name, &namelist, filter, NULL);
184 if (items <= 0)
185 goto out_free_threads;
186
187 total_tasks += items;
188 nt = realloc(threads, (sizeof(*threads) +
189 sizeof(pid_t) * total_tasks));
190 if (nt == NULL)
191 goto out_free_threads;
192
193 threads = nt;
194
195 if (threads) {
196 for (i = 0; i < items; i++)
197 threads->map[j++] = atoi(namelist[i]->d_name);
198 threads->nr = total_tasks;
199 }
200
201 for (i = 0; i < items; i++)
202 free(namelist[i]);
203 free(namelist);
204
205 if (!threads)
206 break;
207 }
208
209out:
210 strlist__delete(slist);
211 return threads;
212
213out_free_threads:
214 free(threads);
215 threads = NULL;
216 goto out;
217}
218
219static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
220{
221 struct thread_map *threads = NULL, *nt;
222 int ntasks = 0;
223 pid_t tid, prev_tid = INT_MAX;
224 char *end_ptr;
225 struct str_node *pos;
226 struct strlist *slist;
227
228 /* perf-stat expects threads to be generated even if tid not given */
229 if (!tid_str) {
230 threads = malloc(sizeof(*threads) + sizeof(pid_t));
231 if (threads != NULL) {
232 threads->map[0] = -1;
233 threads->nr = 1;
234 }
235 return threads;
236 }
237
238 slist = strlist__new(false, tid_str);
239 if (!slist)
240 return NULL;
241
242 strlist__for_each(pos, slist) {
243 tid = strtol(pos->s, &end_ptr, 10);
244
245 if (tid == INT_MIN || tid == INT_MAX ||
246 (*end_ptr != '\0' && *end_ptr != ','))
247 goto out_free_threads;
248
249 if (tid == prev_tid)
250 continue;
251
252 ntasks++;
253 nt = realloc(threads, sizeof(*threads) + sizeof(pid_t) * ntasks);
254
255 if (nt == NULL)
256 goto out_free_threads;
257
258 threads = nt;
259 threads->map[ntasks - 1] = tid;
260 threads->nr = ntasks;
261 }
262out:
263 return threads;
264
265out_free_threads:
266 free(threads);
267 threads = NULL;
268 goto out;
269}
270
271struct thread_map *thread_map__new_str(const char *pid, const char *tid,
272 uid_t uid)
273{
274 if (pid)
275 return thread_map__new_by_pid_str(pid);
276
277 if (!tid && uid != UINT_MAX)
278 return thread_map__new_by_uid(uid);
279
280 return thread_map__new_by_tid_str(tid);
281}
282
61void thread_map__delete(struct thread_map *threads) 283void thread_map__delete(struct thread_map *threads)
62{ 284{
63 free(threads); 285 free(threads);
64} 286}
287
288size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)
289{
290 int i;
291 size_t printed = fprintf(fp, "%d thread%s: ",
292 threads->nr, threads->nr > 1 ? "s" : "");
293 for (i = 0; i < threads->nr; ++i)
294 printed += fprintf(fp, "%s%d", i ? ", " : "", threads->map[i]);
295
296 return printed + fprintf(fp, "\n");
297}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 3cb907311409..7da80f14418b 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -2,6 +2,7 @@
2#define __PERF_THREAD_MAP_H 2#define __PERF_THREAD_MAP_H
3 3
4#include <sys/types.h> 4#include <sys/types.h>
5#include <stdio.h>
5 6
6struct thread_map { 7struct thread_map {
7 int nr; 8 int nr;
@@ -10,6 +11,14 @@ struct thread_map {
10 11
11struct thread_map *thread_map__new_by_pid(pid_t pid); 12struct thread_map *thread_map__new_by_pid(pid_t pid);
12struct thread_map *thread_map__new_by_tid(pid_t tid); 13struct thread_map *thread_map__new_by_tid(pid_t tid);
13struct thread_map *thread_map__new(pid_t pid, pid_t tid); 14struct thread_map *thread_map__new_by_uid(uid_t uid);
15struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
16
17struct thread_map *thread_map__new_str(const char *pid,
18 const char *tid, uid_t uid);
19
14void thread_map__delete(struct thread_map *threads); 20void thread_map__delete(struct thread_map *threads);
21
22size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
23
15#endif /* __PERF_THREAD_MAP_H */ 24#endif /* __PERF_THREAD_MAP_H */
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 500471dffa4f..09fe579ccafb 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -69,12 +69,15 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
69 69
70 ret += SNPRINTF(bf + ret, size - ret, "], "); 70 ret += SNPRINTF(bf + ret, size - ret, "], ");
71 71
72 if (top->target_pid != -1) 72 if (top->target_pid)
73 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %d", 73 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s",
74 top->target_pid); 74 top->target_pid);
75 else if (top->target_tid != -1) 75 else if (top->target_tid)
76 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %d", 76 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s",
77 top->target_tid); 77 top->target_tid);
78 else if (top->uid_str != NULL)
79 ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
80 top->uid_str);
78 else 81 else
79 ret += SNPRINTF(bf + ret, size - ret, " (all"); 82 ret += SNPRINTF(bf + ret, size - ret, " (all");
80 83
@@ -82,7 +85,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
82 ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)", 85 ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
83 top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list); 86 top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list);
84 else { 87 else {
85 if (top->target_tid != -1) 88 if (top->target_tid)
86 ret += SNPRINTF(bf + ret, size - ret, ")"); 89 ret += SNPRINTF(bf + ret, size - ret, ")");
87 else 90 else
88 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", 91 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index a248f3c2c60d..ce61cb2d1acf 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -23,7 +23,8 @@ struct perf_top {
23 u64 guest_us_samples, guest_kernel_samples; 23 u64 guest_us_samples, guest_kernel_samples;
24 int print_entries, count_filter, delay_secs; 24 int print_entries, count_filter, delay_secs;
25 int freq; 25 int freq;
26 pid_t target_pid, target_tid; 26 const char *target_pid, *target_tid;
27 uid_t uid;
27 bool hide_kernel_symbols, hide_user_symbols, zero; 28 bool hide_kernel_symbols, hide_user_symbols, zero;
28 bool system_wide; 29 bool system_wide;
29 bool use_tui, use_stdio; 30 bool use_tui, use_stdio;
@@ -33,7 +34,8 @@ struct perf_top {
33 bool vmlinux_warned; 34 bool vmlinux_warned;
34 bool inherit; 35 bool inherit;
35 bool group; 36 bool group;
36 bool sample_id_all_avail; 37 bool sample_id_all_missing;
38 bool exclude_guest_missing;
37 bool dump_symtab; 39 bool dump_symtab;
38 const char *cpu_list; 40 const char *cpu_list;
39 struct hist_entry *sym_filter_entry; 41 struct hist_entry *sym_filter_entry;
@@ -45,6 +47,7 @@ struct perf_top {
45 int realtime_prio; 47 int realtime_prio;
46 int sym_pcnt_filter; 48 int sym_pcnt_filter;
47 const char *sym_filter; 49 const char *sym_filter;
50 const char *uid_str;
48}; 51};
49 52
50size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 53size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index ac6830d8292b..fc22cf5c605f 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -18,7 +18,6 @@
18 * 18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */ 20 */
21#include <ctype.h>
22#include "util.h" 21#include "util.h"
23#include <dirent.h> 22#include <dirent.h>
24#include <mntent.h> 23#include <mntent.h>
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 6c164dc9ee95..dfd1bd8371a4 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -21,14 +21,12 @@
21 * The parts for function graph printing was taken and modified from the 21 * The parts for function graph printing was taken and modified from the
22 * Linux Kernel that were written by Frederic Weisbecker. 22 * Linux Kernel that were written by Frederic Weisbecker.
23 */ 23 */
24#define _GNU_SOURCE 24
25#include <stdio.h> 25#include <stdio.h>
26#include <stdlib.h> 26#include <stdlib.h>
27#include <string.h> 27#include <string.h>
28#include <ctype.h>
29#include <errno.h> 28#include <errno.h>
30 29
31#undef _GNU_SOURCE
32#include "../perf.h" 30#include "../perf.h"
33#include "util.h" 31#include "util.h"
34#include "trace-event.h" 32#include "trace-event.h"
@@ -724,7 +722,7 @@ static char *event_read_name(void)
724static int event_read_id(void) 722static int event_read_id(void)
725{ 723{
726 char *token; 724 char *token;
727 int id; 725 int id = -1;
728 726
729 if (read_expected_item(EVENT_ITEM, "ID") < 0) 727 if (read_expected_item(EVENT_ITEM, "ID") < 0)
730 return -1; 728 return -1;
@@ -733,15 +731,13 @@ static int event_read_id(void)
733 return -1; 731 return -1;
734 732
735 if (read_expect_type(EVENT_ITEM, &token) < 0) 733 if (read_expect_type(EVENT_ITEM, &token) < 0)
736 goto fail; 734 goto free;
737 735
738 id = strtoul(token, NULL, 0); 736 id = strtoul(token, NULL, 0);
739 free_token(token);
740 return id;
741 737
742 fail: 738 free:
743 free_token(token); 739 free_token(token);
744 return -1; 740 return id;
745} 741}
746 742
747static int field_is_string(struct format_field *field) 743static int field_is_string(struct format_field *field)
@@ -1425,6 +1421,11 @@ static long long arg_num_eval(struct print_arg *arg)
1425 die("unknown op '%s'", arg->op.op); 1421 die("unknown op '%s'", arg->op.op);
1426 } 1422 }
1427 break; 1423 break;
1424 case '+':
1425 left = arg_num_eval(arg->op.left);
1426 right = arg_num_eval(arg->op.right);
1427 val = left + right;
1428 break;
1428 default: 1429 default:
1429 die("unknown op '%s'", arg->op.op); 1430 die("unknown op '%s'", arg->op.op);
1430 } 1431 }
@@ -1485,6 +1486,13 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1485 1486
1486 free_token(token); 1487 free_token(token);
1487 type = process_arg(event, arg, &token); 1488 type = process_arg(event, arg, &token);
1489
1490 if (type == EVENT_OP)
1491 type = process_op(event, arg, &token);
1492
1493 if (type == EVENT_ERROR)
1494 goto out_free;
1495
1488 if (test_type_token(type, token, EVENT_DELIM, ",")) 1496 if (test_type_token(type, token, EVENT_DELIM, ","))
1489 goto out_free; 1497 goto out_free;
1490 1498
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index f55cc3a765a1..b9592e0de8d7 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -33,7 +33,6 @@
33#include <pthread.h> 33#include <pthread.h>
34#include <fcntl.h> 34#include <fcntl.h>
35#include <unistd.h> 35#include <unistd.h>
36#include <ctype.h>
37#include <errno.h> 36#include <errno.h>
38 37
39#include "../perf.h" 38#include "../perf.h"
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index a3fdf55f317b..18ae6c1831d3 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -22,7 +22,6 @@
22#include <stdio.h> 22#include <stdio.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <string.h> 24#include <string.h>
25#include <ctype.h>
26#include <errno.h> 25#include <errno.h>
27 26
28#include "../perf.h" 27#include "../perf.h"
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h
index 84d761b730c1..6ee82f60feaf 100644
--- a/tools/perf/util/ui/browser.h
+++ b/tools/perf/util/ui/browser.h
@@ -49,6 +49,8 @@ int ui_browser__warning(struct ui_browser *browser, int timeout,
49 const char *format, ...); 49 const char *format, ...);
50int ui_browser__help_window(struct ui_browser *browser, const char *text); 50int ui_browser__help_window(struct ui_browser *browser, const char *text);
51bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text); 51bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
52int ui_browser__input_window(const char *title, const char *text, char *input,
53 const char *exit_msg, int delay_sec);
52 54
53void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence); 55void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
54unsigned int ui_browser__argv_refresh(struct ui_browser *browser); 56unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 295a9c93f945..57a4c6ef3fd2 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -69,14 +69,17 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
69 if (!self->navkeypressed) 69 if (!self->navkeypressed)
70 width += 1; 70 width += 1;
71 71
72 if (!ab->hide_src_code && ol->offset != -1)
73 if (!current_entry || (self->use_navkeypressed &&
74 !self->navkeypressed))
75 ui_browser__set_color(self, HE_COLORSET_CODE);
76
72 if (!*ol->line) 77 if (!*ol->line)
73 slsmg_write_nstring(" ", width - 18); 78 slsmg_write_nstring(" ", width - 18);
74 else 79 else
75 slsmg_write_nstring(ol->line, width - 18); 80 slsmg_write_nstring(ol->line, width - 18);
76 81
77 if (!current_entry) 82 if (current_entry)
78 ui_browser__set_color(self, HE_COLORSET_CODE);
79 else
80 ab->selection = ol; 83 ab->selection = ol;
81} 84}
82 85
@@ -230,9 +233,9 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
230 struct rb_node *nd = NULL; 233 struct rb_node *nd = NULL;
231 struct map_symbol *ms = self->b.priv; 234 struct map_symbol *ms = self->b.priv;
232 struct symbol *sym = ms->sym; 235 struct symbol *sym = ms->sym;
233 const char *help = "<-, ESC: exit, TAB/shift+TAB: cycle hottest lines, " 236 const char *help = "<-/ESC: Exit, TAB/shift+TAB: Cycle hot lines, "
234 "H: Hottest, -> Line action, S -> Toggle source " 237 "H: Go to hottest line, ->/ENTER: Line action, "
235 "code view"; 238 "S: Toggle source code view";
236 int key; 239 int key;
237 240
238 if (ui_browser__show(&self->b, sym->name, help) < 0) 241 if (ui_browser__show(&self->b, sym->name, help) < 0)
@@ -284,9 +287,11 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
284 nd = self->curr_hot; 287 nd = self->curr_hot;
285 break; 288 break;
286 case 'H': 289 case 'H':
290 case 'h':
287 nd = self->curr_hot; 291 nd = self->curr_hot;
288 break; 292 break;
289 case 'S': 293 case 'S':
294 case 's':
290 if (annotate_browser__toggle_source(self)) 295 if (annotate_browser__toggle_source(self))
291 ui_helpline__puts(help); 296 ui_helpline__puts(help);
292 continue; 297 continue;
@@ -338,6 +343,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
338 pthread_mutex_unlock(&notes->lock); 343 pthread_mutex_unlock(&notes->lock);
339 symbol__tui_annotate(target, ms->map, evidx, 344 symbol__tui_annotate(target, ms->map, evidx,
340 timer, arg, delay_secs); 345 timer, arg, delay_secs);
346 ui_browser__show_title(&self->b, sym->name);
341 } 347 }
342 continue; 348 continue;
343 case K_LEFT: 349 case K_LEFT:
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index 1212a386a033..d7a1c4afe28b 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -1,6 +1,4 @@
1#define _GNU_SOURCE
2#include <stdio.h> 1#include <stdio.h>
3#undef _GNU_SOURCE
4#include "../libslang.h" 2#include "../libslang.h"
5#include <stdlib.h> 3#include <stdlib.h>
6#include <string.h> 4#include <string.h>
@@ -807,8 +805,11 @@ static struct hist_browser *hist_browser__new(struct hists *hists)
807 self->hists = hists; 805 self->hists = hists;
808 self->b.refresh = hist_browser__refresh; 806 self->b.refresh = hist_browser__refresh;
809 self->b.seek = ui_browser__hists_seek; 807 self->b.seek = ui_browser__hists_seek;
810 self->b.use_navkeypressed = true, 808 self->b.use_navkeypressed = true;
811 self->has_symbols = sort_sym.list.next != NULL; 809 if (sort__branch_mode == 1)
810 self->has_symbols = sort_sym_from.list.next != NULL;
811 else
812 self->has_symbols = sort_sym.list.next != NULL;
812 } 813 }
813 814
814 return self; 815 return self;
@@ -839,19 +840,32 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
839 unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE]; 840 unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];
840 841
841 nr_events = convert_unit(nr_events, &unit); 842 nr_events = convert_unit(nr_events, &unit);
842 printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name); 843 printed = scnprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name);
843 844
844 if (thread) 845 if (self->uid_filter_str)
845 printed += snprintf(bf + printed, size - printed, 846 printed += snprintf(bf + printed, size - printed,
847 ", UID: %s", self->uid_filter_str);
848 if (thread)
849 printed += scnprintf(bf + printed, size - printed,
846 ", Thread: %s(%d)", 850 ", Thread: %s(%d)",
847 (thread->comm_set ? thread->comm : ""), 851 (thread->comm_set ? thread->comm : ""),
848 thread->pid); 852 thread->pid);
849 if (dso) 853 if (dso)
850 printed += snprintf(bf + printed, size - printed, 854 printed += scnprintf(bf + printed, size - printed,
851 ", DSO: %s", dso->short_name); 855 ", DSO: %s", dso->short_name);
852 return printed; 856 return printed;
853} 857}
854 858
859static inline void free_popup_options(char **options, int n)
860{
861 int i;
862
863 for (i = 0; i < n; ++i) {
864 free(options[i]);
865 options[i] = NULL;
866 }
867}
868
855static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, 869static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
856 const char *helpline, const char *ev_name, 870 const char *helpline, const char *ev_name,
857 bool left_exits, 871 bool left_exits,
@@ -860,8 +874,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
860{ 874{
861 struct hists *self = &evsel->hists; 875 struct hists *self = &evsel->hists;
862 struct hist_browser *browser = hist_browser__new(self); 876 struct hist_browser *browser = hist_browser__new(self);
877 struct branch_info *bi;
863 struct pstack *fstack; 878 struct pstack *fstack;
879 char *options[16];
880 int nr_options = 0;
864 int key = -1; 881 int key = -1;
882 char buf[64];
865 883
866 if (browser == NULL) 884 if (browser == NULL)
867 return -1; 885 return -1;
@@ -872,13 +890,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
872 890
873 ui_helpline__push(helpline); 891 ui_helpline__push(helpline);
874 892
893 memset(options, 0, sizeof(options));
894
875 while (1) { 895 while (1) {
876 const struct thread *thread = NULL; 896 const struct thread *thread = NULL;
877 const struct dso *dso = NULL; 897 const struct dso *dso = NULL;
878 char *options[16]; 898 int choice = 0,
879 int nr_options = 0, choice = 0, i,
880 annotate = -2, zoom_dso = -2, zoom_thread = -2, 899 annotate = -2, zoom_dso = -2, zoom_thread = -2,
881 browse_map = -2; 900 annotate_f = -2, annotate_t = -2, browse_map = -2;
901
902 nr_options = 0;
882 903
883 key = hist_browser__run(browser, ev_name, timer, arg, delay_secs); 904 key = hist_browser__run(browser, ev_name, timer, arg, delay_secs);
884 905
@@ -886,7 +907,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
886 thread = hist_browser__selected_thread(browser); 907 thread = hist_browser__selected_thread(browser);
887 dso = browser->selection->map ? browser->selection->map->dso : NULL; 908 dso = browser->selection->map ? browser->selection->map->dso : NULL;
888 } 909 }
889
890 switch (key) { 910 switch (key) {
891 case K_TAB: 911 case K_TAB:
892 case K_UNTAB: 912 case K_UNTAB:
@@ -901,7 +921,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
901 if (!browser->has_symbols) { 921 if (!browser->has_symbols) {
902 ui_browser__warning(&browser->b, delay_secs * 2, 922 ui_browser__warning(&browser->b, delay_secs * 2,
903 "Annotation is only available for symbolic views, " 923 "Annotation is only available for symbolic views, "
904 "include \"sym\" in --sort to use it."); 924 "include \"sym*\" in --sort to use it.");
905 continue; 925 continue;
906 } 926 }
907 927
@@ -914,6 +934,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
914 goto zoom_dso; 934 goto zoom_dso;
915 case 't': 935 case 't':
916 goto zoom_thread; 936 goto zoom_thread;
937 case 's':
938 if (ui_browser__input_window("Symbol to show",
939 "Please enter the name of symbol you want to see",
940 buf, "ENTER: OK, ESC: Cancel",
941 delay_secs * 2) == K_ENTER) {
942 self->symbol_filter_str = *buf ? buf : NULL;
943 hists__filter_by_symbol(self);
944 hist_browser__reset(browser);
945 }
946 continue;
917 case K_F1: 947 case K_F1:
918 case 'h': 948 case 'h':
919 case '?': 949 case '?':
@@ -931,7 +961,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
931 "C Collapse all callchains\n" 961 "C Collapse all callchains\n"
932 "E Expand all callchains\n" 962 "E Expand all callchains\n"
933 "d Zoom into current DSO\n" 963 "d Zoom into current DSO\n"
934 "t Zoom into current Thread"); 964 "t Zoom into current Thread\n"
965 "s Filter symbol by name");
935 continue; 966 continue;
936 case K_ENTER: 967 case K_ENTER:
937 case K_RIGHT: 968 case K_RIGHT:
@@ -971,12 +1002,34 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
971 if (!browser->has_symbols) 1002 if (!browser->has_symbols)
972 goto add_exit_option; 1003 goto add_exit_option;
973 1004
974 if (browser->selection != NULL && 1005 if (sort__branch_mode == 1) {
975 browser->selection->sym != NULL && 1006 bi = browser->he_selection->branch_info;
976 !browser->selection->map->dso->annotate_warned && 1007 if (browser->selection != NULL &&
977 asprintf(&options[nr_options], "Annotate %s", 1008 bi &&
978 browser->selection->sym->name) > 0) 1009 bi->from.sym != NULL &&
979 annotate = nr_options++; 1010 !bi->from.map->dso->annotate_warned &&
1011 asprintf(&options[nr_options], "Annotate %s",
1012 bi->from.sym->name) > 0)
1013 annotate_f = nr_options++;
1014
1015 if (browser->selection != NULL &&
1016 bi &&
1017 bi->to.sym != NULL &&
1018 !bi->to.map->dso->annotate_warned &&
1019 (bi->to.sym != bi->from.sym ||
1020 bi->to.map->dso != bi->from.map->dso) &&
1021 asprintf(&options[nr_options], "Annotate %s",
1022 bi->to.sym->name) > 0)
1023 annotate_t = nr_options++;
1024 } else {
1025
1026 if (browser->selection != NULL &&
1027 browser->selection->sym != NULL &&
1028 !browser->selection->map->dso->annotate_warned &&
1029 asprintf(&options[nr_options], "Annotate %s",
1030 browser->selection->sym->name) > 0)
1031 annotate = nr_options++;
1032 }
980 1033
981 if (thread != NULL && 1034 if (thread != NULL &&
982 asprintf(&options[nr_options], "Zoom %s %s(%d) thread", 1035 asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
@@ -997,25 +1050,39 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
997 browse_map = nr_options++; 1050 browse_map = nr_options++;
998add_exit_option: 1051add_exit_option:
999 options[nr_options++] = (char *)"Exit"; 1052 options[nr_options++] = (char *)"Exit";
1000 1053retry_popup_menu:
1001 choice = ui__popup_menu(nr_options, options); 1054 choice = ui__popup_menu(nr_options, options);
1002 1055
1003 for (i = 0; i < nr_options - 1; ++i)
1004 free(options[i]);
1005
1006 if (choice == nr_options - 1) 1056 if (choice == nr_options - 1)
1007 break; 1057 break;
1008 1058
1009 if (choice == -1) 1059 if (choice == -1) {
1060 free_popup_options(options, nr_options - 1);
1010 continue; 1061 continue;
1062 }
1011 1063
1012 if (choice == annotate) { 1064 if (choice == annotate || choice == annotate_t || choice == annotate_f) {
1013 struct hist_entry *he; 1065 struct hist_entry *he;
1014 int err; 1066 int err;
1015do_annotate: 1067do_annotate:
1016 he = hist_browser__selected_entry(browser); 1068 he = hist_browser__selected_entry(browser);
1017 if (he == NULL) 1069 if (he == NULL)
1018 continue; 1070 continue;
1071
1072 /*
1073 * we stash the branch_info symbol + map into the
1074 * the ms so we don't have to rewrite all the annotation
1075 * code to use branch_info.
1076 * in branch mode, the ms struct is not used
1077 */
1078 if (choice == annotate_f) {
1079 he->ms.sym = he->branch_info->from.sym;
1080 he->ms.map = he->branch_info->from.map;
1081 } else if (choice == annotate_t) {
1082 he->ms.sym = he->branch_info->to.sym;
1083 he->ms.map = he->branch_info->to.map;
1084 }
1085
1019 /* 1086 /*
1020 * Don't let this be freed, say, by hists__decay_entry. 1087 * Don't let this be freed, say, by hists__decay_entry.
1021 */ 1088 */
@@ -1023,9 +1090,18 @@ do_annotate:
1023 err = hist_entry__tui_annotate(he, evsel->idx, 1090 err = hist_entry__tui_annotate(he, evsel->idx,
1024 timer, arg, delay_secs); 1091 timer, arg, delay_secs);
1025 he->used = false; 1092 he->used = false;
1093 /*
1094 * offer option to annotate the other branch source or target
1095 * (if they exists) when returning from annotate
1096 */
1097 if ((err == 'q' || err == CTRL('c'))
1098 && annotate_t != -2 && annotate_f != -2)
1099 goto retry_popup_menu;
1100
1026 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); 1101 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
1027 if (err) 1102 if (err)
1028 ui_browser__handle_resize(&browser->b); 1103 ui_browser__handle_resize(&browser->b);
1104
1029 } else if (choice == browse_map) 1105 } else if (choice == browse_map)
1030 map__browse(browser->selection->map); 1106 map__browse(browser->selection->map);
1031 else if (choice == zoom_dso) { 1107 else if (choice == zoom_dso) {
@@ -1071,6 +1147,7 @@ out_free_stack:
1071 pstack__delete(fstack); 1147 pstack__delete(fstack);
1072out: 1148out:
1073 hist_browser__delete(browser); 1149 hist_browser__delete(browser);
1150 free_popup_options(options, nr_options - 1);
1074 return key; 1151 return key;
1075} 1152}
1076 1153
@@ -1097,7 +1174,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1097 HE_COLORSET_NORMAL); 1174 HE_COLORSET_NORMAL);
1098 1175
1099 nr_events = convert_unit(nr_events, &unit); 1176 nr_events = convert_unit(nr_events, &unit);
1100 printed = snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events, 1177 printed = scnprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
1101 unit, unit == ' ' ? "" : " ", ev_name); 1178 unit, unit == ' ' ? "" : " ", ev_name);
1102 slsmg_printf("%s", bf); 1179 slsmg_printf("%s", bf);
1103 1180
@@ -1107,8 +1184,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1107 if (!current_entry) 1184 if (!current_entry)
1108 ui_browser__set_color(browser, HE_COLORSET_TOP); 1185 ui_browser__set_color(browser, HE_COLORSET_TOP);
1109 nr_events = convert_unit(nr_events, &unit); 1186 nr_events = convert_unit(nr_events, &unit);
1110 snprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!", nr_events, 1187 printed += scnprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!",
1111 unit, unit == ' ' ? "" : " "); 1188 nr_events, unit, unit == ' ' ? "" : " ");
1112 warn = bf; 1189 warn = bf;
1113 } 1190 }
1114 1191
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index 6905bcc8be2d..eca6575abfd0 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -3,9 +3,9 @@
3#include <newt.h> 3#include <newt.h>
4#include <inttypes.h> 4#include <inttypes.h>
5#include <sys/ttydefaults.h> 5#include <sys/ttydefaults.h>
6#include <ctype.h>
7#include <string.h> 6#include <string.h>
8#include <linux/bitops.h> 7#include <linux/bitops.h>
8#include "../../util.h"
9#include "../../debug.h" 9#include "../../debug.h"
10#include "../../symbol.h" 10#include "../../symbol.h"
11#include "../browser.h" 11#include "../browser.h"
diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c
index 6ef3c5691762..2f950c2641c8 100644
--- a/tools/perf/util/ui/helpline.c
+++ b/tools/perf/util/ui/helpline.c
@@ -1,4 +1,3 @@
1#define _GNU_SOURCE
2#include <stdio.h> 1#include <stdio.h>
3#include <stdlib.h> 2#include <stdlib.h>
4#include <string.h> 3#include <string.h>
@@ -65,7 +64,7 @@ int ui_helpline__show_help(const char *format, va_list ap)
65 static int backlog; 64 static int backlog;
66 65
67 pthread_mutex_lock(&ui__lock); 66 pthread_mutex_lock(&ui__lock);
68 ret = vsnprintf(ui_helpline__last_msg + backlog, 67 ret = vscnprintf(ui_helpline__last_msg + backlog,
69 sizeof(ui_helpline__last_msg) - backlog, format, ap); 68 sizeof(ui_helpline__last_msg) - backlog, format, ap);
70 backlog += ret; 69 backlog += ret;
71 70
diff --git a/tools/perf/util/ui/keysyms.h b/tools/perf/util/ui/keysyms.h
index 3458b1985761..809eca5707fa 100644
--- a/tools/perf/util/ui/keysyms.h
+++ b/tools/perf/util/ui/keysyms.h
@@ -16,6 +16,8 @@
16#define K_TAB '\t' 16#define K_TAB '\t'
17#define K_UNTAB SL_KEY_UNTAB 17#define K_UNTAB SL_KEY_UNTAB
18#define K_UP SL_KEY_UP 18#define K_UP SL_KEY_UP
19#define K_BKSPC 0x7f
20#define K_DEL SL_KEY_DELETE
19 21
20/* Not really keys */ 22/* Not really keys */
21#define K_TIMER -1 23#define K_TIMER -1
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
index 45daa7c41dad..ad4374a16bb0 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -69,6 +69,88 @@ int ui__popup_menu(int argc, char * const argv[])
69 return popup_menu__run(&menu); 69 return popup_menu__run(&menu);
70} 70}
71 71
72int ui_browser__input_window(const char *title, const char *text, char *input,
73 const char *exit_msg, int delay_secs)
74{
75 int x, y, len, key;
76 int max_len = 60, nr_lines = 0;
77 static char buf[50];
78 const char *t;
79
80 t = text;
81 while (1) {
82 const char *sep = strchr(t, '\n');
83
84 if (sep == NULL)
85 sep = strchr(t, '\0');
86 len = sep - t;
87 if (max_len < len)
88 max_len = len;
89 ++nr_lines;
90 if (*sep == '\0')
91 break;
92 t = sep + 1;
93 }
94
95 max_len += 2;
96 nr_lines += 8;
97 y = SLtt_Screen_Rows / 2 - nr_lines / 2;
98 x = SLtt_Screen_Cols / 2 - max_len / 2;
99
100 SLsmg_set_color(0);
101 SLsmg_draw_box(y, x++, nr_lines, max_len);
102 if (title) {
103 SLsmg_gotorc(y, x + 1);
104 SLsmg_write_string((char *)title);
105 }
106 SLsmg_gotorc(++y, x);
107 nr_lines -= 7;
108 max_len -= 2;
109 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
110 nr_lines, max_len, 1);
111 y += nr_lines;
112 len = 5;
113 while (len--) {
114 SLsmg_gotorc(y + len - 1, x);
115 SLsmg_write_nstring((char *)" ", max_len);
116 }
117 SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
118
119 SLsmg_gotorc(y + 3, x);
120 SLsmg_write_nstring((char *)exit_msg, max_len);
121 SLsmg_refresh();
122
123 x += 2;
124 len = 0;
125 key = ui__getch(delay_secs);
126 while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
127 if (key == K_BKSPC) {
128 if (len == 0)
129 goto next_key;
130 SLsmg_gotorc(y, x + --len);
131 SLsmg_write_char(' ');
132 } else {
133 buf[len] = key;
134 SLsmg_gotorc(y, x + len++);
135 SLsmg_write_char(key);
136 }
137 SLsmg_refresh();
138
139 /* XXX more graceful overflow handling needed */
140 if (len == sizeof(buf) - 1) {
141 ui_helpline__push("maximum size of symbol name reached!");
142 key = K_ENTER;
143 break;
144 }
145next_key:
146 key = ui__getch(delay_secs);
147 }
148
149 buf[len] = '\0';
150 strncpy(input, buf, len+1);
151 return key;
152}
153
72int ui__question_window(const char *title, const char *text, 154int ui__question_window(const char *title, const char *text,
73 const char *exit_msg, int delay_secs) 155 const char *exit_msg, int delay_secs)
74{ 156{
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index d76d1c0ff98f..52bb07c6442a 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -7,6 +7,7 @@
7 * Copyright (C) Linus Torvalds, 2005 7 * Copyright (C) Linus Torvalds, 2005
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include "debug.h"
10 11
11static void report(const char *prefix, const char *err, va_list params) 12static void report(const char *prefix, const char *err, va_list params)
12{ 13{
@@ -81,3 +82,41 @@ void warning(const char *warn, ...)
81 warn_routine(warn, params); 82 warn_routine(warn, params);
82 va_end(params); 83 va_end(params);
83} 84}
85
86uid_t parse_target_uid(const char *str, const char *tid, const char *pid)
87{
88 struct passwd pwd, *result;
89 char buf[1024];
90
91 if (str == NULL)
92 return UINT_MAX;
93
94 /* UID and PID are mutually exclusive */
95 if (tid || pid) {
96 ui__warning("PID/TID switch overriding UID\n");
97 sleep(1);
98 return UINT_MAX;
99 }
100
101 getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
102
103 if (result == NULL) {
104 char *endptr;
105 int uid = strtol(str, &endptr, 10);
106
107 if (*endptr != '\0') {
108 ui__error("Invalid user %s\n", str);
109 return UINT_MAX - 1;
110 }
111
112 getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
113
114 if (result == NULL) {
115 ui__error("Problems obtaining information for user %s\n",
116 str);
117 return UINT_MAX - 1;
118 }
119 }
120
121 return result->pw_uid;
122}
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 5b3ea49aa63e..8109a907841e 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,6 +1,23 @@
1#include "../perf.h"
1#include "util.h" 2#include "util.h"
2#include <sys/mman.h> 3#include <sys/mman.h>
3 4
5/*
6 * XXX We need to find a better place for these things...
7 */
8bool perf_host = true;
9bool perf_guest = false;
10
11void event_attr_init(struct perf_event_attr *attr)
12{
13 if (!perf_host)
14 attr->exclude_host = 1;
15 if (!perf_guest)
16 attr->exclude_guest = 1;
17 /* to capture ABI version */
18 attr->size = sizeof(*attr);
19}
20
4int mkdir_p(char *path, mode_t mode) 21int mkdir_p(char *path, mode_t mode)
5{ 22{
6 struct stat st; 23 struct stat st;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 37be34dff798..0f99f394d8e0 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -40,7 +40,6 @@
40#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) 40#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
41 41
42#define _ALL_SOURCE 1 42#define _ALL_SOURCE 1
43#define _GNU_SOURCE 1
44#define _BSD_SOURCE 1 43#define _BSD_SOURCE 1
45#define HAS_BOOL 44#define HAS_BOOL
46 45
@@ -200,6 +199,8 @@ static inline int has_extension(const char *filename, const char *ext)
200#undef isalpha 199#undef isalpha
201#undef isprint 200#undef isprint
202#undef isalnum 201#undef isalnum
202#undef islower
203#undef isupper
203#undef tolower 204#undef tolower
204#undef toupper 205#undef toupper
205 206
@@ -220,6 +221,8 @@ extern unsigned char sane_ctype[256];
220#define isalpha(x) sane_istest(x,GIT_ALPHA) 221#define isalpha(x) sane_istest(x,GIT_ALPHA)
221#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 222#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
222#define isprint(x) sane_istest(x,GIT_PRINT) 223#define isprint(x) sane_istest(x,GIT_PRINT)
224#define islower(x) (sane_istest(x,GIT_ALPHA) && sane_istest(x,0x20))
225#define isupper(x) (sane_istest(x,GIT_ALPHA) && !sane_istest(x,0x20))
223#define tolower(x) sane_case((unsigned char)(x), 0x20) 226#define tolower(x) sane_case((unsigned char)(x), 0x20)
224#define toupper(x) sane_case((unsigned char)(x), 0) 227#define toupper(x) sane_case((unsigned char)(x), 0)
225 228
@@ -242,6 +245,12 @@ int strtailcmp(const char *s1, const char *s2);
242unsigned long convert_unit(unsigned long value, char *unit); 245unsigned long convert_unit(unsigned long value, char *unit);
243int readn(int fd, void *buf, size_t size); 246int readn(int fd, void *buf, size_t size);
244 247
248struct perf_event_attr;
249
250void event_attr_init(struct perf_event_attr *attr);
251
252uid_t parse_target_uid(const char *str, const char *tid, const char *pid);
253
245#define _STR(x) #x 254#define _STR(x) #x
246#define STR(x) _STR(x) 255#define STR(x) _STR(x)
247 256
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index e8a03aceceb1..a93e06cfcc2a 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -19,6 +19,16 @@
19# along with this program; if not, write to the Free Software 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 20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21# 21#
22OUTPUT=./
23ifeq ("$(origin O)", "command line")
24 OUTPUT := $(O)/
25endif
26
27ifneq ($(OUTPUT),)
28# check that the output directory actually exists
29OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
30$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
31endif
22 32
23# --- CONFIGURATION BEGIN --- 33# --- CONFIGURATION BEGIN ---
24 34
@@ -87,6 +97,7 @@ AR = $(CROSS)ar
87STRIP = $(CROSS)strip 97STRIP = $(CROSS)strip
88RANLIB = $(CROSS)ranlib 98RANLIB = $(CROSS)ranlib
89HOSTCC = gcc 99HOSTCC = gcc
100MKDIR = mkdir
90 101
91 102
92# Now we set up the build system 103# Now we set up the build system
@@ -95,7 +106,7 @@ HOSTCC = gcc
95# set up PWD so that older versions of make will work with our build. 106# set up PWD so that older versions of make will work with our build.
96PWD = $(shell pwd) 107PWD = $(shell pwd)
97 108
98GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo po/$$HLANG.gmo; done;} 109GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo; done;}
99 110
100export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS 111export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS
101 112
@@ -122,15 +133,18 @@ UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \
122 utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \ 133 utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
123 utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o 134 utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o
124 135
136UTIL_SRC := $(UTIL_OBJS:.o=.c)
137
138UTIL_OBJS := $(addprefix $(OUTPUT),$(UTIL_OBJS))
139
125UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \ 140UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
126 utils/helpers/bitmask.h \ 141 utils/helpers/bitmask.h \
127 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def 142 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
128 143
129UTIL_SRC := $(UTIL_OBJS:.o=.c)
130
131LIB_HEADERS = lib/cpufreq.h lib/sysfs.h 144LIB_HEADERS = lib/cpufreq.h lib/sysfs.h
132LIB_SRC = lib/cpufreq.c lib/sysfs.c 145LIB_SRC = lib/cpufreq.c lib/sysfs.c
133LIB_OBJS = lib/cpufreq.o lib/sysfs.o 146LIB_OBJS = lib/cpufreq.o lib/sysfs.o
147LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS))
134 148
135CFLAGS += -pipe 149CFLAGS += -pipe
136 150
@@ -168,83 +182,90 @@ endif
168 182
169# the actual make rules 183# the actual make rules
170 184
171all: libcpupower cpupower $(COMPILE_NLS) $(COMPILE_BENCH) 185all: libcpupower $(OUTPUT)cpupower $(COMPILE_NLS) $(COMPILE_BENCH)
172 186
173lib/%.o: $(LIB_SRC) $(LIB_HEADERS) 187$(OUTPUT)lib/%.o: $(LIB_SRC) $(LIB_HEADERS)
174 $(ECHO) " CC " $@ 188 $(ECHO) " CC " $@
175 $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c 189 $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c
176 190
177libcpupower.so.$(LIB_MAJ): $(LIB_OBJS) 191$(OUTPUT)libcpupower.so.$(LIB_MAJ): $(LIB_OBJS)
178 $(ECHO) " LD " $@ 192 $(ECHO) " LD " $@
179 $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \ 193 $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \
180 -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS) 194 -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS)
181 @ln -sf $@ libcpupower.so 195 @ln -sf $(@F) $(OUTPUT)libcpupower.so
182 @ln -sf $@ libcpupower.so.$(LIB_MIN) 196 @ln -sf $(@F) $(OUTPUT)libcpupower.so.$(LIB_MIN)
183 197
184libcpupower: libcpupower.so.$(LIB_MAJ) 198libcpupower: $(OUTPUT)libcpupower.so.$(LIB_MAJ)
185 199
186# Let all .o files depend on its .c file and all headers 200# 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 201# Might be worth to put this into utils/Makefile at some point of time
188$(UTIL_OBJS): $(UTIL_HEADERS) 202$(UTIL_OBJS): $(UTIL_HEADERS)
189 203
190.c.o: 204$(OUTPUT)%.o: %.c
191 $(ECHO) " CC " $@ 205 $(ECHO) " CC " $@
192 $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c 206 $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c
193 207
194cpupower: $(UTIL_OBJS) libcpupower.so.$(LIB_MAJ) 208$(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_MAJ)
195 $(ECHO) " CC " $@ 209 $(ECHO) " CC " $@
196 $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpupower -lrt -lpci -L. -o $@ $(UTIL_OBJS) 210 $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lcpupower -lrt -lpci -L$(OUTPUT) -o $@
197 $(QUIET) $(STRIPCMD) $@ 211 $(QUIET) $(STRIPCMD) $@
198 212
199po/$(PACKAGE).pot: $(UTIL_SRC) 213$(OUTPUT)po/$(PACKAGE).pot: $(UTIL_SRC)
200 $(ECHO) " GETTEXT " $@ 214 $(ECHO) " GETTEXT " $@
201 $(QUIET) xgettext --default-domain=$(PACKAGE) --add-comments \ 215 $(QUIET) xgettext --default-domain=$(PACKAGE) --add-comments \
202 --keyword=_ --keyword=N_ $(UTIL_SRC) && \ 216 --keyword=_ --keyword=N_ $(UTIL_SRC) -p $(@D) -o $(@F)
203 test -f $(PACKAGE).po && \
204 mv -f $(PACKAGE).po po/$(PACKAGE).pot
205 217
206po/%.gmo: po/%.po 218$(OUTPUT)po/%.gmo: po/%.po
207 $(ECHO) " MSGFMT " $@ 219 $(ECHO) " MSGFMT " $@
208 $(QUIET) msgfmt -o $@ po/$*.po 220 $(QUIET) msgfmt -o $@ po/$*.po
209 221
210create-gmo: ${GMO_FILES} 222create-gmo: ${GMO_FILES}
211 223
212update-po: po/$(PACKAGE).pot 224update-po: $(OUTPUT)po/$(PACKAGE).pot
213 $(ECHO) " MSGMRG " $@ 225 $(ECHO) " MSGMRG " $@
214 $(QUIET) @for HLANG in $(LANGUAGES); do \ 226 $(QUIET) @for HLANG in $(LANGUAGES); do \
215 echo -n "Updating $$HLANG "; \ 227 echo -n "Updating $$HLANG "; \
216 if msgmerge po/$$HLANG.po po/$(PACKAGE).pot -o \ 228 if msgmerge po/$$HLANG.po $< -o \
217 po/$$HLANG.new.po; then \ 229 $(OUTPUT)po/$$HLANG.new.po; then \
218 mv -f po/$$HLANG.new.po po/$$HLANG.po; \ 230 mv -f $(OUTPUT)po/$$HLANG.new.po $(OUTPUT)po/$$HLANG.po; \
219 else \ 231 else \
220 echo "msgmerge for $$HLANG failed!"; \ 232 echo "msgmerge for $$HLANG failed!"; \
221 rm -f po/$$HLANG.new.po; \ 233 rm -f $(OUTPUT)po/$$HLANG.new.po; \
222 fi; \ 234 fi; \
223 done; 235 done;
224 236
225compile-bench: libcpupower.so.$(LIB_MAJ) 237compile-bench: $(OUTPUT)libcpupower.so.$(LIB_MAJ)
226 @V=$(V) confdir=$(confdir) $(MAKE) -C bench 238 @V=$(V) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT)
239
240# we compile into subdirectories. if the target directory is not the
241# source directory, they might not exists. So we depend the various
242# files onto their directories.
243DIRECTORY_DEPS = $(LIB_OBJS) $(UTIL_OBJS) $(GMO_FILES)
244$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
245
246# In the second step, we make a rule to actually create these directories
247$(sort $(dir $(DIRECTORY_DEPS))):
248 $(ECHO) " MKDIR " $@
249 $(QUIET) $(MKDIR) -p $@ 2>/dev/null
227 250
228clean: 251clean:
229 -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \ 252 -find $(OUTPUT) \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
230 | xargs rm -f 253 | xargs rm -f
231 -rm -f $(UTIL_BINS) 254 -rm -f $(OUTPUT)cpupower
232 -rm -f $(IDLE_OBJS) 255 -rm -f $(OUTPUT)libcpupower.so*
233 -rm -f cpupower 256 -rm -rf $(OUTPUT)po/*.{gmo,pot}
234 -rm -f libcpupower.so* 257 $(MAKE) -C bench O=$(OUTPUT) clean
235 -rm -rf po/*.gmo po/*.pot
236 $(MAKE) -C bench clean
237 258
238 259
239install-lib: 260install-lib:
240 $(INSTALL) -d $(DESTDIR)${libdir} 261 $(INSTALL) -d $(DESTDIR)${libdir}
241 $(CP) libcpupower.so* $(DESTDIR)${libdir}/ 262 $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/
242 $(INSTALL) -d $(DESTDIR)${includedir} 263 $(INSTALL) -d $(DESTDIR)${includedir}
243 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h 264 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
244 265
245install-tools: 266install-tools:
246 $(INSTALL) -d $(DESTDIR)${bindir} 267 $(INSTALL) -d $(DESTDIR)${bindir}
247 $(INSTALL_PROGRAM) cpupower $(DESTDIR)${bindir} 268 $(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir}
248 269
249install-man: 270install-man:
250 $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 271 $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1
@@ -257,13 +278,13 @@ install-man:
257install-gmo: 278install-gmo:
258 $(INSTALL) -d $(DESTDIR)${localedir} 279 $(INSTALL) -d $(DESTDIR)${localedir}
259 for HLANG in $(LANGUAGES); do \ 280 for HLANG in $(LANGUAGES); do \
260 echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \ 281 echo '$(INSTALL_DATA) -D $(OUTPUT)po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \
261 $(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \ 282 $(INSTALL_DATA) -D $(OUTPUT)po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
262 done; 283 done;
263 284
264install-bench: 285install-bench:
265 @#DESTDIR must be set from outside to survive 286 @#DESTDIR must be set from outside to survive
266 @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench install 287 @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT) install
267 288
268install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH) 289install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
269 290
diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile
index 2b67606fc3e3..7ec7021a29cd 100644
--- a/tools/power/cpupower/bench/Makefile
+++ b/tools/power/cpupower/bench/Makefile
@@ -1,29 +1,36 @@
1LIBS = -L../ -lm -lcpupower 1OUTPUT := ./
2ifeq ("$(origin O)", "command line")
3ifneq ($(O),)
4 OUTPUT := $(O)/
5endif
6endif
2 7
3OBJS = main.o parse.o system.o benchmark.o 8LIBS = -L../ -L$(OUTPUT) -lm -lcpupower
9
10OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o
4CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\" 11CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
5 12
6%.o : %.c 13$(OUTPUT)%.o : %.c
7 $(ECHO) " CC " $@ 14 $(ECHO) " CC " $@
8 $(QUIET) $(CC) -c $(CFLAGS) $< -o $@ 15 $(QUIET) $(CC) -c $(CFLAGS) $< -o $@
9 16
10cpufreq-bench: $(OBJS) 17$(OUTPUT)cpufreq-bench: $(OBJS)
11 $(ECHO) " CC " $@ 18 $(ECHO) " CC " $@
12 $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS) 19 $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS)
13 20
14all: cpufreq-bench 21all: $(OUTPUT)cpufreq-bench
15 22
16install: 23install:
17 mkdir -p $(DESTDIR)/$(sbindir) 24 mkdir -p $(DESTDIR)/$(sbindir)
18 mkdir -p $(DESTDIR)/$(bindir) 25 mkdir -p $(DESTDIR)/$(bindir)
19 mkdir -p $(DESTDIR)/$(docdir) 26 mkdir -p $(DESTDIR)/$(docdir)
20 mkdir -p $(DESTDIR)/$(confdir) 27 mkdir -p $(DESTDIR)/$(confdir)
21 install -m 755 cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench 28 install -m 755 $(OUTPUT)cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench
22 install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh 29 install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh
23 install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH 30 install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH
24 install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh 31 install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh
25 install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf 32 install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf
26 33
27clean: 34clean:
28 rm -f *.o 35 rm -f $(OUTPUT)*.o
29 rm -f cpufreq-bench 36 rm -f $(OUTPUT)cpufreq-bench
diff --git a/tools/power/cpupower/debug/i386/Makefile b/tools/power/cpupower/debug/i386/Makefile
index d08cc1ead9bc..3ba158f0e287 100644
--- a/tools/power/cpupower/debug/i386/Makefile
+++ b/tools/power/cpupower/debug/i386/Makefile
@@ -1,20 +1,38 @@
1OUTPUT=./
2ifeq ("$(origin O)", "command line")
3 OUTPUT := $(O)/
4endif
5
6DESTDIR =
7bindir = /usr/bin
8
9INSTALL = /usr/bin/install
10
11
1default: all 12default: all
2 13
3centrino-decode: centrino-decode.c 14$(OUTPUT)centrino-decode: centrino-decode.c
4 $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c 15 $(CC) $(CFLAGS) -o $@ centrino-decode.c
5 16
6dump_psb: dump_psb.c 17$(OUTPUT)dump_psb: dump_psb.c
7 $(CC) $(CFLAGS) -o dump_psb dump_psb.c 18 $(CC) $(CFLAGS) -o $@ dump_psb.c
8 19
9intel_gsic: intel_gsic.c 20$(OUTPUT)intel_gsic: intel_gsic.c
10 $(CC) $(CFLAGS) -o intel_gsic -llrmi intel_gsic.c 21 $(CC) $(CFLAGS) -o $@ -llrmi intel_gsic.c
11 22
12powernow-k8-decode: powernow-k8-decode.c 23$(OUTPUT)powernow-k8-decode: powernow-k8-decode.c
13 $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c 24 $(CC) $(CFLAGS) -o $@ powernow-k8-decode.c
14 25
15all: centrino-decode dump_psb intel_gsic powernow-k8-decode 26all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode
16 27
17clean: 28clean:
18 rm -rf centrino-decode dump_psb intel_gsic powernow-k8-decode 29 rm -rf $(OUTPUT){centrino-decode,dump_psb,intel_gsic,powernow-k8-decode}
30
31install:
32 $(INSTALL) -d $(DESTDIR)${bindir}
33 $(INSTALL) $(OUTPUT)centrino-decode $(DESTDIR)${bindir}
34 $(INSTALL) $(OUTPUT)powernow-k8-decode $(DESTDIR)${bindir}
35 $(INSTALL) $(OUTPUT)dump_psb $(DESTDIR)${bindir}
36 $(INSTALL) $(OUTPUT)intel_gsic $(DESTDIR)${bindir}
19 37
20.PHONY: all default clean 38.PHONY: all default clean install
diff --git a/tools/power/cpupower/debug/x86_64/Makefile b/tools/power/cpupower/debug/x86_64/Makefile
index 3326217dd311..1c5214526716 100644
--- a/tools/power/cpupower/debug/x86_64/Makefile
+++ b/tools/power/cpupower/debug/x86_64/Makefile
@@ -1,14 +1,30 @@
1OUTPUT=./
2ifeq ("$(origin O)", "command line")
3 OUTPUT := $(O)/
4endif
5
6DESTDIR =
7bindir = /usr/bin
8
9INSTALL = /usr/bin/install
10
11
1default: all 12default: all
2 13
3centrino-decode: ../i386/centrino-decode.c 14$(OUTPUT)centrino-decode: ../i386/centrino-decode.c
4 $(CC) $(CFLAGS) -o $@ $< 15 $(CC) $(CFLAGS) -o $@ $<
5 16
6powernow-k8-decode: ../i386/powernow-k8-decode.c 17$(OUTPUT)powernow-k8-decode: ../i386/powernow-k8-decode.c
7 $(CC) $(CFLAGS) -o $@ $< 18 $(CC) $(CFLAGS) -o $@ $<
8 19
9all: centrino-decode powernow-k8-decode 20all: $(OUTPUT)centrino-decode $(OUTPUT)powernow-k8-decode
10 21
11clean: 22clean:
12 rm -rf centrino-decode powernow-k8-decode 23 rm -rf $(OUTPUT)centrino-decode $(OUTPUT)powernow-k8-decode
24
25install:
26 $(INSTALL) -d $(DESTDIR)${bindir}
27 $(INSTALL) $(OUTPUT)centrino-decode $(DESTDIR)${bindir}
28 $(INSTALL) $(OUTPUT)powernow-k8-decode $(DESTDIR)${bindir}
13 29
14.PHONY: all default clean 30.PHONY: all default clean install
diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1
index bb60a8d1e45a..4a1918ea8f9c 100644
--- a/tools/power/cpupower/man/cpupower-frequency-info.1
+++ b/tools/power/cpupower/man/cpupower-frequency-info.1
@@ -1,4 +1,4 @@
1.TH "cpupower-frequency-info" "1" "0.1" "Mattia Dongili" "" 1.TH "CPUPOWER\-FREQUENCY\-INFO" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower frequency\-info \- Utility to retrieve cpufreq kernel information 4cpupower frequency\-info \- Utility to retrieve cpufreq kernel information
@@ -50,8 +50,6 @@ Prints out information like provided by the /proc/cpufreq interface in 2.4. and
50\fB\-m\fR \fB\-\-human\fR 50\fB\-m\fR \fB\-\-human\fR
51human\-readable output for the \-f, \-w, \-s and \-y parameters. 51human\-readable output for the \-f, \-w, \-s and \-y parameters.
52.TP 52.TP
53\fB\-h\fR \fB\-\-help\fR
54Prints out the help screen.
55.SH "REMARKS" 53.SH "REMARKS"
56.LP 54.LP
57By default only values of core zero are displayed. How to display settings of 55By default only values of core zero are displayed. How to display settings of
diff --git a/tools/power/cpupower/man/cpupower-frequency-set.1 b/tools/power/cpupower/man/cpupower-frequency-set.1
index 685f469093ad..3eacc8d03d1a 100644
--- a/tools/power/cpupower/man/cpupower-frequency-set.1
+++ b/tools/power/cpupower/man/cpupower-frequency-set.1
@@ -1,4 +1,4 @@
1.TH "cpupower-freqency-set" "1" "0.1" "Mattia Dongili" "" 1.TH "CPUPOWER\-FREQUENCY\-SET" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower frequency\-set \- A small tool which allows to modify cpufreq settings. 4cpupower frequency\-set \- A small tool which allows to modify cpufreq settings.
@@ -26,8 +26,6 @@ specific frequency to be set. Requires userspace governor to be available and lo
26\fB\-r\fR \fB\-\-related\fR 26\fB\-r\fR \fB\-\-related\fR
27modify all hardware-related CPUs at the same time 27modify all hardware-related CPUs at the same time
28.TP 28.TP
29\fB\-h\fR \fB\-\-help\fR
30Prints out the help screen.
31.SH "REMARKS" 29.SH "REMARKS"
32.LP 30.LP
33By default values are applied on all cores. How to modify single core 31By default values are applied on all cores. How to modify single core
diff --git a/tools/power/cpupower/man/cpupower-idle-info.1 b/tools/power/cpupower/man/cpupower-idle-info.1
new file mode 100644
index 000000000000..4178effd9e99
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-idle-info.1
@@ -0,0 +1,90 @@
1.TH "CPUPOWER-IDLE-INFO" "1" "0.1" "" "cpupower Manual"
2.SH "NAME"
3.LP
4cpupower idle\-info \- Utility to retrieve cpu idle kernel information
5.SH "SYNTAX"
6.LP
7cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP]
8.SH "DESCRIPTION"
9.LP
10A tool which prints out per cpu idle information helpful to developers and interested users.
11.SH "OPTIONS"
12.LP
13.TP
14\fB\-f\fR \fB\-\-silent\fR
15Only print a summary of all available C-states in the system.
16.TP
17\fB\-e\fR \fB\-\-proc\fR
18deprecated.
19Prints out idle information in old /proc/acpi/processor/*/power format. This
20interface has been removed from the kernel for quite some time, do not let
21further code depend on this option, best do not use it.
22
23.SH IDLE\-INFO DESCRIPTIONS
24CPU sleep state statistics and descriptions are retrieved from sysfs files,
25exported by the cpuidle kernel subsystem. The kernel only updates these
26statistics when it enters or leaves an idle state, therefore on a very idle or
27a very busy system, these statistics may not be accurate. They still provide a
28good overview about the usage and availability of processor sleep states on
29the platform.
30
31Be aware that the sleep states as exported by the hardware or BIOS and used by
32the Linux kernel may not exactly reflect the capabilities of the
33processor. This often is the case on the X86 architecture when the acpi_idle
34driver is used. It is also possible that the hardware overrules the kernel
35requests, due to internal activity monitors or other reasons.
36On recent X86 platforms it is often possible to read out hardware registers
37which monitor the duration of sleep states the processor resided in. The
38cpupower monitor tool (cpupower\-monitor(1)) can be used to show real sleep
39state residencies. Please refer to the architecture specific description
40section below.
41
42.SH IDLE\-INFO ARCHITECTURE SPECIFIC DESCRIPTIONS
43.SS "X86"
44POLL idle state
45
46If cpuidle is active, X86 platforms have one special idle state.
47The POLL idle state is not a real idle state, it does not save any
48power. Instead, a busy\-loop is executed doing nothing for a short period of
49time. This state is used if the kernel knows that work has to be processed
50very soon and entering any real hardware idle state may result in a slight
51performance penalty.
52
53There exist two different cpuidle drivers on the X86 architecture platform:
54
55"acpi_idle" cpuidle driver
56
57The acpi_idle cpuidle driver retrieves available sleep states (C\-states) from
58the ACPI BIOS tables (from the _CST ACPI function on recent platforms or from
59the FADT BIOS table on older ones).
60The C1 state is not retrieved from ACPI tables. If the C1 state is entered,
61the kernel will call the hlt instruction (or mwait on Intel).
62
63"intel_idle" cpuidle driver
64
65In kernel 2.6.36 the intel_idle driver was introduced.
66It only serves recent Intel CPUs (Nehalem, Westmere, Sandybridge, Atoms or
67newer). On older Intel CPUs the acpi_idle driver is still used (if the BIOS
68provides C\-state ACPI tables).
69The intel_idle driver knows the sleep state capabilities of the processor and
70ignores ACPI BIOS exported processor sleep states tables.
71
72.SH "REMARKS"
73.LP
74By default only values of core zero are displayed. How to display settings of
75other cores is described in the cpupower(1) manpage in the \-\-cpu option
76section.
77.SH REFERENCES
78http://www.acpi.info/spec.htm
79.SH "FILES"
80.nf
81\fI/sys/devices/system/cpu/cpu*/cpuidle/state*\fP
82\fI/sys/devices/system/cpu/cpuidle/*\fP
83.fi
84.SH "AUTHORS"
85.nf
86Thomas Renninger <trenn@suse.de>
87.fi
88.SH "SEE ALSO"
89.LP
90cpupower(1), cpupower\-monitor(1), cpupower\-info(1), cpupower\-set(1)
diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1
index d5cfa265c3d3..1141c2073719 100644
--- a/tools/power/cpupower/man/cpupower-monitor.1
+++ b/tools/power/cpupower/man/cpupower-monitor.1
@@ -107,7 +107,7 @@ Deepest 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 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. 108manuals (some are provided in the References section) for further details.
109 109
110.SS "Ontario" "Liano" 110.SS "Fam_12h" "Fam_14h"
111AMD laptop and desktop processor (family 12h and 14h) sleep state counters. 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 112The registers are accessed via PCI and therefore can still be read out while
113cores have been offlined. 113cores have been offlined.
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
index b028267c1376..8145af5f93a6 100644
--- a/tools/power/cpupower/utils/cpuidle-info.c
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -35,17 +35,9 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
35 printf(_("CPU %u: Can't read idle state info\n"), cpu); 35 printf(_("CPU %u: Can't read idle state info\n"), cpu);
36 return; 36 return;
37 } 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); 38 printf(_("Number of idle states: %d\n"), idlestates);
46
47 printf(_("Available idle states:")); 39 printf(_("Available idle states:"));
48 for (idlestate = 1; idlestate < idlestates; idlestate++) { 40 for (idlestate = 0; idlestate < idlestates; idlestate++) {
49 tmp = sysfs_get_idlestate_name(cpu, idlestate); 41 tmp = sysfs_get_idlestate_name(cpu, idlestate);
50 if (!tmp) 42 if (!tmp)
51 continue; 43 continue;
@@ -57,7 +49,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
57 if (!verbose) 49 if (!verbose)
58 return; 50 return;
59 51
60 for (idlestate = 1; idlestate < idlestates; idlestate++) { 52 for (idlestate = 0; idlestate < idlestates; idlestate++) {
61 tmp = sysfs_get_idlestate_name(cpu, idlestate); 53 tmp = sysfs_get_idlestate_name(cpu, idlestate);
62 if (!tmp) 54 if (!tmp)
63 continue; 55 continue;
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
index 87d5605bdda8..6437ef39aeea 100644
--- a/tools/power/cpupower/utils/helpers/amd.c
+++ b/tools/power/cpupower/utils/helpers/amd.c
@@ -112,14 +112,12 @@ int decode_pstates(unsigned int cpu, unsigned int cpu_family,
112int amd_pci_get_num_boost_states(int *active, int *states) 112int amd_pci_get_num_boost_states(int *active, int *states)
113{ 113{
114 struct pci_access *pci_acc; 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; 115 struct pci_dev *device;
118 uint8_t val = 0; 116 uint8_t val = 0;
119 117
120 *active = *states = 0; 118 *active = *states = 0;
121 119
122 device = pci_acc_init(&pci_acc, vendor_id, boost_dev_ids); 120 device = pci_slot_func_init(&pci_acc, 0x18, 4);
123 121
124 if (device == NULL) 122 if (device == NULL)
125 return -ENODEV; 123 return -ENODEV;
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 2747e738efb0..2eb584cf2f55 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -66,8 +66,8 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
66#define CPUPOWER_CAP_AMD_CBP 0x00000004 66#define CPUPOWER_CAP_AMD_CBP 0x00000004
67#define CPUPOWER_CAP_PERF_BIAS 0x00000008 67#define CPUPOWER_CAP_PERF_BIAS 0x00000008
68#define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010 68#define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010
69#define CPUPOWER_CAP_IS_SNB 0x00000011 69#define CPUPOWER_CAP_IS_SNB 0x00000020
70#define CPUPOWER_CAP_INTEL_IDA 0x00000012 70#define CPUPOWER_CAP_INTEL_IDA 0x00000040
71 71
72#define MAX_HW_PSTATES 10 72#define MAX_HW_PSTATES 10
73 73
@@ -132,8 +132,11 @@ extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu);
132 132
133/* PCI stuff ****************************/ 133/* PCI stuff ****************************/
134extern int amd_pci_get_num_boost_states(int *active, int *states); 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, 135extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain,
136 int *dev_ids); 136 int bus, int slot, int func, int vendor,
137 int dev);
138extern struct pci_dev *pci_slot_func_init(struct pci_access **pacc,
139 int slot, int func);
137 140
138/* PCI stuff ****************************/ 141/* PCI stuff ****************************/
139 142
diff --git a/tools/power/cpupower/utils/helpers/pci.c b/tools/power/cpupower/utils/helpers/pci.c
index cd2eb6fe41c4..9690798e6446 100644
--- a/tools/power/cpupower/utils/helpers/pci.c
+++ b/tools/power/cpupower/utils/helpers/pci.c
@@ -10,19 +10,24 @@
10 * **pacc : if a valid pci_dev is returned 10 * **pacc : if a valid pci_dev is returned
11 * *pacc must be passed to pci_acc_cleanup to free it 11 * *pacc must be passed to pci_acc_cleanup to free it
12 * 12 *
13 * vendor_id : the pci vendor id matching the pci device to access 13 * domain: domain
14 * dev_ids : device ids matching the pci device to access 14 * bus: bus
15 * slot: slot
16 * func: func
17 * vendor: vendor
18 * device: device
19 * Pass -1 for one of the six above to match any
15 * 20 *
16 * Returns : 21 * Returns :
17 * struct pci_dev which can be used with pci_{read,write}_* functions 22 * struct pci_dev which can be used with pci_{read,write}_* functions
18 * to access the PCI config space of matching pci devices 23 * to access the PCI config space of matching pci devices
19 */ 24 */
20struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id, 25struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, int bus,
21 int *dev_ids) 26 int slot, int func, int vendor, int dev)
22{ 27{
23 struct pci_filter filter_nb_link = { -1, -1, -1, -1, vendor_id, 0}; 28 struct pci_filter filter_nb_link = { domain, bus, slot, func,
29 vendor, dev };
24 struct pci_dev *device; 30 struct pci_dev *device;
25 unsigned int i;
26 31
27 *pacc = pci_alloc(); 32 *pacc = pci_alloc();
28 if (*pacc == NULL) 33 if (*pacc == NULL)
@@ -31,14 +36,20 @@ struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
31 pci_init(*pacc); 36 pci_init(*pacc);
32 pci_scan_bus(*pacc); 37 pci_scan_bus(*pacc);
33 38
34 for (i = 0; dev_ids[i] != 0; i++) { 39 for (device = (*pacc)->devices; device; device = device->next) {
35 filter_nb_link.device = dev_ids[i]; 40 if (pci_filter_match(&filter_nb_link, device))
36 for (device = (*pacc)->devices; device; device = device->next) { 41 return device;
37 if (pci_filter_match(&filter_nb_link, device))
38 return device;
39 }
40 } 42 }
41 pci_cleanup(*pacc); 43 pci_cleanup(*pacc);
42 return NULL; 44 return NULL;
43} 45}
46
47/* Typically one wants to get a specific slot(device)/func of the root domain
48 and bus */
49struct pci_dev *pci_slot_func_init(struct pci_access **pacc, int slot,
50 int func)
51{
52 return pci_acc_init(pacc, 0, 0, slot, func, -1, -1);
53}
54
44#endif /* defined(__i386__) || defined(__x86_64__) */ 55#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
index 202e555988be..2116df9ad832 100644
--- a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
@@ -20,8 +20,6 @@
20#include "idle_monitor/cpupower-monitor.h" 20#include "idle_monitor/cpupower-monitor.h"
21#include "helpers/helpers.h" 21#include "helpers/helpers.h"
22 22
23/******** PCI parts could go into own file and get shared ***************/
24
25#define PCI_NON_PC0_OFFSET 0xb0 23#define PCI_NON_PC0_OFFSET 0xb0
26#define PCI_PC1_OFFSET 0xb4 24#define PCI_PC1_OFFSET 0xb4
27#define PCI_PC6_OFFSET 0xb8 25#define PCI_PC6_OFFSET 0xb8
@@ -82,10 +80,7 @@ static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = {
82}; 80};
83 81
84static struct pci_access *pci_acc; 82static 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; 83static struct pci_dev *amd_fam14h_pci_dev;
88
89static int nbp1_entered; 84static int nbp1_entered;
90 85
91struct timespec start_time; 86struct timespec start_time;
@@ -286,13 +281,13 @@ struct cpuidle_monitor *amd_fam14h_register(void)
286 if (cpupower_cpu_info.vendor != X86_VENDOR_AMD) 281 if (cpupower_cpu_info.vendor != X86_VENDOR_AMD)
287 return NULL; 282 return NULL;
288 283
289 if (cpupower_cpu_info.family == 0x14) { 284 if (cpupower_cpu_info.family == 0x14)
290 if (cpu_count <= 0 || cpu_count > 2) { 285 strncpy(amd_fam14h_monitor.name, "Fam_14h",
291 fprintf(stderr, "AMD fam14h: Invalid cpu count: %d\n", 286 MONITOR_NAME_LEN - 1);
292 cpu_count); 287 else if (cpupower_cpu_info.family == 0x12)
293 return NULL; 288 strncpy(amd_fam14h_monitor.name, "Fam_12h",
294 } 289 MONITOR_NAME_LEN - 1);
295 } else 290 else
296 return NULL; 291 return NULL;
297 292
298 /* We do not alloc for nbp1 machine wide counter */ 293 /* We do not alloc for nbp1 machine wide counter */
@@ -303,7 +298,9 @@ struct cpuidle_monitor *amd_fam14h_register(void)
303 sizeof(unsigned long long)); 298 sizeof(unsigned long long));
304 } 299 }
305 300
306 amd_fam14h_pci_dev = pci_acc_init(&pci_acc, pci_vendor_id, pci_dev_ids); 301 /* We need PCI device: Slot 18, Func 6, compare with BKDG
302 for fam 12h/14h */
303 amd_fam14h_pci_dev = pci_slot_func_init(&pci_acc, 0x18, 6);
307 if (amd_fam14h_pci_dev == NULL || pci_acc == NULL) 304 if (amd_fam14h_pci_dev == NULL || pci_acc == NULL)
308 return NULL; 305 return NULL;
309 306
@@ -325,7 +322,7 @@ static void amd_fam14h_unregister(void)
325} 322}
326 323
327struct cpuidle_monitor amd_fam14h_monitor = { 324struct cpuidle_monitor amd_fam14h_monitor = {
328 .name = "Ontario", 325 .name = "",
329 .hw_states = amd_fam14h_cstates, 326 .hw_states = amd_fam14h_cstates,
330 .hw_states_num = AMD_FAM14H_STATE_NUM, 327 .hw_states_num = AMD_FAM14H_STATE_NUM,
331 .start = amd_fam14h_start, 328 .start = amd_fam14h_start,
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 555c69a5592a..adf175f61496 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -4,11 +4,13 @@ turbostat \- Report processor frequency and idle statistics
4.SH SYNOPSIS 4.SH SYNOPSIS
5.ft B 5.ft B
6.B turbostat 6.B turbostat
7.RB [ "\-s" ]
7.RB [ "\-v" ] 8.RB [ "\-v" ]
8.RB [ "\-M MSR#" ] 9.RB [ "\-M MSR#" ]
9.RB command 10.RB command
10.br 11.br
11.B turbostat 12.B turbostat
13.RB [ "\-s" ]
12.RB [ "\-v" ] 14.RB [ "\-v" ]
13.RB [ "\-M MSR#" ] 15.RB [ "\-M MSR#" ]
14.RB [ "\-i interval_sec" ] 16.RB [ "\-i interval_sec" ]
@@ -25,6 +27,8 @@ supports an "invariant" TSC, plus the APERF and MPERF MSRs.
25on processors that additionally support C-state residency counters. 27on processors that additionally support C-state residency counters.
26 28
27.SS Options 29.SS Options
30The \fB-s\fP option prints only a 1-line summary for each sample interval.
31.PP
28The \fB-v\fP option increases verbosity. 32The \fB-v\fP option increases verbosity.
29.PP 33.PP
30The \fB-M MSR#\fP option dumps the specified MSR, 34The \fB-M MSR#\fP option dumps the specified MSR,
@@ -39,13 +43,14 @@ displays the statistics gathered since it was forked.
39.SH FIELD DESCRIPTIONS 43.SH FIELD DESCRIPTIONS
40.nf 44.nf
41\fBpk\fP processor package number. 45\fBpk\fP processor package number.
42\fBcr\fP processor core number. 46\fBcor\fP processor core number.
43\fBCPU\fP Linux CPU (logical processor) number. 47\fBCPU\fP Linux CPU (logical processor) number.
48Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology.
44\fB%c0\fP percent of the interval that the CPU retired instructions. 49\fB%c0\fP percent of the interval that the CPU retired instructions.
45\fBGHz\fP average clock rate while the CPU was in c0 state. 50\fBGHz\fP average clock rate while the CPU was in c0 state.
46\fBTSC\fP average GHz that the TSC ran during the entire interval. 51\fBTSC\fP average GHz that the TSC ran during the entire interval.
47\fB%c1, %c3, %c6\fP show the percentage residency in hardware core idle states. 52\fB%c1, %c3, %c6, %c7\fP show the percentage residency in hardware core idle states.
48\fB%pc3, %pc6\fP percentage residency in hardware package idle states. 53\fB%pc2, %pc3, %pc6, %pc7\fP percentage residency in hardware package idle states.
49.fi 54.fi
50.PP 55.PP
51.SH EXAMPLE 56.SH EXAMPLE
@@ -53,25 +58,37 @@ Without any parameters, turbostat prints out counters ever 5 seconds.
53(override interval with "-i sec" option, or specify a command 58(override interval with "-i sec" option, or specify a command
54for turbostat to fork). 59for turbostat to fork).
55 60
56The first row of statistics reflect the average for the entire system. 61The first row of statistics is a summary for the entire system.
62Note that the summary is a weighted average.
57Subsequent rows show per-CPU statistics. 63Subsequent rows show per-CPU statistics.
58 64
59.nf 65.nf
60[root@x980]# ./turbostat 66[root@x980]# ./turbostat
61cr CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 67cor CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6
62 0.04 1.62 3.38 0.11 0.00 99.85 0.00 95.07 68 0.60 1.63 3.38 2.91 0.00 96.49 0.00 76.64
63 0 0 0.04 1.62 3.38 0.06 0.00 99.90 0.00 95.07 69 0 0 0.59 1.62 3.38 4.51 0.00 94.90 0.00 76.64
64 0 6 0.02 1.62 3.38 0.08 0.00 99.90 0.00 95.07 70 0 6 1.13 1.64 3.38 3.97 0.00 94.90 0.00 76.64
65 1 2 0.10 1.62 3.38 0.29 0.00 99.61 0.00 95.07 71 1 2 0.08 1.62 3.38 0.07 0.00 99.85 0.00 76.64
66 1 8 0.11 1.62 3.38 0.28 0.00 99.61 0.00 95.07 72 1 8 0.03 1.62 3.38 0.12 0.00 99.85 0.00 76.64
67 2 4 0.01 1.62 3.38 0.01 0.00 99.98 0.00 95.07 73 2 4 0.01 1.62 3.38 0.06 0.00 99.93 0.00 76.64
68 2 10 0.01 1.61 3.38 0.02 0.00 99.98 0.00 95.07 74 2 10 0.04 1.62 3.38 0.02 0.00 99.93 0.00 76.64
69 8 1 0.07 1.62 3.38 0.15 0.00 99.78 0.00 95.07 75 8 1 2.85 1.62 3.38 11.71 0.00 85.44 0.00 76.64
70 8 7 0.03 1.62 3.38 0.19 0.00 99.78 0.00 95.07 76 8 7 1.98 1.62 3.38 12.58 0.00 85.44 0.00 76.64
71 9 3 0.01 1.62 3.38 0.02 0.00 99.98 0.00 95.07 77 9 3 0.36 1.62 3.38 0.71 0.00 98.93 0.00 76.64
72 9 9 0.01 1.62 3.38 0.02 0.00 99.98 0.00 95.07 78 9 9 0.09 1.62 3.38 0.98 0.00 98.93 0.00 76.64
73 10 5 0.01 1.62 3.38 0.13 0.00 99.86 0.00 95.07 79 10 5 0.03 1.62 3.38 0.09 0.00 99.87 0.00 76.64
74 10 11 0.08 1.62 3.38 0.05 0.00 99.86 0.00 95.07 80 10 11 0.07 1.62 3.38 0.06 0.00 99.87 0.00 76.64
81.fi
82.SH SUMMARY EXAMPLE
83The "-s" option prints the column headers just once,
84and then the one line system summary for each sample interval.
85
86.nf
87[root@x980]# ./turbostat -s
88 %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6
89 0.61 1.89 3.38 5.95 0.00 93.44 0.00 66.33
90 0.52 1.62 3.38 6.83 0.00 92.65 0.00 61.11
91 0.62 1.92 3.38 5.47 0.00 93.91 0.00 67.31
75.fi 92.fi
76.SH VERBOSE EXAMPLE 93.SH VERBOSE EXAMPLE
77The "-v" option adds verbosity to the output: 94The "-v" option adds verbosity to the output:
@@ -101,33 +118,33 @@ until ^C while the other CPUs are mostly idle:
101 118
102.nf 119.nf
103[root@x980 lenb]# ./turbostat cat /dev/zero > /dev/null 120[root@x980 lenb]# ./turbostat cat /dev/zero > /dev/null
104 121^C
105^Ccr CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 122cor CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6
106 8.49 3.63 3.38 16.23 0.66 74.63 0.00 0.00 123 8.63 3.64 3.38 14.46 0.49 76.42 0.00 0.00
107 0 0 1.22 3.62 3.38 32.18 0.00 66.60 0.00 0.00 124 0 0 0.34 3.36 3.38 99.66 0.00 0.00 0.00 0.00
108 0 6 0.40 3.61 3.38 33.00 0.00 66.60 0.00 0.00 125 0 6 99.96 3.64 3.38 0.04 0.00 0.00 0.00 0.00
109 1 2 0.11 3.14 3.38 0.19 3.95 95.75 0.00 0.00 126 1 2 0.14 3.50 3.38 1.75 2.04 96.07 0.00 0.00
110 1 8 0.05 2.88 3.38 0.25 3.95 95.75 0.00 0.00 127 1 8 0.38 3.57 3.38 1.51 2.04 96.07 0.00 0.00
111 2 4 0.00 3.13 3.38 0.02 0.00 99.98 0.00 0.00 128 2 4 0.01 2.65 3.38 0.06 0.00 99.93 0.00 0.00
112 2 10 0.00 3.09 3.38 0.02 0.00 99.98 0.00 0.00 129 2 10 0.03 2.12 3.38 0.04 0.00 99.93 0.00 0.00
113 8 1 0.04 3.50 3.38 14.43 0.00 85.54 0.00 0.00 130 8 1 0.91 3.59 3.38 35.27 0.92 62.90 0.00 0.00
114 8 7 0.03 2.98 3.38 14.43 0.00 85.54 0.00 0.00 131 8 7 1.61 3.63 3.38 34.57 0.92 62.90 0.00 0.00
115 9 3 0.00 3.16 3.38 100.00 0.00 0.00 0.00 0.00 132 9 3 0.04 3.38 3.38 0.20 0.00 99.76 0.00 0.00
116 9 9 99.93 3.63 3.38 0.06 0.00 0.00 0.00 0.00 133 9 9 0.04 3.29 3.38 0.20 0.00 99.76 0.00 0.00
117 10 5 0.01 2.82 3.38 0.08 0.00 99.91 0.00 0.00 134 10 5 0.03 3.08 3.38 0.12 0.00 99.85 0.00 0.00
118 10 11 0.02 3.36 3.38 0.06 0.00 99.91 0.00 0.00 135 10 11 0.05 3.07 3.38 0.10 0.00 99.85 0.00 0.00
1196.950866 sec 1364.907015 sec
120 137
121.fi 138.fi
122Above the cycle soaker drives cpu9 up 3.6 Ghz turbo limit 139Above the cycle soaker drives cpu6 up 3.6 Ghz turbo limit
123while the other processors are generally in various states of idle. 140while the other processors are generally in various states of idle.
124 141
125Note that cpu3 is an HT sibling sharing core9 142Note that cpu0 is an HT sibling sharing core0
126with cpu9, and thus it is unable to get to an idle state 143with cpu6, and thus it is unable to get to an idle state
127deeper than c1 while cpu9 is busy. 144deeper than c1 while cpu6 is busy.
128 145
129Note that turbostat reports average GHz of 3.61, while 146Note that turbostat reports average GHz of 3.64, while
130the arithmetic average of the GHz column above is 3.24. 147the arithmetic average of the GHz column above is lower.
131This is a weighted average, where the weight is %c0. ie. it is the total number of 148This is a weighted average, where the weight is %c0. ie. it is the total number of
132un-halted cycles elapsed per time divided by the number of CPUs. 149un-halted cycles elapsed per time divided by the number of CPUs.
133.SH NOTES 150.SH NOTES
@@ -167,6 +184,6 @@ http://www.intel.com/products/processor/manuals/
167.SH "SEE ALSO" 184.SH "SEE ALSO"
168msr(4), vmstat(8) 185msr(4), vmstat(8)
169.PP 186.PP
170.SH AUTHORS 187.SH AUTHOR
171.nf 188.nf
172Written by Len Brown <len.brown@intel.com> 189Written by Len Brown <len.brown@intel.com>
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 3c6f7808efae..ab2f682fd44c 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -2,7 +2,7 @@
2 * turbostat -- show CPU frequency and C-state residency 2 * turbostat -- show CPU frequency and C-state residency
3 * on modern Intel turbo-capable processors. 3 * on modern Intel turbo-capable processors.
4 * 4 *
5 * Copyright (c) 2010, Intel Corporation. 5 * Copyright (c) 2012 Intel Corporation.
6 * Len Brown <len.brown@intel.com> 6 * Len Brown <len.brown@intel.com>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
@@ -19,6 +19,7 @@
19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 */ 20 */
21 21
22#define _GNU_SOURCE
22#include <stdio.h> 23#include <stdio.h>
23#include <unistd.h> 24#include <unistd.h>
24#include <sys/types.h> 25#include <sys/types.h>
@@ -32,6 +33,7 @@
32#include <dirent.h> 33#include <dirent.h>
33#include <string.h> 34#include <string.h>
34#include <ctype.h> 35#include <ctype.h>
36#include <sched.h>
35 37
36#define MSR_TSC 0x10 38#define MSR_TSC 0x10
37#define MSR_NEHALEM_PLATFORM_INFO 0xCE 39#define MSR_NEHALEM_PLATFORM_INFO 0xCE
@@ -49,6 +51,7 @@
49char *proc_stat = "/proc/stat"; 51char *proc_stat = "/proc/stat";
50unsigned int interval_sec = 5; /* set with -i interval_sec */ 52unsigned int interval_sec = 5; /* set with -i interval_sec */
51unsigned int verbose; /* set with -v */ 53unsigned int verbose; /* set with -v */
54unsigned int summary_only; /* set with -s */
52unsigned int skip_c0; 55unsigned int skip_c0;
53unsigned int skip_c1; 56unsigned int skip_c1;
54unsigned int do_nhm_cstates; 57unsigned int do_nhm_cstates;
@@ -68,9 +71,10 @@ unsigned int show_cpu;
68int aperf_mperf_unstable; 71int aperf_mperf_unstable;
69int backwards_count; 72int backwards_count;
70char *progname; 73char *progname;
71int need_reinitialize;
72 74
73int num_cpus; 75int num_cpus;
76cpu_set_t *cpu_mask;
77size_t cpu_mask_size;
74 78
75struct counters { 79struct counters {
76 unsigned long long tsc; /* per thread */ 80 unsigned long long tsc; /* per thread */
@@ -99,44 +103,76 @@ struct timeval tv_even;
99struct timeval tv_odd; 103struct timeval tv_odd;
100struct timeval tv_delta; 104struct timeval tv_delta;
101 105
102unsigned long long get_msr(int cpu, off_t offset) 106/*
107 * cpu_mask_init(ncpus)
108 *
109 * allocate and clear cpu_mask
110 * set cpu_mask_size
111 */
112void cpu_mask_init(int ncpus)
113{
114 cpu_mask = CPU_ALLOC(ncpus);
115 if (cpu_mask == NULL) {
116 perror("CPU_ALLOC");
117 exit(3);
118 }
119 cpu_mask_size = CPU_ALLOC_SIZE(ncpus);
120 CPU_ZERO_S(cpu_mask_size, cpu_mask);
121}
122
123void cpu_mask_uninit()
124{
125 CPU_FREE(cpu_mask);
126 cpu_mask = NULL;
127 cpu_mask_size = 0;
128}
129
130int cpu_migrate(int cpu)
131{
132 CPU_ZERO_S(cpu_mask_size, cpu_mask);
133 CPU_SET_S(cpu, cpu_mask_size, cpu_mask);
134 if (sched_setaffinity(0, cpu_mask_size, cpu_mask) == -1)
135 return -1;
136 else
137 return 0;
138}
139
140int get_msr(int cpu, off_t offset, unsigned long long *msr)
103{ 141{
104 ssize_t retval; 142 ssize_t retval;
105 unsigned long long msr;
106 char pathname[32]; 143 char pathname[32];
107 int fd; 144 int fd;
108 145
109 sprintf(pathname, "/dev/cpu/%d/msr", cpu); 146 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
110 fd = open(pathname, O_RDONLY); 147 fd = open(pathname, O_RDONLY);
111 if (fd < 0) { 148 if (fd < 0)
112 perror(pathname); 149 return -1;
113 need_reinitialize = 1;
114 return 0;
115 }
116
117 retval = pread(fd, &msr, sizeof msr, offset);
118 if (retval != sizeof msr) {
119 fprintf(stderr, "cpu%d pread(..., 0x%zx) = %jd\n",
120 cpu, offset, retval);
121 exit(-2);
122 }
123 150
151 retval = pread(fd, msr, sizeof *msr, offset);
124 close(fd); 152 close(fd);
125 return msr; 153
154 if (retval != sizeof *msr)
155 return -1;
156
157 return 0;
126} 158}
127 159
128void print_header(void) 160void print_header(void)
129{ 161{
130 if (show_pkg) 162 if (show_pkg)
131 fprintf(stderr, "pk"); 163 fprintf(stderr, "pk");
164 if (show_pkg)
165 fprintf(stderr, " ");
132 if (show_core) 166 if (show_core)
133 fprintf(stderr, " cr"); 167 fprintf(stderr, "cor");
134 if (show_cpu) 168 if (show_cpu)
135 fprintf(stderr, " CPU"); 169 fprintf(stderr, " CPU");
170 if (show_pkg || show_core || show_cpu)
171 fprintf(stderr, " ");
136 if (do_nhm_cstates) 172 if (do_nhm_cstates)
137 fprintf(stderr, " %%c0 "); 173 fprintf(stderr, " %%c0");
138 if (has_aperf) 174 if (has_aperf)
139 fprintf(stderr, " GHz"); 175 fprintf(stderr, " GHz");
140 fprintf(stderr, " TSC"); 176 fprintf(stderr, " TSC");
141 if (do_nhm_cstates) 177 if (do_nhm_cstates)
142 fprintf(stderr, " %%c1"); 178 fprintf(stderr, " %%c1");
@@ -147,13 +183,13 @@ void print_header(void)
147 if (do_snb_cstates) 183 if (do_snb_cstates)
148 fprintf(stderr, " %%c7"); 184 fprintf(stderr, " %%c7");
149 if (do_snb_cstates) 185 if (do_snb_cstates)
150 fprintf(stderr, " %%pc2"); 186 fprintf(stderr, " %%pc2");
151 if (do_nhm_cstates) 187 if (do_nhm_cstates)
152 fprintf(stderr, " %%pc3"); 188 fprintf(stderr, " %%pc3");
153 if (do_nhm_cstates) 189 if (do_nhm_cstates)
154 fprintf(stderr, " %%pc6"); 190 fprintf(stderr, " %%pc6");
155 if (do_snb_cstates) 191 if (do_snb_cstates)
156 fprintf(stderr, " %%pc7"); 192 fprintf(stderr, " %%pc7");
157 if (extra_msr_offset) 193 if (extra_msr_offset)
158 fprintf(stderr, " MSR 0x%x ", extra_msr_offset); 194 fprintf(stderr, " MSR 0x%x ", extra_msr_offset);
159 195
@@ -187,6 +223,15 @@ void dump_list(struct counters *cnt)
187 dump_cnt(cnt); 223 dump_cnt(cnt);
188} 224}
189 225
226/*
227 * column formatting convention & formats
228 * package: "pk" 2 columns %2d
229 * core: "cor" 3 columns %3d
230 * CPU: "CPU" 3 columns %3d
231 * GHz: "GHz" 3 columns %3.2
232 * TSC: "TSC" 3 columns %3.2
233 * percentage " %pc3" %6.2
234 */
190void print_cnt(struct counters *p) 235void print_cnt(struct counters *p)
191{ 236{
192 double interval_float; 237 double interval_float;
@@ -196,39 +241,45 @@ void print_cnt(struct counters *p)
196 /* topology columns, print blanks on 1st (average) line */ 241 /* topology columns, print blanks on 1st (average) line */
197 if (p == cnt_average) { 242 if (p == cnt_average) {
198 if (show_pkg) 243 if (show_pkg)
244 fprintf(stderr, " ");
245 if (show_pkg && show_core)
199 fprintf(stderr, " "); 246 fprintf(stderr, " ");
200 if (show_core) 247 if (show_core)
201 fprintf(stderr, " "); 248 fprintf(stderr, " ");
202 if (show_cpu) 249 if (show_cpu)
203 fprintf(stderr, " "); 250 fprintf(stderr, " " " ");
204 } else { 251 } else {
205 if (show_pkg) 252 if (show_pkg)
206 fprintf(stderr, "%d", p->pkg); 253 fprintf(stderr, "%2d", p->pkg);
254 if (show_pkg && show_core)
255 fprintf(stderr, " ");
207 if (show_core) 256 if (show_core)
208 fprintf(stderr, "%4d", p->core); 257 fprintf(stderr, "%3d", p->core);
209 if (show_cpu) 258 if (show_cpu)
210 fprintf(stderr, "%4d", p->cpu); 259 fprintf(stderr, " %3d", p->cpu);
211 } 260 }
212 261
213 /* %c0 */ 262 /* %c0 */
214 if (do_nhm_cstates) { 263 if (do_nhm_cstates) {
264 if (show_pkg || show_core || show_cpu)
265 fprintf(stderr, " ");
215 if (!skip_c0) 266 if (!skip_c0)
216 fprintf(stderr, "%7.2f", 100.0 * p->mperf/p->tsc); 267 fprintf(stderr, "%6.2f", 100.0 * p->mperf/p->tsc);
217 else 268 else
218 fprintf(stderr, " ****"); 269 fprintf(stderr, " ****");
219 } 270 }
220 271
221 /* GHz */ 272 /* GHz */
222 if (has_aperf) { 273 if (has_aperf) {
223 if (!aperf_mperf_unstable) { 274 if (!aperf_mperf_unstable) {
224 fprintf(stderr, "%5.2f", 275 fprintf(stderr, " %3.2f",
225 1.0 * p->tsc / units * p->aperf / 276 1.0 * p->tsc / units * p->aperf /
226 p->mperf / interval_float); 277 p->mperf / interval_float);
227 } else { 278 } else {
228 if (p->aperf > p->tsc || p->mperf > p->tsc) { 279 if (p->aperf > p->tsc || p->mperf > p->tsc) {
229 fprintf(stderr, " ****"); 280 fprintf(stderr, " ***");
230 } else { 281 } else {
231 fprintf(stderr, "%4.1f*", 282 fprintf(stderr, "%3.1f*",
232 1.0 * p->tsc / 283 1.0 * p->tsc /
233 units * p->aperf / 284 units * p->aperf /
234 p->mperf / interval_float); 285 p->mperf / interval_float);
@@ -241,7 +292,7 @@ void print_cnt(struct counters *p)
241 292
242 if (do_nhm_cstates) { 293 if (do_nhm_cstates) {
243 if (!skip_c1) 294 if (!skip_c1)
244 fprintf(stderr, "%7.2f", 100.0 * p->c1/p->tsc); 295 fprintf(stderr, " %6.2f", 100.0 * p->c1/p->tsc);
245 else 296 else
246 fprintf(stderr, " ****"); 297 fprintf(stderr, " ****");
247 } 298 }
@@ -252,13 +303,13 @@ void print_cnt(struct counters *p)
252 if (do_snb_cstates) 303 if (do_snb_cstates)
253 fprintf(stderr, " %6.2f", 100.0 * p->c7/p->tsc); 304 fprintf(stderr, " %6.2f", 100.0 * p->c7/p->tsc);
254 if (do_snb_cstates) 305 if (do_snb_cstates)
255 fprintf(stderr, " %5.2f", 100.0 * p->pc2/p->tsc); 306 fprintf(stderr, " %6.2f", 100.0 * p->pc2/p->tsc);
256 if (do_nhm_cstates) 307 if (do_nhm_cstates)
257 fprintf(stderr, " %5.2f", 100.0 * p->pc3/p->tsc); 308 fprintf(stderr, " %6.2f", 100.0 * p->pc3/p->tsc);
258 if (do_nhm_cstates) 309 if (do_nhm_cstates)
259 fprintf(stderr, " %5.2f", 100.0 * p->pc6/p->tsc); 310 fprintf(stderr, " %6.2f", 100.0 * p->pc6/p->tsc);
260 if (do_snb_cstates) 311 if (do_snb_cstates)
261 fprintf(stderr, " %5.2f", 100.0 * p->pc7/p->tsc); 312 fprintf(stderr, " %6.2f", 100.0 * p->pc7/p->tsc);
262 if (extra_msr_offset) 313 if (extra_msr_offset)
263 fprintf(stderr, " 0x%016llx", p->extra_msr); 314 fprintf(stderr, " 0x%016llx", p->extra_msr);
264 putc('\n', stderr); 315 putc('\n', stderr);
@@ -267,12 +318,20 @@ void print_cnt(struct counters *p)
267void print_counters(struct counters *counters) 318void print_counters(struct counters *counters)
268{ 319{
269 struct counters *cnt; 320 struct counters *cnt;
321 static int printed;
322
270 323
271 print_header(); 324 if (!printed || !summary_only)
325 print_header();
272 326
273 if (num_cpus > 1) 327 if (num_cpus > 1)
274 print_cnt(cnt_average); 328 print_cnt(cnt_average);
275 329
330 printed = 1;
331
332 if (summary_only)
333 return;
334
276 for (cnt = counters; cnt != NULL; cnt = cnt->next) 335 for (cnt = counters; cnt != NULL; cnt = cnt->next)
277 print_cnt(cnt); 336 print_cnt(cnt);
278 337
@@ -440,31 +499,51 @@ void compute_average(struct counters *delta, struct counters *avg)
440 free(sum); 499 free(sum);
441} 500}
442 501
443void get_counters(struct counters *cnt) 502int get_counters(struct counters *cnt)
444{ 503{
445 for ( ; cnt; cnt = cnt->next) { 504 for ( ; cnt; cnt = cnt->next) {
446 cnt->tsc = get_msr(cnt->cpu, MSR_TSC); 505
447 if (do_nhm_cstates) 506 if (cpu_migrate(cnt->cpu))
448 cnt->c3 = get_msr(cnt->cpu, MSR_CORE_C3_RESIDENCY); 507 return -1;
449 if (do_nhm_cstates) 508
450 cnt->c6 = get_msr(cnt->cpu, MSR_CORE_C6_RESIDENCY); 509 if (get_msr(cnt->cpu, MSR_TSC, &cnt->tsc))
451 if (do_snb_cstates) 510 return -1;
452 cnt->c7 = get_msr(cnt->cpu, MSR_CORE_C7_RESIDENCY); 511
453 if (has_aperf) 512 if (has_aperf) {
454 cnt->aperf = get_msr(cnt->cpu, MSR_APERF); 513 if (get_msr(cnt->cpu, MSR_APERF, &cnt->aperf))
455 if (has_aperf) 514 return -1;
456 cnt->mperf = get_msr(cnt->cpu, MSR_MPERF); 515 if (get_msr(cnt->cpu, MSR_MPERF, &cnt->mperf))
457 if (do_snb_cstates) 516 return -1;
458 cnt->pc2 = get_msr(cnt->cpu, MSR_PKG_C2_RESIDENCY); 517 }
459 if (do_nhm_cstates) 518
460 cnt->pc3 = get_msr(cnt->cpu, MSR_PKG_C3_RESIDENCY); 519 if (do_nhm_cstates) {
461 if (do_nhm_cstates) 520 if (get_msr(cnt->cpu, MSR_CORE_C3_RESIDENCY, &cnt->c3))
462 cnt->pc6 = get_msr(cnt->cpu, MSR_PKG_C6_RESIDENCY); 521 return -1;
522 if (get_msr(cnt->cpu, MSR_CORE_C6_RESIDENCY, &cnt->c6))
523 return -1;
524 }
525
463 if (do_snb_cstates) 526 if (do_snb_cstates)
464 cnt->pc7 = get_msr(cnt->cpu, MSR_PKG_C7_RESIDENCY); 527 if (get_msr(cnt->cpu, MSR_CORE_C7_RESIDENCY, &cnt->c7))
528 return -1;
529
530 if (do_nhm_cstates) {
531 if (get_msr(cnt->cpu, MSR_PKG_C3_RESIDENCY, &cnt->pc3))
532 return -1;
533 if (get_msr(cnt->cpu, MSR_PKG_C6_RESIDENCY, &cnt->pc6))
534 return -1;
535 }
536 if (do_snb_cstates) {
537 if (get_msr(cnt->cpu, MSR_PKG_C2_RESIDENCY, &cnt->pc2))
538 return -1;
539 if (get_msr(cnt->cpu, MSR_PKG_C7_RESIDENCY, &cnt->pc7))
540 return -1;
541 }
465 if (extra_msr_offset) 542 if (extra_msr_offset)
466 cnt->extra_msr = get_msr(cnt->cpu, extra_msr_offset); 543 if (get_msr(cnt->cpu, extra_msr_offset, &cnt->extra_msr))
544 return -1;
467 } 545 }
546 return 0;
468} 547}
469 548
470void print_nehalem_info(void) 549void print_nehalem_info(void)
@@ -475,7 +554,7 @@ void print_nehalem_info(void)
475 if (!do_nehalem_platform_info) 554 if (!do_nehalem_platform_info)
476 return; 555 return;
477 556
478 msr = get_msr(0, MSR_NEHALEM_PLATFORM_INFO); 557 get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr);
479 558
480 ratio = (msr >> 40) & 0xFF; 559 ratio = (msr >> 40) & 0xFF;
481 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", 560 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n",
@@ -491,7 +570,7 @@ void print_nehalem_info(void)
491 if (!do_nehalem_turbo_ratio_limit) 570 if (!do_nehalem_turbo_ratio_limit)
492 return; 571 return;
493 572
494 msr = get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT); 573 get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr);
495 574
496 ratio = (msr >> 24) & 0xFF; 575 ratio = (msr >> 24) & 0xFF;
497 if (ratio) 576 if (ratio)
@@ -557,7 +636,8 @@ void insert_counters(struct counters **list,
557 return; 636 return;
558 } 637 }
559 638
560 show_cpu = 1; /* there is more than one CPU */ 639 if (!summary_only)
640 show_cpu = 1; /* there is more than one CPU */
561 641
562 /* 642 /*
563 * insert on front of list. 643 * insert on front of list.
@@ -575,13 +655,15 @@ void insert_counters(struct counters **list,
575 655
576 while (prev->next && (prev->next->pkg < new->pkg)) { 656 while (prev->next && (prev->next->pkg < new->pkg)) {
577 prev = prev->next; 657 prev = prev->next;
578 show_pkg = 1; /* there is more than 1 package */ 658 if (!summary_only)
659 show_pkg = 1; /* there is more than 1 package */
579 } 660 }
580 661
581 while (prev->next && (prev->next->pkg == new->pkg) 662 while (prev->next && (prev->next->pkg == new->pkg)
582 && (prev->next->core < new->core)) { 663 && (prev->next->core < new->core)) {
583 prev = prev->next; 664 prev = prev->next;
584 show_core = 1; /* there is more than 1 core */ 665 if (!summary_only)
666 show_core = 1; /* there is more than 1 core */
585 } 667 }
586 668
587 while (prev->next && (prev->next->pkg == new->pkg) 669 while (prev->next && (prev->next->pkg == new->pkg)
@@ -681,7 +763,7 @@ int get_core_id(int cpu)
681} 763}
682 764
683/* 765/*
684 * run func(index, cpu) on every cpu in /proc/stat 766 * run func(pkg, core, cpu) on every cpu in /proc/stat
685 */ 767 */
686 768
687int for_all_cpus(void (func)(int, int, int)) 769int for_all_cpus(void (func)(int, int, int))
@@ -717,18 +799,18 @@ int for_all_cpus(void (func)(int, int, int))
717 799
718void re_initialize(void) 800void re_initialize(void)
719{ 801{
720 printf("turbostat: topology changed, re-initializing.\n");
721 free_all_counters(); 802 free_all_counters();
722 num_cpus = for_all_cpus(alloc_new_counters); 803 num_cpus = for_all_cpus(alloc_new_counters);
723 need_reinitialize = 0; 804 cpu_mask_uninit();
724 printf("num_cpus is now %d\n", num_cpus); 805 cpu_mask_init(num_cpus);
806 printf("turbostat: re-initialized with num_cpus %d\n", num_cpus);
725} 807}
726 808
727void dummy(int pkg, int core, int cpu) { return; } 809void dummy(int pkg, int core, int cpu) { return; }
728/* 810/*
729 * check to see if a cpu came on-line 811 * check to see if a cpu came on-line
730 */ 812 */
731void verify_num_cpus(void) 813int verify_num_cpus(void)
732{ 814{
733 int new_num_cpus; 815 int new_num_cpus;
734 816
@@ -738,8 +820,9 @@ void verify_num_cpus(void)
738 if (verbose) 820 if (verbose)
739 printf("num_cpus was %d, is now %d\n", 821 printf("num_cpus was %d, is now %d\n",
740 num_cpus, new_num_cpus); 822 num_cpus, new_num_cpus);
741 need_reinitialize = 1; 823 return -1;
742 } 824 }
825 return 0;
743} 826}
744 827
745void turbostat_loop() 828void turbostat_loop()
@@ -749,25 +832,25 @@ restart:
749 gettimeofday(&tv_even, (struct timezone *)NULL); 832 gettimeofday(&tv_even, (struct timezone *)NULL);
750 833
751 while (1) { 834 while (1) {
752 verify_num_cpus(); 835 if (verify_num_cpus()) {
753 if (need_reinitialize) {
754 re_initialize(); 836 re_initialize();
755 goto restart; 837 goto restart;
756 } 838 }
757 sleep(interval_sec); 839 sleep(interval_sec);
758 get_counters(cnt_odd); 840 if (get_counters(cnt_odd)) {
841 re_initialize();
842 goto restart;
843 }
759 gettimeofday(&tv_odd, (struct timezone *)NULL); 844 gettimeofday(&tv_odd, (struct timezone *)NULL);
760
761 compute_delta(cnt_odd, cnt_even, cnt_delta); 845 compute_delta(cnt_odd, cnt_even, cnt_delta);
762 timersub(&tv_odd, &tv_even, &tv_delta); 846 timersub(&tv_odd, &tv_even, &tv_delta);
763 compute_average(cnt_delta, cnt_average); 847 compute_average(cnt_delta, cnt_average);
764 print_counters(cnt_delta); 848 print_counters(cnt_delta);
765 if (need_reinitialize) { 849 sleep(interval_sec);
850 if (get_counters(cnt_even)) {
766 re_initialize(); 851 re_initialize();
767 goto restart; 852 goto restart;
768 } 853 }
769 sleep(interval_sec);
770 get_counters(cnt_even);
771 gettimeofday(&tv_even, (struct timezone *)NULL); 854 gettimeofday(&tv_even, (struct timezone *)NULL);
772 compute_delta(cnt_even, cnt_odd, cnt_delta); 855 compute_delta(cnt_even, cnt_odd, cnt_delta);
773 timersub(&tv_even, &tv_odd, &tv_delta); 856 timersub(&tv_even, &tv_odd, &tv_delta);
@@ -811,6 +894,8 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
811 case 0x2C: /* Westmere EP - Gulftown */ 894 case 0x2C: /* Westmere EP - Gulftown */
812 case 0x2A: /* SNB */ 895 case 0x2A: /* SNB */
813 case 0x2D: /* SNB Xeon */ 896 case 0x2D: /* SNB Xeon */
897 case 0x3A: /* IVB */
898 case 0x3D: /* IVB Xeon */
814 return 1; 899 return 1;
815 case 0x2E: /* Nehalem-EX Xeon - Beckton */ 900 case 0x2E: /* Nehalem-EX Xeon - Beckton */
816 case 0x2F: /* Westmere-EX Xeon - Eagleton */ 901 case 0x2F: /* Westmere-EX Xeon - Eagleton */
@@ -951,6 +1036,7 @@ void turbostat_init()
951 check_super_user(); 1036 check_super_user();
952 1037
953 num_cpus = for_all_cpus(alloc_new_counters); 1038 num_cpus = for_all_cpus(alloc_new_counters);
1039 cpu_mask_init(num_cpus);
954 1040
955 if (verbose) 1041 if (verbose)
956 print_nehalem_info(); 1042 print_nehalem_info();
@@ -1003,8 +1089,11 @@ void cmdline(int argc, char **argv)
1003 1089
1004 progname = argv[0]; 1090 progname = argv[0];
1005 1091
1006 while ((opt = getopt(argc, argv, "+vi:M:")) != -1) { 1092 while ((opt = getopt(argc, argv, "+svi:M:")) != -1) {
1007 switch (opt) { 1093 switch (opt) {
1094 case 's':
1095 summary_only++;
1096 break;
1008 case 'v': 1097 case 'v':
1009 verbose++; 1098 verbose++;
1010 break; 1099 break;
diff --git a/tools/testing/ktest/compare-ktest-sample.pl b/tools/testing/ktest/compare-ktest-sample.pl
index 9a571e71683c..a373a5bfff68 100755
--- a/tools/testing/ktest/compare-ktest-sample.pl
+++ b/tools/testing/ktest/compare-ktest-sample.pl
@@ -2,7 +2,9 @@
2 2
3open (IN,"ktest.pl"); 3open (IN,"ktest.pl");
4while (<IN>) { 4while (<IN>) {
5 # hashes are now used
5 if (/\$opt\{"?([A-Z].*?)(\[.*\])?"?\}/ || 6 if (/\$opt\{"?([A-Z].*?)(\[.*\])?"?\}/ ||
7 /^\s*"?([A-Z].*?)"?\s*=>\s*/ ||
6 /set_test_option\("(.*?)"/) { 8 /set_test_option\("(.*?)"/) {
7 $opt{$1} = 1; 9 $opt{$1} = 1;
8 } 10 }
@@ -11,7 +13,7 @@ close IN;
11 13
12open (IN, "sample.conf"); 14open (IN, "sample.conf");
13while (<IN>) { 15while (<IN>) {
14 if (/^\s*#?\s*(\S+)\s*=/) { 16 if (/^\s*#?\s*([A-Z]\S*)\s*=/) {
15 $samp{$1} = 1; 17 $samp{$1} = 1;
16 } 18 }
17} 19}
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index 8b4c2535b266..95d6a6f7c33a 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -18,40 +18,51 @@ $| = 1;
18my %opt; 18my %opt;
19my %repeat_tests; 19my %repeat_tests;
20my %repeats; 20my %repeats;
21my %default;
22 21
23#default opts 22#default opts
24$default{"NUM_TESTS"} = 1; 23my %default = (
25$default{"REBOOT_TYPE"} = "grub"; 24 "NUM_TESTS" => 1,
26$default{"TEST_TYPE"} = "test"; 25 "TEST_TYPE" => "build",
27$default{"BUILD_TYPE"} = "randconfig"; 26 "BUILD_TYPE" => "randconfig",
28$default{"MAKE_CMD"} = "make"; 27 "MAKE_CMD" => "make",
29$default{"TIMEOUT"} = 120; 28 "TIMEOUT" => 120,
30$default{"TMP_DIR"} = "/tmp/ktest/\${MACHINE}"; 29 "TMP_DIR" => "/tmp/ktest/\${MACHINE}",
31$default{"SLEEP_TIME"} = 60; # sleep time between tests 30 "SLEEP_TIME" => 60, # sleep time between tests
32$default{"BUILD_NOCLEAN"} = 0; 31 "BUILD_NOCLEAN" => 0,
33$default{"REBOOT_ON_ERROR"} = 0; 32 "REBOOT_ON_ERROR" => 0,
34$default{"POWEROFF_ON_ERROR"} = 0; 33 "POWEROFF_ON_ERROR" => 0,
35$default{"REBOOT_ON_SUCCESS"} = 1; 34 "REBOOT_ON_SUCCESS" => 1,
36$default{"POWEROFF_ON_SUCCESS"} = 0; 35 "POWEROFF_ON_SUCCESS" => 0,
37$default{"BUILD_OPTIONS"} = ""; 36 "BUILD_OPTIONS" => "",
38$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects 37 "BISECT_SLEEP_TIME" => 60, # sleep time between bisects
39$default{"PATCHCHECK_SLEEP_TIME"} = 60; # sleep time between patch checks 38 "PATCHCHECK_SLEEP_TIME" => 60, # sleep time between patch checks
40$default{"CLEAR_LOG"} = 0; 39 "CLEAR_LOG" => 0,
41$default{"BISECT_MANUAL"} = 0; 40 "BISECT_MANUAL" => 0,
42$default{"BISECT_SKIP"} = 1; 41 "BISECT_SKIP" => 1,
43$default{"SUCCESS_LINE"} = "login:"; 42 "SUCCESS_LINE" => "login:",
44$default{"DETECT_TRIPLE_FAULT"} = 1; 43 "DETECT_TRIPLE_FAULT" => 1,
45$default{"NO_INSTALL"} = 0; 44 "NO_INSTALL" => 0,
46$default{"BOOTED_TIMEOUT"} = 1; 45 "BOOTED_TIMEOUT" => 1,
47$default{"DIE_ON_FAILURE"} = 1; 46 "DIE_ON_FAILURE" => 1,
48$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; 47 "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
49$default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE"; 48 "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
50$default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot"; 49 "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}",
51$default{"STOP_AFTER_SUCCESS"} = 10; 50 "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot",
52$default{"STOP_AFTER_FAILURE"} = 60; 51 "STOP_AFTER_SUCCESS" => 10,
53$default{"STOP_TEST_AFTER"} = 600; 52 "STOP_AFTER_FAILURE" => 60,
54$default{"LOCALVERSION"} = "-test"; 53 "STOP_TEST_AFTER" => 600,
54
55# required, and we will ask users if they don't have them but we keep the default
56# value something that is common.
57 "REBOOT_TYPE" => "grub",
58 "LOCALVERSION" => "-test",
59 "SSH_USER" => "root",
60 "BUILD_TARGET" => "arch/x86/boot/bzImage",
61 "TARGET_IMAGE" => "/boot/vmlinuz-test",
62
63 "LOG_FILE" => undef,
64 "IGNORE_UNUSED" => 0,
65);
55 66
56my $ktest_config; 67my $ktest_config;
57my $version; 68my $version;
@@ -73,12 +84,16 @@ my $reboot_script;
73my $power_cycle; 84my $power_cycle;
74my $reboot; 85my $reboot;
75my $reboot_on_error; 86my $reboot_on_error;
87my $switch_to_good;
88my $switch_to_test;
76my $poweroff_on_error; 89my $poweroff_on_error;
90my $reboot_on_success;
77my $die_on_failure; 91my $die_on_failure;
78my $powercycle_after_reboot; 92my $powercycle_after_reboot;
79my $poweroff_after_halt; 93my $poweroff_after_halt;
80my $ssh_exec; 94my $ssh_exec;
81my $scp_to_target; 95my $scp_to_target;
96my $scp_to_target_install;
82my $power_off; 97my $power_off;
83my $grub_menu; 98my $grub_menu;
84my $grub_number; 99my $grub_number;
@@ -92,17 +107,24 @@ my $start_minconfig;
92my $start_minconfig_defined; 107my $start_minconfig_defined;
93my $output_minconfig; 108my $output_minconfig;
94my $ignore_config; 109my $ignore_config;
110my $ignore_errors;
95my $addconfig; 111my $addconfig;
96my $in_bisect = 0; 112my $in_bisect = 0;
97my $bisect_bad = ""; 113my $bisect_bad_commit = "";
98my $reverse_bisect; 114my $reverse_bisect;
99my $bisect_manual; 115my $bisect_manual;
100my $bisect_skip; 116my $bisect_skip;
101my $config_bisect_good; 117my $config_bisect_good;
118my $bisect_ret_good;
119my $bisect_ret_bad;
120my $bisect_ret_skip;
121my $bisect_ret_abort;
122my $bisect_ret_default;
102my $in_patchcheck = 0; 123my $in_patchcheck = 0;
103my $run_test; 124my $run_test;
104my $redirect; 125my $redirect;
105my $buildlog; 126my $buildlog;
127my $testlog;
106my $dmesg; 128my $dmesg;
107my $monitor_fp; 129my $monitor_fp;
108my $monitor_pid; 130my $monitor_pid;
@@ -112,6 +134,7 @@ my $bisect_sleep_time;
112my $patchcheck_sleep_time; 134my $patchcheck_sleep_time;
113my $ignore_warnings; 135my $ignore_warnings;
114my $store_failures; 136my $store_failures;
137my $store_successes;
115my $test_name; 138my $test_name;
116my $timeout; 139my $timeout;
117my $booted_timeout; 140my $booted_timeout;
@@ -124,10 +147,34 @@ my $stop_after_failure;
124my $stop_test_after; 147my $stop_test_after;
125my $build_target; 148my $build_target;
126my $target_image; 149my $target_image;
150my $checkout;
127my $localversion; 151my $localversion;
128my $iteration = 0; 152my $iteration = 0;
129my $successes = 0; 153my $successes = 0;
130 154
155my $bisect_good;
156my $bisect_bad;
157my $bisect_type;
158my $bisect_start;
159my $bisect_replay;
160my $bisect_files;
161my $bisect_reverse;
162my $bisect_check;
163
164my $config_bisect;
165my $config_bisect_type;
166
167my $patchcheck_type;
168my $patchcheck_start;
169my $patchcheck_end;
170
171# set when a test is something other that just building or install
172# which would require more options.
173my $buildonly = 1;
174
175# set when creating a new config
176my $newconfig = 0;
177
131my %entered_configs; 178my %entered_configs;
132my %config_help; 179my %config_help;
133my %variable; 180my %variable;
@@ -136,11 +183,101 @@ my %force_config;
136# do not force reboots on config problems 183# do not force reboots on config problems
137my $no_reboot = 1; 184my $no_reboot = 1;
138 185
186my %option_map = (
187 "MACHINE" => \$machine,
188 "SSH_USER" => \$ssh_user,
189 "TMP_DIR" => \$tmpdir,
190 "OUTPUT_DIR" => \$outputdir,
191 "BUILD_DIR" => \$builddir,
192 "TEST_TYPE" => \$test_type,
193 "BUILD_TYPE" => \$build_type,
194 "BUILD_OPTIONS" => \$build_options,
195 "PRE_BUILD" => \$pre_build,
196 "POST_BUILD" => \$post_build,
197 "PRE_BUILD_DIE" => \$pre_build_die,
198 "POST_BUILD_DIE" => \$post_build_die,
199 "POWER_CYCLE" => \$power_cycle,
200 "REBOOT" => \$reboot,
201 "BUILD_NOCLEAN" => \$noclean,
202 "MIN_CONFIG" => \$minconfig,
203 "OUTPUT_MIN_CONFIG" => \$output_minconfig,
204 "START_MIN_CONFIG" => \$start_minconfig,
205 "IGNORE_CONFIG" => \$ignore_config,
206 "TEST" => \$run_test,
207 "ADD_CONFIG" => \$addconfig,
208 "REBOOT_TYPE" => \$reboot_type,
209 "GRUB_MENU" => \$grub_menu,
210 "POST_INSTALL" => \$post_install,
211 "NO_INSTALL" => \$no_install,
212 "REBOOT_SCRIPT" => \$reboot_script,
213 "REBOOT_ON_ERROR" => \$reboot_on_error,
214 "SWITCH_TO_GOOD" => \$switch_to_good,
215 "SWITCH_TO_TEST" => \$switch_to_test,
216 "POWEROFF_ON_ERROR" => \$poweroff_on_error,
217 "REBOOT_ON_SUCCESS" => \$reboot_on_success,
218 "DIE_ON_FAILURE" => \$die_on_failure,
219 "POWER_OFF" => \$power_off,
220 "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot,
221 "POWEROFF_AFTER_HALT" => \$poweroff_after_halt,
222 "SLEEP_TIME" => \$sleep_time,
223 "BISECT_SLEEP_TIME" => \$bisect_sleep_time,
224 "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time,
225 "IGNORE_WARNINGS" => \$ignore_warnings,
226 "IGNORE_ERRORS" => \$ignore_errors,
227 "BISECT_MANUAL" => \$bisect_manual,
228 "BISECT_SKIP" => \$bisect_skip,
229 "CONFIG_BISECT_GOOD" => \$config_bisect_good,
230 "BISECT_RET_GOOD" => \$bisect_ret_good,
231 "BISECT_RET_BAD" => \$bisect_ret_bad,
232 "BISECT_RET_SKIP" => \$bisect_ret_skip,
233 "BISECT_RET_ABORT" => \$bisect_ret_abort,
234 "BISECT_RET_DEFAULT" => \$bisect_ret_default,
235 "STORE_FAILURES" => \$store_failures,
236 "STORE_SUCCESSES" => \$store_successes,
237 "TEST_NAME" => \$test_name,
238 "TIMEOUT" => \$timeout,
239 "BOOTED_TIMEOUT" => \$booted_timeout,
240 "CONSOLE" => \$console,
241 "DETECT_TRIPLE_FAULT" => \$detect_triplefault,
242 "SUCCESS_LINE" => \$success_line,
243 "REBOOT_SUCCESS_LINE" => \$reboot_success_line,
244 "STOP_AFTER_SUCCESS" => \$stop_after_success,
245 "STOP_AFTER_FAILURE" => \$stop_after_failure,
246 "STOP_TEST_AFTER" => \$stop_test_after,
247 "BUILD_TARGET" => \$build_target,
248 "SSH_EXEC" => \$ssh_exec,
249 "SCP_TO_TARGET" => \$scp_to_target,
250 "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install,
251 "CHECKOUT" => \$checkout,
252 "TARGET_IMAGE" => \$target_image,
253 "LOCALVERSION" => \$localversion,
254
255 "BISECT_GOOD" => \$bisect_good,
256 "BISECT_BAD" => \$bisect_bad,
257 "BISECT_TYPE" => \$bisect_type,
258 "BISECT_START" => \$bisect_start,
259 "BISECT_REPLAY" => \$bisect_replay,
260 "BISECT_FILES" => \$bisect_files,
261 "BISECT_REVERSE" => \$bisect_reverse,
262 "BISECT_CHECK" => \$bisect_check,
263
264 "CONFIG_BISECT" => \$config_bisect,
265 "CONFIG_BISECT_TYPE" => \$config_bisect_type,
266
267 "PATCHCHECK_TYPE" => \$patchcheck_type,
268 "PATCHCHECK_START" => \$patchcheck_start,
269 "PATCHCHECK_END" => \$patchcheck_end,
270);
271
272# Options may be used by other options, record them.
273my %used_options;
274
139# default variables that can be used 275# default variables that can be used
140chomp ($variable{"PWD"} = `pwd`); 276chomp ($variable{"PWD"} = `pwd`);
141 277
142$config_help{"MACHINE"} = << "EOF" 278$config_help{"MACHINE"} = << "EOF"
143 The machine hostname that you will test. 279 The machine hostname that you will test.
280 For build only tests, it is still needed to differentiate log files.
144EOF 281EOF
145 ; 282 ;
146$config_help{"SSH_USER"} = << "EOF" 283$config_help{"SSH_USER"} = << "EOF"
@@ -150,11 +287,15 @@ EOF
150 ; 287 ;
151$config_help{"BUILD_DIR"} = << "EOF" 288$config_help{"BUILD_DIR"} = << "EOF"
152 The directory that contains the Linux source code (full path). 289 The directory that contains the Linux source code (full path).
290 You can use \${PWD} that will be the path where ktest.pl is run, or use
291 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
153EOF 292EOF
154 ; 293 ;
155$config_help{"OUTPUT_DIR"} = << "EOF" 294$config_help{"OUTPUT_DIR"} = << "EOF"
156 The directory that the objects will be built (full path). 295 The directory that the objects will be built (full path).
157 (can not be same as BUILD_DIR) 296 (can not be same as BUILD_DIR)
297 You can use \${PWD} that will be the path where ktest.pl is run, or use
298 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
158EOF 299EOF
159 ; 300 ;
160$config_help{"BUILD_TARGET"} = << "EOF" 301$config_help{"BUILD_TARGET"} = << "EOF"
@@ -162,6 +303,11 @@ $config_help{"BUILD_TARGET"} = << "EOF"
162 (relative to OUTPUT_DIR) 303 (relative to OUTPUT_DIR)
163EOF 304EOF
164 ; 305 ;
306$config_help{"BUILD_OPTIONS"} = << "EOF"
307 Options to add to \"make\" when building.
308 i.e. -j20
309EOF
310 ;
165$config_help{"TARGET_IMAGE"} = << "EOF" 311$config_help{"TARGET_IMAGE"} = << "EOF"
166 The place to put your image on the test machine. 312 The place to put your image on the test machine.
167EOF 313EOF
@@ -227,20 +373,36 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF"
227EOF 373EOF
228 ; 374 ;
229 375
230sub read_yn { 376sub read_prompt {
231 my ($prompt) = @_; 377 my ($cancel, $prompt) = @_;
232 378
233 my $ans; 379 my $ans;
234 380
235 for (;;) { 381 for (;;) {
236 print "$prompt [Y/n] "; 382 if ($cancel) {
383 print "$prompt [y/n/C] ";
384 } else {
385 print "$prompt [Y/n] ";
386 }
237 $ans = <STDIN>; 387 $ans = <STDIN>;
238 chomp $ans; 388 chomp $ans;
239 if ($ans =~ /^\s*$/) { 389 if ($ans =~ /^\s*$/) {
240 $ans = "y"; 390 if ($cancel) {
391 $ans = "c";
392 } else {
393 $ans = "y";
394 }
241 } 395 }
242 last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 396 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
243 print "Please answer either 'y' or 'n'.\n"; 397 if ($cancel) {
398 last if ($ans =~ /^c$/i);
399 print "Please answer either 'y', 'n' or 'c'.\n";
400 } else {
401 print "Please answer either 'y' or 'n'.\n";
402 }
403 }
404 if ($ans =~ /^c/i) {
405 exit;
244 } 406 }
245 if ($ans !~ /^y$/i) { 407 if ($ans !~ /^y$/i) {
246 return 0; 408 return 0;
@@ -248,6 +410,18 @@ sub read_yn {
248 return 1; 410 return 1;
249} 411}
250 412
413sub read_yn {
414 my ($prompt) = @_;
415
416 return read_prompt 0, $prompt;
417}
418
419sub read_ync {
420 my ($prompt) = @_;
421
422 return read_prompt 1, $prompt;
423}
424
251sub get_ktest_config { 425sub get_ktest_config {
252 my ($config) = @_; 426 my ($config) = @_;
253 my $ans; 427 my $ans;
@@ -261,7 +435,7 @@ sub get_ktest_config {
261 435
262 for (;;) { 436 for (;;) {
263 print "$config = "; 437 print "$config = ";
264 if (defined($default{$config})) { 438 if (defined($default{$config}) && length($default{$config})) {
265 print "\[$default{$config}\] "; 439 print "\[$default{$config}\] ";
266 } 440 }
267 $ans = <STDIN>; 441 $ans = <STDIN>;
@@ -274,22 +448,37 @@ sub get_ktest_config {
274 next; 448 next;
275 } 449 }
276 } 450 }
277 $entered_configs{$config} = process_variables($ans); 451 $entered_configs{$config} = ${ans};
278 last; 452 last;
279 } 453 }
280} 454}
281 455
282sub get_ktest_configs { 456sub get_ktest_configs {
283 get_ktest_config("MACHINE"); 457 get_ktest_config("MACHINE");
284 get_ktest_config("SSH_USER");
285 get_ktest_config("BUILD_DIR"); 458 get_ktest_config("BUILD_DIR");
286 get_ktest_config("OUTPUT_DIR"); 459 get_ktest_config("OUTPUT_DIR");
287 get_ktest_config("BUILD_TARGET"); 460
288 get_ktest_config("TARGET_IMAGE"); 461 if ($newconfig) {
289 get_ktest_config("POWER_CYCLE"); 462 get_ktest_config("BUILD_OPTIONS");
290 get_ktest_config("CONSOLE"); 463 }
464
465 # options required for other than just building a kernel
466 if (!$buildonly) {
467 get_ktest_config("POWER_CYCLE");
468 get_ktest_config("CONSOLE");
469 }
470
471 # options required for install and more
472 if ($buildonly != 1) {
473 get_ktest_config("SSH_USER");
474 get_ktest_config("BUILD_TARGET");
475 get_ktest_config("TARGET_IMAGE");
476 }
477
291 get_ktest_config("LOCALVERSION"); 478 get_ktest_config("LOCALVERSION");
292 479
480 return if ($buildonly);
481
293 my $rtype = $opt{"REBOOT_TYPE"}; 482 my $rtype = $opt{"REBOOT_TYPE"};
294 483
295 if (!defined($rtype)) { 484 if (!defined($rtype)) {
@@ -303,8 +492,6 @@ sub get_ktest_configs {
303 492
304 if ($rtype eq "grub") { 493 if ($rtype eq "grub") {
305 get_ktest_config("GRUB_MENU"); 494 get_ktest_config("GRUB_MENU");
306 } else {
307 get_ktest_config("REBOOT_SCRIPT");
308 } 495 }
309} 496}
310 497
@@ -334,6 +521,10 @@ sub process_variables {
334 } else { 521 } else {
335 # put back the origin piece. 522 # put back the origin piece.
336 $retval = "$retval\$\{$var\}"; 523 $retval = "$retval\$\{$var\}";
524 # This could be an option that is used later, save
525 # it so we don't warn if this option is not one of
526 # ktests options.
527 $used_options{$var} = 1;
337 } 528 }
338 $value = $end; 529 $value = $end;
339 } 530 }
@@ -348,6 +539,19 @@ sub process_variables {
348sub set_value { 539sub set_value {
349 my ($lvalue, $rvalue, $override, $overrides, $name) = @_; 540 my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
350 541
542 my $prvalue = process_variables($rvalue);
543
544 if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
545 # Note if a test is something other than build, then we
546 # will need other manditory options.
547 if ($prvalue ne "install") {
548 $buildonly = 0;
549 } else {
550 # install still limits some manditory options.
551 $buildonly = 2;
552 }
553 }
554
351 if (defined($opt{$lvalue})) { 555 if (defined($opt{$lvalue})) {
352 if (!$override || defined(${$overrides}{$lvalue})) { 556 if (!$override || defined(${$overrides}{$lvalue})) {
353 my $extra = ""; 557 my $extra = "";
@@ -356,13 +560,12 @@ sub set_value {
356 } 560 }
357 die "$name: $.: Option $lvalue defined more than once!\n$extra"; 561 die "$name: $.: Option $lvalue defined more than once!\n$extra";
358 } 562 }
359 ${$overrides}{$lvalue} = $rvalue; 563 ${$overrides}{$lvalue} = $prvalue;
360 } 564 }
361 if ($rvalue =~ /^\s*$/) { 565 if ($rvalue =~ /^\s*$/) {
362 delete $opt{$lvalue}; 566 delete $opt{$lvalue};
363 } else { 567 } else {
364 $rvalue = process_variables($rvalue); 568 $opt{$lvalue} = $prvalue;
365 $opt{$lvalue} = $rvalue;
366 } 569 }
367} 570}
368 571
@@ -712,6 +915,15 @@ sub __read_config {
712 return $test_case; 915 return $test_case;
713} 916}
714 917
918sub get_test_case {
919 print "What test case would you like to run?\n";
920 print " (build, install or boot)\n";
921 print " Other tests are available but require editing the config file\n";
922 my $ans = <STDIN>;
923 chomp $ans;
924 $default{"TEST_TYPE"} = $ans;
925}
926
715sub read_config { 927sub read_config {
716 my ($config) = @_; 928 my ($config) = @_;
717 929
@@ -726,10 +938,7 @@ sub read_config {
726 # was a test specified? 938 # was a test specified?
727 if (!$test_case) { 939 if (!$test_case) {
728 print "No test case specified.\n"; 940 print "No test case specified.\n";
729 print "What test case would you like to run?\n"; 941 get_test_case;
730 my $ans = <STDIN>;
731 chomp $ans;
732 $default{"TEST_TYPE"} = $ans;
733 } 942 }
734 943
735 # set any defaults 944 # set any defaults
@@ -739,6 +948,37 @@ sub read_config {
739 $opt{$default} = $default{$default}; 948 $opt{$default} = $default{$default};
740 } 949 }
741 } 950 }
951
952 if ($opt{"IGNORE_UNUSED"} == 1) {
953 return;
954 }
955
956 my %not_used;
957
958 # check if there are any stragglers (typos?)
959 foreach my $option (keys %opt) {
960 my $op = $option;
961 # remove per test labels.
962 $op =~ s/\[.*\]//;
963 if (!exists($option_map{$op}) &&
964 !exists($default{$op}) &&
965 !exists($used_options{$op})) {
966 $not_used{$op} = 1;
967 }
968 }
969
970 if (%not_used) {
971 my $s = "s are";
972 $s = " is" if (keys %not_used == 1);
973 print "The following option$s not used; could be a typo:\n";
974 foreach my $option (keys %not_used) {
975 print "$option\n";
976 }
977 print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
978 if (!read_yn "Do you want to continue?") {
979 exit -1;
980 }
981 }
742} 982}
743 983
744sub __eval_option { 984sub __eval_option {
@@ -873,6 +1113,16 @@ sub reboot {
873 } 1113 }
874} 1114}
875 1115
1116sub reboot_to_good {
1117 my ($time) = @_;
1118
1119 if (defined($switch_to_good)) {
1120 run_command $switch_to_good;
1121 }
1122
1123 reboot $time;
1124}
1125
876sub do_not_reboot { 1126sub do_not_reboot {
877 my $i = $iteration; 1127 my $i = $iteration;
878 1128
@@ -889,7 +1139,7 @@ sub dodie {
889 if ($reboot_on_error && !do_not_reboot) { 1139 if ($reboot_on_error && !do_not_reboot) {
890 1140
891 doprint "REBOOTING\n"; 1141 doprint "REBOOTING\n";
892 reboot; 1142 reboot_to_good;
893 1143
894 } elsif ($poweroff_on_error && defined($power_off)) { 1144 } elsif ($poweroff_on_error && defined($power_off)) {
895 doprint "POWERING OFF\n"; 1145 doprint "POWERING OFF\n";
@@ -975,6 +1225,43 @@ sub wait_for_monitor {
975 print "** Monitor flushed **\n"; 1225 print "** Monitor flushed **\n";
976} 1226}
977 1227
1228sub save_logs {
1229 my ($result, $basedir) = @_;
1230 my @t = localtime;
1231 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1232 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1233
1234 my $type = $build_type;
1235 if ($type =~ /useconfig/) {
1236 $type = "useconfig";
1237 }
1238
1239 my $dir = "$machine-$test_type-$type-$result-$date";
1240
1241 $dir = "$basedir/$dir";
1242
1243 if (!-d $dir) {
1244 mkpath($dir) or
1245 die "can't create $dir";
1246 }
1247
1248 my %files = (
1249 "config" => $output_config,
1250 "buildlog" => $buildlog,
1251 "dmesg" => $dmesg,
1252 "testlog" => $testlog,
1253 );
1254
1255 while (my ($name, $source) = each(%files)) {
1256 if (-f "$source") {
1257 cp "$source", "$dir/$name" or
1258 die "failed to copy $source";
1259 }
1260 }
1261
1262 doprint "*** Saved info to $dir ***\n";
1263}
1264
978sub fail { 1265sub fail {
979 1266
980 if ($die_on_failure) { 1267 if ($die_on_failure) {
@@ -988,7 +1275,7 @@ sub fail {
988 # no need to reboot for just building. 1275 # no need to reboot for just building.
989 if (!do_not_reboot) { 1276 if (!do_not_reboot) {
990 doprint "REBOOTING\n"; 1277 doprint "REBOOTING\n";
991 reboot $sleep_time; 1278 reboot_to_good $sleep_time;
992 } 1279 }
993 1280
994 my $name = ""; 1281 my $name = "";
@@ -1003,38 +1290,9 @@ sub fail {
1003 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1290 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1004 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1291 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1005 1292
1006 return 1 if (!defined($store_failures)); 1293 if (defined($store_failures)) {
1007 1294 save_logs "fail", $store_failures;
1008 my @t = localtime; 1295 }
1009 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1010 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1011
1012 my $type = $build_type;
1013 if ($type =~ /useconfig/) {
1014 $type = "useconfig";
1015 }
1016
1017 my $dir = "$machine-$test_type-$type-fail-$date";
1018 my $faildir = "$store_failures/$dir";
1019
1020 if (!-d $faildir) {
1021 mkpath($faildir) or
1022 die "can't create $faildir";
1023 }
1024 if (-f "$output_config") {
1025 cp "$output_config", "$faildir/config" or
1026 die "failed to copy .config";
1027 }
1028 if (-f $buildlog) {
1029 cp $buildlog, "$faildir/buildlog" or
1030 die "failed to move $buildlog";
1031 }
1032 if (-f $dmesg) {
1033 cp $dmesg, "$faildir/dmesg" or
1034 die "failed to move $dmesg";
1035 }
1036
1037 doprint "*** Saved info to $faildir ***\n";
1038 1296
1039 return 1; 1297 return 1;
1040} 1298}
@@ -1095,8 +1353,7 @@ sub run_ssh {
1095} 1353}
1096 1354
1097sub run_scp { 1355sub run_scp {
1098 my ($src, $dst) = @_; 1356 my ($src, $dst, $cp_scp) = @_;
1099 my $cp_scp = $scp_to_target;
1100 1357
1101 $cp_scp =~ s/\$SRC_FILE/$src/g; 1358 $cp_scp =~ s/\$SRC_FILE/$src/g;
1102 $cp_scp =~ s/\$DST_FILE/$dst/g; 1359 $cp_scp =~ s/\$DST_FILE/$dst/g;
@@ -1104,6 +1361,22 @@ sub run_scp {
1104 return run_command "$cp_scp"; 1361 return run_command "$cp_scp";
1105} 1362}
1106 1363
1364sub run_scp_install {
1365 my ($src, $dst) = @_;
1366
1367 my $cp_scp = $scp_to_target_install;
1368
1369 return run_scp($src, $dst, $cp_scp);
1370}
1371
1372sub run_scp_mod {
1373 my ($src, $dst) = @_;
1374
1375 my $cp_scp = $scp_to_target;
1376
1377 return run_scp($src, $dst, $cp_scp);
1378}
1379
1107sub get_grub_index { 1380sub get_grub_index {
1108 1381
1109 if ($reboot_type ne "grub") { 1382 if ($reboot_type ne "grub") {
@@ -1170,13 +1443,16 @@ sub wait_for_input
1170} 1443}
1171 1444
1172sub reboot_to { 1445sub reboot_to {
1446 if (defined($switch_to_test)) {
1447 run_command $switch_to_test;
1448 }
1449
1173 if ($reboot_type eq "grub") { 1450 if ($reboot_type eq "grub") {
1174 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 1451 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1175 reboot; 1452 } elsif (defined $reboot_script) {
1176 return; 1453 run_command "$reboot_script";
1177 } 1454 }
1178 1455 reboot;
1179 run_command "$reboot_script";
1180} 1456}
1181 1457
1182sub get_sha1 { 1458sub get_sha1 {
@@ -1203,6 +1479,7 @@ sub get_sha1 {
1203sub monitor { 1479sub monitor {
1204 my $booted = 0; 1480 my $booted = 0;
1205 my $bug = 0; 1481 my $bug = 0;
1482 my $bug_ignored = 0;
1206 my $skip_call_trace = 0; 1483 my $skip_call_trace = 0;
1207 my $loops; 1484 my $loops;
1208 1485
@@ -1275,8 +1552,12 @@ sub monitor {
1275 1552
1276 if ($full_line =~ /call trace:/i) { 1553 if ($full_line =~ /call trace:/i) {
1277 if (!$bug && !$skip_call_trace) { 1554 if (!$bug && !$skip_call_trace) {
1278 $bug = 1; 1555 if ($ignore_errors) {
1279 $failure_start = time; 1556 $bug_ignored = 1;
1557 } else {
1558 $bug = 1;
1559 $failure_start = time;
1560 }
1280 } 1561 }
1281 } 1562 }
1282 1563
@@ -1338,15 +1619,26 @@ sub monitor {
1338 fail "failed - never got a boot prompt." and return 0; 1619 fail "failed - never got a boot prompt." and return 0;
1339 } 1620 }
1340 1621
1622 if ($bug_ignored) {
1623 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
1624 }
1625
1341 return 1; 1626 return 1;
1342} 1627}
1343 1628
1629sub eval_kernel_version {
1630 my ($option) = @_;
1631
1632 $option =~ s/\$KERNEL_VERSION/$version/g;
1633
1634 return $option;
1635}
1636
1344sub do_post_install { 1637sub do_post_install {
1345 1638
1346 return if (!defined($post_install)); 1639 return if (!defined($post_install));
1347 1640
1348 my $cp_post_install = $post_install; 1641 my $cp_post_install = eval_kernel_version $post_install;
1349 $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1350 run_command "$cp_post_install" or 1642 run_command "$cp_post_install" or
1351 dodie "Failed to run post install"; 1643 dodie "Failed to run post install";
1352} 1644}
@@ -1355,7 +1647,9 @@ sub install {
1355 1647
1356 return if ($no_install); 1648 return if ($no_install);
1357 1649
1358 run_scp "$outputdir/$build_target", "$target_image" or 1650 my $cp_target = eval_kernel_version $target_image;
1651
1652 run_scp_install "$outputdir/$build_target", "$cp_target" or
1359 dodie "failed to copy image"; 1653 dodie "failed to copy image";
1360 1654
1361 my $install_mods = 0; 1655 my $install_mods = 0;
@@ -1377,7 +1671,7 @@ sub install {
1377 return; 1671 return;
1378 } 1672 }
1379 1673
1380 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 1674 run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
1381 dodie "Failed to install modules"; 1675 dodie "Failed to install modules";
1382 1676
1383 my $modlib = "/lib/modules/$version"; 1677 my $modlib = "/lib/modules/$version";
@@ -1390,7 +1684,7 @@ sub install {
1390 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 1684 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
1391 dodie "making tarball"; 1685 dodie "making tarball";
1392 1686
1393 run_scp "$tmpdir/$modtar", "/tmp" or 1687 run_scp_mod "$tmpdir/$modtar", "/tmp" or
1394 dodie "failed to copy modules"; 1688 dodie "failed to copy modules";
1395 1689
1396 unlink "$tmpdir/$modtar"; 1690 unlink "$tmpdir/$modtar";
@@ -1640,9 +1934,13 @@ sub success {
1640 doprint "*******************************************\n"; 1934 doprint "*******************************************\n";
1641 doprint "*******************************************\n"; 1935 doprint "*******************************************\n";
1642 1936
1937 if (defined($store_successes)) {
1938 save_logs "success", $store_successes;
1939 }
1940
1643 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1941 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1644 doprint "Reboot and wait $sleep_time seconds\n"; 1942 doprint "Reboot and wait $sleep_time seconds\n";
1645 reboot $sleep_time; 1943 reboot_to_good $sleep_time;
1646 } 1944 }
1647} 1945}
1648 1946
@@ -1669,7 +1967,10 @@ sub child_run_test {
1669 $poweroff_on_error = 0; 1967 $poweroff_on_error = 0;
1670 $die_on_failure = 1; 1968 $die_on_failure = 1;
1671 1969
1970 $redirect = "$testlog";
1672 run_command $run_test or $failed = 1; 1971 run_command $run_test or $failed = 1;
1972 undef $redirect;
1973
1673 exit $failed; 1974 exit $failed;
1674} 1975}
1675 1976
@@ -1744,6 +2045,43 @@ sub do_run_test {
1744 waitpid $child_pid, 0; 2045 waitpid $child_pid, 0;
1745 $child_exit = $?; 2046 $child_exit = $?;
1746 2047
2048 if (!$bug && $in_bisect) {
2049 if (defined($bisect_ret_good)) {
2050 if ($child_exit == $bisect_ret_good) {
2051 return 1;
2052 }
2053 }
2054 if (defined($bisect_ret_skip)) {
2055 if ($child_exit == $bisect_ret_skip) {
2056 return -1;
2057 }
2058 }
2059 if (defined($bisect_ret_abort)) {
2060 if ($child_exit == $bisect_ret_abort) {
2061 fail "test abort" and return -2;
2062 }
2063 }
2064 if (defined($bisect_ret_bad)) {
2065 if ($child_exit == $bisect_ret_skip) {
2066 return 0;
2067 }
2068 }
2069 if (defined($bisect_ret_default)) {
2070 if ($bisect_ret_default eq "good") {
2071 return 1;
2072 } elsif ($bisect_ret_default eq "bad") {
2073 return 0;
2074 } elsif ($bisect_ret_default eq "skip") {
2075 return -1;
2076 } elsif ($bisect_ret_default eq "abort") {
2077 return -2;
2078 } else {
2079 fail "unknown default action: $bisect_ret_default"
2080 and return -2;
2081 }
2082 }
2083 }
2084
1747 if ($bug || $child_exit) { 2085 if ($bug || $child_exit) {
1748 return 0 if $in_bisect; 2086 return 0 if $in_bisect;
1749 fail "test failed" and return 0; 2087 fail "test failed" and return 0;
@@ -1770,7 +2108,7 @@ sub run_git_bisect {
1770 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 2108 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1771 doprint "$1 [$2]\n"; 2109 doprint "$1 [$2]\n";
1772 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 2110 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1773 $bisect_bad = $1; 2111 $bisect_bad_commit = $1;
1774 doprint "Found bad commit... $1\n"; 2112 doprint "Found bad commit... $1\n";
1775 return 0; 2113 return 0;
1776 } else { 2114 } else {
@@ -1783,7 +2121,7 @@ sub run_git_bisect {
1783 2121
1784sub bisect_reboot { 2122sub bisect_reboot {
1785 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 2123 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
1786 reboot $bisect_sleep_time; 2124 reboot_to_good $bisect_sleep_time;
1787} 2125}
1788 2126
1789# returns 1 on success, 0 on failure, -1 on skip 2127# returns 1 on success, 0 on failure, -1 on skip
@@ -1868,21 +2206,28 @@ sub run_bisect {
1868 } 2206 }
1869} 2207}
1870 2208
2209sub update_bisect_replay {
2210 my $tmp_log = "$tmpdir/ktest_bisect_log";
2211 run_command "git bisect log > $tmp_log" or
2212 die "can't create bisect log";
2213 return $tmp_log;
2214}
2215
1871sub bisect { 2216sub bisect {
1872 my ($i) = @_; 2217 my ($i) = @_;
1873 2218
1874 my $result; 2219 my $result;
1875 2220
1876 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 2221 die "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good));
1877 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 2222 die "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad));
1878 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 2223 die "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type));
1879 2224
1880 my $good = $opt{"BISECT_GOOD[$i]"}; 2225 my $good = $bisect_good;
1881 my $bad = $opt{"BISECT_BAD[$i]"}; 2226 my $bad = $bisect_bad;
1882 my $type = $opt{"BISECT_TYPE[$i]"}; 2227 my $type = $bisect_type;
1883 my $start = $opt{"BISECT_START[$i]"}; 2228 my $start = $bisect_start;
1884 my $replay = $opt{"BISECT_REPLAY[$i]"}; 2229 my $replay = $bisect_replay;
1885 my $start_files = $opt{"BISECT_FILES[$i]"}; 2230 my $start_files = $bisect_files;
1886 2231
1887 if (defined($start_files)) { 2232 if (defined($start_files)) {
1888 $start_files = " -- " . $start_files; 2233 $start_files = " -- " . $start_files;
@@ -1894,8 +2239,7 @@ sub bisect {
1894 $good = get_sha1($good); 2239 $good = get_sha1($good);
1895 $bad = get_sha1($bad); 2240 $bad = get_sha1($bad);
1896 2241
1897 if (defined($opt{"BISECT_REVERSE[$i]"}) && 2242 if (defined($bisect_reverse) && $bisect_reverse == 1) {
1898 $opt{"BISECT_REVERSE[$i]"} == 1) {
1899 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 2243 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1900 $reverse_bisect = 1; 2244 $reverse_bisect = 1;
1901 } else { 2245 } else {
@@ -1907,8 +2251,31 @@ sub bisect {
1907 $type = "boot"; 2251 $type = "boot";
1908 } 2252 }
1909 2253
1910 my $check = $opt{"BISECT_CHECK[$i]"}; 2254 # Check if a bisect was running
1911 if (defined($check) && $check ne "0") { 2255 my $bisect_start_file = "$builddir/.git/BISECT_START";
2256
2257 my $check = $bisect_check;
2258 my $do_check = defined($check) && $check ne "0";
2259
2260 if ( -f $bisect_start_file ) {
2261 print "Bisect in progress found\n";
2262 if ($do_check) {
2263 print " If you say yes, then no checks of good or bad will be done\n";
2264 }
2265 if (defined($replay)) {
2266 print "** BISECT_REPLAY is defined in config file **";
2267 print " Ignore config option and perform new git bisect log?\n";
2268 if (read_ync " (yes, no, or cancel) ") {
2269 $replay = update_bisect_replay;
2270 $do_check = 0;
2271 }
2272 } elsif (read_yn "read git log and continue?") {
2273 $replay = update_bisect_replay;
2274 $do_check = 0;
2275 }
2276 }
2277
2278 if ($do_check) {
1912 2279
1913 # get current HEAD 2280 # get current HEAD
1914 my $head = get_sha1("HEAD"); 2281 my $head = get_sha1("HEAD");
@@ -1973,7 +2340,7 @@ sub bisect {
1973 run_command "git bisect reset" or 2340 run_command "git bisect reset" or
1974 dodie "could not reset git bisect"; 2341 dodie "could not reset git bisect";
1975 2342
1976 doprint "Bad commit was [$bisect_bad]\n"; 2343 doprint "Bad commit was [$bisect_bad_commit]\n";
1977 2344
1978 success $i; 2345 success $i;
1979} 2346}
@@ -2129,7 +2496,7 @@ sub run_config_bisect {
2129 } 2496 }
2130 2497
2131 doprint "***** RUN TEST ***\n"; 2498 doprint "***** RUN TEST ***\n";
2132 my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 2499 my $type = $config_bisect_type;
2133 my $ret; 2500 my $ret;
2134 my %current_config; 2501 my %current_config;
2135 2502
@@ -2233,7 +2600,7 @@ sub run_config_bisect {
2233sub config_bisect { 2600sub config_bisect {
2234 my ($i) = @_; 2601 my ($i) = @_;
2235 2602
2236 my $start_config = $opt{"CONFIG_BISECT[$i]"}; 2603 my $start_config = $config_bisect;
2237 2604
2238 my $tmpconfig = "$tmpdir/use_config"; 2605 my $tmpconfig = "$tmpdir/use_config";
2239 2606
@@ -2262,7 +2629,7 @@ sub config_bisect {
2262 # read directly what we want to check 2629 # read directly what we want to check
2263 my %config_check; 2630 my %config_check;
2264 open (IN, $output_config) 2631 open (IN, $output_config)
2265 or dodie "faied to open $output_config"; 2632 or dodie "failed to open $output_config";
2266 2633
2267 while (<IN>) { 2634 while (<IN>) {
2268 if (/^((CONFIG\S*)=.*)/) { 2635 if (/^((CONFIG\S*)=.*)/) {
@@ -2346,29 +2713,29 @@ sub config_bisect {
2346 2713
2347sub patchcheck_reboot { 2714sub patchcheck_reboot {
2348 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 2715 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
2349 reboot $patchcheck_sleep_time; 2716 reboot_to_good $patchcheck_sleep_time;
2350} 2717}
2351 2718
2352sub patchcheck { 2719sub patchcheck {
2353 my ($i) = @_; 2720 my ($i) = @_;
2354 2721
2355 die "PATCHCHECK_START[$i] not defined\n" 2722 die "PATCHCHECK_START[$i] not defined\n"
2356 if (!defined($opt{"PATCHCHECK_START[$i]"})); 2723 if (!defined($patchcheck_start));
2357 die "PATCHCHECK_TYPE[$i] not defined\n" 2724 die "PATCHCHECK_TYPE[$i] not defined\n"
2358 if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 2725 if (!defined($patchcheck_type));
2359 2726
2360 my $start = $opt{"PATCHCHECK_START[$i]"}; 2727 my $start = $patchcheck_start;
2361 2728
2362 my $end = "HEAD"; 2729 my $end = "HEAD";
2363 if (defined($opt{"PATCHCHECK_END[$i]"})) { 2730 if (defined($patchcheck_end)) {
2364 $end = $opt{"PATCHCHECK_END[$i]"}; 2731 $end = $patchcheck_end;
2365 } 2732 }
2366 2733
2367 # Get the true sha1's since we can use things like HEAD~3 2734 # Get the true sha1's since we can use things like HEAD~3
2368 $start = get_sha1($start); 2735 $start = get_sha1($start);
2369 $end = get_sha1($end); 2736 $end = get_sha1($end);
2370 2737
2371 my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 2738 my $type = $patchcheck_type;
2372 2739
2373 # Can't have a test without having a test to run 2740 # Can't have a test without having a test to run
2374 if ($type eq "test" && !defined($run_test)) { 2741 if ($type eq "test" && !defined($run_test)) {
@@ -2905,9 +3272,11 @@ sub make_min_config {
2905 $in_bisect = 1; 3272 $in_bisect = 1;
2906 3273
2907 my $failed = 0; 3274 my $failed = 0;
2908 build "oldconfig"; 3275 build "oldconfig" or $failed = 1;
2909 start_monitor_and_boot or $failed = 1; 3276 if (!$failed) {
2910 end_monitor; 3277 start_monitor_and_boot or $failed = 1;
3278 end_monitor;
3279 }
2911 3280
2912 $in_bisect = 0; 3281 $in_bisect = 0;
2913 3282
@@ -2963,7 +3332,7 @@ sub make_min_config {
2963 } 3332 }
2964 3333
2965 doprint "Reboot and wait $sleep_time seconds\n"; 3334 doprint "Reboot and wait $sleep_time seconds\n";
2966 reboot $sleep_time; 3335 reboot_to_good $sleep_time;
2967 } 3336 }
2968 3337
2969 success $i; 3338 success $i;
@@ -2985,13 +3354,27 @@ if ($#ARGV == 0) {
2985} 3354}
2986 3355
2987if (! -f $ktest_config) { 3356if (! -f $ktest_config) {
3357 $newconfig = 1;
3358 get_test_case;
2988 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 3359 open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
2989 print OUT << "EOF" 3360 print OUT << "EOF"
2990# Generated by ktest.pl 3361# Generated by ktest.pl
2991# 3362#
3363
3364# PWD is a ktest.pl variable that will result in the process working
3365# directory that ktest.pl is executed in.
3366
3367# THIS_DIR is automatically assigned the PWD of the path that generated
3368# the config file. It is best to use this variable when assigning other
3369# directory paths within this directory. This allows you to easily
3370# move the test cases to other locations or to other machines.
3371#
3372THIS_DIR := $variable{"PWD"}
3373
2992# Define each test with TEST_START 3374# Define each test with TEST_START
2993# The config options below it will override the defaults 3375# The config options below it will override the defaults
2994TEST_START 3376TEST_START
3377TEST_TYPE = $default{"TEST_TYPE"}
2995 3378
2996DEFAULTS 3379DEFAULTS
2997EOF 3380EOF
@@ -3011,7 +3394,7 @@ if ($#new_configs >= 0) {
3011 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 3394 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
3012 foreach my $config (@new_configs) { 3395 foreach my $config (@new_configs) {
3013 print OUT "$config = $entered_configs{$config}\n"; 3396 print OUT "$config = $entered_configs{$config}\n";
3014 $opt{$config} = $entered_configs{$config}; 3397 $opt{$config} = process_variables($entered_configs{$config});
3015 } 3398 }
3016} 3399}
3017 3400
@@ -3091,61 +3474,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3091 3474
3092 my $makecmd = set_test_option("MAKE_CMD", $i); 3475 my $makecmd = set_test_option("MAKE_CMD", $i);
3093 3476
3094 $machine = set_test_option("MACHINE", $i); 3477 # Load all the options into their mapped variable names
3095 $ssh_user = set_test_option("SSH_USER", $i); 3478 foreach my $opt (keys %option_map) {
3096 $tmpdir = set_test_option("TMP_DIR", $i); 3479 ${$option_map{$opt}} = set_test_option($opt, $i);
3097 $outputdir = set_test_option("OUTPUT_DIR", $i); 3480 }
3098 $builddir = set_test_option("BUILD_DIR", $i);
3099 $test_type = set_test_option("TEST_TYPE", $i);
3100 $build_type = set_test_option("BUILD_TYPE", $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);
3106 $power_cycle = set_test_option("POWER_CYCLE", $i);
3107 $reboot = set_test_option("REBOOT", $i);
3108 $noclean = set_test_option("BUILD_NOCLEAN", $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);
3113 $run_test = set_test_option("TEST", $i);
3114 $addconfig = set_test_option("ADD_CONFIG", $i);
3115 $reboot_type = set_test_option("REBOOT_TYPE", $i);
3116 $grub_menu = set_test_option("GRUB_MENU", $i);
3117 $post_install = set_test_option("POST_INSTALL", $i);
3118 $no_install = set_test_option("NO_INSTALL", $i);
3119 $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
3120 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
3121 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
3122 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
3123 $power_off = set_test_option("POWER_OFF", $i);
3124 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
3125 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
3126 $sleep_time = set_test_option("SLEEP_TIME", $i);
3127 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
3128 $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
3129 $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
3130 $bisect_manual = set_test_option("BISECT_MANUAL", $i);
3131 $bisect_skip = set_test_option("BISECT_SKIP", $i);
3132 $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
3133 $store_failures = set_test_option("STORE_FAILURES", $i);
3134 $test_name = set_test_option("TEST_NAME", $i);
3135 $timeout = set_test_option("TIMEOUT", $i);
3136 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
3137 $console = set_test_option("CONSOLE", $i);
3138 $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
3139 $success_line = set_test_option("SUCCESS_LINE", $i);
3140 $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
3141 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
3142 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
3143 $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
3144 $build_target = set_test_option("BUILD_TARGET", $i);
3145 $ssh_exec = set_test_option("SSH_EXEC", $i);
3146 $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
3147 $target_image = set_test_option("TARGET_IMAGE", $i);
3148 $localversion = set_test_option("LOCALVERSION", $i);
3149 3481
3150 $start_minconfig_defined = 1; 3482 $start_minconfig_defined = 1;
3151 3483
@@ -3166,26 +3498,26 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3166 $ENV{"SSH_USER"} = $ssh_user; 3498 $ENV{"SSH_USER"} = $ssh_user;
3167 $ENV{"MACHINE"} = $machine; 3499 $ENV{"MACHINE"} = $machine;
3168 3500
3169 $target = "$ssh_user\@$machine";
3170
3171 $buildlog = "$tmpdir/buildlog-$machine"; 3501 $buildlog = "$tmpdir/buildlog-$machine";
3502 $testlog = "$tmpdir/testlog-$machine";
3172 $dmesg = "$tmpdir/dmesg-$machine"; 3503 $dmesg = "$tmpdir/dmesg-$machine";
3173 $make = "$makecmd O=$outputdir"; 3504 $make = "$makecmd O=$outputdir";
3174 $output_config = "$outputdir/.config"; 3505 $output_config = "$outputdir/.config";
3175 3506
3176 if ($reboot_type eq "grub") { 3507 if (!$buildonly) {
3177 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 3508 $target = "$ssh_user\@$machine";
3178 } elsif (!defined($reboot_script)) { 3509 if ($reboot_type eq "grub") {
3179 dodie "REBOOT_SCRIPT not defined" 3510 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3511 }
3180 } 3512 }
3181 3513
3182 my $run_type = $build_type; 3514 my $run_type = $build_type;
3183 if ($test_type eq "patchcheck") { 3515 if ($test_type eq "patchcheck") {
3184 $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 3516 $run_type = $patchcheck_type;
3185 } elsif ($test_type eq "bisect") { 3517 } elsif ($test_type eq "bisect") {
3186 $run_type = $opt{"BISECT_TYPE[$i]"}; 3518 $run_type = $bisect_type;
3187 } elsif ($test_type eq "config_bisect") { 3519 } elsif ($test_type eq "config_bisect") {
3188 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 3520 $run_type = $config_bisect_type;
3189 } 3521 }
3190 3522
3191 if ($test_type eq "make_min_config") { 3523 if ($test_type eq "make_min_config") {
@@ -3205,6 +3537,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3205 3537
3206 unlink $dmesg; 3538 unlink $dmesg;
3207 unlink $buildlog; 3539 unlink $buildlog;
3540 unlink $testlog;
3208 3541
3209 if (defined($addconfig)) { 3542 if (defined($addconfig)) {
3210 my $min = $minconfig; 3543 my $min = $minconfig;
@@ -3216,14 +3549,15 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3216 $minconfig = "$tmpdir/add_config"; 3549 $minconfig = "$tmpdir/add_config";
3217 } 3550 }
3218 3551
3219 my $checkout = $opt{"CHECKOUT[$i]"};
3220 if (defined($checkout)) { 3552 if (defined($checkout)) {
3221 run_command "git checkout $checkout" or 3553 run_command "git checkout $checkout" or
3222 die "failed to checkout $checkout"; 3554 die "failed to checkout $checkout";
3223 } 3555 }
3224 3556
3225 $no_reboot = 0; 3557 # A test may opt to not reboot the box
3226 3558 if ($reboot_on_success) {
3559 $no_reboot = 0;
3560 }
3227 3561
3228 if ($test_type eq "bisect") { 3562 if ($test_type eq "bisect") {
3229 bisect $i; 3563 bisect $i;
@@ -3267,9 +3601,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3267if ($opt{"POWEROFF_ON_SUCCESS"}) { 3601if ($opt{"POWEROFF_ON_SUCCESS"}) {
3268 halt; 3602 halt;
3269} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 3603} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
3270 reboot; 3604 reboot_to_good;
3605} elsif (defined($switch_to_good)) {
3606 # still need to get to the good kernel
3607 run_command $switch_to_good;
3271} 3608}
3272 3609
3610
3273doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 3611doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n";
3274 3612
3275exit 0; 3613exit 0;
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index 553c06b7d6f2..b682456afda8 100644
--- a/tools/testing/ktest/sample.conf
+++ b/tools/testing/ktest/sample.conf
@@ -346,7 +346,10 @@
346#GRUB_MENU = Test Kernel 346#GRUB_MENU = Test Kernel
347 347
348# A script to reboot the target into the test kernel 348# A script to reboot the target into the test kernel
349# (Only mandatory if REBOOT_TYPE = script) 349# This and SWITCH_TO_TEST are about the same, except
350# SWITCH_TO_TEST is run even for REBOOT_TYPE = grub.
351# This may be left undefined.
352# (default undefined)
350#REBOOT_SCRIPT = 353#REBOOT_SCRIPT =
351 354
352#### Optional Config Options (all have defaults) #### 355#### Optional Config Options (all have defaults) ####
@@ -468,6 +471,27 @@
468# The test will not modify that file. 471# The test will not modify that file.
469#REBOOT_TYPE = grub 472#REBOOT_TYPE = grub
470 473
474# If you are using a machine that doesn't boot with grub, and
475# perhaps gets its kernel from a remote server (tftp), then
476# you can use this option to update the target image with the
477# test image.
478#
479# You could also do the same with POST_INSTALL, but the difference
480# between that option and this option is that POST_INSTALL runs
481# after the install, where this one runs just before a reboot.
482# (default undefined)
483#SWITCH_TO_TEST = cp ${OUTPUT_DIR}/${BUILD_TARGET} ${TARGET_IMAGE}
484
485# If you are using a machine that doesn't boot with grub, and
486# perhaps gets its kernel from a remote server (tftp), then
487# you can use this option to update the target image with the
488# the known good image to reboot safely back into.
489#
490# This option holds a command that will execute before needing
491# to reboot to a good known image.
492# (default undefined)
493#SWITCH_TO_GOOD = ssh ${SSH_USER}/${MACHINE} cp good_image ${TARGET_IMAGE}
494
471# The min config that is needed to build for the machine 495# The min config that is needed to build for the machine
472# A nice way to create this is with the following: 496# A nice way to create this is with the following:
473# 497#
@@ -589,6 +613,12 @@
589# (default undefined) 613# (default undefined)
590#STORE_FAILURES = /home/test/failures 614#STORE_FAILURES = /home/test/failures
591 615
616# Directory to store success directories on success. If this is not
617# set, the .config, dmesg and bootlog will not be saved if a
618# test succeeds.
619# (default undefined)
620#STORE_SUCCESSES = /home/test/successes
621
592# Build without doing a make mrproper, or removing .config 622# Build without doing a make mrproper, or removing .config
593# (default 0) 623# (default 0)
594#BUILD_NOCLEAN = 0 624#BUILD_NOCLEAN = 0
@@ -680,10 +710,18 @@
680# The variables SSH_USER, MACHINE and SSH_COMMAND are defined 710# The variables SSH_USER, MACHINE and SSH_COMMAND are defined
681#SSH_EXEC = ssh $SSH_USER@$MACHINE $SSH_COMMAND"; 711#SSH_EXEC = ssh $SSH_USER@$MACHINE $SSH_COMMAND";
682 712
683# The way to copy a file to the target 713# The way to copy a file to the target (install and modules)
684# (default scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE) 714# (default scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE)
685# The variables SSH_USER, MACHINE, SRC_FILE and DST_FILE are defined. 715# The variables SSH_USER, MACHINE are defined by the config
686#SCP_TO_TARGET = scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE 716# SRC_FILE and DST_FILE are ktest internal variables and
717# should only have '$' and not the '${}' notation.
718# (default scp $SRC_FILE ${SSH_USER}@${MACHINE}:$DST_FILE)
719#SCP_TO_TARGET = echo skip scp for $SRC_FILE $DST_FILE
720
721# If install needs to be different than modules, then this
722# option will override the SCP_TO_TARGET for installation.
723# (default ${SCP_TO_TARGET} )
724#SCP_TO_TARGET_INSTALL = scp $SRC_FILE tftp@tftpserver:$DST_FILE
687 725
688# The nice way to reboot the target 726# The nice way to reboot the target
689# (default ssh $SSH_USER@$MACHINE reboot) 727# (default ssh $SSH_USER@$MACHINE reboot)
@@ -700,6 +738,25 @@
700# (default 1) 738# (default 1)
701#DETECT_TRIPLE_FAULT = 0 739#DETECT_TRIPLE_FAULT = 0
702 740
741# All options in the config file should be either used by ktest
742# or could be used within a value of another option. If an option
743# in the config file is not used, ktest will warn about it and ask
744# if you want to continue.
745#
746# If you don't care if there are non-used options, enable this
747# option. Be careful though, a non-used option is usually a sign
748# of an option name being typed incorrectly.
749# (default 0)
750#IGNORE_UNUSED = 1
751
752# When testing a kernel that happens to have WARNINGs, and call
753# traces, ktest.pl will detect these and fail a boot or test run
754# due to warnings. By setting this option, ktest will ignore
755# call traces, and will not fail a test if the kernel produces
756# an oops. Use this option with care.
757# (default 0)
758#IGNORE_ERRORS = 1
759
703#### Per test run options #### 760#### Per test run options ####
704# The following options are only allowed in TEST_START sections. 761# The following options are only allowed in TEST_START sections.
705# They are ignored in the DEFAULTS sections. 762# They are ignored in the DEFAULTS sections.
@@ -862,6 +919,42 @@
862# BISECT_BAD with BISECT_CHECK = good or 919# BISECT_BAD with BISECT_CHECK = good or
863# BISECT_CHECK = bad, respectively. 920# BISECT_CHECK = bad, respectively.
864# 921#
922# BISECT_RET_GOOD = 0 (optional, default undefined)
923#
924# In case the specificed test returns something other than just
925# 0 for good, and non-zero for bad, you can override 0 being
926# good by defining BISECT_RET_GOOD.
927#
928# BISECT_RET_BAD = 1 (optional, default undefined)
929#
930# In case the specificed test returns something other than just
931# 0 for good, and non-zero for bad, you can override non-zero being
932# bad by defining BISECT_RET_BAD.
933#
934# BISECT_RET_ABORT = 255 (optional, default undefined)
935#
936# If you need to abort the bisect if the test discovers something
937# that was wrong, you can define BISECT_RET_ABORT to be the error
938# code returned by the test in order to abort the bisect.
939#
940# BISECT_RET_SKIP = 2 (optional, default undefined)
941#
942# If the test detects that the current commit is neither good
943# nor bad, but something else happened (another bug detected)
944# you can specify BISECT_RET_SKIP to an error code that the
945# test returns when it should skip the current commit.
946#
947# BISECT_RET_DEFAULT = good (optional, default undefined)
948#
949# You can override the default of what to do when the above
950# options are not hit. This may be one of, "good", "bad",
951# "abort" or "skip" (without the quotes).
952#
953# Note, if you do not define any of the previous BISECT_RET_*
954# and define BISECT_RET_DEFAULT, all bisects results will do
955# what the BISECT_RET_DEFAULT has.
956#
957#
865# Example: 958# Example:
866# TEST_START 959# TEST_START
867# TEST_TYPE = bisect 960# TEST_TYPE = bisect
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
new file mode 100644
index 000000000000..28bc57ee757c
--- /dev/null
+++ b/tools/testing/selftests/Makefile
@@ -0,0 +1,16 @@
1TARGETS = breakpoints vm
2
3all:
4 for TARGET in $(TARGETS); do \
5 make -C $$TARGET; \
6 done;
7
8run_tests: all
9 for TARGET in $(TARGETS); do \
10 make -C $$TARGET run_tests; \
11 done;
12
13clean:
14 for TARGET in $(TARGETS); do \
15 make -C $$TARGET clean; \
16 done;
diff --git a/tools/testing/selftests/breakpoints/Makefile b/tools/testing/selftests/breakpoints/Makefile
new file mode 100644
index 000000000000..931278035f5c
--- /dev/null
+++ b/tools/testing/selftests/breakpoints/Makefile
@@ -0,0 +1,23 @@
1# Taken from perf makefile
2uname_M := $(shell uname -m 2>/dev/null || echo not)
3ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
4ifeq ($(ARCH),i386)
5 ARCH := x86
6endif
7ifeq ($(ARCH),x86_64)
8 ARCH := x86
9endif
10
11
12all:
13ifeq ($(ARCH),x86)
14 gcc breakpoint_test.c -o breakpoint_test
15else
16 echo "Not an x86 target, can't build breakpoints selftests"
17endif
18
19run_tests:
20 ./breakpoint_test
21
22clean:
23 rm -fr breakpoint_test
diff --git a/tools/testing/selftests/breakpoints/breakpoint_test.c b/tools/testing/selftests/breakpoints/breakpoint_test.c
new file mode 100644
index 000000000000..a0743f3b2b57
--- /dev/null
+++ b/tools/testing/selftests/breakpoints/breakpoint_test.c
@@ -0,0 +1,394 @@
1/*
2 * Copyright (C) 2011 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com>
3 *
4 * Licensed under the terms of the GNU GPL License version 2
5 *
6 * Selftests for breakpoints (and more generally the do_debug() path) in x86.
7 */
8
9
10#include <sys/ptrace.h>
11#include <unistd.h>
12#include <stddef.h>
13#include <sys/user.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <signal.h>
17#include <sys/types.h>
18#include <sys/wait.h>
19
20
21/* Breakpoint access modes */
22enum {
23 BP_X = 1,
24 BP_RW = 2,
25 BP_W = 4,
26};
27
28static pid_t child_pid;
29
30/*
31 * Ensures the child and parent are always "talking" about
32 * the same test sequence. (ie: that we haven't forgotten
33 * to call check_trapped() somewhere).
34 */
35static int nr_tests;
36
37static void set_breakpoint_addr(void *addr, int n)
38{
39 int ret;
40
41 ret = ptrace(PTRACE_POKEUSER, child_pid,
42 offsetof(struct user, u_debugreg[n]), addr);
43 if (ret) {
44 perror("Can't set breakpoint addr\n");
45 exit(-1);
46 }
47}
48
49static void toggle_breakpoint(int n, int type, int len,
50 int local, int global, int set)
51{
52 int ret;
53
54 int xtype, xlen;
55 unsigned long vdr7, dr7;
56
57 switch (type) {
58 case BP_X:
59 xtype = 0;
60 break;
61 case BP_W:
62 xtype = 1;
63 break;
64 case BP_RW:
65 xtype = 3;
66 break;
67 }
68
69 switch (len) {
70 case 1:
71 xlen = 0;
72 break;
73 case 2:
74 xlen = 4;
75 break;
76 case 4:
77 xlen = 0xc;
78 break;
79 case 8:
80 xlen = 8;
81 break;
82 }
83
84 dr7 = ptrace(PTRACE_PEEKUSER, child_pid,
85 offsetof(struct user, u_debugreg[7]), 0);
86
87 vdr7 = (xlen | xtype) << 16;
88 vdr7 <<= 4 * n;
89
90 if (local) {
91 vdr7 |= 1 << (2 * n);
92 vdr7 |= 1 << 8;
93 }
94 if (global) {
95 vdr7 |= 2 << (2 * n);
96 vdr7 |= 1 << 9;
97 }
98
99 if (set)
100 dr7 |= vdr7;
101 else
102 dr7 &= ~vdr7;
103
104 ret = ptrace(PTRACE_POKEUSER, child_pid,
105 offsetof(struct user, u_debugreg[7]), dr7);
106 if (ret) {
107 perror("Can't set dr7");
108 exit(-1);
109 }
110}
111
112/* Dummy variables to test read/write accesses */
113static unsigned long long dummy_var[4];
114
115/* Dummy functions to test execution accesses */
116static void dummy_func(void) { }
117static void dummy_func1(void) { }
118static void dummy_func2(void) { }
119static void dummy_func3(void) { }
120
121static void (*dummy_funcs[])(void) = {
122 dummy_func,
123 dummy_func1,
124 dummy_func2,
125 dummy_func3,
126};
127
128static int trapped;
129
130static void check_trapped(void)
131{
132 /*
133 * If we haven't trapped, wake up the parent
134 * so that it notices the failure.
135 */
136 if (!trapped)
137 kill(getpid(), SIGUSR1);
138 trapped = 0;
139
140 nr_tests++;
141}
142
143static void write_var(int len)
144{
145 char *pcval; short *psval; int *pival; long long *plval;
146 int i;
147
148 for (i = 0; i < 4; i++) {
149 switch (len) {
150 case 1:
151 pcval = (char *)&dummy_var[i];
152 *pcval = 0xff;
153 break;
154 case 2:
155 psval = (short *)&dummy_var[i];
156 *psval = 0xffff;
157 break;
158 case 4:
159 pival = (int *)&dummy_var[i];
160 *pival = 0xffffffff;
161 break;
162 case 8:
163 plval = (long long *)&dummy_var[i];
164 *plval = 0xffffffffffffffffLL;
165 break;
166 }
167 check_trapped();
168 }
169}
170
171static void read_var(int len)
172{
173 char cval; short sval; int ival; long long lval;
174 int i;
175
176 for (i = 0; i < 4; i++) {
177 switch (len) {
178 case 1:
179 cval = *(char *)&dummy_var[i];
180 break;
181 case 2:
182 sval = *(short *)&dummy_var[i];
183 break;
184 case 4:
185 ival = *(int *)&dummy_var[i];
186 break;
187 case 8:
188 lval = *(long long *)&dummy_var[i];
189 break;
190 }
191 check_trapped();
192 }
193}
194
195/*
196 * Do the r/w/x accesses to trigger the breakpoints. And run
197 * the usual traps.
198 */
199static void trigger_tests(void)
200{
201 int len, local, global, i;
202 char val;
203 int ret;
204
205 ret = ptrace(PTRACE_TRACEME, 0, NULL, 0);
206 if (ret) {
207 perror("Can't be traced?\n");
208 return;
209 }
210
211 /* Wake up father so that it sets up the first test */
212 kill(getpid(), SIGUSR1);
213
214 /* Test instruction breakpoints */
215 for (local = 0; local < 2; local++) {
216 for (global = 0; global < 2; global++) {
217 if (!local && !global)
218 continue;
219
220 for (i = 0; i < 4; i++) {
221 dummy_funcs[i]();
222 check_trapped();
223 }
224 }
225 }
226
227 /* Test write watchpoints */
228 for (len = 1; len <= sizeof(long); len <<= 1) {
229 for (local = 0; local < 2; local++) {
230 for (global = 0; global < 2; global++) {
231 if (!local && !global)
232 continue;
233 write_var(len);
234 }
235 }
236 }
237
238 /* Test read/write watchpoints (on read accesses) */
239 for (len = 1; len <= sizeof(long); len <<= 1) {
240 for (local = 0; local < 2; local++) {
241 for (global = 0; global < 2; global++) {
242 if (!local && !global)
243 continue;
244 read_var(len);
245 }
246 }
247 }
248
249 /* Icebp trap */
250 asm(".byte 0xf1\n");
251 check_trapped();
252
253 /* Int 3 trap */
254 asm("int $3\n");
255 check_trapped();
256
257 kill(getpid(), SIGUSR1);
258}
259
260static void check_success(const char *msg)
261{
262 const char *msg2;
263 int child_nr_tests;
264 int status;
265
266 /* Wait for the child to SIGTRAP */
267 wait(&status);
268
269 msg2 = "Failed";
270
271 if (WSTOPSIG(status) == SIGTRAP) {
272 child_nr_tests = ptrace(PTRACE_PEEKDATA, child_pid,
273 &nr_tests, 0);
274 if (child_nr_tests == nr_tests)
275 msg2 = "Ok";
276 if (ptrace(PTRACE_POKEDATA, child_pid, &trapped, 1)) {
277 perror("Can't poke\n");
278 exit(-1);
279 }
280 }
281
282 nr_tests++;
283
284 printf("%s [%s]\n", msg, msg2);
285}
286
287static void launch_instruction_breakpoints(char *buf, int local, int global)
288{
289 int i;
290
291 for (i = 0; i < 4; i++) {
292 set_breakpoint_addr(dummy_funcs[i], i);
293 toggle_breakpoint(i, BP_X, 1, local, global, 1);
294 ptrace(PTRACE_CONT, child_pid, NULL, 0);
295 sprintf(buf, "Test breakpoint %d with local: %d global: %d",
296 i, local, global);
297 check_success(buf);
298 toggle_breakpoint(i, BP_X, 1, local, global, 0);
299 }
300}
301
302static void launch_watchpoints(char *buf, int mode, int len,
303 int local, int global)
304{
305 const char *mode_str;
306 int i;
307
308 if (mode == BP_W)
309 mode_str = "write";
310 else
311 mode_str = "read";
312
313 for (i = 0; i < 4; i++) {
314 set_breakpoint_addr(&dummy_var[i], i);
315 toggle_breakpoint(i, mode, len, local, global, 1);
316 ptrace(PTRACE_CONT, child_pid, NULL, 0);
317 sprintf(buf, "Test %s watchpoint %d with len: %d local: "
318 "%d global: %d", mode_str, i, len, local, global);
319 check_success(buf);
320 toggle_breakpoint(i, mode, len, local, global, 0);
321 }
322}
323
324/* Set the breakpoints and check the child successfully trigger them */
325static void launch_tests(void)
326{
327 char buf[1024];
328 int len, local, global, i;
329
330 /* Instruction breakpoints */
331 for (local = 0; local < 2; local++) {
332 for (global = 0; global < 2; global++) {
333 if (!local && !global)
334 continue;
335 launch_instruction_breakpoints(buf, local, global);
336 }
337 }
338
339 /* Write watchpoint */
340 for (len = 1; len <= sizeof(long); len <<= 1) {
341 for (local = 0; local < 2; local++) {
342 for (global = 0; global < 2; global++) {
343 if (!local && !global)
344 continue;
345 launch_watchpoints(buf, BP_W, len,
346 local, global);
347 }
348 }
349 }
350
351 /* Read-Write watchpoint */
352 for (len = 1; len <= sizeof(long); len <<= 1) {
353 for (local = 0; local < 2; local++) {
354 for (global = 0; global < 2; global++) {
355 if (!local && !global)
356 continue;
357 launch_watchpoints(buf, BP_RW, len,
358 local, global);
359 }
360 }
361 }
362
363 /* Icebp traps */
364 ptrace(PTRACE_CONT, child_pid, NULL, 0);
365 check_success("Test icebp");
366
367 /* Int 3 traps */
368 ptrace(PTRACE_CONT, child_pid, NULL, 0);
369 check_success("Test int 3 trap");
370
371 ptrace(PTRACE_CONT, child_pid, NULL, 0);
372}
373
374int main(int argc, char **argv)
375{
376 pid_t pid;
377 int ret;
378
379 pid = fork();
380 if (!pid) {
381 trigger_tests();
382 return 0;
383 }
384
385 child_pid = pid;
386
387 wait(NULL);
388
389 launch_tests();
390
391 wait(NULL);
392
393 return 0;
394}
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
new file mode 100644
index 000000000000..b336b24aa6c0
--- /dev/null
+++ b/tools/testing/selftests/vm/Makefile
@@ -0,0 +1,14 @@
1# Makefile for vm selftests
2
3CC = $(CROSS_COMPILE)gcc
4CFLAGS = -Wall -Wextra
5
6all: hugepage-mmap hugepage-shm map_hugetlb
7%: %.c
8 $(CC) $(CFLAGS) -o $@ $^
9
10run_tests: all
11 /bin/sh ./run_vmtests
12
13clean:
14 $(RM) hugepage-mmap hugepage-shm map_hugetlb
diff --git a/tools/testing/selftests/vm/hugepage-mmap.c b/tools/testing/selftests/vm/hugepage-mmap.c
new file mode 100644
index 000000000000..a10f310d2362
--- /dev/null
+++ b/tools/testing/selftests/vm/hugepage-mmap.c
@@ -0,0 +1,92 @@
1/*
2 * hugepage-mmap:
3 *
4 * Example of using huge page memory in a user application using the mmap
5 * system call. Before running this application, make sure that the
6 * administrator has mounted the hugetlbfs filesystem (on some directory
7 * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this
8 * example, the app is requesting memory of size 256MB that is backed by
9 * huge pages.
10 *
11 * For the ia64 architecture, the Linux kernel reserves Region number 4 for
12 * huge pages. That means that if one requires a fixed address, a huge page
13 * aligned address starting with 0x800000... will be required. If a fixed
14 * address is not required, the kernel will select an address in the proper
15 * range.
16 * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
17 */
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <unistd.h>
22#include <sys/mman.h>
23#include <fcntl.h>
24
25#define FILE_NAME "huge/hugepagefile"
26#define LENGTH (256UL*1024*1024)
27#define PROTECTION (PROT_READ | PROT_WRITE)
28
29/* Only ia64 requires this */
30#ifdef __ia64__
31#define ADDR (void *)(0x8000000000000000UL)
32#define FLAGS (MAP_SHARED | MAP_FIXED)
33#else
34#define ADDR (void *)(0x0UL)
35#define FLAGS (MAP_SHARED)
36#endif
37
38static void check_bytes(char *addr)
39{
40 printf("First hex is %x\n", *((unsigned int *)addr));
41}
42
43static void write_bytes(char *addr)
44{
45 unsigned long i;
46
47 for (i = 0; i < LENGTH; i++)
48 *(addr + i) = (char)i;
49}
50
51static int read_bytes(char *addr)
52{
53 unsigned long i;
54
55 check_bytes(addr);
56 for (i = 0; i < LENGTH; i++)
57 if (*(addr + i) != (char)i) {
58 printf("Mismatch at %lu\n", i);
59 return 1;
60 }
61 return 0;
62}
63
64int main(void)
65{
66 void *addr;
67 int fd, ret;
68
69 fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
70 if (fd < 0) {
71 perror("Open failed");
72 exit(1);
73 }
74
75 addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0);
76 if (addr == MAP_FAILED) {
77 perror("mmap");
78 unlink(FILE_NAME);
79 exit(1);
80 }
81
82 printf("Returned address is %p\n", addr);
83 check_bytes(addr);
84 write_bytes(addr);
85 ret = read_bytes(addr);
86
87 munmap(addr, LENGTH);
88 close(fd);
89 unlink(FILE_NAME);
90
91 return ret;
92}
diff --git a/tools/testing/selftests/vm/hugepage-shm.c b/tools/testing/selftests/vm/hugepage-shm.c
new file mode 100644
index 000000000000..0d0ef4fc0c04
--- /dev/null
+++ b/tools/testing/selftests/vm/hugepage-shm.c
@@ -0,0 +1,100 @@
1/*
2 * hugepage-shm:
3 *
4 * Example of using huge page memory in a user application using Sys V shared
5 * memory system calls. In this example the app is requesting 256MB of
6 * memory that is backed by huge pages. The application uses the flag
7 * SHM_HUGETLB in the shmget system call to inform the kernel that it is
8 * requesting huge pages.
9 *
10 * For the ia64 architecture, the Linux kernel reserves Region number 4 for
11 * huge pages. That means that if one requires a fixed address, a huge page
12 * aligned address starting with 0x800000... will be required. If a fixed
13 * address is not required, the kernel will select an address in the proper
14 * range.
15 * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
16 *
17 * Note: The default shared memory limit is quite low on many kernels,
18 * you may need to increase it via:
19 *
20 * echo 268435456 > /proc/sys/kernel/shmmax
21 *
22 * This will increase the maximum size per shared memory segment to 256MB.
23 * The other limit that you will hit eventually is shmall which is the
24 * total amount of shared memory in pages. To set it to 16GB on a system
25 * with a 4kB pagesize do:
26 *
27 * echo 4194304 > /proc/sys/kernel/shmall
28 */
29
30#include <stdlib.h>
31#include <stdio.h>
32#include <sys/types.h>
33#include <sys/ipc.h>
34#include <sys/shm.h>
35#include <sys/mman.h>
36
37#ifndef SHM_HUGETLB
38#define SHM_HUGETLB 04000
39#endif
40
41#define LENGTH (256UL*1024*1024)
42
43#define dprintf(x) printf(x)
44
45/* Only ia64 requires this */
46#ifdef __ia64__
47#define ADDR (void *)(0x8000000000000000UL)
48#define SHMAT_FLAGS (SHM_RND)
49#else
50#define ADDR (void *)(0x0UL)
51#define SHMAT_FLAGS (0)
52#endif
53
54int main(void)
55{
56 int shmid;
57 unsigned long i;
58 char *shmaddr;
59
60 shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
61 if (shmid < 0) {
62 perror("shmget");
63 exit(1);
64 }
65 printf("shmid: 0x%x\n", shmid);
66
67 shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS);
68 if (shmaddr == (char *)-1) {
69 perror("Shared memory attach failure");
70 shmctl(shmid, IPC_RMID, NULL);
71 exit(2);
72 }
73 printf("shmaddr: %p\n", shmaddr);
74
75 dprintf("Starting the writes:\n");
76 for (i = 0; i < LENGTH; i++) {
77 shmaddr[i] = (char)(i);
78 if (!(i % (1024 * 1024)))
79 dprintf(".");
80 }
81 dprintf("\n");
82
83 dprintf("Starting the Check...");
84 for (i = 0; i < LENGTH; i++)
85 if (shmaddr[i] != (char)i) {
86 printf("\nIndex %lu mismatched\n", i);
87 exit(3);
88 }
89 dprintf("Done.\n");
90
91 if (shmdt((const void *)shmaddr) != 0) {
92 perror("Detach failure");
93 shmctl(shmid, IPC_RMID, NULL);
94 exit(4);
95 }
96
97 shmctl(shmid, IPC_RMID, NULL);
98
99 return 0;
100}
diff --git a/tools/testing/selftests/vm/map_hugetlb.c b/tools/testing/selftests/vm/map_hugetlb.c
new file mode 100644
index 000000000000..ac56639dd4a9
--- /dev/null
+++ b/tools/testing/selftests/vm/map_hugetlb.c
@@ -0,0 +1,79 @@
1/*
2 * Example of using hugepage memory in a user application using the mmap
3 * system call with MAP_HUGETLB flag. Before running this program make
4 * sure the administrator has allocated enough default sized huge pages
5 * to cover the 256 MB allocation.
6 *
7 * For ia64 architecture, Linux kernel reserves Region number 4 for hugepages.
8 * That means the addresses starting with 0x800000... will need to be
9 * specified. Specifying a fixed address is not required on ppc64, i386
10 * or x86_64.
11 */
12#include <stdlib.h>
13#include <stdio.h>
14#include <unistd.h>
15#include <sys/mman.h>
16#include <fcntl.h>
17
18#define LENGTH (256UL*1024*1024)
19#define PROTECTION (PROT_READ | PROT_WRITE)
20
21#ifndef MAP_HUGETLB
22#define MAP_HUGETLB 0x40000 /* arch specific */
23#endif
24
25/* Only ia64 requires this */
26#ifdef __ia64__
27#define ADDR (void *)(0x8000000000000000UL)
28#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_FIXED)
29#else
30#define ADDR (void *)(0x0UL)
31#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)
32#endif
33
34static void check_bytes(char *addr)
35{
36 printf("First hex is %x\n", *((unsigned int *)addr));
37}
38
39static void write_bytes(char *addr)
40{
41 unsigned long i;
42
43 for (i = 0; i < LENGTH; i++)
44 *(addr + i) = (char)i;
45}
46
47static int read_bytes(char *addr)
48{
49 unsigned long i;
50
51 check_bytes(addr);
52 for (i = 0; i < LENGTH; i++)
53 if (*(addr + i) != (char)i) {
54 printf("Mismatch at %lu\n", i);
55 return 1;
56 }
57 return 0;
58}
59
60int main(void)
61{
62 void *addr;
63 int ret;
64
65 addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
66 if (addr == MAP_FAILED) {
67 perror("mmap");
68 exit(1);
69 }
70
71 printf("Returned address is %p\n", addr);
72 check_bytes(addr);
73 write_bytes(addr);
74 ret = read_bytes(addr);
75
76 munmap(addr, LENGTH);
77
78 return ret;
79}
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
new file mode 100644
index 000000000000..8b40bd5e5cc2
--- /dev/null
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -0,0 +1,77 @@
1#!/bin/bash
2#please run as root
3
4#we need 256M, below is the size in kB
5needmem=262144
6mnt=./huge
7
8#get pagesize and freepages from /proc/meminfo
9while read name size unit; do
10 if [ "$name" = "HugePages_Free:" ]; then
11 freepgs=$size
12 fi
13 if [ "$name" = "Hugepagesize:" ]; then
14 pgsize=$size
15 fi
16done < /proc/meminfo
17
18#set proper nr_hugepages
19if [ -n "$freepgs" ] && [ -n "$pgsize" ]; then
20 nr_hugepgs=`cat /proc/sys/vm/nr_hugepages`
21 needpgs=`expr $needmem / $pgsize`
22 if [ $freepgs -lt $needpgs ]; then
23 lackpgs=$(( $needpgs - $freepgs ))
24 echo $(( $lackpgs + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages
25 if [ $? -ne 0 ]; then
26 echo "Please run this test as root"
27 exit 1
28 fi
29 fi
30else
31 echo "no hugetlbfs support in kernel?"
32 exit 1
33fi
34
35mkdir $mnt
36mount -t hugetlbfs none $mnt
37
38echo "--------------------"
39echo "runing hugepage-mmap"
40echo "--------------------"
41./hugepage-mmap
42if [ $? -ne 0 ]; then
43 echo "[FAIL]"
44else
45 echo "[PASS]"
46fi
47
48shmmax=`cat /proc/sys/kernel/shmmax`
49shmall=`cat /proc/sys/kernel/shmall`
50echo 268435456 > /proc/sys/kernel/shmmax
51echo 4194304 > /proc/sys/kernel/shmall
52echo "--------------------"
53echo "runing hugepage-shm"
54echo "--------------------"
55./hugepage-shm
56if [ $? -ne 0 ]; then
57 echo "[FAIL]"
58else
59 echo "[PASS]"
60fi
61echo $shmmax > /proc/sys/kernel/shmmax
62echo $shmall > /proc/sys/kernel/shmall
63
64echo "--------------------"
65echo "runing map_hugetlb"
66echo "--------------------"
67./map_hugetlb
68if [ $? -ne 0 ]; then
69 echo "[FAIL]"
70else
71 echo "[PASS]"
72fi
73
74#cleanup
75umount $mnt
76rm -rf $mnt
77echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
diff --git a/tools/usb/Makefile b/tools/usb/Makefile
index 8b704af14349..396d6c44e9d7 100644
--- a/tools/usb/Makefile
+++ b/tools/usb/Makefile
@@ -3,7 +3,7 @@
3CC = $(CROSS_COMPILE)gcc 3CC = $(CROSS_COMPILE)gcc
4PTHREAD_LIBS = -lpthread 4PTHREAD_LIBS = -lpthread
5WARNINGS = -Wall -Wextra 5WARNINGS = -Wall -Wextra
6CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) 6CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) -I../include
7 7
8all: testusb ffs-test 8all: testusb ffs-test
9%: %.c 9%: %.c
diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c
index b9c798631699..4b107b5e623f 100644
--- a/tools/usb/ffs-test.c
+++ b/tools/usb/ffs-test.c
@@ -2,7 +2,7 @@
2 * ffs-test.c.c -- user mode filesystem api for usb composite function 2 * ffs-test.c.c -- user mode filesystem api for usb composite function
3 * 3 *
4 * Copyright (C) 2010 Samsung Electronics 4 * Copyright (C) 2010 Samsung Electronics
5 * Author: Michal Nazarewicz <m.nazarewicz@samsung.com> 5 * Author: Michal Nazarewicz <mina86@mina86.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -36,6 +36,7 @@
36#include <sys/stat.h> 36#include <sys/stat.h>
37#include <sys/types.h> 37#include <sys/types.h>
38#include <unistd.h> 38#include <unistd.h>
39#include <tools/le_byteshift.h>
39 40
40#include "../../include/linux/usb/functionfs.h" 41#include "../../include/linux/usb/functionfs.h"
41 42
@@ -47,34 +48,6 @@
47#define le32_to_cpu(x) le32toh(x) 48#define le32_to_cpu(x) le32toh(x)
48#define le16_to_cpu(x) le16toh(x) 49#define le16_to_cpu(x) le16toh(x)
49 50
50static inline __u16 get_unaligned_le16(const void *_ptr)
51{
52 const __u8 *ptr = _ptr;
53 return ptr[0] | (ptr[1] << 8);
54}
55
56static inline __u32 get_unaligned_le32(const void *_ptr)
57{
58 const __u8 *ptr = _ptr;
59 return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
60}
61
62static inline void put_unaligned_le16(__u16 val, void *_ptr)
63{
64 __u8 *ptr = _ptr;
65 *ptr++ = val;
66 *ptr++ = val >> 8;
67}
68
69static inline void put_unaligned_le32(__u32 val, void *_ptr)
70{
71 __u8 *ptr = _ptr;
72 *ptr++ = val;
73 *ptr++ = val >> 8;
74 *ptr++ = val >> 16;
75 *ptr++ = val >> 24;
76}
77
78 51
79/******************** Messages and Errors ***********************************/ 52/******************** Messages and Errors ***********************************/
80 53
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index f08e89463842..6e0f56701e44 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -3,7 +3,7 @@
3/* 3/*
4 * Copyright (c) 2002 by David Brownell 4 * Copyright (c) 2002 by David Brownell
5 * Copyright (c) 2010 by Samsung Electronics 5 * Copyright (c) 2010 by Samsung Electronics
6 * Author: Michal Nazarewicz <m.nazarewicz@samsung.com> 6 * Author: Michal Nazarewicz <mina86@mina86.com>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 9 * under the terms of the GNU General Public License as published by the
diff --git a/tools/virtio/linux/hrtimer.h b/tools/virtio/linux/hrtimer.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/virtio/linux/hrtimer.h
diff --git a/tools/virtio/linux/module.h b/tools/virtio/linux/module.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/virtio/linux/module.h
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index 669bcdd45805..7579f19e61e0 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -181,26 +181,20 @@ struct virtqueue {
181#define smp_mb() mb() 181#define smp_mb() mb()
182# define smp_rmb() barrier() 182# define smp_rmb() barrier()
183# define smp_wmb() barrier() 183# define smp_wmb() barrier()
184/* Weak barriers should be used. If not - it's a bug */
185# define rmb() abort()
186# define wmb() abort()
184#else 187#else
185#error Please fill in barrier macros 188#error Please fill in barrier macros
186#endif 189#endif
187 190
188/* Interfaces exported by virtio_ring. */ 191/* Interfaces exported by virtio_ring. */
189int virtqueue_add_buf_gfp(struct virtqueue *vq, 192int virtqueue_add_buf(struct virtqueue *vq,
190 struct scatterlist sg[], 193 struct scatterlist sg[],
191 unsigned int out_num, 194 unsigned int out_num,
192 unsigned int in_num, 195 unsigned int in_num,
193 void *data, 196 void *data,
194 gfp_t gfp); 197 gfp_t gfp);
195
196static inline int virtqueue_add_buf(struct virtqueue *vq,
197 struct scatterlist sg[],
198 unsigned int out_num,
199 unsigned int in_num,
200 void *data)
201{
202 return virtqueue_add_buf_gfp(vq, sg, out_num, in_num, data, GFP_ATOMIC);
203}
204 198
205void virtqueue_kick(struct virtqueue *vq); 199void virtqueue_kick(struct virtqueue *vq);
206 200
@@ -214,6 +208,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *vq);
214struct virtqueue *vring_new_virtqueue(unsigned int num, 208struct virtqueue *vring_new_virtqueue(unsigned int num,
215 unsigned int vring_align, 209 unsigned int vring_align,
216 struct virtio_device *vdev, 210 struct virtio_device *vdev,
211 bool weak_barriers,
217 void *pages, 212 void *pages,
218 void (*notify)(struct virtqueue *vq), 213 void (*notify)(struct virtqueue *vq),
219 void (*callback)(struct virtqueue *vq), 214 void (*callback)(struct virtqueue *vq),
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
index 74d3331bdaf9..6bf95f995364 100644
--- a/tools/virtio/virtio_test.c
+++ b/tools/virtio/virtio_test.c
@@ -92,7 +92,8 @@ static void vq_info_add(struct vdev_info *dev, int num)
92 assert(r >= 0); 92 assert(r >= 0);
93 memset(info->ring, 0, vring_size(num, 4096)); 93 memset(info->ring, 0, vring_size(num, 4096));
94 vring_init(&info->vring, num, info->ring, 4096); 94 vring_init(&info->vring, num, info->ring, 4096);
95 info->vq = vring_new_virtqueue(info->vring.num, 4096, &dev->vdev, info->ring, 95 info->vq = vring_new_virtqueue(info->vring.num, 4096, &dev->vdev,
96 true, info->ring,
96 vq_notify, vq_callback, "test"); 97 vq_notify, vq_callback, "test");
97 assert(info->vq); 98 assert(info->vq);
98 info->vq->priv = info; 99 info->vq->priv = info;
@@ -160,7 +161,8 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq, int bufs)
160 if (started < bufs) { 161 if (started < bufs) {
161 sg_init_one(&sl, dev->buf, dev->buf_size); 162 sg_init_one(&sl, dev->buf, dev->buf_size);
162 r = virtqueue_add_buf(vq->vq, &sl, 1, 0, 163 r = virtqueue_add_buf(vq->vq, &sl, 1, 0,
163 dev->buf + started); 164 dev->buf + started,
165 GFP_ATOMIC);
164 if (likely(r >= 0)) { 166 if (likely(r >= 0)) {
165 ++started; 167 ++started;
166 virtqueue_kick(vq->vq); 168 virtqueue_kick(vq->vq);
diff --git a/tools/vm/Makefile b/tools/vm/Makefile
new file mode 100644
index 000000000000..8e30e5c40f8a
--- /dev/null
+++ b/tools/vm/Makefile
@@ -0,0 +1,11 @@
1# Makefile for vm tools
2
3CC = $(CROSS_COMPILE)gcc
4CFLAGS = -Wall -Wextra
5
6all: page-types slabinfo
7%: %.c
8 $(CC) $(CFLAGS) -o $@ $^
9
10clean:
11 $(RM) page-types slabinfo
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
new file mode 100644
index 000000000000..7dab7b25b5c6
--- /dev/null
+++ b/tools/vm/page-types.c
@@ -0,0 +1,1102 @@
1/*
2 * page-types: Tool for querying page flags
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should find a copy of v2 of the GNU General Public License somewhere on
14 * your Linux system; if not, write to the Free Software Foundation, Inc., 59
15 * Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16 *
17 * Copyright (C) 2009 Intel corporation
18 *
19 * Authors: Wu Fengguang <fengguang.wu@intel.com>
20 */
21
22#define _LARGEFILE64_SOURCE
23#include <stdio.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <stdint.h>
27#include <stdarg.h>
28#include <string.h>
29#include <getopt.h>
30#include <limits.h>
31#include <assert.h>
32#include <sys/types.h>
33#include <sys/errno.h>
34#include <sys/fcntl.h>
35#include <sys/mount.h>
36#include <sys/statfs.h>
37#include "../../include/linux/magic.h"
38
39
40#ifndef MAX_PATH
41# define MAX_PATH 256
42#endif
43
44#ifndef STR
45# define _STR(x) #x
46# define STR(x) _STR(x)
47#endif
48
49/*
50 * pagemap kernel ABI bits
51 */
52
53#define PM_ENTRY_BYTES sizeof(uint64_t)
54#define PM_STATUS_BITS 3
55#define PM_STATUS_OFFSET (64 - PM_STATUS_BITS)
56#define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET)
57#define PM_STATUS(nr) (((nr) << PM_STATUS_OFFSET) & PM_STATUS_MASK)
58#define PM_PSHIFT_BITS 6
59#define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS)
60#define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET)
61#define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK)
62#define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1)
63#define PM_PFRAME(x) ((x) & PM_PFRAME_MASK)
64
65#define PM_PRESENT PM_STATUS(4LL)
66#define PM_SWAP PM_STATUS(2LL)
67
68
69/*
70 * kernel page flags
71 */
72
73#define KPF_BYTES 8
74#define PROC_KPAGEFLAGS "/proc/kpageflags"
75
76/* copied from kpageflags_read() */
77#define KPF_LOCKED 0
78#define KPF_ERROR 1
79#define KPF_REFERENCED 2
80#define KPF_UPTODATE 3
81#define KPF_DIRTY 4
82#define KPF_LRU 5
83#define KPF_ACTIVE 6
84#define KPF_SLAB 7
85#define KPF_WRITEBACK 8
86#define KPF_RECLAIM 9
87#define KPF_BUDDY 10
88
89/* [11-20] new additions in 2.6.31 */
90#define KPF_MMAP 11
91#define KPF_ANON 12
92#define KPF_SWAPCACHE 13
93#define KPF_SWAPBACKED 14
94#define KPF_COMPOUND_HEAD 15
95#define KPF_COMPOUND_TAIL 16
96#define KPF_HUGE 17
97#define KPF_UNEVICTABLE 18
98#define KPF_HWPOISON 19
99#define KPF_NOPAGE 20
100#define KPF_KSM 21
101#define KPF_THP 22
102
103/* [32-] kernel hacking assistances */
104#define KPF_RESERVED 32
105#define KPF_MLOCKED 33
106#define KPF_MAPPEDTODISK 34
107#define KPF_PRIVATE 35
108#define KPF_PRIVATE_2 36
109#define KPF_OWNER_PRIVATE 37
110#define KPF_ARCH 38
111#define KPF_UNCACHED 39
112
113/* [48-] take some arbitrary free slots for expanding overloaded flags
114 * not part of kernel API
115 */
116#define KPF_READAHEAD 48
117#define KPF_SLOB_FREE 49
118#define KPF_SLUB_FROZEN 50
119#define KPF_SLUB_DEBUG 51
120
121#define KPF_ALL_BITS ((uint64_t)~0ULL)
122#define KPF_HACKERS_BITS (0xffffULL << 32)
123#define KPF_OVERLOADED_BITS (0xffffULL << 48)
124#define BIT(name) (1ULL << KPF_##name)
125#define BITS_COMPOUND (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL))
126
127static const char * const page_flag_names[] = {
128 [KPF_LOCKED] = "L:locked",
129 [KPF_ERROR] = "E:error",
130 [KPF_REFERENCED] = "R:referenced",
131 [KPF_UPTODATE] = "U:uptodate",
132 [KPF_DIRTY] = "D:dirty",
133 [KPF_LRU] = "l:lru",
134 [KPF_ACTIVE] = "A:active",
135 [KPF_SLAB] = "S:slab",
136 [KPF_WRITEBACK] = "W:writeback",
137 [KPF_RECLAIM] = "I:reclaim",
138 [KPF_BUDDY] = "B:buddy",
139
140 [KPF_MMAP] = "M:mmap",
141 [KPF_ANON] = "a:anonymous",
142 [KPF_SWAPCACHE] = "s:swapcache",
143 [KPF_SWAPBACKED] = "b:swapbacked",
144 [KPF_COMPOUND_HEAD] = "H:compound_head",
145 [KPF_COMPOUND_TAIL] = "T:compound_tail",
146 [KPF_HUGE] = "G:huge",
147 [KPF_UNEVICTABLE] = "u:unevictable",
148 [KPF_HWPOISON] = "X:hwpoison",
149 [KPF_NOPAGE] = "n:nopage",
150 [KPF_KSM] = "x:ksm",
151 [KPF_THP] = "t:thp",
152
153 [KPF_RESERVED] = "r:reserved",
154 [KPF_MLOCKED] = "m:mlocked",
155 [KPF_MAPPEDTODISK] = "d:mappedtodisk",
156 [KPF_PRIVATE] = "P:private",
157 [KPF_PRIVATE_2] = "p:private_2",
158 [KPF_OWNER_PRIVATE] = "O:owner_private",
159 [KPF_ARCH] = "h:arch",
160 [KPF_UNCACHED] = "c:uncached",
161
162 [KPF_READAHEAD] = "I:readahead",
163 [KPF_SLOB_FREE] = "P:slob_free",
164 [KPF_SLUB_FROZEN] = "A:slub_frozen",
165 [KPF_SLUB_DEBUG] = "E:slub_debug",
166};
167
168
169static const char * const debugfs_known_mountpoints[] = {
170 "/sys/kernel/debug",
171 "/debug",
172 0,
173};
174
175/*
176 * data structures
177 */
178
179static int opt_raw; /* for kernel developers */
180static int opt_list; /* list pages (in ranges) */
181static int opt_no_summary; /* don't show summary */
182static pid_t opt_pid; /* process to walk */
183
184#define MAX_ADDR_RANGES 1024
185static int nr_addr_ranges;
186static unsigned long opt_offset[MAX_ADDR_RANGES];
187static unsigned long opt_size[MAX_ADDR_RANGES];
188
189#define MAX_VMAS 10240
190static int nr_vmas;
191static unsigned long pg_start[MAX_VMAS];
192static unsigned long pg_end[MAX_VMAS];
193
194#define MAX_BIT_FILTERS 64
195static int nr_bit_filters;
196static uint64_t opt_mask[MAX_BIT_FILTERS];
197static uint64_t opt_bits[MAX_BIT_FILTERS];
198
199static int page_size;
200
201static int pagemap_fd;
202static int kpageflags_fd;
203
204static int opt_hwpoison;
205static int opt_unpoison;
206
207static char hwpoison_debug_fs[MAX_PATH+1];
208static int hwpoison_inject_fd;
209static int hwpoison_forget_fd;
210
211#define HASH_SHIFT 13
212#define HASH_SIZE (1 << HASH_SHIFT)
213#define HASH_MASK (HASH_SIZE - 1)
214#define HASH_KEY(flags) (flags & HASH_MASK)
215
216static unsigned long total_pages;
217static unsigned long nr_pages[HASH_SIZE];
218static uint64_t page_flags[HASH_SIZE];
219
220
221/*
222 * helper functions
223 */
224
225#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
226
227#define min_t(type, x, y) ({ \
228 type __min1 = (x); \
229 type __min2 = (y); \
230 __min1 < __min2 ? __min1 : __min2; })
231
232#define max_t(type, x, y) ({ \
233 type __max1 = (x); \
234 type __max2 = (y); \
235 __max1 > __max2 ? __max1 : __max2; })
236
237static unsigned long pages2mb(unsigned long pages)
238{
239 return (pages * page_size) >> 20;
240}
241
242static void fatal(const char *x, ...)
243{
244 va_list ap;
245
246 va_start(ap, x);
247 vfprintf(stderr, x, ap);
248 va_end(ap);
249 exit(EXIT_FAILURE);
250}
251
252static int checked_open(const char *pathname, int flags)
253{
254 int fd = open(pathname, flags);
255
256 if (fd < 0) {
257 perror(pathname);
258 exit(EXIT_FAILURE);
259 }
260
261 return fd;
262}
263
264/*
265 * pagemap/kpageflags routines
266 */
267
268static unsigned long do_u64_read(int fd, char *name,
269 uint64_t *buf,
270 unsigned long index,
271 unsigned long count)
272{
273 long bytes;
274
275 if (index > ULONG_MAX / 8)
276 fatal("index overflow: %lu\n", index);
277
278 if (lseek(fd, index * 8, SEEK_SET) < 0) {
279 perror(name);
280 exit(EXIT_FAILURE);
281 }
282
283 bytes = read(fd, buf, count * 8);
284 if (bytes < 0) {
285 perror(name);
286 exit(EXIT_FAILURE);
287 }
288 if (bytes % 8)
289 fatal("partial read: %lu bytes\n", bytes);
290
291 return bytes / 8;
292}
293
294static unsigned long kpageflags_read(uint64_t *buf,
295 unsigned long index,
296 unsigned long pages)
297{
298 return do_u64_read(kpageflags_fd, PROC_KPAGEFLAGS, buf, index, pages);
299}
300
301static unsigned long pagemap_read(uint64_t *buf,
302 unsigned long index,
303 unsigned long pages)
304{
305 return do_u64_read(pagemap_fd, "/proc/pid/pagemap", buf, index, pages);
306}
307
308static unsigned long pagemap_pfn(uint64_t val)
309{
310 unsigned long pfn;
311
312 if (val & PM_PRESENT)
313 pfn = PM_PFRAME(val);
314 else
315 pfn = 0;
316
317 return pfn;
318}
319
320
321/*
322 * page flag names
323 */
324
325static char *page_flag_name(uint64_t flags)
326{
327 static char buf[65];
328 int present;
329 int i, j;
330
331 for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
332 present = (flags >> i) & 1;
333 if (!page_flag_names[i]) {
334 if (present)
335 fatal("unknown flag bit %d\n", i);
336 continue;
337 }
338 buf[j++] = present ? page_flag_names[i][0] : '_';
339 }
340
341 return buf;
342}
343
344static char *page_flag_longname(uint64_t flags)
345{
346 static char buf[1024];
347 int i, n;
348
349 for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) {
350 if (!page_flag_names[i])
351 continue;
352 if ((flags >> i) & 1)
353 n += snprintf(buf + n, sizeof(buf) - n, "%s,",
354 page_flag_names[i] + 2);
355 }
356 if (n)
357 n--;
358 buf[n] = '\0';
359
360 return buf;
361}
362
363
364/*
365 * page list and summary
366 */
367
368static void show_page_range(unsigned long voffset,
369 unsigned long offset, uint64_t flags)
370{
371 static uint64_t flags0;
372 static unsigned long voff;
373 static unsigned long index;
374 static unsigned long count;
375
376 if (flags == flags0 && offset == index + count &&
377 (!opt_pid || voffset == voff + count)) {
378 count++;
379 return;
380 }
381
382 if (count) {
383 if (opt_pid)
384 printf("%lx\t", voff);
385 printf("%lx\t%lx\t%s\n",
386 index, count, page_flag_name(flags0));
387 }
388
389 flags0 = flags;
390 index = offset;
391 voff = voffset;
392 count = 1;
393}
394
395static void show_page(unsigned long voffset,
396 unsigned long offset, uint64_t flags)
397{
398 if (opt_pid)
399 printf("%lx\t", voffset);
400 printf("%lx\t%s\n", offset, page_flag_name(flags));
401}
402
403static void show_summary(void)
404{
405 int i;
406
407 printf(" flags\tpage-count MB"
408 " symbolic-flags\t\t\tlong-symbolic-flags\n");
409
410 for (i = 0; i < ARRAY_SIZE(nr_pages); i++) {
411 if (nr_pages[i])
412 printf("0x%016llx\t%10lu %8lu %s\t%s\n",
413 (unsigned long long)page_flags[i],
414 nr_pages[i],
415 pages2mb(nr_pages[i]),
416 page_flag_name(page_flags[i]),
417 page_flag_longname(page_flags[i]));
418 }
419
420 printf(" total\t%10lu %8lu\n",
421 total_pages, pages2mb(total_pages));
422}
423
424
425/*
426 * page flag filters
427 */
428
429static int bit_mask_ok(uint64_t flags)
430{
431 int i;
432
433 for (i = 0; i < nr_bit_filters; i++) {
434 if (opt_bits[i] == KPF_ALL_BITS) {
435 if ((flags & opt_mask[i]) == 0)
436 return 0;
437 } else {
438 if ((flags & opt_mask[i]) != opt_bits[i])
439 return 0;
440 }
441 }
442
443 return 1;
444}
445
446static uint64_t expand_overloaded_flags(uint64_t flags)
447{
448 /* SLOB/SLUB overload several page flags */
449 if (flags & BIT(SLAB)) {
450 if (flags & BIT(PRIVATE))
451 flags ^= BIT(PRIVATE) | BIT(SLOB_FREE);
452 if (flags & BIT(ACTIVE))
453 flags ^= BIT(ACTIVE) | BIT(SLUB_FROZEN);
454 if (flags & BIT(ERROR))
455 flags ^= BIT(ERROR) | BIT(SLUB_DEBUG);
456 }
457
458 /* PG_reclaim is overloaded as PG_readahead in the read path */
459 if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM))
460 flags ^= BIT(RECLAIM) | BIT(READAHEAD);
461
462 return flags;
463}
464
465static uint64_t well_known_flags(uint64_t flags)
466{
467 /* hide flags intended only for kernel hacker */
468 flags &= ~KPF_HACKERS_BITS;
469
470 /* hide non-hugeTLB compound pages */
471 if ((flags & BITS_COMPOUND) && !(flags & BIT(HUGE)))
472 flags &= ~BITS_COMPOUND;
473
474 return flags;
475}
476
477static uint64_t kpageflags_flags(uint64_t flags)
478{
479 flags = expand_overloaded_flags(flags);
480
481 if (!opt_raw)
482 flags = well_known_flags(flags);
483
484 return flags;
485}
486
487/* verify that a mountpoint is actually a debugfs instance */
488static int debugfs_valid_mountpoint(const char *debugfs)
489{
490 struct statfs st_fs;
491
492 if (statfs(debugfs, &st_fs) < 0)
493 return -ENOENT;
494 else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
495 return -ENOENT;
496
497 return 0;
498}
499
500/* find the path to the mounted debugfs */
501static const char *debugfs_find_mountpoint(void)
502{
503 const char **ptr;
504 char type[100];
505 FILE *fp;
506
507 ptr = debugfs_known_mountpoints;
508 while (*ptr) {
509 if (debugfs_valid_mountpoint(*ptr) == 0) {
510 strcpy(hwpoison_debug_fs, *ptr);
511 return hwpoison_debug_fs;
512 }
513 ptr++;
514 }
515
516 /* give up and parse /proc/mounts */
517 fp = fopen("/proc/mounts", "r");
518 if (fp == NULL)
519 perror("Can't open /proc/mounts for read");
520
521 while (fscanf(fp, "%*s %"
522 STR(MAX_PATH)
523 "s %99s %*s %*d %*d\n",
524 hwpoison_debug_fs, type) == 2) {
525 if (strcmp(type, "debugfs") == 0)
526 break;
527 }
528 fclose(fp);
529
530 if (strcmp(type, "debugfs") != 0)
531 return NULL;
532
533 return hwpoison_debug_fs;
534}
535
536/* mount the debugfs somewhere if it's not mounted */
537
538static void debugfs_mount(void)
539{
540 const char **ptr;
541
542 /* see if it's already mounted */
543 if (debugfs_find_mountpoint())
544 return;
545
546 ptr = debugfs_known_mountpoints;
547 while (*ptr) {
548 if (mount(NULL, *ptr, "debugfs", 0, NULL) == 0) {
549 /* save the mountpoint */
550 strcpy(hwpoison_debug_fs, *ptr);
551 break;
552 }
553 ptr++;
554 }
555
556 if (*ptr == NULL) {
557 perror("mount debugfs");
558 exit(EXIT_FAILURE);
559 }
560}
561
562/*
563 * page actions
564 */
565
566static void prepare_hwpoison_fd(void)
567{
568 char buf[MAX_PATH + 1];
569
570 debugfs_mount();
571
572 if (opt_hwpoison && !hwpoison_inject_fd) {
573 snprintf(buf, MAX_PATH, "%s/hwpoison/corrupt-pfn",
574 hwpoison_debug_fs);
575 hwpoison_inject_fd = checked_open(buf, O_WRONLY);
576 }
577
578 if (opt_unpoison && !hwpoison_forget_fd) {
579 snprintf(buf, MAX_PATH, "%s/hwpoison/unpoison-pfn",
580 hwpoison_debug_fs);
581 hwpoison_forget_fd = checked_open(buf, O_WRONLY);
582 }
583}
584
585static int hwpoison_page(unsigned long offset)
586{
587 char buf[100];
588 int len;
589
590 len = sprintf(buf, "0x%lx\n", offset);
591 len = write(hwpoison_inject_fd, buf, len);
592 if (len < 0) {
593 perror("hwpoison inject");
594 return len;
595 }
596 return 0;
597}
598
599static int unpoison_page(unsigned long offset)
600{
601 char buf[100];
602 int len;
603
604 len = sprintf(buf, "0x%lx\n", offset);
605 len = write(hwpoison_forget_fd, buf, len);
606 if (len < 0) {
607 perror("hwpoison forget");
608 return len;
609 }
610 return 0;
611}
612
613/*
614 * page frame walker
615 */
616
617static int hash_slot(uint64_t flags)
618{
619 int k = HASH_KEY(flags);
620 int i;
621
622 /* Explicitly reserve slot 0 for flags 0: the following logic
623 * cannot distinguish an unoccupied slot from slot (flags==0).
624 */
625 if (flags == 0)
626 return 0;
627
628 /* search through the remaining (HASH_SIZE-1) slots */
629 for (i = 1; i < ARRAY_SIZE(page_flags); i++, k++) {
630 if (!k || k >= ARRAY_SIZE(page_flags))
631 k = 1;
632 if (page_flags[k] == 0) {
633 page_flags[k] = flags;
634 return k;
635 }
636 if (page_flags[k] == flags)
637 return k;
638 }
639
640 fatal("hash table full: bump up HASH_SHIFT?\n");
641 exit(EXIT_FAILURE);
642}
643
644static void add_page(unsigned long voffset,
645 unsigned long offset, uint64_t flags)
646{
647 flags = kpageflags_flags(flags);
648
649 if (!bit_mask_ok(flags))
650 return;
651
652 if (opt_hwpoison)
653 hwpoison_page(offset);
654 if (opt_unpoison)
655 unpoison_page(offset);
656
657 if (opt_list == 1)
658 show_page_range(voffset, offset, flags);
659 else if (opt_list == 2)
660 show_page(voffset, offset, flags);
661
662 nr_pages[hash_slot(flags)]++;
663 total_pages++;
664}
665
666#define KPAGEFLAGS_BATCH (64 << 10) /* 64k pages */
667static void walk_pfn(unsigned long voffset,
668 unsigned long index,
669 unsigned long count)
670{
671 uint64_t buf[KPAGEFLAGS_BATCH];
672 unsigned long batch;
673 long pages;
674 unsigned long i;
675
676 while (count) {
677 batch = min_t(unsigned long, count, KPAGEFLAGS_BATCH);
678 pages = kpageflags_read(buf, index, batch);
679 if (pages == 0)
680 break;
681
682 for (i = 0; i < pages; i++)
683 add_page(voffset + i, index + i, buf[i]);
684
685 index += pages;
686 count -= pages;
687 }
688}
689
690#define PAGEMAP_BATCH (64 << 10)
691static void walk_vma(unsigned long index, unsigned long count)
692{
693 uint64_t buf[PAGEMAP_BATCH];
694 unsigned long batch;
695 unsigned long pages;
696 unsigned long pfn;
697 unsigned long i;
698
699 while (count) {
700 batch = min_t(unsigned long, count, PAGEMAP_BATCH);
701 pages = pagemap_read(buf, index, batch);
702 if (pages == 0)
703 break;
704
705 for (i = 0; i < pages; i++) {
706 pfn = pagemap_pfn(buf[i]);
707 if (pfn)
708 walk_pfn(index + i, pfn, 1);
709 }
710
711 index += pages;
712 count -= pages;
713 }
714}
715
716static void walk_task(unsigned long index, unsigned long count)
717{
718 const unsigned long end = index + count;
719 unsigned long start;
720 int i = 0;
721
722 while (index < end) {
723
724 while (pg_end[i] <= index)
725 if (++i >= nr_vmas)
726 return;
727 if (pg_start[i] >= end)
728 return;
729
730 start = max_t(unsigned long, pg_start[i], index);
731 index = min_t(unsigned long, pg_end[i], end);
732
733 assert(start < index);
734 walk_vma(start, index - start);
735 }
736}
737
738static void add_addr_range(unsigned long offset, unsigned long size)
739{
740 if (nr_addr_ranges >= MAX_ADDR_RANGES)
741 fatal("too many addr ranges\n");
742
743 opt_offset[nr_addr_ranges] = offset;
744 opt_size[nr_addr_ranges] = min_t(unsigned long, size, ULONG_MAX-offset);
745 nr_addr_ranges++;
746}
747
748static void walk_addr_ranges(void)
749{
750 int i;
751
752 kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY);
753
754 if (!nr_addr_ranges)
755 add_addr_range(0, ULONG_MAX);
756
757 for (i = 0; i < nr_addr_ranges; i++)
758 if (!opt_pid)
759 walk_pfn(0, opt_offset[i], opt_size[i]);
760 else
761 walk_task(opt_offset[i], opt_size[i]);
762
763 close(kpageflags_fd);
764}
765
766
767/*
768 * user interface
769 */
770
771static const char *page_flag_type(uint64_t flag)
772{
773 if (flag & KPF_HACKERS_BITS)
774 return "(r)";
775 if (flag & KPF_OVERLOADED_BITS)
776 return "(o)";
777 return " ";
778}
779
780static void usage(void)
781{
782 int i, j;
783
784 printf(
785"page-types [options]\n"
786" -r|--raw Raw mode, for kernel developers\n"
787" -d|--describe flags Describe flags\n"
788" -a|--addr addr-spec Walk a range of pages\n"
789" -b|--bits bits-spec Walk pages with specified bits\n"
790" -p|--pid pid Walk process address space\n"
791#if 0 /* planned features */
792" -f|--file filename Walk file address space\n"
793#endif
794" -l|--list Show page details in ranges\n"
795" -L|--list-each Show page details one by one\n"
796" -N|--no-summary Don't show summary info\n"
797" -X|--hwpoison hwpoison pages\n"
798" -x|--unpoison unpoison pages\n"
799" -h|--help Show this usage message\n"
800"flags:\n"
801" 0x10 bitfield format, e.g.\n"
802" anon bit-name, e.g.\n"
803" 0x10,anon comma-separated list, e.g.\n"
804"addr-spec:\n"
805" N one page at offset N (unit: pages)\n"
806" N+M pages range from N to N+M-1\n"
807" N,M pages range from N to M-1\n"
808" N, pages range from N to end\n"
809" ,M pages range from 0 to M-1\n"
810"bits-spec:\n"
811" bit1,bit2 (flags & (bit1|bit2)) != 0\n"
812" bit1,bit2=bit1 (flags & (bit1|bit2)) == bit1\n"
813" bit1,~bit2 (flags & (bit1|bit2)) == bit1\n"
814" =bit1,bit2 flags == (bit1|bit2)\n"
815"bit-names:\n"
816 );
817
818 for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
819 if (!page_flag_names[i])
820 continue;
821 printf("%16s%s", page_flag_names[i] + 2,
822 page_flag_type(1ULL << i));
823 if (++j > 3) {
824 j = 0;
825 putchar('\n');
826 }
827 }
828 printf("\n "
829 "(r) raw mode bits (o) overloaded bits\n");
830}
831
832static unsigned long long parse_number(const char *str)
833{
834 unsigned long long n;
835
836 n = strtoll(str, NULL, 0);
837
838 if (n == 0 && str[0] != '0')
839 fatal("invalid name or number: %s\n", str);
840
841 return n;
842}
843
844static void parse_pid(const char *str)
845{
846 FILE *file;
847 char buf[5000];
848
849 opt_pid = parse_number(str);
850
851 sprintf(buf, "/proc/%d/pagemap", opt_pid);
852 pagemap_fd = checked_open(buf, O_RDONLY);
853
854 sprintf(buf, "/proc/%d/maps", opt_pid);
855 file = fopen(buf, "r");
856 if (!file) {
857 perror(buf);
858 exit(EXIT_FAILURE);
859 }
860
861 while (fgets(buf, sizeof(buf), file) != NULL) {
862 unsigned long vm_start;
863 unsigned long vm_end;
864 unsigned long long pgoff;
865 int major, minor;
866 char r, w, x, s;
867 unsigned long ino;
868 int n;
869
870 n = sscanf(buf, "%lx-%lx %c%c%c%c %llx %x:%x %lu",
871 &vm_start,
872 &vm_end,
873 &r, &w, &x, &s,
874 &pgoff,
875 &major, &minor,
876 &ino);
877 if (n < 10) {
878 fprintf(stderr, "unexpected line: %s\n", buf);
879 continue;
880 }
881 pg_start[nr_vmas] = vm_start / page_size;
882 pg_end[nr_vmas] = vm_end / page_size;
883 if (++nr_vmas >= MAX_VMAS) {
884 fprintf(stderr, "too many VMAs\n");
885 break;
886 }
887 }
888 fclose(file);
889}
890
891static void parse_file(const char *name)
892{
893}
894
895static void parse_addr_range(const char *optarg)
896{
897 unsigned long offset;
898 unsigned long size;
899 char *p;
900
901 p = strchr(optarg, ',');
902 if (!p)
903 p = strchr(optarg, '+');
904
905 if (p == optarg) {
906 offset = 0;
907 size = parse_number(p + 1);
908 } else if (p) {
909 offset = parse_number(optarg);
910 if (p[1] == '\0')
911 size = ULONG_MAX;
912 else {
913 size = parse_number(p + 1);
914 if (*p == ',') {
915 if (size < offset)
916 fatal("invalid range: %lu,%lu\n",
917 offset, size);
918 size -= offset;
919 }
920 }
921 } else {
922 offset = parse_number(optarg);
923 size = 1;
924 }
925
926 add_addr_range(offset, size);
927}
928
929static void add_bits_filter(uint64_t mask, uint64_t bits)
930{
931 if (nr_bit_filters >= MAX_BIT_FILTERS)
932 fatal("too much bit filters\n");
933
934 opt_mask[nr_bit_filters] = mask;
935 opt_bits[nr_bit_filters] = bits;
936 nr_bit_filters++;
937}
938
939static uint64_t parse_flag_name(const char *str, int len)
940{
941 int i;
942
943 if (!*str || !len)
944 return 0;
945
946 if (len <= 8 && !strncmp(str, "compound", len))
947 return BITS_COMPOUND;
948
949 for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) {
950 if (!page_flag_names[i])
951 continue;
952 if (!strncmp(str, page_flag_names[i] + 2, len))
953 return 1ULL << i;
954 }
955
956 return parse_number(str);
957}
958
959static uint64_t parse_flag_names(const char *str, int all)
960{
961 const char *p = str;
962 uint64_t flags = 0;
963
964 while (1) {
965 if (*p == ',' || *p == '=' || *p == '\0') {
966 if ((*str != '~') || (*str == '~' && all && *++str))
967 flags |= parse_flag_name(str, p - str);
968 if (*p != ',')
969 break;
970 str = p + 1;
971 }
972 p++;
973 }
974
975 return flags;
976}
977
978static void parse_bits_mask(const char *optarg)
979{
980 uint64_t mask;
981 uint64_t bits;
982 const char *p;
983
984 p = strchr(optarg, '=');
985 if (p == optarg) {
986 mask = KPF_ALL_BITS;
987 bits = parse_flag_names(p + 1, 0);
988 } else if (p) {
989 mask = parse_flag_names(optarg, 0);
990 bits = parse_flag_names(p + 1, 0);
991 } else if (strchr(optarg, '~')) {
992 mask = parse_flag_names(optarg, 1);
993 bits = parse_flag_names(optarg, 0);
994 } else {
995 mask = parse_flag_names(optarg, 0);
996 bits = KPF_ALL_BITS;
997 }
998
999 add_bits_filter(mask, bits);
1000}
1001
1002static void describe_flags(const char *optarg)
1003{
1004 uint64_t flags = parse_flag_names(optarg, 0);
1005
1006 printf("0x%016llx\t%s\t%s\n",
1007 (unsigned long long)flags,
1008 page_flag_name(flags),
1009 page_flag_longname(flags));
1010}
1011
1012static const struct option opts[] = {
1013 { "raw" , 0, NULL, 'r' },
1014 { "pid" , 1, NULL, 'p' },
1015 { "file" , 1, NULL, 'f' },
1016 { "addr" , 1, NULL, 'a' },
1017 { "bits" , 1, NULL, 'b' },
1018 { "describe" , 1, NULL, 'd' },
1019 { "list" , 0, NULL, 'l' },
1020 { "list-each" , 0, NULL, 'L' },
1021 { "no-summary", 0, NULL, 'N' },
1022 { "hwpoison" , 0, NULL, 'X' },
1023 { "unpoison" , 0, NULL, 'x' },
1024 { "help" , 0, NULL, 'h' },
1025 { NULL , 0, NULL, 0 }
1026};
1027
1028int main(int argc, char *argv[])
1029{
1030 int c;
1031
1032 page_size = getpagesize();
1033
1034 while ((c = getopt_long(argc, argv,
1035 "rp:f:a:b:d:lLNXxh", opts, NULL)) != -1) {
1036 switch (c) {
1037 case 'r':
1038 opt_raw = 1;
1039 break;
1040 case 'p':
1041 parse_pid(optarg);
1042 break;
1043 case 'f':
1044 parse_file(optarg);
1045 break;
1046 case 'a':
1047 parse_addr_range(optarg);
1048 break;
1049 case 'b':
1050 parse_bits_mask(optarg);
1051 break;
1052 case 'd':
1053 describe_flags(optarg);
1054 exit(0);
1055 case 'l':
1056 opt_list = 1;
1057 break;
1058 case 'L':
1059 opt_list = 2;
1060 break;
1061 case 'N':
1062 opt_no_summary = 1;
1063 break;
1064 case 'X':
1065 opt_hwpoison = 1;
1066 prepare_hwpoison_fd();
1067 break;
1068 case 'x':
1069 opt_unpoison = 1;
1070 prepare_hwpoison_fd();
1071 break;
1072 case 'h':
1073 usage();
1074 exit(0);
1075 default:
1076 usage();
1077 exit(1);
1078 }
1079 }
1080
1081 if (opt_list && opt_pid)
1082 printf("voffset\t");
1083 if (opt_list == 1)
1084 printf("offset\tlen\tflags\n");
1085 if (opt_list == 2)
1086 printf("offset\tflags\n");
1087
1088 walk_addr_ranges();
1089
1090 if (opt_list == 1)
1091 show_page_range(0, 0, 0); /* drain the buffer */
1092
1093 if (opt_no_summary)
1094 return 0;
1095
1096 if (opt_list)
1097 printf("\n\n");
1098
1099 show_summary();
1100
1101 return 0;
1102}
diff --git a/tools/slub/slabinfo.c b/tools/vm/slabinfo.c
index 164cbcf61106..164cbcf61106 100644
--- a/tools/slub/slabinfo.c
+++ b/tools/vm/slabinfo.c