aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-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/examples.txt34
-rw-r--r--tools/perf/Documentation/perf-annotate.txt4
-rw-r--r--tools/perf/Documentation/perf-buildid-list.txt2
-rw-r--r--tools/perf/Documentation/perf-evlist.txt2
-rw-r--r--tools/perf/Documentation/perf-kmem.txt2
-rw-r--r--tools/perf/Documentation/perf-list.txt2
-rw-r--r--tools/perf/Documentation/perf-lock.txt2
-rw-r--r--tools/perf/Documentation/perf-record.txt2
-rw-r--r--tools/perf/Documentation/perf-report.txt11
-rw-r--r--tools/perf/Documentation/perf-sched.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt9
-rw-r--r--tools/perf/Documentation/perf-test.txt8
-rw-r--r--tools/perf/Documentation/perf-timechart.txt2
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile10
-rw-r--r--tools/perf/arch/powerpc/util/dwarf-regs.c3
-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/mem-memcpy-x86-64-asm.S6
-rw-r--r--tools/perf/builtin-annotate.c139
-rw-r--r--tools/perf/builtin-buildid-list.c53
-rw-r--r--tools/perf/builtin-diff.c21
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-inject.c118
-rw-r--r--tools/perf/builtin-kmem.c19
-rw-r--r--tools/perf/builtin-kvm.c8
-rw-r--r--tools/perf/builtin-lock.c12
-rw-r--r--tools/perf/builtin-probe.c3
-rw-r--r--tools/perf/builtin-record.c626
-rw-r--r--tools/perf/builtin-report.c236
-rw-r--r--tools/perf/builtin-sched.c200
-rw-r--r--tools/perf/builtin-script.c134
-rw-r--r--tools/perf/builtin-stat.c134
-rw-r--r--tools/perf/builtin-test.c547
-rw-r--r--tools/perf/builtin-timechart.c38
-rw-r--r--tools/perf/builtin-top.c591
-rw-r--r--tools/perf/perf.c33
-rw-r--r--tools/perf/perf.h31
-rw-r--r--tools/perf/util/annotate.c8
-rw-r--r--tools/perf/util/annotate.h5
-rw-r--r--tools/perf/util/build-id.c26
-rw-r--r--tools/perf/util/build-id.h2
-rw-r--r--tools/perf/util/callchain.h3
-rw-r--r--tools/perf/util/cgroup.c15
-rw-r--r--tools/perf/util/color.c9
-rw-r--r--tools/perf/util/config.c5
-rw-r--r--tools/perf/util/debugfs.c35
-rw-r--r--tools/perf/util/debugfs.h31
-rw-r--r--tools/perf/util/event.c363
-rw-r--r--tools/perf/util/event.h68
-rw-r--r--tools/perf/util/evlist.c308
-rw-r--r--tools/perf/util/evlist.h43
-rw-r--r--tools/perf/util/evsel.c155
-rw-r--r--tools/perf/util/evsel.h8
-rw-r--r--tools/perf/util/header.c743
-rw-r--r--tools/perf/util/header.h51
-rw-r--r--tools/perf/util/hist.c161
-rw-r--r--tools/perf/util/hist.h10
-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/bitops.h118
-rw-r--r--tools/perf/util/map.c4
-rw-r--r--tools/perf/util/map.h19
-rw-r--r--tools/perf/util/parse-events.c47
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/probe-event.c8
-rw-r--r--tools/perf/util/probe-finder.c12
-rw-r--r--tools/perf/util/probe-finder.h1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c75
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/session.c342
-rw-r--r--tools/perf/util/session.h72
-rw-r--r--tools/perf/util/setup.py3
-rw-r--r--tools/perf/util/sort.c3
-rw-r--r--tools/perf/util/strbuf.c7
-rw-r--r--tools/perf/util/symbol.c12
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/thread.c6
-rw-r--r--tools/perf/util/thread.h14
-rw-r--r--tools/perf/util/tool.h50
-rw-r--r--tools/perf/util/top.h21
-rw-r--r--tools/perf/util/trace-event-info.c27
-rw-r--r--tools/perf/util/trace-event-parse.c3
-rw-r--r--tools/perf/util/trace-event-scripting.c2
-rw-r--r--tools/perf/util/trace-event.h8
-rw-r--r--tools/perf/util/ui/browsers/annotate.c16
-rw-r--r--tools/perf/util/ui/browsers/hists.c16
-rw-r--r--tools/perf/util/ui/helpline.c3
-rw-r--r--tools/perf/util/ui/progress.c3
-rw-r--r--tools/perf/util/usage.c5
-rw-r--r--tools/perf/util/util.c15
-rw-r--r--tools/perf/util/util.h16
-rw-r--r--tools/perf/util/values.c1
-rw-r--r--tools/power/x86/turbostat/turbostat.88
-rw-r--r--tools/power/x86/turbostat/turbostat.c2
-rwxr-xr-xtools/testing/ktest/compare-ktest-sample.pl4
-rwxr-xr-xtools/testing/ktest/ktest.pl690
-rw-r--r--tools/testing/ktest/sample.conf89
-rw-r--r--tools/testing/selftests/Makefile11
-rw-r--r--tools/testing/selftests/breakpoints/Makefile20
-rw-r--r--tools/testing/selftests/breakpoints/breakpoint_test.c394
-rw-r--r--tools/testing/selftests/run_tests8
-rw-r--r--tools/virtio/linux/virtio.h22
-rw-r--r--tools/virtio/virtio_test.c6
110 files changed, 7059 insertions, 2542 deletions
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/examples.txt b/tools/perf/Documentation/examples.txt
index 8eb6c489fb15..77f952762426 100644
--- a/tools/perf/Documentation/examples.txt
+++ b/tools/perf/Documentation/examples.txt
@@ -17,8 +17,8 @@ titan:~> perf list
17 kmem:kmem_cache_alloc_node [Tracepoint event] 17 kmem:kmem_cache_alloc_node [Tracepoint event]
18 kmem:kfree [Tracepoint event] 18 kmem:kfree [Tracepoint event]
19 kmem:kmem_cache_free [Tracepoint event] 19 kmem:kmem_cache_free [Tracepoint event]
20 kmem:mm_page_free_direct [Tracepoint event] 20 kmem:mm_page_free [Tracepoint event]
21 kmem:mm_pagevec_free [Tracepoint event] 21 kmem:mm_page_free_batched [Tracepoint event]
22 kmem:mm_page_alloc [Tracepoint event] 22 kmem:mm_page_alloc [Tracepoint event]
23 kmem:mm_page_alloc_zone_locked [Tracepoint event] 23 kmem:mm_page_alloc_zone_locked [Tracepoint event]
24 kmem:mm_page_pcpu_drain [Tracepoint event] 24 kmem:mm_page_pcpu_drain [Tracepoint event]
@@ -29,15 +29,15 @@ measured. For example the page alloc/free properties of a 'hackbench
29run' are: 29run' are:
30 30
31 titan:~> perf stat -e kmem:mm_page_pcpu_drain -e kmem:mm_page_alloc 31 titan:~> perf stat -e kmem:mm_page_pcpu_drain -e kmem:mm_page_alloc
32 -e kmem:mm_pagevec_free -e kmem:mm_page_free_direct ./hackbench 10 32 -e kmem:mm_page_free_batched -e kmem:mm_page_free ./hackbench 10
33 Time: 0.575 33 Time: 0.575
34 34
35 Performance counter stats for './hackbench 10': 35 Performance counter stats for './hackbench 10':
36 36
37 13857 kmem:mm_page_pcpu_drain 37 13857 kmem:mm_page_pcpu_drain
38 27576 kmem:mm_page_alloc 38 27576 kmem:mm_page_alloc
39 6025 kmem:mm_pagevec_free 39 6025 kmem:mm_page_free_batched
40 20934 kmem:mm_page_free_direct 40 20934 kmem:mm_page_free
41 41
42 0.613972165 seconds time elapsed 42 0.613972165 seconds time elapsed
43 43
@@ -45,8 +45,8 @@ You can observe the statistical properties as well, by using the
45'repeat the workload N times' feature of perf stat: 45'repeat the workload N times' feature of perf stat:
46 46
47 titan:~> perf stat --repeat 5 -e kmem:mm_page_pcpu_drain -e 47 titan:~> perf stat --repeat 5 -e kmem:mm_page_pcpu_drain -e
48 kmem:mm_page_alloc -e kmem:mm_pagevec_free -e 48 kmem:mm_page_alloc -e kmem:mm_page_free_batched -e
49 kmem:mm_page_free_direct ./hackbench 10 49 kmem:mm_page_free ./hackbench 10
50 Time: 0.627 50 Time: 0.627
51 Time: 0.644 51 Time: 0.644
52 Time: 0.564 52 Time: 0.564
@@ -57,8 +57,8 @@ You can observe the statistical properties as well, by using the
57 57
58 12920 kmem:mm_page_pcpu_drain ( +- 3.359% ) 58 12920 kmem:mm_page_pcpu_drain ( +- 3.359% )
59 25035 kmem:mm_page_alloc ( +- 3.783% ) 59 25035 kmem:mm_page_alloc ( +- 3.783% )
60 6104 kmem:mm_pagevec_free ( +- 0.934% ) 60 6104 kmem:mm_page_free_batched ( +- 0.934% )
61 18376 kmem:mm_page_free_direct ( +- 4.941% ) 61 18376 kmem:mm_page_free ( +- 4.941% )
62 62
63 0.643954516 seconds time elapsed ( +- 2.363% ) 63 0.643954516 seconds time elapsed ( +- 2.363% )
64 64
@@ -158,15 +158,15 @@ Or you can observe the whole system's page allocations for 10
158seconds: 158seconds:
159 159
160titan:~/git> perf stat -a -e kmem:mm_page_pcpu_drain -e 160titan:~/git> perf stat -a -e kmem:mm_page_pcpu_drain -e
161kmem:mm_page_alloc -e kmem:mm_pagevec_free -e 161kmem:mm_page_alloc -e kmem:mm_page_free_batched -e
162kmem:mm_page_free_direct sleep 10 162kmem:mm_page_free sleep 10
163 163
164 Performance counter stats for 'sleep 10': 164 Performance counter stats for 'sleep 10':
165 165
166 171585 kmem:mm_page_pcpu_drain 166 171585 kmem:mm_page_pcpu_drain
167 322114 kmem:mm_page_alloc 167 322114 kmem:mm_page_alloc
168 73623 kmem:mm_pagevec_free 168 73623 kmem:mm_page_free_batched
169 254115 kmem:mm_page_free_direct 169 254115 kmem:mm_page_free
170 170
171 10.000591410 seconds time elapsed 171 10.000591410 seconds time elapsed
172 172
@@ -174,15 +174,15 @@ Or observe how fluctuating the page allocations are, via statistical
174analysis done over ten 1-second intervals: 174analysis done over ten 1-second intervals:
175 175
176 titan:~/git> perf stat --repeat 10 -a -e kmem:mm_page_pcpu_drain -e 176 titan:~/git> perf stat --repeat 10 -a -e kmem:mm_page_pcpu_drain -e
177 kmem:mm_page_alloc -e kmem:mm_pagevec_free -e 177 kmem:mm_page_alloc -e kmem:mm_page_free_batched -e
178 kmem:mm_page_free_direct sleep 1 178 kmem:mm_page_free sleep 1
179 179
180 Performance counter stats for 'sleep 1' (10 runs): 180 Performance counter stats for 'sleep 1' (10 runs):
181 181
182 17254 kmem:mm_page_pcpu_drain ( +- 3.709% ) 182 17254 kmem:mm_page_pcpu_drain ( +- 3.709% )
183 34394 kmem:mm_page_alloc ( +- 4.617% ) 183 34394 kmem:mm_page_alloc ( +- 4.617% )
184 7509 kmem:mm_pagevec_free ( +- 4.820% ) 184 7509 kmem:mm_page_free_batched ( +- 4.820% )
185 25653 kmem:mm_page_free_direct ( +- 3.672% ) 185 25653 kmem:mm_page_free ( +- 3.672% )
186 186
187 1.058135029 seconds time elapsed ( +- 3.089% ) 187 1.058135029 seconds time elapsed ( +- 3.089% )
188 188
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index fe6762ed56bd..c89f9e1453f7 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -22,7 +22,7 @@ OPTIONS
22------- 22-------
23-i:: 23-i::
24--input=:: 24--input=::
25 Input file name. (default: perf.data) 25 Input file name. (default: perf.data unless stdin is a fifo)
26 26
27-d:: 27-d::
28--dsos=<dso[,dso...]>:: 28--dsos=<dso[,dso...]>::
@@ -66,7 +66,7 @@ OPTIONS
66 used. This interfaces starts by centering on the line with more 66 used. This interfaces starts by centering on the line with more
67 samples, TAB/UNTAB cycles through the lines with more samples. 67 samples, TAB/UNTAB cycles through the lines with more samples.
68 68
69-c:: 69-C::
70--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 70--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
71 be provided as a comma-separated list with no space: 0,1. Ranges of 71 be provided as a comma-separated list with no space: 0,1. Ranges of
72 CPUs are specified with -: 0-2. Default is to report samples on all 72 CPUs are specified with -: 0-2. Default is to report samples on all
diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
index cc22325ffd1b..25c52efcc7f0 100644
--- a/tools/perf/Documentation/perf-buildid-list.txt
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -26,7 +26,7 @@ OPTIONS
26 Show only DSOs with hits. 26 Show only DSOs with hits.
27-i:: 27-i::
28--input=:: 28--input=::
29 Input file name. (default: perf.data) 29 Input file name. (default: perf.data unless stdin is a fifo)
30-f:: 30-f::
31--force:: 31--force::
32 Don't do ownership validation. 32 Don't do ownership validation.
diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
index 0cada9e053dc..0507ec7bad71 100644
--- a/tools/perf/Documentation/perf-evlist.txt
+++ b/tools/perf/Documentation/perf-evlist.txt
@@ -18,7 +18,7 @@ OPTIONS
18------- 18-------
19-i:: 19-i::
20--input=:: 20--input=::
21 Input file name. (default: perf.data) 21 Input file name. (default: perf.data unless stdin is a fifo)
22 22
23SEE ALSO 23SEE ALSO
24-------- 24--------
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index a52fcde894c7..7c8fbbf3f61c 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -23,7 +23,7 @@ OPTIONS
23------- 23-------
24-i <file>:: 24-i <file>::
25--input=<file>:: 25--input=<file>::
26 Select the input file (default: perf.data) 26 Select the input file (default: perf.data unless stdin is a fifo)
27 27
28--caller:: 28--caller::
29 Show per-callsite statistics 29 Show per-callsite statistics
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 4a26a2f3a6a3..d6b2a4f2108b 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -29,7 +29,7 @@ COMMON OPTIONS
29 29
30-i:: 30-i::
31--input=<file>:: 31--input=<file>::
32 Input file name. 32 Input file name. (default: perf.data unless stdin is a fifo)
33 33
34-v:: 34-v::
35--verbose:: 35--verbose::
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 5a520f825295..2937f7e14bb7 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -89,7 +89,7 @@ OPTIONS
89 89
90-m:: 90-m::
91--mmap-pages=:: 91--mmap-pages=::
92 Number of mmap data pages. 92 Number of mmap data pages. Must be a power of two.
93 93
94-g:: 94-g::
95--call-graph:: 95--call-graph::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 212f24d672e1..9b430e98712e 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -19,7 +19,7 @@ OPTIONS
19------- 19-------
20-i:: 20-i::
21--input=:: 21--input=::
22 Input file name. (default: perf.data) 22 Input file name. (default: perf.data unless stdin is a fifo)
23 23
24-v:: 24-v::
25--verbose:: 25--verbose::
@@ -39,7 +39,7 @@ OPTIONS
39-T:: 39-T::
40--threads:: 40--threads::
41 Show per-thread event counters 41 Show per-thread event counters
42-C:: 42-c::
43--comms=:: 43--comms=::
44 Only consider symbols in these comms. CSV that understands 44 Only consider symbols in these comms. CSV that understands
45 file://filename entries. 45 file://filename entries.
@@ -80,9 +80,10 @@ OPTIONS
80--dump-raw-trace:: 80--dump-raw-trace::
81 Dump raw trace in ASCII. 81 Dump raw trace in ASCII.
82 82
83-g [type,min,order]:: 83-g [type,min[,limit],order]::
84--call-graph:: 84--call-graph::
85 Display call chains using type, min percent threshold and order. 85 Display call chains using type, min percent threshold, optional print
86 limit and order.
86 type can be either: 87 type can be either:
87 - flat: single column, linear exposure of call chains. 88 - flat: single column, linear exposure of call chains.
88 - graph: use a graph tree, displaying absolute overhead rates. 89 - graph: use a graph tree, displaying absolute overhead rates.
@@ -128,7 +129,7 @@ OPTIONS
128--symfs=<directory>:: 129--symfs=<directory>::
129 Look for files with symbols relative to this directory. 130 Look for files with symbols relative to this directory.
130 131
131-c:: 132-C::
132--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 133--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
133 be provided as a comma-separated list with no space: 0,1. Ranges of 134 be provided as a comma-separated list with no space: 0,1. Ranges of
134 CPUs are specified with -: 0-2. Default is to report samples on all 135 CPUs are specified with -: 0-2. Default is to report samples on all
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 5b212b57f70b..8ff4df956951 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -40,7 +40,7 @@ OPTIONS
40------- 40-------
41-i:: 41-i::
42--input=<file>:: 42--input=<file>::
43 Input file name. (default: perf.data) 43 Input file name. (default: perf.data unless stdin is a fifo)
44 44
45-v:: 45-v::
46--verbose:: 46--verbose::
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index dec87ecb530e..2f6cef43da25 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -106,7 +106,7 @@ OPTIONS
106 106
107-i:: 107-i::
108--input=:: 108--input=::
109 Input file name. 109 Input file name. (default: perf.data unless stdin is a fifo)
110 110
111-d:: 111-d::
112--debug-mode:: 112--debug-mode::
@@ -182,12 +182,17 @@ OPTIONS
182--hide-call-graph:: 182--hide-call-graph::
183 When printing symbols do not display call chain. 183 When printing symbols do not display call chain.
184 184
185-c:: 185-C::
186--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 186--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
187 be provided as a comma-separated list with no space: 0,1. Ranges of 187 be provided as a comma-separated list with no space: 0,1. Ranges of
188 CPUs are specified with -: 0-2. Default is to report samples on all 188 CPUs are specified with -: 0-2. Default is to report samples on all
189 CPUs. 189 CPUs.
190 190
191-c::
192--comms=::
193 Only display events for these comms. CSV that understands
194 file://filename entries.
195
191-I:: 196-I::
192--show-info:: 197--show-info::
193 Display extended information about the perf.data file. This adds 198 Display extended information about the perf.data file. This adds
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index 2c3b462f64b0..b24ac40fcd58 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -8,13 +8,19 @@ perf-test - Runs sanity tests.
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf test <options>' 11'perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]'
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command does assorted sanity tests, initially through linked routines but 15This command does assorted sanity tests, initially through linked routines but
16also will look for a directory with more tests in the form of scripts. 16also will look for a directory with more tests in the form of scripts.
17 17
18To get a list of available tests use 'perf test list', specifying a test name
19fragment will show all tests that have it.
20
21To run just specific tests, inform test name fragments or the numbers obtained
22from 'perf test list'.
23
18OPTIONS 24OPTIONS
19------- 25-------
20-v:: 26-v::
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index d7b79e2ba2ad..1632b0efc757 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -27,7 +27,7 @@ OPTIONS
27 Select the output file (default: output.svg) 27 Select the output file (default: output.svg)
28-i:: 28-i::
29--input=:: 29--input=::
30 Select the input file (default: perf.data) 30 Select the input file (default: perf.data unless stdin is a fifo)
31-w:: 31-w::
32--width=:: 32--width=::
33 Select the width of the SVG file (default: 1000) 33 Select the width of the SVG file (default: 1000)
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index c12659d8cb26..1078c5fadd5b 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
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index b98e3075646b..8a4b9bccf8b2 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -104,7 +104,7 @@ endif
104 104
105CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 105CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
106EXTLIBS = -lpthread -lrt -lelf -lm 106EXTLIBS = -lpthread -lrt -lelf -lm
107ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 107ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
108ALL_LDFLAGS = $(LDFLAGS) 108ALL_LDFLAGS = $(LDFLAGS)
109STRIP ?= strip 109STRIP ?= strip
110 110
@@ -168,10 +168,7 @@ endif
168 168
169### --- END CONFIGURATION SECTION --- 169### --- END CONFIGURATION SECTION ---
170 170
171# Those must not be GNU-specific; they are shared with perl/ which may 171BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -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 = 172BASIC_LDFLAGS =
176 173
177# Guard against environment variables 174# Guard against environment variables
@@ -252,6 +249,8 @@ LIB_H += util/include/asm/uaccess.h
252LIB_H += util/include/dwarf-regs.h 249LIB_H += util/include/dwarf-regs.h
253LIB_H += util/include/asm/dwarf2.h 250LIB_H += util/include/asm/dwarf2.h
254LIB_H += util/include/asm/cpufeature.h 251LIB_H += util/include/asm/cpufeature.h
252LIB_H += util/include/asm/unistd_32.h
253LIB_H += util/include/asm/unistd_64.h
255LIB_H += perf.h 254LIB_H += perf.h
256LIB_H += util/annotate.h 255LIB_H += util/annotate.h
257LIB_H += util/cache.h 256LIB_H += util/cache.h
@@ -278,6 +277,7 @@ LIB_H += util/strbuf.h
278LIB_H += util/strlist.h 277LIB_H += util/strlist.h
279LIB_H += util/strfilter.h 278LIB_H += util/strfilter.h
280LIB_H += util/svghelper.h 279LIB_H += util/svghelper.h
280LIB_H += util/tool.h
281LIB_H += util/run-command.h 281LIB_H += util/run-command.h
282LIB_H += util/sigchain.h 282LIB_H += util/sigchain.h
283LIB_H += util/symbol.h 283LIB_H += util/symbol.h
diff --git a/tools/perf/arch/powerpc/util/dwarf-regs.c b/tools/perf/arch/powerpc/util/dwarf-regs.c
index 48ae0c5e3f73..7cdd61d0e27c 100644
--- a/tools/perf/arch/powerpc/util/dwarf-regs.c
+++ b/tools/perf/arch/powerpc/util/dwarf-regs.c
@@ -9,7 +9,10 @@
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11 11
12#include <stdlib.h>
13#ifndef __UCLIBC__
12#include <libio.h> 14#include <libio.h>
15#endif
13#include <dwarf-regs.h> 16#include <dwarf-regs.h>
14 17
15 18
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/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index a57b66e853c2..185a96d66dd1 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -1,2 +1,8 @@
1 1
2#include "../../../arch/x86/lib/memcpy_64.S" 2#include "../../../arch/x86/lib/memcpy_64.S"
3/*
4 * We need to provide note.GNU-stack section, saying that we want
5 * NOT executable stack. Otherwise the final linking will assume that
6 * the ELF stack should not be restricted at all and set it RWX.
7 */
8.section .note.GNU-stack,"",@progbits
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 46b4c24f338e..806e0a286634 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -27,32 +27,32 @@
27#include "util/sort.h" 27#include "util/sort.h"
28#include "util/hist.h" 28#include "util/hist.h"
29#include "util/session.h" 29#include "util/session.h"
30#include "util/tool.h"
30 31
31#include <linux/bitmap.h> 32#include <linux/bitmap.h>
32 33
33static char const *input_name = "perf.data"; 34struct perf_annotate {
34 35 struct perf_tool tool;
35static bool force, use_tui, use_stdio; 36 char const *input_name;
36 37 bool force, use_tui, use_stdio;
37static bool full_paths; 38 bool full_paths;
38 39 bool print_line;
39static bool print_line; 40 const char *sym_hist_filter;
40 41 const char *cpu_list;
41static const char *sym_hist_filter; 42 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
42 43};
43static const char *cpu_list;
44static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
45 44
46static int perf_evlist__add_sample(struct perf_evlist *evlist, 45static int perf_evsel__add_sample(struct perf_evsel *evsel,
47 struct perf_sample *sample, 46 struct perf_sample *sample,
48 struct perf_evsel *evsel, 47 struct addr_location *al,
49 struct addr_location *al) 48 struct perf_annotate *ann)
50{ 49{
51 struct hist_entry *he; 50 struct hist_entry *he;
52 int ret; 51 int ret;
53 52
54 if (sym_hist_filter != NULL && 53 if (ann->sym_hist_filter != NULL &&
55 (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) { 54 (al->sym == NULL ||
55 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
56 /* We're only interested in a symbol named sym_hist_filter */ 56 /* We're only interested in a symbol named sym_hist_filter */
57 if (al->sym != NULL) { 57 if (al->sym != NULL) {
58 rb_erase(&al->sym->rb_node, 58 rb_erase(&al->sym->rb_node,
@@ -69,8 +69,7 @@ static int perf_evlist__add_sample(struct perf_evlist *evlist,
69 ret = 0; 69 ret = 0;
70 if (he->ms.sym != NULL) { 70 if (he->ms.sym != NULL) {
71 struct annotation *notes = symbol__annotation(he->ms.sym); 71 struct annotation *notes = symbol__annotation(he->ms.sym);
72 if (notes->src == NULL && 72 if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
73 symbol__alloc_hist(he->ms.sym, evlist->nr_entries) < 0)
74 return -ENOMEM; 73 return -ENOMEM;
75 74
76 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 75 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
@@ -81,25 +80,26 @@ static int perf_evlist__add_sample(struct perf_evlist *evlist,
81 return ret; 80 return ret;
82} 81}
83 82
84static int process_sample_event(union perf_event *event, 83static int process_sample_event(struct perf_tool *tool,
84 union perf_event *event,
85 struct perf_sample *sample, 85 struct perf_sample *sample,
86 struct perf_evsel *evsel, 86 struct perf_evsel *evsel,
87 struct perf_session *session) 87 struct machine *machine)
88{ 88{
89 struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);
89 struct addr_location al; 90 struct addr_location al;
90 91
91 if (perf_event__preprocess_sample(event, session, &al, sample, 92 if (perf_event__preprocess_sample(event, machine, &al, sample,
92 symbol__annotate_init) < 0) { 93 symbol__annotate_init) < 0) {
93 pr_warning("problem processing %d event, skipping it.\n", 94 pr_warning("problem processing %d event, skipping it.\n",
94 event->header.type); 95 event->header.type);
95 return -1; 96 return -1;
96 } 97 }
97 98
98 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 99 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
99 return 0; 100 return 0;
100 101
101 if (!al.filtered && 102 if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) {
102 perf_evlist__add_sample(session->evlist, sample, evsel, &al)) {
103 pr_warning("problem incrementing symbol count, " 103 pr_warning("problem incrementing symbol count, "
104 "skipping event\n"); 104 "skipping event\n");
105 return -1; 105 return -1;
@@ -108,14 +108,15 @@ static int process_sample_event(union perf_event *event,
108 return 0; 108 return 0;
109} 109}
110 110
111static int hist_entry__tty_annotate(struct hist_entry *he, int evidx) 111static int hist_entry__tty_annotate(struct hist_entry *he, int evidx,
112 struct perf_annotate *ann)
112{ 113{
113 return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx, 114 return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
114 print_line, full_paths, 0, 0); 115 ann->print_line, ann->full_paths, 0, 0);
115} 116}
116 117
117static void hists__find_annotations(struct hists *self, int evidx, 118static void hists__find_annotations(struct hists *self, int evidx,
118 int nr_events) 119 struct perf_annotate *ann)
119{ 120{
120 struct rb_node *nd = rb_first(&self->entries), *next; 121 struct rb_node *nd = rb_first(&self->entries), *next;
121 int key = K_RIGHT; 122 int key = K_RIGHT;
@@ -138,8 +139,7 @@ find_next:
138 } 139 }
139 140
140 if (use_browser > 0) { 141 if (use_browser > 0) {
141 key = hist_entry__tui_annotate(he, evidx, nr_events, 142 key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0);
142 NULL, NULL, 0);
143 switch (key) { 143 switch (key) {
144 case K_RIGHT: 144 case K_RIGHT:
145 next = rb_next(nd); 145 next = rb_next(nd);
@@ -154,7 +154,7 @@ find_next:
154 if (next != NULL) 154 if (next != NULL)
155 nd = next; 155 nd = next;
156 } else { 156 } else {
157 hist_entry__tty_annotate(he, evidx); 157 hist_entry__tty_annotate(he, evidx, ann);
158 nd = rb_next(nd); 158 nd = rb_next(nd);
159 /* 159 /*
160 * Since we have a hist_entry per IP for the same 160 * Since we have a hist_entry per IP for the same
@@ -167,33 +167,26 @@ find_next:
167 } 167 }
168} 168}
169 169
170static struct perf_event_ops event_ops = { 170static int __cmd_annotate(struct perf_annotate *ann)
171 .sample = process_sample_event,
172 .mmap = perf_event__process_mmap,
173 .comm = perf_event__process_comm,
174 .fork = perf_event__process_task,
175 .ordered_samples = true,
176 .ordering_requires_timestamps = true,
177};
178
179static int __cmd_annotate(void)
180{ 171{
181 int ret; 172 int ret;
182 struct perf_session *session; 173 struct perf_session *session;
183 struct perf_evsel *pos; 174 struct perf_evsel *pos;
184 u64 total_nr_samples; 175 u64 total_nr_samples;
185 176
186 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops); 177 session = perf_session__new(ann->input_name, O_RDONLY,
178 ann->force, false, &ann->tool);
187 if (session == NULL) 179 if (session == NULL)
188 return -ENOMEM; 180 return -ENOMEM;
189 181
190 if (cpu_list) { 182 if (ann->cpu_list) {
191 ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); 183 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
184 ann->cpu_bitmap);
192 if (ret) 185 if (ret)
193 goto out_delete; 186 goto out_delete;
194 } 187 }
195 188
196 ret = perf_session__process_events(session, &event_ops); 189 ret = perf_session__process_events(session, &ann->tool);
197 if (ret) 190 if (ret)
198 goto out_delete; 191 goto out_delete;
199 192
@@ -217,13 +210,12 @@ static int __cmd_annotate(void)
217 total_nr_samples += nr_samples; 210 total_nr_samples += nr_samples;
218 hists__collapse_resort(hists); 211 hists__collapse_resort(hists);
219 hists__output_resort(hists); 212 hists__output_resort(hists);
220 hists__find_annotations(hists, pos->idx, 213 hists__find_annotations(hists, pos->idx, ann);
221 session->evlist->nr_entries);
222 } 214 }
223 } 215 }
224 216
225 if (total_nr_samples == 0) { 217 if (total_nr_samples == 0) {
226 ui__warning("The %s file has no samples!\n", input_name); 218 ui__warning("The %s file has no samples!\n", session->filename);
227 goto out_delete; 219 goto out_delete;
228 } 220 }
229out_delete: 221out_delete:
@@ -243,33 +235,45 @@ out_delete:
243} 235}
244 236
245static const char * const annotate_usage[] = { 237static const char * const annotate_usage[] = {
246 "perf annotate [<options>] <command>", 238 "perf annotate [<options>]",
247 NULL 239 NULL
248}; 240};
249 241
250static const struct option options[] = { 242int cmd_annotate(int argc, const char **argv, const char *prefix __used)
251 OPT_STRING('i', "input", &input_name, "file", 243{
244 struct perf_annotate annotate = {
245 .tool = {
246 .sample = process_sample_event,
247 .mmap = perf_event__process_mmap,
248 .comm = perf_event__process_comm,
249 .fork = perf_event__process_task,
250 .ordered_samples = true,
251 .ordering_requires_timestamps = true,
252 },
253 };
254 const struct option options[] = {
255 OPT_STRING('i', "input", &annotate.input_name, "file",
252 "input file name"), 256 "input file name"),
253 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 257 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
254 "only consider symbols in these dsos"), 258 "only consider symbols in these dsos"),
255 OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", 259 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
256 "symbol to annotate"), 260 "symbol to annotate"),
257 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 261 OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"),
258 OPT_INCR('v', "verbose", &verbose, 262 OPT_INCR('v', "verbose", &verbose,
259 "be more verbose (show symbol address, etc)"), 263 "be more verbose (show symbol address, etc)"),
260 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 264 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
261 "dump raw trace in ASCII"), 265 "dump raw trace in ASCII"),
262 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), 266 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
263 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 267 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
264 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 268 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
265 "file", "vmlinux pathname"), 269 "file", "vmlinux pathname"),
266 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 270 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
267 "load module symbols - WARNING: use only with -k and LIVE kernel"), 271 "load module symbols - WARNING: use only with -k and LIVE kernel"),
268 OPT_BOOLEAN('l', "print-line", &print_line, 272 OPT_BOOLEAN('l', "print-line", &annotate.print_line,
269 "print matching source lines (may be slow)"), 273 "print matching source lines (may be slow)"),
270 OPT_BOOLEAN('P', "full-paths", &full_paths, 274 OPT_BOOLEAN('P', "full-paths", &annotate.full_paths,
271 "Don't shorten the displayed pathnames"), 275 "Don't shorten the displayed pathnames"),
272 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 276 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
273 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 277 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
274 "Look for files with symbols relative to this directory"), 278 "Look for files with symbols relative to this directory"),
275 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 279 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
@@ -279,15 +283,13 @@ static const struct option options[] = {
279 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 283 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
280 "Specify disassembler style (e.g. -M intel for intel syntax)"), 284 "Specify disassembler style (e.g. -M intel for intel syntax)"),
281 OPT_END() 285 OPT_END()
282}; 286 };
283 287
284int cmd_annotate(int argc, const char **argv, const char *prefix __used)
285{
286 argc = parse_options(argc, argv, options, annotate_usage, 0); 288 argc = parse_options(argc, argv, options, annotate_usage, 0);
287 289
288 if (use_stdio) 290 if (annotate.use_stdio)
289 use_browser = 0; 291 use_browser = 0;
290 else if (use_tui) 292 else if (annotate.use_tui)
291 use_browser = 1; 293 use_browser = 1;
292 294
293 setup_browser(true); 295 setup_browser(true);
@@ -308,13 +310,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
308 if (argc > 1) 310 if (argc > 1)
309 usage_with_options(annotate_usage, options); 311 usage_with_options(annotate_usage, options);
310 312
311 sym_hist_filter = argv[0]; 313 annotate.sym_hist_filter = argv[0];
312 }
313
314 if (field_sep && *field_sep == '.') {
315 pr_err("'.' is the only non valid --field-separator argument\n");
316 return -1;
317 } 314 }
318 315
319 return __cmd_annotate(); 316 return __cmd_annotate(&annotate);
320} 317}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index cb690a65bf02..52480467e9ff 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -18,7 +18,7 @@
18 18
19#include <libelf.h> 19#include <libelf.h>
20 20
21static char const *input_name = "perf.data"; 21static const char *input_name;
22static bool force; 22static bool force;
23static bool show_kernel; 23static bool show_kernel;
24static bool with_hits; 24static bool with_hits;
@@ -39,24 +39,6 @@ static const struct option options[] = {
39 OPT_END() 39 OPT_END()
40}; 40};
41 41
42static int perf_session__list_build_ids(void)
43{
44 struct perf_session *session;
45
46 session = perf_session__new(input_name, O_RDONLY, force, false,
47 &build_id__mark_dso_hit_ops);
48 if (session == NULL)
49 return -1;
50
51 if (with_hits)
52 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
53
54 perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
55
56 perf_session__delete(session);
57 return 0;
58}
59
60static int sysfs__fprintf_build_id(FILE *fp) 42static int sysfs__fprintf_build_id(FILE *fp)
61{ 43{
62 u8 kallsyms_build_id[BUILD_ID_SIZE]; 44 u8 kallsyms_build_id[BUILD_ID_SIZE];
@@ -85,17 +67,36 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
85 return fprintf(fp, "%s\n", sbuild_id); 67 return fprintf(fp, "%s\n", sbuild_id);
86} 68}
87 69
88static int __cmd_buildid_list(void) 70static int perf_session__list_build_ids(void)
89{ 71{
90 if (show_kernel) 72 struct perf_session *session;
91 return sysfs__fprintf_build_id(stdout);
92 73
93 elf_version(EV_CURRENT); 74 elf_version(EV_CURRENT);
75
76 session = perf_session__new(input_name, O_RDONLY, force, false,
77 &build_id__mark_dso_hit_ops);
78 if (session == NULL)
79 return -1;
80
94 /* 81 /*
95 * See if this is an ELF file first: 82 * See if this is an ELF file first:
96 */ 83 */
97 if (filename__fprintf_build_id(input_name, stdout)) 84 if (filename__fprintf_build_id(session->filename, stdout))
98 return 0; 85 goto out;
86
87 if (with_hits)
88 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
89
90 perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
91out:
92 perf_session__delete(session);
93 return 0;
94}
95
96static int __cmd_buildid_list(void)
97{
98 if (show_kernel)
99 return sysfs__fprintf_build_id(stdout);
99 100
100 return perf_session__list_build_ids(); 101 return perf_session__list_build_ids();
101} 102}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index b39f3a1ee7dc..4f19513d7dda 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -9,7 +9,9 @@
9#include "util/debug.h" 9#include "util/debug.h"
10#include "util/event.h" 10#include "util/event.h"
11#include "util/hist.h" 11#include "util/hist.h"
12#include "util/evsel.h"
12#include "util/session.h" 13#include "util/session.h"
14#include "util/tool.h"
13#include "util/sort.h" 15#include "util/sort.h"
14#include "util/symbol.h" 16#include "util/symbol.h"
15#include "util/util.h" 17#include "util/util.h"
@@ -30,14 +32,15 @@ static int hists__add_entry(struct hists *self,
30 return -ENOMEM; 32 return -ENOMEM;
31} 33}
32 34
33static int diff__process_sample_event(union perf_event *event, 35static int diff__process_sample_event(struct perf_tool *tool __used,
36 union perf_event *event,
34 struct perf_sample *sample, 37 struct perf_sample *sample,
35 struct perf_evsel *evsel __used, 38 struct perf_evsel *evsel __used,
36 struct perf_session *session) 39 struct machine *machine)
37{ 40{
38 struct addr_location al; 41 struct addr_location al;
39 42
40 if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) { 43 if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) {
41 pr_warning("problem processing %d event, skipping it.\n", 44 pr_warning("problem processing %d event, skipping it.\n",
42 event->header.type); 45 event->header.type);
43 return -1; 46 return -1;
@@ -46,16 +49,16 @@ static int diff__process_sample_event(union perf_event *event,
46 if (al.filtered || al.sym == NULL) 49 if (al.filtered || al.sym == NULL)
47 return 0; 50 return 0;
48 51
49 if (hists__add_entry(&session->hists, &al, sample->period)) { 52 if (hists__add_entry(&evsel->hists, &al, sample->period)) {
50 pr_warning("problem incrementing symbol period, skipping event\n"); 53 pr_warning("problem incrementing symbol period, skipping event\n");
51 return -1; 54 return -1;
52 } 55 }
53 56
54 session->hists.stats.total_period += sample->period; 57 evsel->hists.stats.total_period += sample->period;
55 return 0; 58 return 0;
56} 59}
57 60
58static struct perf_event_ops event_ops = { 61static struct perf_tool perf_diff = {
59 .sample = diff__process_sample_event, 62 .sample = diff__process_sample_event,
60 .mmap = perf_event__process_mmap, 63 .mmap = perf_event__process_mmap,
61 .comm = perf_event__process_comm, 64 .comm = perf_event__process_comm,
@@ -145,13 +148,13 @@ static int __cmd_diff(void)
145 int ret, i; 148 int ret, i;
146 struct perf_session *session[2]; 149 struct perf_session *session[2];
147 150
148 session[0] = perf_session__new(input_old, O_RDONLY, force, false, &event_ops); 151 session[0] = perf_session__new(input_old, O_RDONLY, force, false, &perf_diff);
149 session[1] = perf_session__new(input_new, O_RDONLY, force, false, &event_ops); 152 session[1] = perf_session__new(input_new, O_RDONLY, force, false, &perf_diff);
150 if (session[0] == NULL || session[1] == NULL) 153 if (session[0] == NULL || session[1] == NULL)
151 return -ENOMEM; 154 return -ENOMEM;
152 155
153 for (i = 0; i < 2; ++i) { 156 for (i = 0; i < 2; ++i) {
154 ret = perf_session__process_events(session[i], &event_ops); 157 ret = perf_session__process_events(session[i], &perf_diff);
155 if (ret) 158 if (ret)
156 goto out_delete; 159 goto out_delete;
157 } 160 }
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 4c5e9e04a41f..26760322c4f4 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -15,7 +15,7 @@
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16#include "util/session.h" 16#include "util/session.h"
17 17
18static char const *input_name = "perf.data"; 18static const char *input_name;
19 19
20static int __cmd_evlist(void) 20static int __cmd_evlist(void)
21{ 21{
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 8dfc12bb119b..09c106193e65 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -9,6 +9,7 @@
9 9
10#include "perf.h" 10#include "perf.h"
11#include "util/session.h" 11#include "util/session.h"
12#include "util/tool.h"
12#include "util/debug.h" 13#include "util/debug.h"
13 14
14#include "util/parse-options.h" 15#include "util/parse-options.h"
@@ -16,8 +17,9 @@
16static char const *input_name = "-"; 17static char const *input_name = "-";
17static bool inject_build_ids; 18static bool inject_build_ids;
18 19
19static int perf_event__repipe_synth(union perf_event *event, 20static int perf_event__repipe_synth(struct perf_tool *tool __used,
20 struct perf_session *session __used) 21 union perf_event *event,
22 struct machine *machine __used)
21{ 23{
22 uint32_t size; 24 uint32_t size;
23 void *buf = event; 25 void *buf = event;
@@ -36,41 +38,70 @@ static int perf_event__repipe_synth(union perf_event *event,
36 return 0; 38 return 0;
37} 39}
38 40
39static int perf_event__repipe(union perf_event *event, 41static int perf_event__repipe_op2_synth(struct perf_tool *tool,
42 union perf_event *event,
43 struct perf_session *session __used)
44{
45 return perf_event__repipe_synth(tool, event, NULL);
46}
47
48static int perf_event__repipe_event_type_synth(struct perf_tool *tool,
49 union perf_event *event)
50{
51 return perf_event__repipe_synth(tool, event, NULL);
52}
53
54static int perf_event__repipe_tracing_data_synth(union perf_event *event,
55 struct perf_session *session __used)
56{
57 return perf_event__repipe_synth(NULL, event, NULL);
58}
59
60static int perf_event__repipe_attr(union perf_event *event,
61 struct perf_evlist **pevlist __used)
62{
63 return perf_event__repipe_synth(NULL, event, NULL);
64}
65
66static int perf_event__repipe(struct perf_tool *tool,
67 union perf_event *event,
40 struct perf_sample *sample __used, 68 struct perf_sample *sample __used,
41 struct perf_session *session) 69 struct machine *machine)
42{ 70{
43 return perf_event__repipe_synth(event, session); 71 return perf_event__repipe_synth(tool, event, machine);
44} 72}
45 73
46static int perf_event__repipe_sample(union perf_event *event, 74static int perf_event__repipe_sample(struct perf_tool *tool,
75 union perf_event *event,
47 struct perf_sample *sample __used, 76 struct perf_sample *sample __used,
48 struct perf_evsel *evsel __used, 77 struct perf_evsel *evsel __used,
49 struct perf_session *session) 78 struct machine *machine)
50{ 79{
51 return perf_event__repipe_synth(event, session); 80 return perf_event__repipe_synth(tool, event, machine);
52} 81}
53 82
54static int perf_event__repipe_mmap(union perf_event *event, 83static int perf_event__repipe_mmap(struct perf_tool *tool,
84 union perf_event *event,
55 struct perf_sample *sample, 85 struct perf_sample *sample,
56 struct perf_session *session) 86 struct machine *machine)
57{ 87{
58 int err; 88 int err;
59 89
60 err = perf_event__process_mmap(event, sample, session); 90 err = perf_event__process_mmap(tool, event, sample, machine);
61 perf_event__repipe(event, sample, session); 91 perf_event__repipe(tool, event, sample, machine);
62 92
63 return err; 93 return err;
64} 94}
65 95
66static int perf_event__repipe_task(union perf_event *event, 96static int perf_event__repipe_task(struct perf_tool *tool,
97 union perf_event *event,
67 struct perf_sample *sample, 98 struct perf_sample *sample,
68 struct perf_session *session) 99 struct machine *machine)
69{ 100{
70 int err; 101 int err;
71 102
72 err = perf_event__process_task(event, sample, session); 103 err = perf_event__process_task(tool, event, sample, machine);
73 perf_event__repipe(event, sample, session); 104 perf_event__repipe(tool, event, sample, machine);
74 105
75 return err; 106 return err;
76} 107}
@@ -80,7 +111,7 @@ static int perf_event__repipe_tracing_data(union perf_event *event,
80{ 111{
81 int err; 112 int err;
82 113
83 perf_event__repipe_synth(event, session); 114 perf_event__repipe_synth(NULL, event, NULL);
84 err = perf_event__process_tracing_data(event, session); 115 err = perf_event__process_tracing_data(event, session);
85 116
86 return err; 117 return err;
@@ -100,10 +131,10 @@ static int dso__read_build_id(struct dso *self)
100 return -1; 131 return -1;
101} 132}
102 133
103static int dso__inject_build_id(struct dso *self, struct perf_session *session) 134static int dso__inject_build_id(struct dso *self, struct perf_tool *tool,
135 struct machine *machine)
104{ 136{
105 u16 misc = PERF_RECORD_MISC_USER; 137 u16 misc = PERF_RECORD_MISC_USER;
106 struct machine *machine;
107 int err; 138 int err;
108 139
109 if (dso__read_build_id(self) < 0) { 140 if (dso__read_build_id(self) < 0) {
@@ -111,17 +142,11 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
111 return -1; 142 return -1;
112 } 143 }
113 144
114 machine = perf_session__find_host_machine(session);
115 if (machine == NULL) {
116 pr_err("Can't find machine for session\n");
117 return -1;
118 }
119
120 if (self->kernel) 145 if (self->kernel)
121 misc = PERF_RECORD_MISC_KERNEL; 146 misc = PERF_RECORD_MISC_KERNEL;
122 147
123 err = perf_event__synthesize_build_id(self, misc, perf_event__repipe, 148 err = perf_event__synthesize_build_id(tool, self, misc, perf_event__repipe,
124 machine, session); 149 machine);
125 if (err) { 150 if (err) {
126 pr_err("Can't synthesize build_id event for %s\n", self->long_name); 151 pr_err("Can't synthesize build_id event for %s\n", self->long_name);
127 return -1; 152 return -1;
@@ -130,10 +155,11 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
130 return 0; 155 return 0;
131} 156}
132 157
133static int perf_event__inject_buildid(union perf_event *event, 158static int perf_event__inject_buildid(struct perf_tool *tool,
159 union perf_event *event,
134 struct perf_sample *sample, 160 struct perf_sample *sample,
135 struct perf_evsel *evsel __used, 161 struct perf_evsel *evsel __used,
136 struct perf_session *session) 162 struct machine *machine)
137{ 163{
138 struct addr_location al; 164 struct addr_location al;
139 struct thread *thread; 165 struct thread *thread;
@@ -141,21 +167,21 @@ static int perf_event__inject_buildid(union perf_event *event,
141 167
142 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 168 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
143 169
144 thread = perf_session__findnew(session, event->ip.pid); 170 thread = machine__findnew_thread(machine, event->ip.pid);
145 if (thread == NULL) { 171 if (thread == NULL) {
146 pr_err("problem processing %d event, skipping it.\n", 172 pr_err("problem processing %d event, skipping it.\n",
147 event->header.type); 173 event->header.type);
148 goto repipe; 174 goto repipe;
149 } 175 }
150 176
151 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 177 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
152 event->ip.pid, event->ip.ip, &al); 178 event->ip.ip, &al);
153 179
154 if (al.map != NULL) { 180 if (al.map != NULL) {
155 if (!al.map->dso->hit) { 181 if (!al.map->dso->hit) {
156 al.map->dso->hit = 1; 182 al.map->dso->hit = 1;
157 if (map__load(al.map, NULL) >= 0) { 183 if (map__load(al.map, NULL) >= 0) {
158 dso__inject_build_id(al.map->dso, session); 184 dso__inject_build_id(al.map->dso, tool, machine);
159 /* 185 /*
160 * If this fails, too bad, let the other side 186 * If this fails, too bad, let the other side
161 * account this as unresolved. 187 * account this as unresolved.
@@ -168,24 +194,24 @@ static int perf_event__inject_buildid(union perf_event *event,
168 } 194 }
169 195
170repipe: 196repipe:
171 perf_event__repipe(event, sample, session); 197 perf_event__repipe(tool, event, sample, machine);
172 return 0; 198 return 0;
173} 199}
174 200
175struct perf_event_ops inject_ops = { 201struct perf_tool perf_inject = {
176 .sample = perf_event__repipe_sample, 202 .sample = perf_event__repipe_sample,
177 .mmap = perf_event__repipe, 203 .mmap = perf_event__repipe,
178 .comm = perf_event__repipe, 204 .comm = perf_event__repipe,
179 .fork = perf_event__repipe, 205 .fork = perf_event__repipe,
180 .exit = perf_event__repipe, 206 .exit = perf_event__repipe,
181 .lost = perf_event__repipe, 207 .lost = perf_event__repipe,
182 .read = perf_event__repipe, 208 .read = perf_event__repipe_sample,
183 .throttle = perf_event__repipe, 209 .throttle = perf_event__repipe,
184 .unthrottle = perf_event__repipe, 210 .unthrottle = perf_event__repipe,
185 .attr = perf_event__repipe_synth, 211 .attr = perf_event__repipe_attr,
186 .event_type = perf_event__repipe_synth, 212 .event_type = perf_event__repipe_event_type_synth,
187 .tracing_data = perf_event__repipe_synth, 213 .tracing_data = perf_event__repipe_tracing_data_synth,
188 .build_id = perf_event__repipe_synth, 214 .build_id = perf_event__repipe_op2_synth,
189}; 215};
190 216
191extern volatile int session_done; 217extern volatile int session_done;
@@ -203,17 +229,17 @@ static int __cmd_inject(void)
203 signal(SIGINT, sig_handler); 229 signal(SIGINT, sig_handler);
204 230
205 if (inject_build_ids) { 231 if (inject_build_ids) {
206 inject_ops.sample = perf_event__inject_buildid; 232 perf_inject.sample = perf_event__inject_buildid;
207 inject_ops.mmap = perf_event__repipe_mmap; 233 perf_inject.mmap = perf_event__repipe_mmap;
208 inject_ops.fork = perf_event__repipe_task; 234 perf_inject.fork = perf_event__repipe_task;
209 inject_ops.tracing_data = perf_event__repipe_tracing_data; 235 perf_inject.tracing_data = perf_event__repipe_tracing_data;
210 } 236 }
211 237
212 session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops); 238 session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject);
213 if (session == NULL) 239 if (session == NULL)
214 return -ENOMEM; 240 return -ENOMEM;
215 241
216 ret = perf_session__process_events(session, &inject_ops); 242 ret = perf_session__process_events(session, &perf_inject);
217 243
218 perf_session__delete(session); 244 perf_session__delete(session);
219 245
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 225e963df105..39104c0beea3 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -7,6 +7,7 @@
7#include "util/thread.h" 7#include "util/thread.h"
8#include "util/header.h" 8#include "util/header.h"
9#include "util/session.h" 9#include "util/session.h"
10#include "util/tool.h"
10 11
11#include "util/parse-options.h" 12#include "util/parse-options.h"
12#include "util/trace-event.h" 13#include "util/trace-event.h"
@@ -18,7 +19,7 @@
18struct alloc_stat; 19struct alloc_stat;
19typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 20typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
20 21
21static char const *input_name = "perf.data"; 22static const char *input_name;
22 23
23static int alloc_flag; 24static int alloc_flag;
24static int caller_flag; 25static int caller_flag;
@@ -107,7 +108,9 @@ static void setup_cpunode_map(void)
107 continue; 108 continue;
108 cpunode_map[cpu] = mem; 109 cpunode_map[cpu] = mem;
109 } 110 }
111 closedir(dir2);
110 } 112 }
113 closedir(dir1);
111} 114}
112 115
113static void insert_alloc_stat(unsigned long call_site, unsigned long ptr, 116static void insert_alloc_stat(unsigned long call_site, unsigned long ptr,
@@ -303,12 +306,13 @@ static void process_raw_event(union perf_event *raw_event __used, void *data,
303 } 306 }
304} 307}
305 308
306static int process_sample_event(union perf_event *event, 309static int process_sample_event(struct perf_tool *tool __used,
310 union perf_event *event,
307 struct perf_sample *sample, 311 struct perf_sample *sample,
308 struct perf_evsel *evsel __used, 312 struct perf_evsel *evsel __used,
309 struct perf_session *session) 313 struct machine *machine)
310{ 314{
311 struct thread *thread = perf_session__findnew(session, event->ip.pid); 315 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
312 316
313 if (thread == NULL) { 317 if (thread == NULL) {
314 pr_debug("problem processing %d event, skipping it.\n", 318 pr_debug("problem processing %d event, skipping it.\n",
@@ -324,7 +328,7 @@ static int process_sample_event(union perf_event *event,
324 return 0; 328 return 0;
325} 329}
326 330
327static struct perf_event_ops event_ops = { 331static struct perf_tool perf_kmem = {
328 .sample = process_sample_event, 332 .sample = process_sample_event,
329 .comm = perf_event__process_comm, 333 .comm = perf_event__process_comm,
330 .ordered_samples = true, 334 .ordered_samples = true,
@@ -483,7 +487,7 @@ static int __cmd_kmem(void)
483{ 487{
484 int err = -EINVAL; 488 int err = -EINVAL;
485 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 489 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
486 0, false, &event_ops); 490 0, false, &perf_kmem);
487 if (session == NULL) 491 if (session == NULL)
488 return -ENOMEM; 492 return -ENOMEM;
489 493
@@ -494,7 +498,7 @@ static int __cmd_kmem(void)
494 goto out_delete; 498 goto out_delete;
495 499
496 setup_pager(); 500 setup_pager();
497 err = perf_session__process_events(session, &event_ops); 501 err = perf_session__process_events(session, &perf_kmem);
498 if (err != 0) 502 if (err != 0)
499 goto out_delete; 503 goto out_delete;
500 sort_result(); 504 sort_result();
@@ -643,6 +647,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
643 break; 647 break;
644 if (sort_dimension__add(tok, sort_list) < 0) { 648 if (sort_dimension__add(tok, sort_list) < 0) {
645 error("Unknown --sort key: '%s'", tok); 649 error("Unknown --sort key: '%s'", tok);
650 free(str);
646 return -1; 651 return -1;
647 } 652 }
648 } 653 }
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 34d1e853829d..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
@@ -38,7 +35,7 @@ static const struct option kvm_options[] = {
38 OPT_BOOLEAN(0, "guest", &perf_guest, 35 OPT_BOOLEAN(0, "guest", &perf_guest,
39 "Collect guest os data"), 36 "Collect guest os data"),
40 OPT_BOOLEAN(0, "host", &perf_host, 37 OPT_BOOLEAN(0, "host", &perf_host,
41 "Collect guest os data"), 38 "Collect host os data"),
42 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory", 39 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
43 "guest mount directory under which every guest os" 40 "guest mount directory under which every guest os"
44 " instance has a subdir"), 41 " instance has a subdir"),
@@ -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 899080ace267..2296c391d0f5 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -12,6 +12,7 @@
12 12
13#include "util/debug.h" 13#include "util/debug.h"
14#include "util/session.h" 14#include "util/session.h"
15#include "util/tool.h"
15 16
16#include <sys/types.h> 17#include <sys/types.h>
17#include <sys/prctl.h> 18#include <sys/prctl.h>
@@ -325,7 +326,7 @@ alloc_failed:
325 die("memory allocation failed\n"); 326 die("memory allocation failed\n");
326} 327}
327 328
328static char const *input_name = "perf.data"; 329static const char *input_name;
329 330
330struct raw_event_sample { 331struct raw_event_sample {
331 u32 size; 332 u32 size;
@@ -845,12 +846,13 @@ static void dump_info(void)
845 die("Unknown type of information\n"); 846 die("Unknown type of information\n");
846} 847}
847 848
848static int process_sample_event(union perf_event *event, 849static int process_sample_event(struct perf_tool *tool __used,
850 union perf_event *event,
849 struct perf_sample *sample, 851 struct perf_sample *sample,
850 struct perf_evsel *evsel __used, 852 struct perf_evsel *evsel __used,
851 struct perf_session *s) 853 struct machine *machine)
852{ 854{
853 struct thread *thread = perf_session__findnew(s, sample->tid); 855 struct thread *thread = machine__findnew_thread(machine, sample->tid);
854 856
855 if (thread == NULL) { 857 if (thread == NULL) {
856 pr_debug("problem processing %d event, skipping it.\n", 858 pr_debug("problem processing %d event, skipping it.\n",
@@ -863,7 +865,7 @@ static int process_sample_event(union perf_event *event,
863 return 0; 865 return 0;
864} 866}
865 867
866static struct perf_event_ops eops = { 868static struct perf_tool eops = {
867 .sample = process_sample_event, 869 .sample = process_sample_event,
868 .comm = perf_event__process_comm, 870 .comm = perf_event__process_comm,
869 .ordered_samples = true, 871 .ordered_samples = true,
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 710ae3d0a489..fb8566181f27 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"
@@ -46,7 +44,6 @@
46 44
47#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" 45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
48#define DEFAULT_FUNC_FILTER "!_*" 46#define DEFAULT_FUNC_FILTER "!_*"
49#define MAX_PATH_LEN 256
50 47
51/* Session management structure */ 48/* Session management structure */
52static struct { 49static struct {
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6ab58cc99d53..227b6ae99785 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -22,6 +22,7 @@
22#include "util/evsel.h" 22#include "util/evsel.h"
23#include "util/debug.h" 23#include "util/debug.h"
24#include "util/session.h" 24#include "util/session.h"
25#include "util/tool.h"
25#include "util/symbol.h" 26#include "util/symbol.h"
26#include "util/cpumap.h" 27#include "util/cpumap.h"
27#include "util/thread_map.h" 28#include "util/thread_map.h"
@@ -35,55 +36,36 @@ enum write_mode_t {
35 WRITE_APPEND 36 WRITE_APPEND
36}; 37};
37 38
38static u64 user_interval = ULLONG_MAX; 39struct perf_record {
39static u64 default_interval = 0; 40 struct perf_tool tool;
40 41 struct perf_record_opts opts;
41static unsigned int page_size; 42 u64 bytes_written;
42static unsigned int mmap_pages = UINT_MAX; 43 const char *output_name;
43static unsigned int user_freq = UINT_MAX; 44 struct perf_evlist *evlist;
44static int freq = 1000; 45 struct perf_session *session;
45static int output; 46 const char *progname;
46static int pipe_output = 0; 47 int output;
47static const char *output_name = NULL; 48 unsigned int page_size;
48static bool group = false; 49 int realtime_prio;
49static int realtime_prio = 0; 50 enum write_mode_t write_mode;
50static bool nodelay = false; 51 bool no_buildid;
51static bool raw_samples = false; 52 bool no_buildid_cache;
52static bool sample_id_all_avail = true; 53 bool force;
53static bool system_wide = false; 54 bool file_new;
54static pid_t target_pid = -1; 55 bool append_file;
55static pid_t target_tid = -1; 56 long samples;
56static pid_t child_pid = -1; 57 off_t post_processing_offset;
57static bool no_inherit = false; 58};
58static enum write_mode_t write_mode = WRITE_FORCE; 59
59static bool call_graph = false; 60static void advance_output(struct perf_record *rec, size_t size)
60static bool inherit_stat = false;
61static bool no_samples = false;
62static bool sample_address = false;
63static bool sample_time = false;
64static bool no_buildid = false;
65static bool no_buildid_cache = false;
66static struct perf_evlist *evsel_list;
67
68static long samples = 0;
69static u64 bytes_written = 0;
70
71static int file_new = 1;
72static off_t post_processing_offset;
73
74static struct perf_session *session;
75static const char *cpu_list;
76static const char *progname;
77
78static void advance_output(size_t size)
79{ 61{
80 bytes_written += size; 62 rec->bytes_written += size;
81} 63}
82 64
83static void write_output(void *buf, size_t size) 65static void write_output(struct perf_record *rec, void *buf, size_t size)
84{ 66{
85 while (size) { 67 while (size) {
86 int ret = write(output, buf, size); 68 int ret = write(rec->output, buf, size);
87 69
88 if (ret < 0) 70 if (ret < 0)
89 die("failed to write"); 71 die("failed to write");
@@ -91,30 +73,33 @@ static void write_output(void *buf, size_t size)
91 size -= ret; 73 size -= ret;
92 buf += ret; 74 buf += ret;
93 75
94 bytes_written += ret; 76 rec->bytes_written += ret;
95 } 77 }
96} 78}
97 79
98static int process_synthesized_event(union perf_event *event, 80static int process_synthesized_event(struct perf_tool *tool,
81 union perf_event *event,
99 struct perf_sample *sample __used, 82 struct perf_sample *sample __used,
100 struct perf_session *self __used) 83 struct machine *machine __used)
101{ 84{
102 write_output(event, event->header.size); 85 struct perf_record *rec = container_of(tool, struct perf_record, tool);
86 write_output(rec, event, event->header.size);
103 return 0; 87 return 0;
104} 88}
105 89
106static void mmap_read(struct perf_mmap *md) 90static void perf_record__mmap_read(struct perf_record *rec,
91 struct perf_mmap *md)
107{ 92{
108 unsigned int head = perf_mmap__read_head(md); 93 unsigned int head = perf_mmap__read_head(md);
109 unsigned int old = md->prev; 94 unsigned int old = md->prev;
110 unsigned char *data = md->base + page_size; 95 unsigned char *data = md->base + rec->page_size;
111 unsigned long size; 96 unsigned long size;
112 void *buf; 97 void *buf;
113 98
114 if (old == head) 99 if (old == head)
115 return; 100 return;
116 101
117 samples++; 102 rec->samples++;
118 103
119 size = head - old; 104 size = head - old;
120 105
@@ -123,14 +108,14 @@ static void mmap_read(struct perf_mmap *md)
123 size = md->mask + 1 - (old & md->mask); 108 size = md->mask + 1 - (old & md->mask);
124 old += size; 109 old += size;
125 110
126 write_output(buf, size); 111 write_output(rec, buf, size);
127 } 112 }
128 113
129 buf = &data[old & md->mask]; 114 buf = &data[old & md->mask];
130 size = head - old; 115 size = head - old;
131 old += size; 116 old += size;
132 117
133 write_output(buf, size); 118 write_output(rec, buf, size);
134 119
135 md->prev = old; 120 md->prev = old;
136 perf_mmap__write_tail(md, old); 121 perf_mmap__write_tail(md, old);
@@ -149,17 +134,18 @@ static void sig_handler(int sig)
149 signr = sig; 134 signr = sig;
150} 135}
151 136
152static void sig_atexit(void) 137static void perf_record__sig_exit(int exit_status __used, void *arg)
153{ 138{
139 struct perf_record *rec = arg;
154 int status; 140 int status;
155 141
156 if (child_pid > 0) { 142 if (rec->evlist->workload.pid > 0) {
157 if (!child_finished) 143 if (!child_finished)
158 kill(child_pid, SIGTERM); 144 kill(rec->evlist->workload.pid, SIGTERM);
159 145
160 wait(&status); 146 wait(&status);
161 if (WIFSIGNALED(status)) 147 if (WIFSIGNALED(status))
162 psignal(WTERMSIG(status), progname); 148 psignal(WTERMSIG(status), rec->progname);
163 } 149 }
164 150
165 if (signr == -1 || signr == SIGUSR1) 151 if (signr == -1 || signr == SIGUSR1)
@@ -169,78 +155,6 @@ static void sig_atexit(void)
169 kill(getpid(), signr); 155 kill(getpid(), signr);
170} 156}
171 157
172static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
173{
174 struct perf_event_attr *attr = &evsel->attr;
175 int track = !evsel->idx; /* only the first counter needs these */
176
177 attr->disabled = 1;
178 attr->inherit = !no_inherit;
179 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
180 PERF_FORMAT_TOTAL_TIME_RUNNING |
181 PERF_FORMAT_ID;
182
183 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
184
185 if (evlist->nr_entries > 1)
186 attr->sample_type |= PERF_SAMPLE_ID;
187
188 /*
189 * We default some events to a 1 default interval. But keep
190 * it a weak assumption overridable by the user.
191 */
192 if (!attr->sample_period || (user_freq != UINT_MAX &&
193 user_interval != ULLONG_MAX)) {
194 if (freq) {
195 attr->sample_type |= PERF_SAMPLE_PERIOD;
196 attr->freq = 1;
197 attr->sample_freq = freq;
198 } else {
199 attr->sample_period = default_interval;
200 }
201 }
202
203 if (no_samples)
204 attr->sample_freq = 0;
205
206 if (inherit_stat)
207 attr->inherit_stat = 1;
208
209 if (sample_address) {
210 attr->sample_type |= PERF_SAMPLE_ADDR;
211 attr->mmap_data = track;
212 }
213
214 if (call_graph)
215 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
216
217 if (system_wide)
218 attr->sample_type |= PERF_SAMPLE_CPU;
219
220 if (sample_id_all_avail &&
221 (sample_time || system_wide || !no_inherit || cpu_list))
222 attr->sample_type |= PERF_SAMPLE_TIME;
223
224 if (raw_samples) {
225 attr->sample_type |= PERF_SAMPLE_TIME;
226 attr->sample_type |= PERF_SAMPLE_RAW;
227 attr->sample_type |= PERF_SAMPLE_CPU;
228 }
229
230 if (nodelay) {
231 attr->watermark = 0;
232 attr->wakeup_events = 1;
233 }
234
235 attr->mmap = track;
236 attr->comm = track;
237
238 if (target_pid == -1 && target_tid == -1 && !system_wide) {
239 attr->disabled = 1;
240 attr->enable_on_exec = 1;
241 }
242}
243
244static bool perf_evlist__equal(struct perf_evlist *evlist, 158static bool perf_evlist__equal(struct perf_evlist *evlist,
245 struct perf_evlist *other) 159 struct perf_evlist *other)
246{ 160{
@@ -260,15 +174,17 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
260 return true; 174 return true;
261} 175}
262 176
263static void open_counters(struct perf_evlist *evlist) 177static void perf_record__open(struct perf_record *rec)
264{ 178{
265 struct perf_evsel *pos, *first; 179 struct perf_evsel *pos, *first;
266 180 struct perf_evlist *evlist = rec->evlist;
267 if (evlist->cpus->map[0] < 0) 181 struct perf_session *session = rec->session;
268 no_inherit = true; 182 struct perf_record_opts *opts = &rec->opts;
269 183
270 first = list_entry(evlist->entries.next, struct perf_evsel, node); 184 first = list_entry(evlist->entries.next, struct perf_evsel, node);
271 185
186 perf_evlist__config_attrs(evlist, opts);
187
272 list_for_each_entry(pos, &evlist->entries, node) { 188 list_for_each_entry(pos, &evlist->entries, node) {
273 struct perf_event_attr *attr = &pos->attr; 189 struct perf_event_attr *attr = &pos->attr;
274 struct xyarray *group_fd = NULL; 190 struct xyarray *group_fd = NULL;
@@ -286,32 +202,41 @@ static void open_counters(struct perf_evlist *evlist)
286 */ 202 */
287 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 203 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
288 204
289 if (group && pos != first) 205 if (opts->group && pos != first)
290 group_fd = first->fd; 206 group_fd = first->fd;
291 207fallback_missing_features:
292 config_attr(pos, evlist); 208 if (opts->exclude_guest_missing)
209 attr->exclude_guest = attr->exclude_host = 0;
293retry_sample_id: 210retry_sample_id:
294 attr->sample_id_all = sample_id_all_avail ? 1 : 0; 211 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
295try_again: 212try_again:
296 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group, 213 if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
297 group_fd) < 0) { 214 opts->group, group_fd) < 0) {
298 int err = errno; 215 int err = errno;
299 216
300 if (err == EPERM || err == EACCES) { 217 if (err == EPERM || err == EACCES) {
301 ui__error_paranoid(); 218 ui__error_paranoid();
302 exit(EXIT_FAILURE); 219 exit(EXIT_FAILURE);
303 } else if (err == ENODEV && cpu_list) { 220 } else if (err == ENODEV && opts->cpu_list) {
304 die("No such device - did you specify" 221 die("No such device - did you specify"
305 " an out-of-range profile CPU?\n"); 222 " an out-of-range profile CPU?\n");
306 } else if (err == EINVAL && sample_id_all_avail) { 223 } else if (err == EINVAL) {
307 /* 224 if (!opts->exclude_guest_missing &&
308 * Old kernel, no attr->sample_id_type_all field 225 (attr->exclude_guest || attr->exclude_host)) {
309 */ 226 pr_debug("Old kernel, cannot exclude "
310 sample_id_all_avail = false; 227 "guest or host samples.\n");
311 if (!sample_time && !raw_samples && !time_needed) 228 opts->exclude_guest_missing = true;
312 attr->sample_type &= ~PERF_SAMPLE_TIME; 229 goto fallback_missing_features;
313 230 } else if (opts->sample_id_all_avail) {
314 goto retry_sample_id; 231 /*
232 * Old kernel, no attr->sample_id_type_all field
233 */
234 opts->sample_id_all_avail = false;
235 if (!opts->sample_time && !opts->raw_samples && !time_needed)
236 attr->sample_type &= ~PERF_SAMPLE_TIME;
237
238 goto retry_sample_id;
239 }
315 } 240 }
316 241
317 /* 242 /*
@@ -358,10 +283,20 @@ try_again:
358 exit(-1); 283 exit(-1);
359 } 284 }
360 285
361 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) 286 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
287 if (errno == EPERM)
288 die("Permission error mapping pages.\n"
289 "Consider increasing "
290 "/proc/sys/kernel/perf_event_mlock_kb,\n"
291 "or try again with a smaller value of -m/--mmap_pages.\n"
292 "(current value: %d)\n", opts->mmap_pages);
293 else if (!is_power_of_2(opts->mmap_pages))
294 die("--mmap_pages/-m value must be a power of two.");
295
362 die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 296 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
297 }
363 298
364 if (file_new) 299 if (rec->file_new)
365 session->evlist = evlist; 300 session->evlist = evlist;
366 else { 301 else {
367 if (!perf_evlist__equal(session->evlist, evlist)) { 302 if (!perf_evlist__equal(session->evlist, evlist)) {
@@ -373,29 +308,32 @@ try_again:
373 perf_session__update_sample_type(session); 308 perf_session__update_sample_type(session);
374} 309}
375 310
376static int process_buildids(void) 311static int process_buildids(struct perf_record *rec)
377{ 312{
378 u64 size = lseek(output, 0, SEEK_CUR); 313 u64 size = lseek(rec->output, 0, SEEK_CUR);
379 314
380 if (size == 0) 315 if (size == 0)
381 return 0; 316 return 0;
382 317
383 session->fd = output; 318 rec->session->fd = rec->output;
384 return __perf_session__process_events(session, post_processing_offset, 319 return __perf_session__process_events(rec->session, rec->post_processing_offset,
385 size - post_processing_offset, 320 size - rec->post_processing_offset,
386 size, &build_id__mark_dso_hit_ops); 321 size, &build_id__mark_dso_hit_ops);
387} 322}
388 323
389static void atexit_header(void) 324static void perf_record__exit(int status __used, void *arg)
390{ 325{
391 if (!pipe_output) { 326 struct perf_record *rec = arg;
392 session->header.data_size += bytes_written; 327
393 328 if (!rec->opts.pipe_output) {
394 if (!no_buildid) 329 rec->session->header.data_size += rec->bytes_written;
395 process_buildids(); 330
396 perf_session__write_header(session, evsel_list, output, true); 331 if (!rec->no_buildid)
397 perf_session__delete(session); 332 process_buildids(rec);
398 perf_evlist__delete(evsel_list); 333 perf_session__write_header(rec->session, rec->evlist,
334 rec->output, true);
335 perf_session__delete(rec->session);
336 perf_evlist__delete(rec->evlist);
399 symbol__exit(); 337 symbol__exit();
400 } 338 }
401} 339}
@@ -403,7 +341,7 @@ static void atexit_header(void)
403static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 341static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
404{ 342{
405 int err; 343 int err;
406 struct perf_session *psession = data; 344 struct perf_tool *tool = data;
407 345
408 if (machine__is_host(machine)) 346 if (machine__is_host(machine))
409 return; 347 return;
@@ -416,8 +354,8 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
416 *method is used to avoid symbol missing when the first addr is 354 *method is used to avoid symbol missing when the first addr is
417 *in module instead of in guest kernel. 355 *in module instead of in guest kernel.
418 */ 356 */
419 err = perf_event__synthesize_modules(process_synthesized_event, 357 err = perf_event__synthesize_modules(tool, process_synthesized_event,
420 psession, machine); 358 machine);
421 if (err < 0) 359 if (err < 0)
422 pr_err("Couldn't record guest kernel [%d]'s reference" 360 pr_err("Couldn't record guest kernel [%d]'s reference"
423 " relocation symbol.\n", machine->pid); 361 " relocation symbol.\n", machine->pid);
@@ -426,12 +364,11 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
426 * We use _stext for guest kernel because guest kernel's /proc/kallsyms 364 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
427 * have no _text sometimes. 365 * have no _text sometimes.
428 */ 366 */
429 err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 367 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
430 psession, machine, "_text"); 368 machine, "_text");
431 if (err < 0) 369 if (err < 0)
432 err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 370 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
433 psession, machine, 371 machine, "_stext");
434 "_stext");
435 if (err < 0) 372 if (err < 0)
436 pr_err("Couldn't record guest kernel [%d]'s reference" 373 pr_err("Couldn't record guest kernel [%d]'s reference"
437 " relocation symbol.\n", machine->pid); 374 " relocation symbol.\n", machine->pid);
@@ -442,73 +379,71 @@ static struct perf_event_header finished_round_event = {
442 .type = PERF_RECORD_FINISHED_ROUND, 379 .type = PERF_RECORD_FINISHED_ROUND,
443}; 380};
444 381
445static void mmap_read_all(void) 382static void perf_record__mmap_read_all(struct perf_record *rec)
446{ 383{
447 int i; 384 int i;
448 385
449 for (i = 0; i < evsel_list->nr_mmaps; i++) { 386 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
450 if (evsel_list->mmap[i].base) 387 if (rec->evlist->mmap[i].base)
451 mmap_read(&evsel_list->mmap[i]); 388 perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
452 } 389 }
453 390
454 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) 391 if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO))
455 write_output(&finished_round_event, sizeof(finished_round_event)); 392 write_output(rec, &finished_round_event, sizeof(finished_round_event));
456} 393}
457 394
458static int __cmd_record(int argc, const char **argv) 395static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
459{ 396{
460 struct stat st; 397 struct stat st;
461 int flags; 398 int flags;
462 int err; 399 int err, output;
463 unsigned long waking = 0; 400 unsigned long waking = 0;
464 int child_ready_pipe[2], go_pipe[2];
465 const bool forks = argc > 0; 401 const bool forks = argc > 0;
466 char buf;
467 struct machine *machine; 402 struct machine *machine;
403 struct perf_tool *tool = &rec->tool;
404 struct perf_record_opts *opts = &rec->opts;
405 struct perf_evlist *evsel_list = rec->evlist;
406 const char *output_name = rec->output_name;
407 struct perf_session *session;
468 408
469 progname = argv[0]; 409 rec->progname = argv[0];
470 410
471 page_size = sysconf(_SC_PAGE_SIZE); 411 rec->page_size = sysconf(_SC_PAGE_SIZE);
472 412
473 atexit(sig_atexit); 413 on_exit(perf_record__sig_exit, rec);
474 signal(SIGCHLD, sig_handler); 414 signal(SIGCHLD, sig_handler);
475 signal(SIGINT, sig_handler); 415 signal(SIGINT, sig_handler);
476 signal(SIGUSR1, sig_handler); 416 signal(SIGUSR1, sig_handler);
477 417
478 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
479 perror("failed to create pipes");
480 exit(-1);
481 }
482
483 if (!output_name) { 418 if (!output_name) {
484 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 419 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
485 pipe_output = 1; 420 opts->pipe_output = true;
486 else 421 else
487 output_name = "perf.data"; 422 rec->output_name = output_name = "perf.data";
488 } 423 }
489 if (output_name) { 424 if (output_name) {
490 if (!strcmp(output_name, "-")) 425 if (!strcmp(output_name, "-"))
491 pipe_output = 1; 426 opts->pipe_output = true;
492 else if (!stat(output_name, &st) && st.st_size) { 427 else if (!stat(output_name, &st) && st.st_size) {
493 if (write_mode == WRITE_FORCE) { 428 if (rec->write_mode == WRITE_FORCE) {
494 char oldname[PATH_MAX]; 429 char oldname[PATH_MAX];
495 snprintf(oldname, sizeof(oldname), "%s.old", 430 snprintf(oldname, sizeof(oldname), "%s.old",
496 output_name); 431 output_name);
497 unlink(oldname); 432 unlink(oldname);
498 rename(output_name, oldname); 433 rename(output_name, oldname);
499 } 434 }
500 } else if (write_mode == WRITE_APPEND) { 435 } else if (rec->write_mode == WRITE_APPEND) {
501 write_mode = WRITE_FORCE; 436 rec->write_mode = WRITE_FORCE;
502 } 437 }
503 } 438 }
504 439
505 flags = O_CREAT|O_RDWR; 440 flags = O_CREAT|O_RDWR;
506 if (write_mode == WRITE_APPEND) 441 if (rec->write_mode == WRITE_APPEND)
507 file_new = 0; 442 rec->file_new = 0;
508 else 443 else
509 flags |= O_TRUNC; 444 flags |= O_TRUNC;
510 445
511 if (pipe_output) 446 if (opts->pipe_output)
512 output = STDOUT_FILENO; 447 output = STDOUT_FILENO;
513 else 448 else
514 output = open(output_name, flags, S_IRUSR | S_IWUSR); 449 output = open(output_name, flags, S_IRUSR | S_IWUSR);
@@ -517,17 +452,21 @@ static int __cmd_record(int argc, const char **argv)
517 exit(-1); 452 exit(-1);
518 } 453 }
519 454
455 rec->output = output;
456
520 session = perf_session__new(output_name, O_WRONLY, 457 session = perf_session__new(output_name, O_WRONLY,
521 write_mode == WRITE_FORCE, false, NULL); 458 rec->write_mode == WRITE_FORCE, false, NULL);
522 if (session == NULL) { 459 if (session == NULL) {
523 pr_err("Not enough memory for reading perf file header\n"); 460 pr_err("Not enough memory for reading perf file header\n");
524 return -1; 461 return -1;
525 } 462 }
526 463
527 if (!no_buildid) 464 rec->session = session;
465
466 if (!rec->no_buildid)
528 perf_header__set_feat(&session->header, HEADER_BUILD_ID); 467 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
529 468
530 if (!file_new) { 469 if (!rec->file_new) {
531 err = perf_session__read_header(session, output); 470 err = perf_session__read_header(session, output);
532 if (err < 0) 471 if (err < 0)
533 goto out_delete_session; 472 goto out_delete_session;
@@ -549,94 +488,57 @@ static int __cmd_record(int argc, const char **argv)
549 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY); 488 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
550 perf_header__set_feat(&session->header, HEADER_CPUID); 489 perf_header__set_feat(&session->header, HEADER_CPUID);
551 490
552 /* 512 kiB: default amount of unprivileged mlocked memory */
553 if (mmap_pages == UINT_MAX)
554 mmap_pages = (512 * 1024) / page_size;
555
556 if (forks) { 491 if (forks) {
557 child_pid = fork(); 492 err = perf_evlist__prepare_workload(evsel_list, opts, argv);
558 if (child_pid < 0) { 493 if (err < 0) {
559 perror("failed to fork"); 494 pr_err("Couldn't run the workload!\n");
560 exit(-1); 495 goto out_delete_session;
561 }
562
563 if (!child_pid) {
564 if (pipe_output)
565 dup2(2, 1);
566 close(child_ready_pipe[0]);
567 close(go_pipe[1]);
568 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
569
570 /*
571 * Do a dummy execvp to get the PLT entry resolved,
572 * so we avoid the resolver overhead on the real
573 * execvp call.
574 */
575 execvp("", (char **)argv);
576
577 /*
578 * Tell the parent we're ready to go
579 */
580 close(child_ready_pipe[1]);
581
582 /*
583 * Wait until the parent tells us to go.
584 */
585 if (read(go_pipe[0], &buf, 1) == -1)
586 perror("unable to read pipe");
587
588 execvp(argv[0], (char **)argv);
589
590 perror(argv[0]);
591 kill(getppid(), SIGUSR1);
592 exit(-1);
593 }
594
595 if (!system_wide && target_tid == -1 && target_pid == -1)
596 evsel_list->threads->map[0] = child_pid;
597
598 close(child_ready_pipe[1]);
599 close(go_pipe[0]);
600 /*
601 * wait for child to settle
602 */
603 if (read(child_ready_pipe[0], &buf, 1) == -1) {
604 perror("unable to read pipe");
605 exit(-1);
606 } 496 }
607 close(child_ready_pipe[0]);
608 } 497 }
609 498
610 open_counters(evsel_list); 499 perf_record__open(rec);
611 500
612 /* 501 /*
613 * perf_session__delete(session) will be called at atexit_header() 502 * perf_session__delete(session) will be called at perf_record__exit()
614 */ 503 */
615 atexit(atexit_header); 504 on_exit(perf_record__exit, rec);
616 505
617 if (pipe_output) { 506 if (opts->pipe_output) {
618 err = perf_header__write_pipe(output); 507 err = perf_header__write_pipe(output);
619 if (err < 0) 508 if (err < 0)
620 return err; 509 return err;
621 } else if (file_new) { 510 } else if (rec->file_new) {
622 err = perf_session__write_header(session, evsel_list, 511 err = perf_session__write_header(session, evsel_list,
623 output, false); 512 output, false);
624 if (err < 0) 513 if (err < 0)
625 return err; 514 return err;
626 } 515 }
627 516
628 post_processing_offset = lseek(output, 0, SEEK_CUR); 517 if (!rec->no_buildid
518 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
519 pr_err("Couldn't generate buildids. "
520 "Use --no-buildid to profile anyway.\n");
521 return -1;
522 }
629 523
630 if (pipe_output) { 524 rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
631 err = perf_session__synthesize_attrs(session, 525
632 process_synthesized_event); 526 machine = perf_session__find_host_machine(session);
527 if (!machine) {
528 pr_err("Couldn't find native kernel information.\n");
529 return -1;
530 }
531
532 if (opts->pipe_output) {
533 err = perf_event__synthesize_attrs(tool, session,
534 process_synthesized_event);
633 if (err < 0) { 535 if (err < 0) {
634 pr_err("Couldn't synthesize attrs.\n"); 536 pr_err("Couldn't synthesize attrs.\n");
635 return err; 537 return err;
636 } 538 }
637 539
638 err = perf_event__synthesize_event_types(process_synthesized_event, 540 err = perf_event__synthesize_event_types(tool, process_synthesized_event,
639 session); 541 machine);
640 if (err < 0) { 542 if (err < 0) {
641 pr_err("Couldn't synthesize event_types.\n"); 543 pr_err("Couldn't synthesize event_types.\n");
642 return err; 544 return err;
@@ -651,56 +553,49 @@ static int __cmd_record(int argc, const char **argv)
651 * return this more properly and also 553 * return this more properly and also
652 * propagate errors that now are calling die() 554 * propagate errors that now are calling die()
653 */ 555 */
654 err = perf_event__synthesize_tracing_data(output, evsel_list, 556 err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
655 process_synthesized_event, 557 process_synthesized_event);
656 session);
657 if (err <= 0) { 558 if (err <= 0) {
658 pr_err("Couldn't record tracing data.\n"); 559 pr_err("Couldn't record tracing data.\n");
659 return err; 560 return err;
660 } 561 }
661 advance_output(err); 562 advance_output(rec, err);
662 } 563 }
663 } 564 }
664 565
665 machine = perf_session__find_host_machine(session); 566 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
666 if (!machine) { 567 machine, "_text");
667 pr_err("Couldn't find native kernel information.\n");
668 return -1;
669 }
670
671 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
672 session, machine, "_text");
673 if (err < 0) 568 if (err < 0)
674 err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 569 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
675 session, machine, "_stext"); 570 machine, "_stext");
676 if (err < 0) 571 if (err < 0)
677 pr_err("Couldn't record kernel reference relocation symbol\n" 572 pr_err("Couldn't record kernel reference relocation symbol\n"
678 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 573 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
679 "Check /proc/kallsyms permission or run as root.\n"); 574 "Check /proc/kallsyms permission or run as root.\n");
680 575
681 err = perf_event__synthesize_modules(process_synthesized_event, 576 err = perf_event__synthesize_modules(tool, process_synthesized_event,
682 session, machine); 577 machine);
683 if (err < 0) 578 if (err < 0)
684 pr_err("Couldn't record kernel module information.\n" 579 pr_err("Couldn't record kernel module information.\n"
685 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 580 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
686 "Check /proc/modules permission or run as root.\n"); 581 "Check /proc/modules permission or run as root.\n");
687 582
688 if (perf_guest) 583 if (perf_guest)
689 perf_session__process_machines(session, 584 perf_session__process_machines(session, tool,
690 perf_event__synthesize_guest_os); 585 perf_event__synthesize_guest_os);
691 586
692 if (!system_wide) 587 if (!opts->system_wide)
693 perf_event__synthesize_thread_map(evsel_list->threads, 588 perf_event__synthesize_thread_map(tool, evsel_list->threads,
694 process_synthesized_event, 589 process_synthesized_event,
695 session); 590 machine);
696 else 591 else
697 perf_event__synthesize_threads(process_synthesized_event, 592 perf_event__synthesize_threads(tool, process_synthesized_event,
698 session); 593 machine);
699 594
700 if (realtime_prio) { 595 if (rec->realtime_prio) {
701 struct sched_param param; 596 struct sched_param param;
702 597
703 param.sched_priority = realtime_prio; 598 param.sched_priority = rec->realtime_prio;
704 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 599 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
705 pr_err("Could not set realtime priority.\n"); 600 pr_err("Could not set realtime priority.\n");
706 exit(-1); 601 exit(-1);
@@ -713,14 +608,14 @@ static int __cmd_record(int argc, const char **argv)
713 * Let the child rip 608 * Let the child rip
714 */ 609 */
715 if (forks) 610 if (forks)
716 close(go_pipe[1]); 611 perf_evlist__start_workload(evsel_list);
717 612
718 for (;;) { 613 for (;;) {
719 int hits = samples; 614 int hits = rec->samples;
720 615
721 mmap_read_all(); 616 perf_record__mmap_read_all(rec);
722 617
723 if (hits == samples) { 618 if (hits == rec->samples) {
724 if (done) 619 if (done)
725 break; 620 break;
726 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 621 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
@@ -741,9 +636,9 @@ static int __cmd_record(int argc, const char **argv)
741 */ 636 */
742 fprintf(stderr, 637 fprintf(stderr,
743 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 638 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
744 (double)bytes_written / 1024.0 / 1024.0, 639 (double)rec->bytes_written / 1024.0 / 1024.0,
745 output_name, 640 output_name,
746 bytes_written / 24); 641 rec->bytes_written / 24);
747 642
748 return 0; 643 return 0;
749 644
@@ -758,58 +653,89 @@ static const char * const record_usage[] = {
758 NULL 653 NULL
759}; 654};
760 655
761static bool force, append_file; 656/*
657 * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
658 * because we need to have access to it in perf_record__exit, that is called
659 * after cmd_record() exits, but since record_options need to be accessible to
660 * builtin-script, leave it here.
661 *
662 * At least we don't ouch it in all the other functions here directly.
663 *
664 * Just say no to tons of global variables, sigh.
665 */
666static struct perf_record record = {
667 .opts = {
668 .target_pid = -1,
669 .target_tid = -1,
670 .mmap_pages = UINT_MAX,
671 .user_freq = UINT_MAX,
672 .user_interval = ULLONG_MAX,
673 .freq = 1000,
674 .sample_id_all_avail = true,
675 },
676 .write_mode = WRITE_FORCE,
677 .file_new = true,
678};
762 679
680/*
681 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
682 * with it and switch to use the library functions in perf_evlist that came
683 * from builtin-record.c, i.e. use perf_record_opts,
684 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
685 * using pipes, etc.
686 */
763const struct option record_options[] = { 687const struct option record_options[] = {
764 OPT_CALLBACK('e', "event", &evsel_list, "event", 688 OPT_CALLBACK('e', "event", &record.evlist, "event",
765 "event selector. use 'perf list' to list available events", 689 "event selector. use 'perf list' to list available events",
766 parse_events_option), 690 parse_events_option),
767 OPT_CALLBACK(0, "filter", &evsel_list, "filter", 691 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
768 "event filter", parse_filter), 692 "event filter", parse_filter),
769 OPT_INTEGER('p', "pid", &target_pid, 693 OPT_INTEGER('p', "pid", &record.opts.target_pid,
770 "record events on existing process id"), 694 "record events on existing process id"),
771 OPT_INTEGER('t', "tid", &target_tid, 695 OPT_INTEGER('t', "tid", &record.opts.target_tid,
772 "record events on existing thread id"), 696 "record events on existing thread id"),
773 OPT_INTEGER('r', "realtime", &realtime_prio, 697 OPT_INTEGER('r', "realtime", &record.realtime_prio,
774 "collect data with this RT SCHED_FIFO priority"), 698 "collect data with this RT SCHED_FIFO priority"),
775 OPT_BOOLEAN('D', "no-delay", &nodelay, 699 OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
776 "collect data without buffering"), 700 "collect data without buffering"),
777 OPT_BOOLEAN('R', "raw-samples", &raw_samples, 701 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
778 "collect raw sample records from all opened counters"), 702 "collect raw sample records from all opened counters"),
779 OPT_BOOLEAN('a', "all-cpus", &system_wide, 703 OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide,
780 "system-wide collection from all CPUs"), 704 "system-wide collection from all CPUs"),
781 OPT_BOOLEAN('A', "append", &append_file, 705 OPT_BOOLEAN('A', "append", &record.append_file,
782 "append to the output file to do incremental profiling"), 706 "append to the output file to do incremental profiling"),
783 OPT_STRING('C', "cpu", &cpu_list, "cpu", 707 OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu",
784 "list of cpus to monitor"), 708 "list of cpus to monitor"),
785 OPT_BOOLEAN('f', "force", &force, 709 OPT_BOOLEAN('f', "force", &record.force,
786 "overwrite existing data file (deprecated)"), 710 "overwrite existing data file (deprecated)"),
787 OPT_U64('c', "count", &user_interval, "event period to sample"), 711 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
788 OPT_STRING('o', "output", &output_name, "file", 712 OPT_STRING('o', "output", &record.output_name, "file",
789 "output file name"), 713 "output file name"),
790 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 714 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
791 "child tasks do not inherit counters"), 715 "child tasks do not inherit counters"),
792 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), 716 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
793 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 717 OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
794 OPT_BOOLEAN(0, "group", &group, 718 "number of mmap data pages"),
719 OPT_BOOLEAN(0, "group", &record.opts.group,
795 "put the counters into a counter group"), 720 "put the counters into a counter group"),
796 OPT_BOOLEAN('g', "call-graph", &call_graph, 721 OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph,
797 "do call-graph (stack chain/backtrace) recording"), 722 "do call-graph (stack chain/backtrace) recording"),
798 OPT_INCR('v', "verbose", &verbose, 723 OPT_INCR('v', "verbose", &verbose,
799 "be more verbose (show counter open errors, etc)"), 724 "be more verbose (show counter open errors, etc)"),
800 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 725 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
801 OPT_BOOLEAN('s', "stat", &inherit_stat, 726 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
802 "per thread counts"), 727 "per thread counts"),
803 OPT_BOOLEAN('d', "data", &sample_address, 728 OPT_BOOLEAN('d', "data", &record.opts.sample_address,
804 "Sample addresses"), 729 "Sample addresses"),
805 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"), 730 OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
806 OPT_BOOLEAN('n', "no-samples", &no_samples, 731 OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
732 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
807 "don't sample"), 733 "don't sample"),
808 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache, 734 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
809 "do not update the buildid cache"), 735 "do not update the buildid cache"),
810 OPT_BOOLEAN('B', "no-buildid", &no_buildid, 736 OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
811 "do not collect buildids in perf.data"), 737 "do not collect buildids in perf.data"),
812 OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 738 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
813 "monitor event in cgroup name only", 739 "monitor event in cgroup name only",
814 parse_cgroups), 740 parse_cgroups),
815 OPT_END() 741 OPT_END()
@@ -819,6 +745,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
819{ 745{
820 int err = -ENOMEM; 746 int err = -ENOMEM;
821 struct perf_evsel *pos; 747 struct perf_evsel *pos;
748 struct perf_evlist *evsel_list;
749 struct perf_record *rec = &record;
822 750
823 perf_header__set_cmdline(argc, argv); 751 perf_header__set_cmdline(argc, argv);
824 752
@@ -826,23 +754,25 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
826 if (evsel_list == NULL) 754 if (evsel_list == NULL)
827 return -ENOMEM; 755 return -ENOMEM;
828 756
757 rec->evlist = evsel_list;
758
829 argc = parse_options(argc, argv, record_options, record_usage, 759 argc = parse_options(argc, argv, record_options, record_usage,
830 PARSE_OPT_STOP_AT_NON_OPTION); 760 PARSE_OPT_STOP_AT_NON_OPTION);
831 if (!argc && target_pid == -1 && target_tid == -1 && 761 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 &&
832 !system_wide && !cpu_list) 762 !rec->opts.system_wide && !rec->opts.cpu_list)
833 usage_with_options(record_usage, record_options); 763 usage_with_options(record_usage, record_options);
834 764
835 if (force && append_file) { 765 if (rec->force && rec->append_file) {
836 fprintf(stderr, "Can't overwrite and append at the same time." 766 fprintf(stderr, "Can't overwrite and append at the same time."
837 " You need to choose between -f and -A"); 767 " You need to choose between -f and -A");
838 usage_with_options(record_usage, record_options); 768 usage_with_options(record_usage, record_options);
839 } else if (append_file) { 769 } else if (rec->append_file) {
840 write_mode = WRITE_APPEND; 770 rec->write_mode = WRITE_APPEND;
841 } else { 771 } else {
842 write_mode = WRITE_FORCE; 772 rec->write_mode = WRITE_FORCE;
843 } 773 }
844 774
845 if (nr_cgroups && !system_wide) { 775 if (nr_cgroups && !rec->opts.system_wide) {
846 fprintf(stderr, "cgroup monitoring only available in" 776 fprintf(stderr, "cgroup monitoring only available in"
847 " system-wide mode\n"); 777 " system-wide mode\n");
848 usage_with_options(record_usage, record_options); 778 usage_with_options(record_usage, record_options);
@@ -860,7 +790,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
860"If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 790"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
861"even with a suitable vmlinux or kallsyms file.\n\n"); 791"even with a suitable vmlinux or kallsyms file.\n\n");
862 792
863 if (no_buildid_cache || no_buildid) 793 if (rec->no_buildid_cache || rec->no_buildid)
864 disable_buildid_cache(); 794 disable_buildid_cache();
865 795
866 if (evsel_list->nr_entries == 0 && 796 if (evsel_list->nr_entries == 0 &&
@@ -869,43 +799,37 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
869 goto out_symbol_exit; 799 goto out_symbol_exit;
870 } 800 }
871 801
872 if (target_pid != -1) 802 if (rec->opts.target_pid != -1)
873 target_tid = target_pid; 803 rec->opts.target_tid = rec->opts.target_pid;
874 804
875 if (perf_evlist__create_maps(evsel_list, target_pid, 805 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
876 target_tid, cpu_list) < 0) 806 rec->opts.target_tid, rec->opts.cpu_list) < 0)
877 usage_with_options(record_usage, record_options); 807 usage_with_options(record_usage, record_options);
878 808
879 list_for_each_entry(pos, &evsel_list->entries, node) { 809 list_for_each_entry(pos, &evsel_list->entries, node) {
880 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
881 evsel_list->threads->nr) < 0)
882 goto out_free_fd;
883 if (perf_header__push_event(pos->attr.config, event_name(pos))) 810 if (perf_header__push_event(pos->attr.config, event_name(pos)))
884 goto out_free_fd; 811 goto out_free_fd;
885 } 812 }
886 813
887 if (perf_evlist__alloc_pollfd(evsel_list) < 0) 814 if (rec->opts.user_interval != ULLONG_MAX)
888 goto out_free_fd; 815 rec->opts.default_interval = rec->opts.user_interval;
889 816 if (rec->opts.user_freq != UINT_MAX)
890 if (user_interval != ULLONG_MAX) 817 rec->opts.freq = rec->opts.user_freq;
891 default_interval = user_interval;
892 if (user_freq != UINT_MAX)
893 freq = user_freq;
894 818
895 /* 819 /*
896 * User specified count overrides default frequency. 820 * User specified count overrides default frequency.
897 */ 821 */
898 if (default_interval) 822 if (rec->opts.default_interval)
899 freq = 0; 823 rec->opts.freq = 0;
900 else if (freq) { 824 else if (rec->opts.freq) {
901 default_interval = freq; 825 rec->opts.default_interval = rec->opts.freq;
902 } else { 826 } else {
903 fprintf(stderr, "frequency and count are zero, aborting\n"); 827 fprintf(stderr, "frequency and count are zero, aborting\n");
904 err = -EINVAL; 828 err = -EINVAL;
905 goto out_free_fd; 829 goto out_free_fd;
906 } 830 }
907 831
908 err = __cmd_record(argc, argv); 832 err = __cmd_record(&record, argc, argv);
909out_free_fd: 833out_free_fd:
910 perf_evlist__delete_maps(evsel_list); 834 perf_evlist__delete_maps(evsel_list);
911out_symbol_exit: 835out_symbol_exit:
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4d7c8340c326..25d34d483e49 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -25,6 +25,7 @@
25#include "util/evsel.h" 25#include "util/evsel.h"
26#include "util/header.h" 26#include "util/header.h"
27#include "util/session.h" 27#include "util/session.h"
28#include "util/tool.h"
28 29
29#include "util/parse-options.h" 30#include "util/parse-options.h"
30#include "util/parse-events.h" 31#include "util/parse-events.h"
@@ -35,38 +36,35 @@
35 36
36#include <linux/bitmap.h> 37#include <linux/bitmap.h>
37 38
38static char const *input_name = "perf.data"; 39struct perf_report {
39 40 struct perf_tool tool;
40static bool force, use_tui, use_stdio; 41 struct perf_session *session;
41static bool hide_unresolved; 42 char const *input_name;
42static bool dont_use_callchains; 43 bool force, use_tui, use_stdio;
43static bool show_full_info; 44 bool hide_unresolved;
44 45 bool dont_use_callchains;
45static bool show_threads; 46 bool show_full_info;
46static struct perf_read_values show_threads_values; 47 bool show_threads;
47 48 bool inverted_callchain;
48static const char default_pretty_printing_style[] = "normal"; 49 struct perf_read_values show_threads_values;
49static const char *pretty_printing_style = default_pretty_printing_style; 50 const char *pretty_printing_style;
50 51 symbol_filter_t annotate_init;
51static char callchain_default_opt[] = "fractal,0.5,callee"; 52 const char *cpu_list;
52static bool inverted_callchain; 53 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
53static symbol_filter_t annotate_init; 54};
54
55static const char *cpu_list;
56static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
57 55
58static int perf_session__add_hist_entry(struct perf_session *session, 56static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
59 struct addr_location *al, 57 struct addr_location *al,
60 struct perf_sample *sample, 58 struct perf_sample *sample,
61 struct perf_evsel *evsel) 59 struct machine *machine)
62{ 60{
63 struct symbol *parent = NULL; 61 struct symbol *parent = NULL;
64 int err = 0; 62 int err = 0;
65 struct hist_entry *he; 63 struct hist_entry *he;
66 64
67 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { 65 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
68 err = perf_session__resolve_callchain(session, al->thread, 66 err = machine__resolve_callchain(machine, evsel, al->thread,
69 sample->callchain, &parent); 67 sample->callchain, &parent);
70 if (err) 68 if (err)
71 return err; 69 return err;
72 } 70 }
@@ -76,7 +74,8 @@ static int perf_session__add_hist_entry(struct perf_session *session,
76 return -ENOMEM; 74 return -ENOMEM;
77 75
78 if (symbol_conf.use_callchain) { 76 if (symbol_conf.use_callchain) {
79 err = callchain_append(he->callchain, &session->callchain_cursor, 77 err = callchain_append(he->callchain,
78 &evsel->hists.callchain_cursor,
80 sample->period); 79 sample->period);
81 if (err) 80 if (err)
82 return err; 81 return err;
@@ -92,8 +91,7 @@ static int perf_session__add_hist_entry(struct perf_session *session,
92 assert(evsel != NULL); 91 assert(evsel != NULL);
93 92
94 err = -ENOMEM; 93 err = -ENOMEM;
95 if (notes->src == NULL && 94 if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
96 symbol__alloc_hist(he->ms.sym, session->evlist->nr_entries) < 0)
97 goto out; 95 goto out;
98 96
99 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 97 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
@@ -106,30 +104,32 @@ out:
106} 104}
107 105
108 106
109static int process_sample_event(union perf_event *event, 107static int process_sample_event(struct perf_tool *tool,
108 union perf_event *event,
110 struct perf_sample *sample, 109 struct perf_sample *sample,
111 struct perf_evsel *evsel, 110 struct perf_evsel *evsel,
112 struct perf_session *session) 111 struct machine *machine)
113{ 112{
113 struct perf_report *rep = container_of(tool, struct perf_report, tool);
114 struct addr_location al; 114 struct addr_location al;
115 115
116 if (perf_event__preprocess_sample(event, session, &al, sample, 116 if (perf_event__preprocess_sample(event, machine, &al, sample,
117 annotate_init) < 0) { 117 rep->annotate_init) < 0) {
118 fprintf(stderr, "problem processing %d event, skipping it.\n", 118 fprintf(stderr, "problem processing %d event, skipping it.\n",
119 event->header.type); 119 event->header.type);
120 return -1; 120 return -1;
121 } 121 }
122 122
123 if (al.filtered || (hide_unresolved && al.sym == NULL)) 123 if (al.filtered || (rep->hide_unresolved && al.sym == NULL))
124 return 0; 124 return 0;
125 125
126 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 126 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
127 return 0; 127 return 0;
128 128
129 if (al.map != NULL) 129 if (al.map != NULL)
130 al.map->dso->hit = 1; 130 al.map->dso->hit = 1;
131 131
132 if (perf_session__add_hist_entry(session, &al, sample, evsel)) { 132 if (perf_evsel__add_hist_entry(evsel, &al, sample, machine)) {
133 pr_debug("problem incrementing symbol period, skipping event\n"); 133 pr_debug("problem incrementing symbol period, skipping event\n");
134 return -1; 134 return -1;
135 } 135 }
@@ -137,15 +137,17 @@ static int process_sample_event(union perf_event *event,
137 return 0; 137 return 0;
138} 138}
139 139
140static int process_read_event(union perf_event *event, 140static int process_read_event(struct perf_tool *tool,
141 union perf_event *event,
141 struct perf_sample *sample __used, 142 struct perf_sample *sample __used,
142 struct perf_session *session) 143 struct perf_evsel *evsel,
144 struct machine *machine __used)
143{ 145{
144 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, 146 struct perf_report *rep = container_of(tool, struct perf_report, tool);
145 event->read.id); 147
146 if (show_threads) { 148 if (rep->show_threads) {
147 const char *name = evsel ? event_name(evsel) : "unknown"; 149 const char *name = evsel ? event_name(evsel) : "unknown";
148 perf_read_values_add_value(&show_threads_values, 150 perf_read_values_add_value(&rep->show_threads_values,
149 event->read.pid, event->read.tid, 151 event->read.pid, event->read.tid,
150 event->read.id, 152 event->read.id,
151 name, 153 name,
@@ -159,8 +161,10 @@ static int process_read_event(union perf_event *event,
159 return 0; 161 return 0;
160} 162}
161 163
162static int perf_session__setup_sample_type(struct perf_session *self) 164static int perf_report__setup_sample_type(struct perf_report *rep)
163{ 165{
166 struct perf_session *self = rep->session;
167
164 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { 168 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
165 if (sort__has_parent) { 169 if (sort__has_parent) {
166 ui__warning("Selected --sort parent, but no " 170 ui__warning("Selected --sort parent, but no "
@@ -173,7 +177,8 @@ static int perf_session__setup_sample_type(struct perf_session *self)
173 "you call 'perf record' without -g?\n"); 177 "you call 'perf record' without -g?\n");
174 return -1; 178 return -1;
175 } 179 }
176 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE && 180 } else if (!rep->dont_use_callchains &&
181 callchain_param.mode != CHAIN_NONE &&
177 !symbol_conf.use_callchain) { 182 !symbol_conf.use_callchain) {
178 symbol_conf.use_callchain = true; 183 symbol_conf.use_callchain = true;
179 if (callchain_register_param(&callchain_param) < 0) { 184 if (callchain_register_param(&callchain_param) < 0) {
@@ -186,22 +191,6 @@ static int perf_session__setup_sample_type(struct perf_session *self)
186 return 0; 191 return 0;
187} 192}
188 193
189static struct perf_event_ops event_ops = {
190 .sample = process_sample_event,
191 .mmap = perf_event__process_mmap,
192 .comm = perf_event__process_comm,
193 .exit = perf_event__process_task,
194 .fork = perf_event__process_task,
195 .lost = perf_event__process_lost,
196 .read = process_read_event,
197 .attr = perf_event__process_attr,
198 .event_type = perf_event__process_event_type,
199 .tracing_data = perf_event__process_tracing_data,
200 .build_id = perf_event__process_build_id,
201 .ordered_samples = true,
202 .ordering_requires_timestamps = true,
203};
204
205extern volatile int session_done; 194extern volatile int session_done;
206 195
207static void sig_handler(int sig __used) 196static void sig_handler(int sig __used)
@@ -224,6 +213,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
224} 213}
225 214
226static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, 215static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
216 struct perf_report *rep,
227 const char *help) 217 const char *help)
228{ 218{
229 struct perf_evsel *pos; 219 struct perf_evsel *pos;
@@ -241,18 +231,18 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
241 parent_pattern == default_parent_pattern) { 231 parent_pattern == default_parent_pattern) {
242 fprintf(stdout, "#\n# (%s)\n#\n", help); 232 fprintf(stdout, "#\n# (%s)\n#\n", help);
243 233
244 if (show_threads) { 234 if (rep->show_threads) {
245 bool style = !strcmp(pretty_printing_style, "raw"); 235 bool style = !strcmp(rep->pretty_printing_style, "raw");
246 perf_read_values_display(stdout, &show_threads_values, 236 perf_read_values_display(stdout, &rep->show_threads_values,
247 style); 237 style);
248 perf_read_values_destroy(&show_threads_values); 238 perf_read_values_destroy(&rep->show_threads_values);
249 } 239 }
250 } 240 }
251 241
252 return 0; 242 return 0;
253} 243}
254 244
255static int __cmd_report(void) 245static int __cmd_report(struct perf_report *rep)
256{ 246{
257 int ret = -EINVAL; 247 int ret = -EINVAL;
258 u64 nr_samples; 248 u64 nr_samples;
@@ -264,27 +254,31 @@ static int __cmd_report(void)
264 254
265 signal(SIGINT, sig_handler); 255 signal(SIGINT, sig_handler);
266 256
267 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops); 257 session = perf_session__new(rep->input_name, O_RDONLY,
258 rep->force, false, &rep->tool);
268 if (session == NULL) 259 if (session == NULL)
269 return -ENOMEM; 260 return -ENOMEM;
270 261
271 if (cpu_list) { 262 rep->session = session;
272 ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); 263
264 if (rep->cpu_list) {
265 ret = perf_session__cpu_bitmap(session, rep->cpu_list,
266 rep->cpu_bitmap);
273 if (ret) 267 if (ret)
274 goto out_delete; 268 goto out_delete;
275 } 269 }
276 270
277 if (use_browser <= 0) 271 if (use_browser <= 0)
278 perf_session__fprintf_info(session, stdout, show_full_info); 272 perf_session__fprintf_info(session, stdout, rep->show_full_info);
279 273
280 if (show_threads) 274 if (rep->show_threads)
281 perf_read_values_init(&show_threads_values); 275 perf_read_values_init(&rep->show_threads_values);
282 276
283 ret = perf_session__setup_sample_type(session); 277 ret = perf_report__setup_sample_type(rep);
284 if (ret) 278 if (ret)
285 goto out_delete; 279 goto out_delete;
286 280
287 ret = perf_session__process_events(session, &event_ops); 281 ret = perf_session__process_events(session, &rep->tool);
288 if (ret) 282 if (ret)
289 goto out_delete; 283 goto out_delete;
290 284
@@ -327,7 +321,7 @@ static int __cmd_report(void)
327 } 321 }
328 322
329 if (nr_samples == 0) { 323 if (nr_samples == 0) {
330 ui__warning("The %s file has no samples!\n", input_name); 324 ui__warning("The %s file has no samples!\n", session->filename);
331 goto out_delete; 325 goto out_delete;
332 } 326 }
333 327
@@ -335,7 +329,7 @@ static int __cmd_report(void)
335 perf_evlist__tui_browse_hists(session->evlist, help, 329 perf_evlist__tui_browse_hists(session->evlist, help,
336 NULL, NULL, 0); 330 NULL, NULL, 0);
337 } else 331 } else
338 perf_evlist__tty_browse_hists(session->evlist, help); 332 perf_evlist__tty_browse_hists(session->evlist, rep, help);
339 333
340out_delete: 334out_delete:
341 /* 335 /*
@@ -354,9 +348,9 @@ out_delete:
354} 348}
355 349
356static int 350static int
357parse_callchain_opt(const struct option *opt __used, const char *arg, 351parse_callchain_opt(const struct option *opt, const char *arg, int unset)
358 int unset)
359{ 352{
353 struct perf_report *rep = (struct perf_report *)opt->value;
360 char *tok, *tok2; 354 char *tok, *tok2;
361 char *endptr; 355 char *endptr;
362 356
@@ -364,7 +358,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
364 * --no-call-graph 358 * --no-call-graph
365 */ 359 */
366 if (unset) { 360 if (unset) {
367 dont_use_callchains = true; 361 rep->dont_use_callchains = true;
368 return 0; 362 return 0;
369 } 363 }
370 364
@@ -412,7 +406,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
412 goto setup; 406 goto setup;
413 407
414 if (tok2[0] != 'c') { 408 if (tok2[0] != 'c') {
415 callchain_param.print_limit = strtod(tok2, &endptr); 409 callchain_param.print_limit = strtoul(tok2, &endptr, 0);
416 tok2 = strtok(NULL, ","); 410 tok2 = strtok(NULL, ",");
417 if (!tok2) 411 if (!tok2)
418 goto setup; 412 goto setup;
@@ -433,13 +427,34 @@ setup:
433 return 0; 427 return 0;
434} 428}
435 429
436static const char * const report_usage[] = { 430int cmd_report(int argc, const char **argv, const char *prefix __used)
437 "perf report [<options>] <command>", 431{
438 NULL 432 struct stat st;
439}; 433 char callchain_default_opt[] = "fractal,0.5,callee";
440 434 const char * const report_usage[] = {
441static const struct option options[] = { 435 "perf report [<options>]",
442 OPT_STRING('i', "input", &input_name, "file", 436 NULL
437 };
438 struct perf_report report = {
439 .tool = {
440 .sample = process_sample_event,
441 .mmap = perf_event__process_mmap,
442 .comm = perf_event__process_comm,
443 .exit = perf_event__process_task,
444 .fork = perf_event__process_task,
445 .lost = perf_event__process_lost,
446 .read = process_read_event,
447 .attr = perf_event__process_attr,
448 .event_type = perf_event__process_event_type,
449 .tracing_data = perf_event__process_tracing_data,
450 .build_id = perf_event__process_build_id,
451 .ordered_samples = true,
452 .ordering_requires_timestamps = true,
453 },
454 .pretty_printing_style = "normal",
455 };
456 const struct option options[] = {
457 OPT_STRING('i', "input", &report.input_name, "file",
443 "input file name"), 458 "input file name"),
444 OPT_INCR('v', "verbose", &verbose, 459 OPT_INCR('v', "verbose", &verbose,
445 "be more verbose (show symbol address, etc)"), 460 "be more verbose (show symbol address, etc)"),
@@ -449,17 +464,18 @@ static const struct option options[] = {
449 "file", "vmlinux pathname"), 464 "file", "vmlinux pathname"),
450 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 465 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
451 "file", "kallsyms pathname"), 466 "file", "kallsyms pathname"),
452 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 467 OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"),
453 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 468 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
454 "load module symbols - WARNING: use only with -k and LIVE kernel"), 469 "load module symbols - WARNING: use only with -k and LIVE kernel"),
455 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 470 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
456 "Show a column with the number of samples"), 471 "Show a column with the number of samples"),
457 OPT_BOOLEAN('T', "threads", &show_threads, 472 OPT_BOOLEAN('T', "threads", &report.show_threads,
458 "Show per-thread event counters"), 473 "Show per-thread event counters"),
459 OPT_STRING(0, "pretty", &pretty_printing_style, "key", 474 OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
460 "pretty printing style key: normal raw"), 475 "pretty printing style key: normal raw"),
461 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), 476 OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
462 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 477 OPT_BOOLEAN(0, "stdio", &report.use_stdio,
478 "Use the stdio interface"),
463 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 479 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
464 "sort by key(s): pid, comm, dso, symbol, parent"), 480 "sort by key(s): pid, comm, dso, symbol, parent"),
465 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 481 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
@@ -468,13 +484,14 @@ static const struct option options[] = {
468 "regex filter to identify parent, see: '--sort parent'"), 484 "regex filter to identify parent, see: '--sort parent'"),
469 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 485 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
470 "Only display entries with parent-match"), 486 "Only display entries with parent-match"),
471 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order", 487 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
472 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. " 488 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit and callchain order. "
473 "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt), 489 "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
474 OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"), 490 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
491 "alias for inverted call graph"),
475 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 492 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
476 "only consider symbols in these dsos"), 493 "only consider symbols in these dsos"),
477 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 494 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
478 "only consider symbols in these comms"), 495 "only consider symbols in these comms"),
479 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 496 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
480 "only consider these symbols"), 497 "only consider these symbols"),
@@ -484,12 +501,13 @@ static const struct option options[] = {
484 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 501 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
485 "separator for columns, no spaces will be added between " 502 "separator for columns, no spaces will be added between "
486 "columns '.' is reserved."), 503 "columns '.' is reserved."),
487 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved, 504 OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
488 "Only display entries resolved to a symbol"), 505 "Only display entries resolved to a symbol"),
489 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 506 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
490 "Look for files with symbols relative to this directory"), 507 "Look for files with symbols relative to this directory"),
491 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 508 OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
492 OPT_BOOLEAN('I', "show-info", &show_full_info, 509 "list of cpus to profile"),
510 OPT_BOOLEAN('I', "show-info", &report.show_full_info,
493 "Display extended information about perf.data file"), 511 "Display extended information about perf.data file"),
494 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 512 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
495 "Interleave source code with assembly code (default)"), 513 "Interleave source code with assembly code (default)"),
@@ -500,24 +518,30 @@ static const struct option options[] = {
500 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 518 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
501 "Show a column with the sum of periods"), 519 "Show a column with the sum of periods"),
502 OPT_END() 520 OPT_END()
503}; 521 };
504 522
505int cmd_report(int argc, const char **argv, const char *prefix __used)
506{
507 argc = parse_options(argc, argv, options, report_usage, 0); 523 argc = parse_options(argc, argv, options, report_usage, 0);
508 524
509 if (use_stdio) 525 if (report.use_stdio)
510 use_browser = 0; 526 use_browser = 0;
511 else if (use_tui) 527 else if (report.use_tui)
512 use_browser = 1; 528 use_browser = 1;
513 529
514 if (inverted_callchain) 530 if (report.inverted_callchain)
515 callchain_param.order = ORDER_CALLER; 531 callchain_param.order = ORDER_CALLER;
516 532
517 if (strcmp(input_name, "-") != 0) 533 if (!report.input_name || !strlen(report.input_name)) {
534 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
535 report.input_name = "-";
536 else
537 report.input_name = "perf.data";
538 }
539
540 if (strcmp(report.input_name, "-") != 0)
518 setup_browser(true); 541 setup_browser(true);
519 else 542 else
520 use_browser = 0; 543 use_browser = 0;
544
521 /* 545 /*
522 * Only in the newt browser we are doing integrated annotation, 546 * Only in the newt browser we are doing integrated annotation,
523 * so don't allocate extra space that won't be used in the stdio 547 * so don't allocate extra space that won't be used in the stdio
@@ -525,7 +549,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
525 */ 549 */
526 if (use_browser > 0) { 550 if (use_browser > 0) {
527 symbol_conf.priv_size = sizeof(struct annotation); 551 symbol_conf.priv_size = sizeof(struct annotation);
528 annotate_init = symbol__annotate_init; 552 report.annotate_init = symbol__annotate_init;
529 /* 553 /*
530 * For searching by name on the "Browse map details". 554 * For searching by name on the "Browse map details".
531 * providing it only in verbose mode not to bloat too 555 * providing it only in verbose mode not to bloat too
@@ -572,5 +596,5 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
572 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout); 596 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
573 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout); 597 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
574 598
575 return __cmd_report(); 599 return __cmd_report(&report);
576} 600}
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 5177964943e7..fb8b5f83b4a0 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -2,11 +2,14 @@
2#include "perf.h" 2#include "perf.h"
3 3
4#include "util/util.h" 4#include "util/util.h"
5#include "util/evlist.h"
5#include "util/cache.h" 6#include "util/cache.h"
7#include "util/evsel.h"
6#include "util/symbol.h" 8#include "util/symbol.h"
7#include "util/thread.h" 9#include "util/thread.h"
8#include "util/header.h" 10#include "util/header.h"
9#include "util/session.h" 11#include "util/session.h"
12#include "util/tool.h"
10 13
11#include "util/parse-options.h" 14#include "util/parse-options.h"
12#include "util/trace-event.h" 15#include "util/trace-event.h"
@@ -19,7 +22,7 @@
19#include <pthread.h> 22#include <pthread.h>
20#include <math.h> 23#include <math.h>
21 24
22static char const *input_name = "perf.data"; 25static const char *input_name;
23 26
24static char default_sort_order[] = "avg, max, switch, runtime"; 27static char default_sort_order[] = "avg, max, switch, runtime";
25static const char *sort_order = default_sort_order; 28static const char *sort_order = default_sort_order;
@@ -723,21 +726,21 @@ struct trace_migrate_task_event {
723 726
724struct trace_sched_handler { 727struct trace_sched_handler {
725 void (*switch_event)(struct trace_switch_event *, 728 void (*switch_event)(struct trace_switch_event *,
726 struct perf_session *, 729 struct machine *,
727 struct event *, 730 struct event *,
728 int cpu, 731 int cpu,
729 u64 timestamp, 732 u64 timestamp,
730 struct thread *thread); 733 struct thread *thread);
731 734
732 void (*runtime_event)(struct trace_runtime_event *, 735 void (*runtime_event)(struct trace_runtime_event *,
733 struct perf_session *, 736 struct machine *,
734 struct event *, 737 struct event *,
735 int cpu, 738 int cpu,
736 u64 timestamp, 739 u64 timestamp,
737 struct thread *thread); 740 struct thread *thread);
738 741
739 void (*wakeup_event)(struct trace_wakeup_event *, 742 void (*wakeup_event)(struct trace_wakeup_event *,
740 struct perf_session *, 743 struct machine *,
741 struct event *, 744 struct event *,
742 int cpu, 745 int cpu,
743 u64 timestamp, 746 u64 timestamp,
@@ -750,7 +753,7 @@ struct trace_sched_handler {
750 struct thread *thread); 753 struct thread *thread);
751 754
752 void (*migrate_task_event)(struct trace_migrate_task_event *, 755 void (*migrate_task_event)(struct trace_migrate_task_event *,
753 struct perf_session *session, 756 struct machine *machine,
754 struct event *, 757 struct event *,
755 int cpu, 758 int cpu,
756 u64 timestamp, 759 u64 timestamp,
@@ -760,7 +763,7 @@ struct trace_sched_handler {
760 763
761static void 764static void
762replay_wakeup_event(struct trace_wakeup_event *wakeup_event, 765replay_wakeup_event(struct trace_wakeup_event *wakeup_event,
763 struct perf_session *session __used, 766 struct machine *machine __used,
764 struct event *event, 767 struct event *event,
765 int cpu __used, 768 int cpu __used,
766 u64 timestamp __used, 769 u64 timestamp __used,
@@ -787,7 +790,7 @@ static u64 cpu_last_switched[MAX_CPUS];
787 790
788static void 791static void
789replay_switch_event(struct trace_switch_event *switch_event, 792replay_switch_event(struct trace_switch_event *switch_event,
790 struct perf_session *session __used, 793 struct machine *machine __used,
791 struct event *event, 794 struct event *event,
792 int cpu, 795 int cpu,
793 u64 timestamp, 796 u64 timestamp,
@@ -1021,7 +1024,7 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
1021 1024
1022static void 1025static void
1023latency_switch_event(struct trace_switch_event *switch_event, 1026latency_switch_event(struct trace_switch_event *switch_event,
1024 struct perf_session *session, 1027 struct machine *machine,
1025 struct event *event __used, 1028 struct event *event __used,
1026 int cpu, 1029 int cpu,
1027 u64 timestamp, 1030 u64 timestamp,
@@ -1045,8 +1048,8 @@ latency_switch_event(struct trace_switch_event *switch_event,
1045 die("hm, delta: %" PRIu64 " < 0 ?\n", delta); 1048 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
1046 1049
1047 1050
1048 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1051 sched_out = machine__findnew_thread(machine, switch_event->prev_pid);
1049 sched_in = perf_session__findnew(session, switch_event->next_pid); 1052 sched_in = machine__findnew_thread(machine, switch_event->next_pid);
1050 1053
1051 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); 1054 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid);
1052 if (!out_events) { 1055 if (!out_events) {
@@ -1074,13 +1077,13 @@ latency_switch_event(struct trace_switch_event *switch_event,
1074 1077
1075static void 1078static void
1076latency_runtime_event(struct trace_runtime_event *runtime_event, 1079latency_runtime_event(struct trace_runtime_event *runtime_event,
1077 struct perf_session *session, 1080 struct machine *machine,
1078 struct event *event __used, 1081 struct event *event __used,
1079 int cpu, 1082 int cpu,
1080 u64 timestamp, 1083 u64 timestamp,
1081 struct thread *this_thread __used) 1084 struct thread *this_thread __used)
1082{ 1085{
1083 struct thread *thread = perf_session__findnew(session, runtime_event->pid); 1086 struct thread *thread = machine__findnew_thread(machine, runtime_event->pid);
1084 struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); 1087 struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
1085 1088
1086 BUG_ON(cpu >= MAX_CPUS || cpu < 0); 1089 BUG_ON(cpu >= MAX_CPUS || cpu < 0);
@@ -1097,7 +1100,7 @@ latency_runtime_event(struct trace_runtime_event *runtime_event,
1097 1100
1098static void 1101static void
1099latency_wakeup_event(struct trace_wakeup_event *wakeup_event, 1102latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1100 struct perf_session *session, 1103 struct machine *machine,
1101 struct event *__event __used, 1104 struct event *__event __used,
1102 int cpu __used, 1105 int cpu __used,
1103 u64 timestamp, 1106 u64 timestamp,
@@ -1111,7 +1114,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1111 if (!wakeup_event->success) 1114 if (!wakeup_event->success)
1112 return; 1115 return;
1113 1116
1114 wakee = perf_session__findnew(session, wakeup_event->pid); 1117 wakee = machine__findnew_thread(machine, wakeup_event->pid);
1115 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); 1118 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid);
1116 if (!atoms) { 1119 if (!atoms) {
1117 thread_atoms_insert(wakee); 1120 thread_atoms_insert(wakee);
@@ -1145,7 +1148,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1145 1148
1146static void 1149static void
1147latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event, 1150latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
1148 struct perf_session *session, 1151 struct machine *machine,
1149 struct event *__event __used, 1152 struct event *__event __used,
1150 int cpu __used, 1153 int cpu __used,
1151 u64 timestamp, 1154 u64 timestamp,
@@ -1161,7 +1164,7 @@ latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
1161 if (profile_cpu == -1) 1164 if (profile_cpu == -1)
1162 return; 1165 return;
1163 1166
1164 migrant = perf_session__findnew(session, migrate_task_event->pid); 1167 migrant = machine__findnew_thread(machine, migrate_task_event->pid);
1165 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); 1168 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
1166 if (!atoms) { 1169 if (!atoms) {
1167 thread_atoms_insert(migrant); 1170 thread_atoms_insert(migrant);
@@ -1356,12 +1359,13 @@ static void sort_lat(void)
1356static struct trace_sched_handler *trace_handler; 1359static struct trace_sched_handler *trace_handler;
1357 1360
1358static void 1361static void
1359process_sched_wakeup_event(void *data, struct perf_session *session, 1362process_sched_wakeup_event(struct perf_tool *tool __used,
1360 struct event *event, 1363 struct event *event,
1361 int cpu __used, 1364 struct perf_sample *sample,
1362 u64 timestamp __used, 1365 struct machine *machine,
1363 struct thread *thread __used) 1366 struct thread *thread)
1364{ 1367{
1368 void *data = sample->raw_data;
1365 struct trace_wakeup_event wakeup_event; 1369 struct trace_wakeup_event wakeup_event;
1366 1370
1367 FILL_COMMON_FIELDS(wakeup_event, event, data); 1371 FILL_COMMON_FIELDS(wakeup_event, event, data);
@@ -1373,8 +1377,8 @@ process_sched_wakeup_event(void *data, struct perf_session *session,
1373 FILL_FIELD(wakeup_event, cpu, event, data); 1377 FILL_FIELD(wakeup_event, cpu, event, data);
1374 1378
1375 if (trace_handler->wakeup_event) 1379 if (trace_handler->wakeup_event)
1376 trace_handler->wakeup_event(&wakeup_event, session, event, 1380 trace_handler->wakeup_event(&wakeup_event, machine, event,
1377 cpu, timestamp, thread); 1381 sample->cpu, sample->time, thread);
1378} 1382}
1379 1383
1380/* 1384/*
@@ -1392,7 +1396,7 @@ static char next_shortname2 = '0';
1392 1396
1393static void 1397static void
1394map_switch_event(struct trace_switch_event *switch_event, 1398map_switch_event(struct trace_switch_event *switch_event,
1395 struct perf_session *session, 1399 struct machine *machine,
1396 struct event *event __used, 1400 struct event *event __used,
1397 int this_cpu, 1401 int this_cpu,
1398 u64 timestamp, 1402 u64 timestamp,
@@ -1420,8 +1424,8 @@ map_switch_event(struct trace_switch_event *switch_event,
1420 die("hm, delta: %" PRIu64 " < 0 ?\n", delta); 1424 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
1421 1425
1422 1426
1423 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1427 sched_out = machine__findnew_thread(machine, switch_event->prev_pid);
1424 sched_in = perf_session__findnew(session, switch_event->next_pid); 1428 sched_in = machine__findnew_thread(machine, switch_event->next_pid);
1425 1429
1426 curr_thread[this_cpu] = sched_in; 1430 curr_thread[this_cpu] = sched_in;
1427 1431
@@ -1469,14 +1473,15 @@ map_switch_event(struct trace_switch_event *switch_event,
1469 } 1473 }
1470} 1474}
1471 1475
1472
1473static void 1476static void
1474process_sched_switch_event(void *data, struct perf_session *session, 1477process_sched_switch_event(struct perf_tool *tool __used,
1475 struct event *event, 1478 struct event *event,
1476 int this_cpu, 1479 struct perf_sample *sample,
1477 u64 timestamp __used, 1480 struct machine *machine,
1478 struct thread *thread __used) 1481 struct thread *thread)
1479{ 1482{
1483 int this_cpu = sample->cpu;
1484 void *data = sample->raw_data;
1480 struct trace_switch_event switch_event; 1485 struct trace_switch_event switch_event;
1481 1486
1482 FILL_COMMON_FIELDS(switch_event, event, data); 1487 FILL_COMMON_FIELDS(switch_event, event, data);
@@ -1498,19 +1503,20 @@ process_sched_switch_event(void *data, struct perf_session *session,
1498 nr_context_switch_bugs++; 1503 nr_context_switch_bugs++;
1499 } 1504 }
1500 if (trace_handler->switch_event) 1505 if (trace_handler->switch_event)
1501 trace_handler->switch_event(&switch_event, session, event, 1506 trace_handler->switch_event(&switch_event, machine, event,
1502 this_cpu, timestamp, thread); 1507 this_cpu, sample->time, thread);
1503 1508
1504 curr_pid[this_cpu] = switch_event.next_pid; 1509 curr_pid[this_cpu] = switch_event.next_pid;
1505} 1510}
1506 1511
1507static void 1512static void
1508process_sched_runtime_event(void *data, struct perf_session *session, 1513process_sched_runtime_event(struct perf_tool *tool __used,
1509 struct event *event, 1514 struct event *event,
1510 int cpu __used, 1515 struct perf_sample *sample,
1511 u64 timestamp __used, 1516 struct machine *machine,
1512 struct thread *thread __used) 1517 struct thread *thread)
1513{ 1518{
1519 void *data = sample->raw_data;
1514 struct trace_runtime_event runtime_event; 1520 struct trace_runtime_event runtime_event;
1515 1521
1516 FILL_ARRAY(runtime_event, comm, event, data); 1522 FILL_ARRAY(runtime_event, comm, event, data);
@@ -1519,16 +1525,18 @@ process_sched_runtime_event(void *data, struct perf_session *session,
1519 FILL_FIELD(runtime_event, vruntime, event, data); 1525 FILL_FIELD(runtime_event, vruntime, event, data);
1520 1526
1521 if (trace_handler->runtime_event) 1527 if (trace_handler->runtime_event)
1522 trace_handler->runtime_event(&runtime_event, session, event, cpu, timestamp, thread); 1528 trace_handler->runtime_event(&runtime_event, machine, event,
1529 sample->cpu, sample->time, thread);
1523} 1530}
1524 1531
1525static void 1532static void
1526process_sched_fork_event(void *data, 1533process_sched_fork_event(struct perf_tool *tool __used,
1527 struct event *event, 1534 struct event *event,
1528 int cpu __used, 1535 struct perf_sample *sample,
1529 u64 timestamp __used, 1536 struct machine *machine __used,
1530 struct thread *thread __used) 1537 struct thread *thread)
1531{ 1538{
1539 void *data = sample->raw_data;
1532 struct trace_fork_event fork_event; 1540 struct trace_fork_event fork_event;
1533 1541
1534 FILL_COMMON_FIELDS(fork_event, event, data); 1542 FILL_COMMON_FIELDS(fork_event, event, data);
@@ -1540,13 +1548,14 @@ process_sched_fork_event(void *data,
1540 1548
1541 if (trace_handler->fork_event) 1549 if (trace_handler->fork_event)
1542 trace_handler->fork_event(&fork_event, event, 1550 trace_handler->fork_event(&fork_event, event,
1543 cpu, timestamp, thread); 1551 sample->cpu, sample->time, thread);
1544} 1552}
1545 1553
1546static void 1554static void
1547process_sched_exit_event(struct event *event, 1555process_sched_exit_event(struct perf_tool *tool __used,
1548 int cpu __used, 1556 struct event *event,
1549 u64 timestamp __used, 1557 struct perf_sample *sample __used,
1558 struct machine *machine __used,
1550 struct thread *thread __used) 1559 struct thread *thread __used)
1551{ 1560{
1552 if (verbose) 1561 if (verbose)
@@ -1554,12 +1563,13 @@ process_sched_exit_event(struct event *event,
1554} 1563}
1555 1564
1556static void 1565static void
1557process_sched_migrate_task_event(void *data, struct perf_session *session, 1566process_sched_migrate_task_event(struct perf_tool *tool __used,
1558 struct event *event, 1567 struct event *event,
1559 int cpu __used, 1568 struct perf_sample *sample,
1560 u64 timestamp __used, 1569 struct machine *machine,
1561 struct thread *thread __used) 1570 struct thread *thread)
1562{ 1571{
1572 void *data = sample->raw_data;
1563 struct trace_migrate_task_event migrate_task_event; 1573 struct trace_migrate_task_event migrate_task_event;
1564 1574
1565 FILL_COMMON_FIELDS(migrate_task_event, event, data); 1575 FILL_COMMON_FIELDS(migrate_task_event, event, data);
@@ -1570,67 +1580,47 @@ process_sched_migrate_task_event(void *data, struct perf_session *session,
1570 FILL_FIELD(migrate_task_event, cpu, event, data); 1580 FILL_FIELD(migrate_task_event, cpu, event, data);
1571 1581
1572 if (trace_handler->migrate_task_event) 1582 if (trace_handler->migrate_task_event)
1573 trace_handler->migrate_task_event(&migrate_task_event, session, 1583 trace_handler->migrate_task_event(&migrate_task_event, machine,
1574 event, cpu, timestamp, thread); 1584 event, sample->cpu,
1585 sample->time, thread);
1575} 1586}
1576 1587
1577static void process_raw_event(union perf_event *raw_event __used, 1588typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event *event,
1578 struct perf_session *session, void *data, int cpu, 1589 struct perf_sample *sample,
1579 u64 timestamp, struct thread *thread) 1590 struct machine *machine,
1580{ 1591 struct thread *thread);
1581 struct event *event;
1582 int type;
1583
1584
1585 type = trace_parse_common_type(data);
1586 event = trace_find_event(type);
1587
1588 if (!strcmp(event->name, "sched_switch"))
1589 process_sched_switch_event(data, session, event, cpu, timestamp, thread);
1590 if (!strcmp(event->name, "sched_stat_runtime"))
1591 process_sched_runtime_event(data, session, event, cpu, timestamp, thread);
1592 if (!strcmp(event->name, "sched_wakeup"))
1593 process_sched_wakeup_event(data, session, event, cpu, timestamp, thread);
1594 if (!strcmp(event->name, "sched_wakeup_new"))
1595 process_sched_wakeup_event(data, session, event, cpu, timestamp, thread);
1596 if (!strcmp(event->name, "sched_process_fork"))
1597 process_sched_fork_event(data, event, cpu, timestamp, thread);
1598 if (!strcmp(event->name, "sched_process_exit"))
1599 process_sched_exit_event(event, cpu, timestamp, thread);
1600 if (!strcmp(event->name, "sched_migrate_task"))
1601 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
1602}
1603 1592
1604static int process_sample_event(union perf_event *event, 1593static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
1605 struct perf_sample *sample, 1594 union perf_event *event __used,
1606 struct perf_evsel *evsel __used, 1595 struct perf_sample *sample,
1607 struct perf_session *session) 1596 struct perf_evsel *evsel,
1597 struct machine *machine)
1608{ 1598{
1609 struct thread *thread; 1599 struct thread *thread = machine__findnew_thread(machine, sample->pid);
1610
1611 if (!(session->sample_type & PERF_SAMPLE_RAW))
1612 return 0;
1613 1600
1614 thread = perf_session__findnew(session, sample->pid);
1615 if (thread == NULL) { 1601 if (thread == NULL) {
1616 pr_debug("problem processing %d event, skipping it.\n", 1602 pr_debug("problem processing %s event, skipping it.\n",
1617 event->header.type); 1603 evsel->name);
1618 return -1; 1604 return -1;
1619 } 1605 }
1620 1606
1621 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1607 evsel->hists.stats.total_period += sample->period;
1608 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
1622 1609
1623 if (profile_cpu != -1 && profile_cpu != (int)sample->cpu) 1610 if (evsel->handler.func != NULL) {
1624 return 0; 1611 tracepoint_handler f = evsel->handler.func;
1625 1612
1626 process_raw_event(event, session, sample->raw_data, sample->cpu, 1613 if (evsel->handler.data == NULL)
1627 sample->time, thread); 1614 evsel->handler.data = trace_find_event(evsel->attr.config);
1615
1616 f(tool, evsel->handler.data, sample, machine, thread);
1617 }
1628 1618
1629 return 0; 1619 return 0;
1630} 1620}
1631 1621
1632static struct perf_event_ops event_ops = { 1622static struct perf_tool perf_sched = {
1633 .sample = process_sample_event, 1623 .sample = perf_sched__process_tracepoint_sample,
1634 .comm = perf_event__process_comm, 1624 .comm = perf_event__process_comm,
1635 .lost = perf_event__process_lost, 1625 .lost = perf_event__process_lost,
1636 .fork = perf_event__process_task, 1626 .fork = perf_event__process_task,
@@ -1640,13 +1630,25 @@ static struct perf_event_ops event_ops = {
1640static void read_events(bool destroy, struct perf_session **psession) 1630static void read_events(bool destroy, struct perf_session **psession)
1641{ 1631{
1642 int err = -EINVAL; 1632 int err = -EINVAL;
1633 const struct perf_evsel_str_handler handlers[] = {
1634 { "sched:sched_switch", process_sched_switch_event, },
1635 { "sched:sched_stat_runtime", process_sched_runtime_event, },
1636 { "sched:sched_wakeup", process_sched_wakeup_event, },
1637 { "sched:sched_wakeup_new", process_sched_wakeup_event, },
1638 { "sched:sched_process_fork", process_sched_fork_event, },
1639 { "sched:sched_process_exit", process_sched_exit_event, },
1640 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1641 };
1643 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 1642 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1644 0, false, &event_ops); 1643 0, false, &perf_sched);
1645 if (session == NULL) 1644 if (session == NULL)
1646 die("No Memory"); 1645 die("No Memory");
1647 1646
1647 err = perf_evlist__set_tracepoints_handlers_array(session->evlist, handlers);
1648 assert(err == 0);
1649
1648 if (perf_session__has_traces(session, "record -R")) { 1650 if (perf_session__has_traces(session, "record -R")) {
1649 err = perf_session__process_events(session, &event_ops); 1651 err = perf_session__process_events(session, &perf_sched);
1650 if (err) 1652 if (err)
1651 die("Failed to process events, error %d", err); 1653 die("Failed to process events, error %d", err);
1652 1654
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 2f62a2952269..bb68ddf257b7 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -7,6 +7,7 @@
7#include "util/header.h" 7#include "util/header.h"
8#include "util/parse-options.h" 8#include "util/parse-options.h"
9#include "util/session.h" 9#include "util/session.h"
10#include "util/tool.h"
10#include "util/symbol.h" 11#include "util/symbol.h"
11#include "util/thread.h" 12#include "util/thread.h"
12#include "util/trace-event.h" 13#include "util/trace-event.h"
@@ -23,6 +24,7 @@ static u64 nr_unordered;
23extern const struct option record_options[]; 24extern const struct option record_options[];
24static bool no_callchain; 25static bool no_callchain;
25static bool show_full_info; 26static bool show_full_info;
27static bool system_wide;
26static const char *cpu_list; 28static const char *cpu_list;
27static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 29static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
28 30
@@ -315,7 +317,7 @@ static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
315 317
316static void print_sample_addr(union perf_event *event, 318static void print_sample_addr(union perf_event *event,
317 struct perf_sample *sample, 319 struct perf_sample *sample,
318 struct perf_session *session, 320 struct machine *machine,
319 struct thread *thread, 321 struct thread *thread,
320 struct perf_event_attr *attr) 322 struct perf_event_attr *attr)
321{ 323{
@@ -328,11 +330,11 @@ static void print_sample_addr(union perf_event *event,
328 if (!sample_addr_correlates_sym(attr)) 330 if (!sample_addr_correlates_sym(attr))
329 return; 331 return;
330 332
331 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 333 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
332 event->ip.pid, sample->addr, &al); 334 sample->addr, &al);
333 if (!al.map) 335 if (!al.map)
334 thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE, 336 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE,
335 event->ip.pid, sample->addr, &al); 337 sample->addr, &al);
336 338
337 al.cpu = sample->cpu; 339 al.cpu = sample->cpu;
338 al.sym = NULL; 340 al.sym = NULL;
@@ -362,7 +364,7 @@ static void print_sample_addr(union perf_event *event,
362static void process_event(union perf_event *event __unused, 364static void process_event(union perf_event *event __unused,
363 struct perf_sample *sample, 365 struct perf_sample *sample,
364 struct perf_evsel *evsel, 366 struct perf_evsel *evsel,
365 struct perf_session *session, 367 struct machine *machine,
366 struct thread *thread) 368 struct thread *thread)
367{ 369{
368 struct perf_event_attr *attr = &evsel->attr; 370 struct perf_event_attr *attr = &evsel->attr;
@@ -377,15 +379,15 @@ static void process_event(union perf_event *event __unused,
377 sample->raw_size); 379 sample->raw_size);
378 380
379 if (PRINT_FIELD(ADDR)) 381 if (PRINT_FIELD(ADDR))
380 print_sample_addr(event, sample, session, thread, attr); 382 print_sample_addr(event, sample, machine, thread, attr);
381 383
382 if (PRINT_FIELD(IP)) { 384 if (PRINT_FIELD(IP)) {
383 if (!symbol_conf.use_callchain) 385 if (!symbol_conf.use_callchain)
384 printf(" "); 386 printf(" ");
385 else 387 else
386 printf("\n"); 388 printf("\n");
387 perf_session__print_ip(event, sample, session, 389 perf_event__print_ip(event, sample, machine, evsel,
388 PRINT_FIELD(SYM), PRINT_FIELD(DSO)); 390 PRINT_FIELD(SYM), PRINT_FIELD(DSO));
389 } 391 }
390 392
391 printf("\n"); 393 printf("\n");
@@ -432,14 +434,16 @@ static int cleanup_scripting(void)
432 return scripting_ops->stop_script(); 434 return scripting_ops->stop_script();
433} 435}
434 436
435static char const *input_name = "perf.data"; 437static const char *input_name;
436 438
437static int process_sample_event(union perf_event *event, 439static int process_sample_event(struct perf_tool *tool __used,
440 union perf_event *event,
438 struct perf_sample *sample, 441 struct perf_sample *sample,
439 struct perf_evsel *evsel, 442 struct perf_evsel *evsel,
440 struct perf_session *session) 443 struct machine *machine)
441{ 444{
442 struct thread *thread = perf_session__findnew(session, event->ip.pid); 445 struct addr_location al;
446 struct thread *thread = machine__findnew_thread(machine, event->ip.tid);
443 447
444 if (thread == NULL) { 448 if (thread == NULL) {
445 pr_debug("problem processing %d event, skipping it.\n", 449 pr_debug("problem processing %d event, skipping it.\n",
@@ -458,16 +462,25 @@ static int process_sample_event(union perf_event *event,
458 return 0; 462 return 0;
459 } 463 }
460 464
465 if (perf_event__preprocess_sample(event, machine, &al, sample, 0) < 0) {
466 pr_err("problem processing %d event, skipping it.\n",
467 event->header.type);
468 return -1;
469 }
470
471 if (al.filtered)
472 return 0;
473
461 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 474 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
462 return 0; 475 return 0;
463 476
464 scripting_ops->process_event(event, sample, evsel, session, thread); 477 scripting_ops->process_event(event, sample, evsel, machine, thread);
465 478
466 session->hists.stats.total_period += sample->period; 479 evsel->hists.stats.total_period += sample->period;
467 return 0; 480 return 0;
468} 481}
469 482
470static struct perf_event_ops event_ops = { 483static struct perf_tool perf_script = {
471 .sample = process_sample_event, 484 .sample = process_sample_event,
472 .mmap = perf_event__process_mmap, 485 .mmap = perf_event__process_mmap,
473 .comm = perf_event__process_comm, 486 .comm = perf_event__process_comm,
@@ -494,7 +507,7 @@ static int __cmd_script(struct perf_session *session)
494 507
495 signal(SIGINT, sig_handler); 508 signal(SIGINT, sig_handler);
496 509
497 ret = perf_session__process_events(session, &event_ops); 510 ret = perf_session__process_events(session, &perf_script);
498 511
499 if (debug_mode) 512 if (debug_mode)
500 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 513 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -523,12 +536,6 @@ static struct script_spec *script_spec__new(const char *spec,
523 return s; 536 return s;
524} 537}
525 538
526static void script_spec__delete(struct script_spec *s)
527{
528 free(s->spec);
529 free(s);
530}
531
532static void script_spec__add(struct script_spec *s) 539static void script_spec__add(struct script_spec *s)
533{ 540{
534 list_add_tail(&s->node, &script_specs); 541 list_add_tail(&s->node, &script_specs);
@@ -554,16 +561,11 @@ static struct script_spec *script_spec__findnew(const char *spec,
554 561
555 s = script_spec__new(spec, ops); 562 s = script_spec__new(spec, ops);
556 if (!s) 563 if (!s)
557 goto out_delete_spec; 564 return NULL;
558 565
559 script_spec__add(s); 566 script_spec__add(s);
560 567
561 return s; 568 return s;
562
563out_delete_spec:
564 script_spec__delete(s);
565
566 return NULL;
567} 569}
568 570
569int script_spec_register(const char *spec, struct scripting_ops *ops) 571int script_spec_register(const char *spec, struct scripting_ops *ops)
@@ -681,7 +683,8 @@ static int parse_output_fields(const struct option *opt __used,
681 type = PERF_TYPE_RAW; 683 type = PERF_TYPE_RAW;
682 else { 684 else {
683 fprintf(stderr, "Invalid event type in field string.\n"); 685 fprintf(stderr, "Invalid event type in field string.\n");
684 return -EINVAL; 686 rc = -EINVAL;
687 goto out;
685 } 688 }
686 689
687 if (output[type].user_set) 690 if (output[type].user_set)
@@ -923,6 +926,24 @@ static int read_script_info(struct script_desc *desc, const char *filename)
923 return 0; 926 return 0;
924} 927}
925 928
929static char *get_script_root(struct dirent *script_dirent, const char *suffix)
930{
931 char *script_root, *str;
932
933 script_root = strdup(script_dirent->d_name);
934 if (!script_root)
935 return NULL;
936
937 str = (char *)ends_with(script_root, suffix);
938 if (!str) {
939 free(script_root);
940 return NULL;
941 }
942
943 *str = '\0';
944 return script_root;
945}
946
926static int list_available_scripts(const struct option *opt __used, 947static int list_available_scripts(const struct option *opt __used,
927 const char *s __used, int unset __used) 948 const char *s __used, int unset __used)
928{ 949{
@@ -934,7 +955,6 @@ static int list_available_scripts(const struct option *opt __used,
934 struct script_desc *desc; 955 struct script_desc *desc;
935 char first_half[BUFSIZ]; 956 char first_half[BUFSIZ];
936 char *script_root; 957 char *script_root;
937 char *str;
938 958
939 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 959 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
940 960
@@ -950,16 +970,14 @@ static int list_available_scripts(const struct option *opt __used,
950 continue; 970 continue;
951 971
952 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 972 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
953 script_root = strdup(script_dirent.d_name); 973 script_root = get_script_root(&script_dirent, REPORT_SUFFIX);
954 str = (char *)ends_with(script_root, REPORT_SUFFIX); 974 if (script_root) {
955 if (str) {
956 *str = '\0';
957 desc = script_desc__findnew(script_root); 975 desc = script_desc__findnew(script_root);
958 snprintf(script_path, MAXPATHLEN, "%s/%s", 976 snprintf(script_path, MAXPATHLEN, "%s/%s",
959 lang_path, script_dirent.d_name); 977 lang_path, script_dirent.d_name);
960 read_script_info(desc, script_path); 978 read_script_info(desc, script_path);
979 free(script_root);
961 } 980 }
962 free(script_root);
963 } 981 }
964 } 982 }
965 983
@@ -981,8 +999,7 @@ static char *get_script_path(const char *script_root, const char *suffix)
981 char script_path[MAXPATHLEN]; 999 char script_path[MAXPATHLEN];
982 DIR *scripts_dir, *lang_dir; 1000 DIR *scripts_dir, *lang_dir;
983 char lang_path[MAXPATHLEN]; 1001 char lang_path[MAXPATHLEN];
984 char *str, *__script_root; 1002 char *__script_root;
985 char *path = NULL;
986 1003
987 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 1004 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
988 1005
@@ -998,23 +1015,22 @@ static char *get_script_path(const char *script_root, const char *suffix)
998 continue; 1015 continue;
999 1016
1000 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 1017 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
1001 __script_root = strdup(script_dirent.d_name); 1018 __script_root = get_script_root(&script_dirent, suffix);
1002 str = (char *)ends_with(__script_root, suffix); 1019 if (__script_root && !strcmp(script_root, __script_root)) {
1003 if (str) { 1020 free(__script_root);
1004 *str = '\0'; 1021 closedir(lang_dir);
1005 if (strcmp(__script_root, script_root)) 1022 closedir(scripts_dir);
1006 continue;
1007 snprintf(script_path, MAXPATHLEN, "%s/%s", 1023 snprintf(script_path, MAXPATHLEN, "%s/%s",
1008 lang_path, script_dirent.d_name); 1024 lang_path, script_dirent.d_name);
1009 path = strdup(script_path); 1025 return strdup(script_path);
1010 free(__script_root);
1011 break;
1012 } 1026 }
1013 free(__script_root); 1027 free(__script_root);
1014 } 1028 }
1029 closedir(lang_dir);
1015 } 1030 }
1031 closedir(scripts_dir);
1016 1032
1017 return path; 1033 return NULL;
1018} 1034}
1019 1035
1020static bool is_top_script(const char *script_path) 1036static bool is_top_script(const char *script_path)
@@ -1083,7 +1099,11 @@ static const struct option options[] = {
1083 OPT_CALLBACK('f', "fields", NULL, "str", 1099 OPT_CALLBACK('f', "fields", NULL, "str",
1084 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr", 1100 "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",
1085 parse_output_fields), 1101 parse_output_fields),
1086 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 1102 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1103 "system-wide collection from all CPUs"),
1104 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
1105 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
1106 "only display events for these comms"),
1087 OPT_BOOLEAN('I', "show-info", &show_full_info, 1107 OPT_BOOLEAN('I', "show-info", &show_full_info,
1088 "display extended information from perf.data file"), 1108 "display extended information from perf.data file"),
1089 OPT_END() 1109 OPT_END()
@@ -1110,7 +1130,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1110 struct perf_session *session; 1130 struct perf_session *session;
1111 char *script_path = NULL; 1131 char *script_path = NULL;
1112 const char **__argv; 1132 const char **__argv;
1113 bool system_wide;
1114 int i, j, err; 1133 int i, j, err;
1115 1134
1116 setup_scripting(); 1135 setup_scripting();
@@ -1178,15 +1197,17 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1178 } 1197 }
1179 1198
1180 if (!pid) { 1199 if (!pid) {
1181 system_wide = true;
1182 j = 0; 1200 j = 0;
1183 1201
1184 dup2(live_pipe[1], 1); 1202 dup2(live_pipe[1], 1);
1185 close(live_pipe[0]); 1203 close(live_pipe[0]);
1186 1204
1187 if (!is_top_script(argv[0])) 1205 if (is_top_script(argv[0])) {
1206 system_wide = true;
1207 } else if (!system_wide) {
1188 system_wide = !have_cmd(argc - rep_args, 1208 system_wide = !have_cmd(argc - rep_args,
1189 &argv[rep_args]); 1209 &argv[rep_args]);
1210 }
1190 1211
1191 __argv = malloc((argc + 6) * sizeof(const char *)); 1212 __argv = malloc((argc + 6) * sizeof(const char *));
1192 if (!__argv) 1213 if (!__argv)
@@ -1234,10 +1255,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1234 script_path = rep_script_path; 1255 script_path = rep_script_path;
1235 1256
1236 if (script_path) { 1257 if (script_path) {
1237 system_wide = false;
1238 j = 0; 1258 j = 0;
1239 1259
1240 if (rec_script_path) 1260 if (!rec_script_path)
1261 system_wide = false;
1262 else if (!system_wide)
1241 system_wide = !have_cmd(argc - 1, &argv[1]); 1263 system_wide = !have_cmd(argc - 1, &argv[1]);
1242 1264
1243 __argv = malloc((argc + 2) * sizeof(const char *)); 1265 __argv = malloc((argc + 2) * sizeof(const char *));
@@ -1261,7 +1283,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1261 if (!script_name) 1283 if (!script_name)
1262 setup_pager(); 1284 setup_pager();
1263 1285
1264 session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops); 1286 session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_script);
1265 if (session == NULL) 1287 if (session == NULL)
1266 return -ENOMEM; 1288 return -ENOMEM;
1267 1289
@@ -1287,7 +1309,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1287 return -1; 1309 return -1;
1288 } 1310 }
1289 1311
1290 input = open(input_name, O_RDONLY); 1312 input = open(session->filename, O_RDONLY); /* input_name */
1291 if (input < 0) { 1313 if (input < 0) {
1292 perror("failed to open file"); 1314 perror("failed to open file");
1293 exit(-1); 1315 exit(-1);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 955930e0a5c3..f5d2a63eba66 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -578,6 +578,33 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
578 avg / avg_stats(&walltime_nsecs_stats)); 578 avg / avg_stats(&walltime_nsecs_stats));
579} 579}
580 580
581/* used for get_ratio_color() */
582enum grc_type {
583 GRC_STALLED_CYCLES_FE,
584 GRC_STALLED_CYCLES_BE,
585 GRC_CACHE_MISSES,
586 GRC_MAX_NR
587};
588
589static const char *get_ratio_color(enum grc_type type, double ratio)
590{
591 static const double grc_table[GRC_MAX_NR][3] = {
592 [GRC_STALLED_CYCLES_FE] = { 50.0, 30.0, 10.0 },
593 [GRC_STALLED_CYCLES_BE] = { 75.0, 50.0, 20.0 },
594 [GRC_CACHE_MISSES] = { 20.0, 10.0, 5.0 },
595 };
596 const char *color = PERF_COLOR_NORMAL;
597
598 if (ratio > grc_table[type][0])
599 color = PERF_COLOR_RED;
600 else if (ratio > grc_table[type][1])
601 color = PERF_COLOR_MAGENTA;
602 else if (ratio > grc_table[type][2])
603 color = PERF_COLOR_YELLOW;
604
605 return color;
606}
607
581static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) 608static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg)
582{ 609{
583 double total, ratio = 0.0; 610 double total, ratio = 0.0;
@@ -588,13 +615,7 @@ static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __us
588 if (total) 615 if (total)
589 ratio = avg / total * 100.0; 616 ratio = avg / total * 100.0;
590 617
591 color = PERF_COLOR_NORMAL; 618 color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
592 if (ratio > 50.0)
593 color = PERF_COLOR_RED;
594 else if (ratio > 30.0)
595 color = PERF_COLOR_MAGENTA;
596 else if (ratio > 10.0)
597 color = PERF_COLOR_YELLOW;
598 619
599 fprintf(output, " # "); 620 fprintf(output, " # ");
600 color_fprintf(output, color, "%6.2f%%", ratio); 621 color_fprintf(output, color, "%6.2f%%", ratio);
@@ -611,13 +632,7 @@ static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __use
611 if (total) 632 if (total)
612 ratio = avg / total * 100.0; 633 ratio = avg / total * 100.0;
613 634
614 color = PERF_COLOR_NORMAL; 635 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
615 if (ratio > 75.0)
616 color = PERF_COLOR_RED;
617 else if (ratio > 50.0)
618 color = PERF_COLOR_MAGENTA;
619 else if (ratio > 20.0)
620 color = PERF_COLOR_YELLOW;
621 636
622 fprintf(output, " # "); 637 fprintf(output, " # ");
623 color_fprintf(output, color, "%6.2f%%", ratio); 638 color_fprintf(output, color, "%6.2f%%", ratio);
@@ -634,13 +649,7 @@ static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double
634 if (total) 649 if (total)
635 ratio = avg / total * 100.0; 650 ratio = avg / total * 100.0;
636 651
637 color = PERF_COLOR_NORMAL; 652 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
638 if (ratio > 20.0)
639 color = PERF_COLOR_RED;
640 else if (ratio > 10.0)
641 color = PERF_COLOR_MAGENTA;
642 else if (ratio > 5.0)
643 color = PERF_COLOR_YELLOW;
644 653
645 fprintf(output, " # "); 654 fprintf(output, " # ");
646 color_fprintf(output, color, "%6.2f%%", ratio); 655 color_fprintf(output, color, "%6.2f%%", ratio);
@@ -657,13 +666,7 @@ static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, dou
657 if (total) 666 if (total)
658 ratio = avg / total * 100.0; 667 ratio = avg / total * 100.0;
659 668
660 color = PERF_COLOR_NORMAL; 669 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
661 if (ratio > 20.0)
662 color = PERF_COLOR_RED;
663 else if (ratio > 10.0)
664 color = PERF_COLOR_MAGENTA;
665 else if (ratio > 5.0)
666 color = PERF_COLOR_YELLOW;
667 670
668 fprintf(output, " # "); 671 fprintf(output, " # ");
669 color_fprintf(output, color, "%6.2f%%", ratio); 672 color_fprintf(output, color, "%6.2f%%", ratio);
@@ -680,13 +683,7 @@ static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, dou
680 if (total) 683 if (total)
681 ratio = avg / total * 100.0; 684 ratio = avg / total * 100.0;
682 685
683 color = PERF_COLOR_NORMAL; 686 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
684 if (ratio > 20.0)
685 color = PERF_COLOR_RED;
686 else if (ratio > 10.0)
687 color = PERF_COLOR_MAGENTA;
688 else if (ratio > 5.0)
689 color = PERF_COLOR_YELLOW;
690 687
691 fprintf(output, " # "); 688 fprintf(output, " # ");
692 color_fprintf(output, color, "%6.2f%%", ratio); 689 color_fprintf(output, color, "%6.2f%%", ratio);
@@ -703,13 +700,7 @@ static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
703 if (total) 700 if (total)
704 ratio = avg / total * 100.0; 701 ratio = avg / total * 100.0;
705 702
706 color = PERF_COLOR_NORMAL; 703 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
707 if (ratio > 20.0)
708 color = PERF_COLOR_RED;
709 else if (ratio > 10.0)
710 color = PERF_COLOR_MAGENTA;
711 else if (ratio > 5.0)
712 color = PERF_COLOR_YELLOW;
713 704
714 fprintf(output, " # "); 705 fprintf(output, " # ");
715 color_fprintf(output, color, "%6.2f%%", ratio); 706 color_fprintf(output, color, "%6.2f%%", ratio);
@@ -726,13 +717,7 @@ static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
726 if (total) 717 if (total)
727 ratio = avg / total * 100.0; 718 ratio = avg / total * 100.0;
728 719
729 color = PERF_COLOR_NORMAL; 720 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
730 if (ratio > 20.0)
731 color = PERF_COLOR_RED;
732 else if (ratio > 10.0)
733 color = PERF_COLOR_MAGENTA;
734 else if (ratio > 5.0)
735 color = PERF_COLOR_YELLOW;
736 721
737 fprintf(output, " # "); 722 fprintf(output, " # ");
738 color_fprintf(output, color, "%6.2f%%", ratio); 723 color_fprintf(output, color, "%6.2f%%", ratio);
@@ -749,13 +734,7 @@ static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, doub
749 if (total) 734 if (total)
750 ratio = avg / total * 100.0; 735 ratio = avg / total * 100.0;
751 736
752 color = PERF_COLOR_NORMAL; 737 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
753 if (ratio > 20.0)
754 color = PERF_COLOR_RED;
755 else if (ratio > 10.0)
756 color = PERF_COLOR_MAGENTA;
757 else if (ratio > 5.0)
758 color = PERF_COLOR_YELLOW;
759 738
760 fprintf(output, " # "); 739 fprintf(output, " # ");
761 color_fprintf(output, color, "%6.2f%%", ratio); 740 color_fprintf(output, color, "%6.2f%%", ratio);
@@ -1108,22 +1087,13 @@ static const struct option options[] = {
1108 */ 1087 */
1109static int add_default_attributes(void) 1088static int add_default_attributes(void)
1110{ 1089{
1111 struct perf_evsel *pos;
1112 size_t attr_nr = 0;
1113 size_t c;
1114
1115 /* Set attrs if no event is selected and !null_run: */ 1090 /* Set attrs if no event is selected and !null_run: */
1116 if (null_run) 1091 if (null_run)
1117 return 0; 1092 return 0;
1118 1093
1119 if (!evsel_list->nr_entries) { 1094 if (!evsel_list->nr_entries) {
1120 for (c = 0; c < ARRAY_SIZE(default_attrs); c++) { 1095 if (perf_evlist__add_attrs_array(evsel_list, default_attrs) < 0)
1121 pos = perf_evsel__new(default_attrs + c, c + attr_nr); 1096 return -1;
1122 if (pos == NULL)
1123 return -1;
1124 perf_evlist__add(evsel_list, pos);
1125 }
1126 attr_nr += c;
1127 } 1097 }
1128 1098
1129 /* Detailed events get appended to the event list: */ 1099 /* Detailed events get appended to the event list: */
@@ -1132,38 +1102,21 @@ static int add_default_attributes(void)
1132 return 0; 1102 return 0;
1133 1103
1134 /* Append detailed run extra attributes: */ 1104 /* Append detailed run extra attributes: */
1135 for (c = 0; c < ARRAY_SIZE(detailed_attrs); c++) { 1105 if (perf_evlist__add_attrs_array(evsel_list, detailed_attrs) < 0)
1136 pos = perf_evsel__new(detailed_attrs + c, c + attr_nr); 1106 return -1;
1137 if (pos == NULL)
1138 return -1;
1139 perf_evlist__add(evsel_list, pos);
1140 }
1141 attr_nr += c;
1142 1107
1143 if (detailed_run < 2) 1108 if (detailed_run < 2)
1144 return 0; 1109 return 0;
1145 1110
1146 /* Append very detailed run extra attributes: */ 1111 /* Append very detailed run extra attributes: */
1147 for (c = 0; c < ARRAY_SIZE(very_detailed_attrs); c++) { 1112 if (perf_evlist__add_attrs_array(evsel_list, very_detailed_attrs) < 0)
1148 pos = perf_evsel__new(very_detailed_attrs + c, c + attr_nr); 1113 return -1;
1149 if (pos == NULL)
1150 return -1;
1151 perf_evlist__add(evsel_list, pos);
1152 }
1153 1114
1154 if (detailed_run < 3) 1115 if (detailed_run < 3)
1155 return 0; 1116 return 0;
1156 1117
1157 /* Append very, very detailed run extra attributes: */ 1118 /* Append very, very detailed run extra attributes: */
1158 for (c = 0; c < ARRAY_SIZE(very_very_detailed_attrs); c++) { 1119 return perf_evlist__add_attrs_array(evsel_list, very_very_detailed_attrs);
1159 pos = perf_evsel__new(very_very_detailed_attrs + c, c + attr_nr);
1160 if (pos == NULL)
1161 return -1;
1162 perf_evlist__add(evsel_list, pos);
1163 }
1164
1165
1166 return 0;
1167} 1120}
1168 1121
1169int cmd_stat(int argc, const char **argv, const char *prefix __used) 1122int cmd_stat(int argc, const char **argv, const char *prefix __used)
@@ -1267,8 +1220,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1267 1220
1268 list_for_each_entry(pos, &evsel_list->entries, node) { 1221 list_for_each_entry(pos, &evsel_list->entries, node) {
1269 if (perf_evsel__alloc_stat_priv(pos) < 0 || 1222 if (perf_evsel__alloc_stat_priv(pos) < 0 ||
1270 perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 || 1223 perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0)
1271 perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0)
1272 goto out_free_fd; 1224 goto out_free_fd;
1273 } 1225 }
1274 1226
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 831d1baeac37..3854e869dce1 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -7,6 +7,7 @@
7 7
8#include "util/cache.h" 8#include "util/cache.h"
9#include "util/debug.h" 9#include "util/debug.h"
10#include "util/debugfs.h"
10#include "util/evlist.h" 11#include "util/evlist.h"
11#include "util/parse-options.h" 12#include "util/parse-options.h"
12#include "util/parse-events.h" 13#include "util/parse-events.h"
@@ -14,8 +15,6 @@
14#include "util/thread_map.h" 15#include "util/thread_map.h"
15#include "../../include/linux/hw_breakpoint.h" 16#include "../../include/linux/hw_breakpoint.h"
16 17
17static long page_size;
18
19static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) 18static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym)
20{ 19{
21 bool *visited = symbol__priv(sym); 20 bool *visited = symbol__priv(sym);
@@ -31,6 +30,7 @@ static int test__vmlinux_matches_kallsyms(void)
31 struct map *kallsyms_map, *vmlinux_map; 30 struct map *kallsyms_map, *vmlinux_map;
32 struct machine kallsyms, vmlinux; 31 struct machine kallsyms, vmlinux;
33 enum map_type type = MAP__FUNCTION; 32 enum map_type type = MAP__FUNCTION;
33 long page_size = sysconf(_SC_PAGE_SIZE);
34 struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; 34 struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
35 35
36 /* 36 /*
@@ -247,7 +247,7 @@ static int trace_event__id(const char *evname)
247 247
248 if (asprintf(&filename, 248 if (asprintf(&filename,
249 "%s/syscalls/%s/id", 249 "%s/syscalls/%s/id",
250 debugfs_path, evname) < 0) 250 tracing_events_path, evname) < 0)
251 return -1; 251 return -1;
252 252
253 fd = open(filename, O_RDONLY); 253 fd = open(filename, O_RDONLY);
@@ -603,7 +603,7 @@ out_free_threads:
603 603
604#define TEST_ASSERT_VAL(text, cond) \ 604#define TEST_ASSERT_VAL(text, cond) \
605do { \ 605do { \
606 if (!cond) { \ 606 if (!(cond)) { \
607 pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ 607 pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
608 return -1; \ 608 return -1; \
609 } \ 609 } \
@@ -759,6 +759,103 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
759 return 0; 759 return 0;
760} 760}
761 761
762static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
763{
764 struct perf_evsel *evsel = list_entry(evlist->entries.next,
765 struct perf_evsel, node);
766
767 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
768 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
769 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
770 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
771
772 return test__checkevent_tracepoint(evlist);
773}
774
775static int
776test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
777{
778 struct perf_evsel *evsel;
779
780 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
781
782 list_for_each_entry(evsel, &evlist->entries, node) {
783 TEST_ASSERT_VAL("wrong exclude_user",
784 !evsel->attr.exclude_user);
785 TEST_ASSERT_VAL("wrong exclude_kernel",
786 evsel->attr.exclude_kernel);
787 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
788 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
789 }
790
791 return test__checkevent_tracepoint_multi(evlist);
792}
793
794static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
795{
796 struct perf_evsel *evsel = list_entry(evlist->entries.next,
797 struct perf_evsel, node);
798
799 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
800 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
801 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
802 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
803
804 return test__checkevent_raw(evlist);
805}
806
807static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
808{
809 struct perf_evsel *evsel = list_entry(evlist->entries.next,
810 struct perf_evsel, node);
811
812 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
813 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
814 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
815 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
816
817 return test__checkevent_numeric(evlist);
818}
819
820static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
821{
822 struct perf_evsel *evsel = list_entry(evlist->entries.next,
823 struct perf_evsel, node);
824
825 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
826 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
827 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
828 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
829
830 return test__checkevent_symbolic_name(evlist);
831}
832
833static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
834{
835 struct perf_evsel *evsel = list_entry(evlist->entries.next,
836 struct perf_evsel, node);
837
838 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
839 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
840 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
841 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
842
843 return test__checkevent_symbolic_alias(evlist);
844}
845
846static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
847{
848 struct perf_evsel *evsel = list_entry(evlist->entries.next,
849 struct perf_evsel, node);
850
851 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
852 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
853 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
854 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
855
856 return test__checkevent_genhw(evlist);
857}
858
762static struct test__event_st { 859static struct test__event_st {
763 const char *name; 860 const char *name;
764 __u32 type; 861 __u32 type;
@@ -808,6 +905,34 @@ static struct test__event_st {
808 .name = "mem:0:w", 905 .name = "mem:0:w",
809 .check = test__checkevent_breakpoint_w, 906 .check = test__checkevent_breakpoint_w,
810 }, 907 },
908 {
909 .name = "syscalls:sys_enter_open:k",
910 .check = test__checkevent_tracepoint_modifier,
911 },
912 {
913 .name = "syscalls:*:u",
914 .check = test__checkevent_tracepoint_multi_modifier,
915 },
916 {
917 .name = "r1:kp",
918 .check = test__checkevent_raw_modifier,
919 },
920 {
921 .name = "1:1:hp",
922 .check = test__checkevent_numeric_modifier,
923 },
924 {
925 .name = "instructions:h",
926 .check = test__checkevent_symbolic_name_modifier,
927 },
928 {
929 .name = "faults:u",
930 .check = test__checkevent_symbolic_alias_modifier,
931 },
932 {
933 .name = "L1-dcache-load-miss:kp",
934 .check = test__checkevent_genhw_modifier,
935 },
811}; 936};
812 937
813#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st)) 938#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
@@ -841,6 +966,336 @@ static int test__parse_events(void)
841 966
842 return ret; 967 return ret;
843} 968}
969
970static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp,
971 size_t *sizep)
972{
973 cpu_set_t *mask;
974 size_t size;
975 int i, cpu = -1, nrcpus = 1024;
976realloc:
977 mask = CPU_ALLOC(nrcpus);
978 size = CPU_ALLOC_SIZE(nrcpus);
979 CPU_ZERO_S(size, mask);
980
981 if (sched_getaffinity(pid, size, mask) == -1) {
982 CPU_FREE(mask);
983 if (errno == EINVAL && nrcpus < (1024 << 8)) {
984 nrcpus = nrcpus << 2;
985 goto realloc;
986 }
987 perror("sched_getaffinity");
988 return -1;
989 }
990
991 for (i = 0; i < nrcpus; i++) {
992 if (CPU_ISSET_S(i, size, mask)) {
993 if (cpu == -1) {
994 cpu = i;
995 *maskp = mask;
996 *sizep = size;
997 } else
998 CPU_CLR_S(i, size, mask);
999 }
1000 }
1001
1002 if (cpu == -1)
1003 CPU_FREE(mask);
1004
1005 return cpu;
1006}
1007
1008static int test__PERF_RECORD(void)
1009{
1010 struct perf_record_opts opts = {
1011 .target_pid = -1,
1012 .target_tid = -1,
1013 .no_delay = true,
1014 .freq = 10,
1015 .mmap_pages = 256,
1016 .sample_id_all_avail = true,
1017 };
1018 cpu_set_t *cpu_mask = NULL;
1019 size_t cpu_mask_size = 0;
1020 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
1021 struct perf_evsel *evsel;
1022 struct perf_sample sample;
1023 const char *cmd = "sleep";
1024 const char *argv[] = { cmd, "1", NULL, };
1025 char *bname;
1026 u64 sample_type, prev_time = 0;
1027 bool found_cmd_mmap = false,
1028 found_libc_mmap = false,
1029 found_vdso_mmap = false,
1030 found_ld_mmap = false;
1031 int err = -1, errs = 0, i, wakeups = 0, sample_size;
1032 u32 cpu;
1033 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
1034
1035 if (evlist == NULL || argv == NULL) {
1036 pr_debug("Not enough memory to create evlist\n");
1037 goto out;
1038 }
1039
1040 /*
1041 * We need at least one evsel in the evlist, use the default
1042 * one: "cycles".
1043 */
1044 err = perf_evlist__add_default(evlist);
1045 if (err < 0) {
1046 pr_debug("Not enough memory to create evsel\n");
1047 goto out_delete_evlist;
1048 }
1049
1050 /*
1051 * Create maps of threads and cpus to monitor. In this case
1052 * we start with all threads and cpus (-1, -1) but then in
1053 * perf_evlist__prepare_workload we'll fill in the only thread
1054 * we're monitoring, the one forked there.
1055 */
1056 err = perf_evlist__create_maps(evlist, opts.target_pid,
1057 opts.target_tid, opts.cpu_list);
1058 if (err < 0) {
1059 pr_debug("Not enough memory to create thread/cpu maps\n");
1060 goto out_delete_evlist;
1061 }
1062
1063 /*
1064 * Prepare the workload in argv[] to run, it'll fork it, and then wait
1065 * for perf_evlist__start_workload() to exec it. This is done this way
1066 * so that we have time to open the evlist (calling sys_perf_event_open
1067 * on all the fds) and then mmap them.
1068 */
1069 err = perf_evlist__prepare_workload(evlist, &opts, argv);
1070 if (err < 0) {
1071 pr_debug("Couldn't run the workload!\n");
1072 goto out_delete_evlist;
1073 }
1074
1075 /*
1076 * Config the evsels, setting attr->comm on the first one, etc.
1077 */
1078 evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
1079 evsel->attr.sample_type |= PERF_SAMPLE_CPU;
1080 evsel->attr.sample_type |= PERF_SAMPLE_TID;
1081 evsel->attr.sample_type |= PERF_SAMPLE_TIME;
1082 perf_evlist__config_attrs(evlist, &opts);
1083
1084 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask,
1085 &cpu_mask_size);
1086 if (err < 0) {
1087 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
1088 goto out_delete_evlist;
1089 }
1090
1091 cpu = err;
1092
1093 /*
1094 * So that we can check perf_sample.cpu on all the samples.
1095 */
1096 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, cpu_mask) < 0) {
1097 pr_debug("sched_setaffinity: %s\n", strerror(errno));
1098 goto out_free_cpu_mask;
1099 }
1100
1101 /*
1102 * Call sys_perf_event_open on all the fds on all the evsels,
1103 * grouping them if asked to.
1104 */
1105 err = perf_evlist__open(evlist, opts.group);
1106 if (err < 0) {
1107 pr_debug("perf_evlist__open: %s\n", strerror(errno));
1108 goto out_delete_evlist;
1109 }
1110
1111 /*
1112 * mmap the first fd on a given CPU and ask for events for the other
1113 * fds in the same CPU to be injected in the same mmap ring buffer
1114 * (using ioctl(PERF_EVENT_IOC_SET_OUTPUT)).
1115 */
1116 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
1117 if (err < 0) {
1118 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
1119 goto out_delete_evlist;
1120 }
1121
1122 /*
1123 * We'll need these two to parse the PERF_SAMPLE_* fields in each
1124 * event.
1125 */
1126 sample_type = perf_evlist__sample_type(evlist);
1127 sample_size = __perf_evsel__sample_size(sample_type);
1128
1129 /*
1130 * Now that all is properly set up, enable the events, they will
1131 * count just on workload.pid, which will start...
1132 */
1133 perf_evlist__enable(evlist);
1134
1135 /*
1136 * Now!
1137 */
1138 perf_evlist__start_workload(evlist);
1139
1140 while (1) {
1141 int before = total_events;
1142
1143 for (i = 0; i < evlist->nr_mmaps; i++) {
1144 union perf_event *event;
1145
1146 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1147 const u32 type = event->header.type;
1148 const char *name = perf_event__name(type);
1149
1150 ++total_events;
1151 if (type < PERF_RECORD_MAX)
1152 nr_events[type]++;
1153
1154 err = perf_event__parse_sample(event, sample_type,
1155 sample_size, true,
1156 &sample, false);
1157 if (err < 0) {
1158 if (verbose)
1159 perf_event__fprintf(event, stderr);
1160 pr_debug("Couldn't parse sample\n");
1161 goto out_err;
1162 }
1163
1164 if (verbose) {
1165 pr_info("%" PRIu64" %d ", sample.time, sample.cpu);
1166 perf_event__fprintf(event, stderr);
1167 }
1168
1169 if (prev_time > sample.time) {
1170 pr_debug("%s going backwards in time, prev=%" PRIu64 ", curr=%" PRIu64 "\n",
1171 name, prev_time, sample.time);
1172 ++errs;
1173 }
1174
1175 prev_time = sample.time;
1176
1177 if (sample.cpu != cpu) {
1178 pr_debug("%s with unexpected cpu, expected %d, got %d\n",
1179 name, cpu, sample.cpu);
1180 ++errs;
1181 }
1182
1183 if ((pid_t)sample.pid != evlist->workload.pid) {
1184 pr_debug("%s with unexpected pid, expected %d, got %d\n",
1185 name, evlist->workload.pid, sample.pid);
1186 ++errs;
1187 }
1188
1189 if ((pid_t)sample.tid != evlist->workload.pid) {
1190 pr_debug("%s with unexpected tid, expected %d, got %d\n",
1191 name, evlist->workload.pid, sample.tid);
1192 ++errs;
1193 }
1194
1195 if ((type == PERF_RECORD_COMM ||
1196 type == PERF_RECORD_MMAP ||
1197 type == PERF_RECORD_FORK ||
1198 type == PERF_RECORD_EXIT) &&
1199 (pid_t)event->comm.pid != evlist->workload.pid) {
1200 pr_debug("%s with unexpected pid/tid\n", name);
1201 ++errs;
1202 }
1203
1204 if ((type == PERF_RECORD_COMM ||
1205 type == PERF_RECORD_MMAP) &&
1206 event->comm.pid != event->comm.tid) {
1207 pr_debug("%s with different pid/tid!\n", name);
1208 ++errs;
1209 }
1210
1211 switch (type) {
1212 case PERF_RECORD_COMM:
1213 if (strcmp(event->comm.comm, cmd)) {
1214 pr_debug("%s with unexpected comm!\n", name);
1215 ++errs;
1216 }
1217 break;
1218 case PERF_RECORD_EXIT:
1219 goto found_exit;
1220 case PERF_RECORD_MMAP:
1221 bname = strrchr(event->mmap.filename, '/');
1222 if (bname != NULL) {
1223 if (!found_cmd_mmap)
1224 found_cmd_mmap = !strcmp(bname + 1, cmd);
1225 if (!found_libc_mmap)
1226 found_libc_mmap = !strncmp(bname + 1, "libc", 4);
1227 if (!found_ld_mmap)
1228 found_ld_mmap = !strncmp(bname + 1, "ld", 2);
1229 } else if (!found_vdso_mmap)
1230 found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
1231 break;
1232
1233 case PERF_RECORD_SAMPLE:
1234 /* Just ignore samples for now */
1235 break;
1236 default:
1237 pr_debug("Unexpected perf_event->header.type %d!\n",
1238 type);
1239 ++errs;
1240 }
1241 }
1242 }
1243
1244 /*
1245 * We don't use poll here because at least at 3.1 times the
1246 * PERF_RECORD_{!SAMPLE} events don't honour
1247 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
1248 */
1249 if (total_events == before && false)
1250 poll(evlist->pollfd, evlist->nr_fds, -1);
1251
1252 sleep(1);
1253 if (++wakeups > 5) {
1254 pr_debug("No PERF_RECORD_EXIT event!\n");
1255 break;
1256 }
1257 }
1258
1259found_exit:
1260 if (nr_events[PERF_RECORD_COMM] > 1) {
1261 pr_debug("Excessive number of PERF_RECORD_COMM events!\n");
1262 ++errs;
1263 }
1264
1265 if (nr_events[PERF_RECORD_COMM] == 0) {
1266 pr_debug("Missing PERF_RECORD_COMM for %s!\n", cmd);
1267 ++errs;
1268 }
1269
1270 if (!found_cmd_mmap) {
1271 pr_debug("PERF_RECORD_MMAP for %s missing!\n", cmd);
1272 ++errs;
1273 }
1274
1275 if (!found_libc_mmap) {
1276 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "libc");
1277 ++errs;
1278 }
1279
1280 if (!found_ld_mmap) {
1281 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "ld");
1282 ++errs;
1283 }
1284
1285 if (!found_vdso_mmap) {
1286 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]");
1287 ++errs;
1288 }
1289out_err:
1290 perf_evlist__munmap(evlist);
1291out_free_cpu_mask:
1292 CPU_FREE(cpu_mask);
1293out_delete_evlist:
1294 perf_evlist__delete(evlist);
1295out:
1296 return (err < 0 || errs > 0) ? -1 : 0;
1297}
1298
844static struct test { 1299static struct test {
845 const char *desc; 1300 const char *desc;
846 int (*func)(void); 1301 int (*func)(void);
@@ -866,45 +1321,89 @@ static struct test {
866 .func = test__parse_events, 1321 .func = test__parse_events,
867 }, 1322 },
868 { 1323 {
1324 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
1325 .func = test__PERF_RECORD,
1326 },
1327 {
869 .func = NULL, 1328 .func = NULL,
870 }, 1329 },
871}; 1330};
872 1331
873static int __cmd_test(void) 1332static bool perf_test__matches(int curr, int argc, const char *argv[])
874{ 1333{
875 int i = 0; 1334 int i;
1335
1336 if (argc == 0)
1337 return true;
876 1338
877 page_size = sysconf(_SC_PAGE_SIZE); 1339 for (i = 0; i < argc; ++i) {
1340 char *end;
1341 long nr = strtoul(argv[i], &end, 10);
1342
1343 if (*end == '\0') {
1344 if (nr == curr + 1)
1345 return true;
1346 continue;
1347 }
1348
1349 if (strstr(tests[curr].desc, argv[i]))
1350 return true;
1351 }
1352
1353 return false;
1354}
1355
1356static int __cmd_test(int argc, const char *argv[])
1357{
1358 int i = 0;
878 1359
879 while (tests[i].func) { 1360 while (tests[i].func) {
880 int err; 1361 int curr = i++, err;
881 pr_info("%2d: %s:", i + 1, tests[i].desc); 1362
1363 if (!perf_test__matches(curr, argc, argv))
1364 continue;
1365
1366 pr_info("%2d: %s:", i, tests[curr].desc);
882 pr_debug("\n--- start ---\n"); 1367 pr_debug("\n--- start ---\n");
883 err = tests[i].func(); 1368 err = tests[curr].func();
884 pr_debug("---- end ----\n%s:", tests[i].desc); 1369 pr_debug("---- end ----\n%s:", tests[curr].desc);
885 pr_info(" %s\n", err ? "FAILED!\n" : "Ok"); 1370 pr_info(" %s\n", err ? "FAILED!\n" : "Ok");
886 ++i;
887 } 1371 }
888 1372
889 return 0; 1373 return 0;
890} 1374}
891 1375
892static const char * const test_usage[] = { 1376static int perf_test__list(int argc, const char **argv)
893 "perf test [<options>]", 1377{
894 NULL, 1378 int i = 0;
895};
896 1379
897static const struct option test_options[] = { 1380 while (tests[i].func) {
898 OPT_INTEGER('v', "verbose", &verbose, 1381 int curr = i++;
899 "be more verbose (show symbol address, etc)"), 1382
900 OPT_END() 1383 if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
901}; 1384 continue;
1385
1386 pr_info("%2d: %s\n", i, tests[curr].desc);
1387 }
1388
1389 return 0;
1390}
902 1391
903int cmd_test(int argc, const char **argv, const char *prefix __used) 1392int cmd_test(int argc, const char **argv, const char *prefix __used)
904{ 1393{
1394 const char * const test_usage[] = {
1395 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
1396 NULL,
1397 };
1398 const struct option test_options[] = {
1399 OPT_INCR('v', "verbose", &verbose,
1400 "be more verbose (show symbol address, etc)"),
1401 OPT_END()
1402 };
1403
905 argc = parse_options(argc, argv, test_options, test_usage, 0); 1404 argc = parse_options(argc, argv, test_options, test_usage, 0);
906 if (argc) 1405 if (argc >= 1 && !strcmp(argv[0], "list"))
907 usage_with_options(test_usage, test_options); 1406 return perf_test__list(argc, argv);
908 1407
909 symbol_conf.priv_size = sizeof(int); 1408 symbol_conf.priv_size = sizeof(int);
910 symbol_conf.sort_by_name = true; 1409 symbol_conf.sort_by_name = true;
@@ -915,5 +1414,5 @@ int cmd_test(int argc, const char **argv, const char *prefix __used)
915 1414
916 setup_pager(); 1415 setup_pager();
917 1416
918 return __cmd_test(); 1417 return __cmd_test(argc, argv);
919} 1418}
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index aa26f4d66d10..3b75b2e21ea5 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -19,6 +19,7 @@
19#include "util/color.h" 19#include "util/color.h"
20#include <linux/list.h> 20#include <linux/list.h>
21#include "util/cache.h" 21#include "util/cache.h"
22#include "util/evsel.h"
22#include <linux/rbtree.h> 23#include <linux/rbtree.h>
23#include "util/symbol.h" 24#include "util/symbol.h"
24#include "util/callchain.h" 25#include "util/callchain.h"
@@ -31,13 +32,14 @@
31#include "util/event.h" 32#include "util/event.h"
32#include "util/session.h" 33#include "util/session.h"
33#include "util/svghelper.h" 34#include "util/svghelper.h"
35#include "util/tool.h"
34 36
35#define SUPPORT_OLD_POWER_EVENTS 1 37#define SUPPORT_OLD_POWER_EVENTS 1
36#define PWR_EVENT_EXIT -1 38#define PWR_EVENT_EXIT -1
37 39
38 40
39static char const *input_name = "perf.data"; 41static const char *input_name;
40static char const *output_name = "output.svg"; 42static const char *output_name = "output.svg";
41 43
42static unsigned int numcpus; 44static unsigned int numcpus;
43static u64 min_freq; /* Lowest CPU frequency seen */ 45static u64 min_freq; /* Lowest CPU frequency seen */
@@ -273,25 +275,28 @@ static int cpus_cstate_state[MAX_CPUS];
273static u64 cpus_pstate_start_times[MAX_CPUS]; 275static u64 cpus_pstate_start_times[MAX_CPUS];
274static u64 cpus_pstate_state[MAX_CPUS]; 276static u64 cpus_pstate_state[MAX_CPUS];
275 277
276static int process_comm_event(union perf_event *event, 278static int process_comm_event(struct perf_tool *tool __used,
279 union perf_event *event,
277 struct perf_sample *sample __used, 280 struct perf_sample *sample __used,
278 struct perf_session *session __used) 281 struct machine *machine __used)
279{ 282{
280 pid_set_comm(event->comm.tid, event->comm.comm); 283 pid_set_comm(event->comm.tid, event->comm.comm);
281 return 0; 284 return 0;
282} 285}
283 286
284static int process_fork_event(union perf_event *event, 287static int process_fork_event(struct perf_tool *tool __used,
288 union perf_event *event,
285 struct perf_sample *sample __used, 289 struct perf_sample *sample __used,
286 struct perf_session *session __used) 290 struct machine *machine __used)
287{ 291{
288 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); 292 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
289 return 0; 293 return 0;
290} 294}
291 295
292static int process_exit_event(union perf_event *event, 296static int process_exit_event(struct perf_tool *tool __used,
297 union perf_event *event,
293 struct perf_sample *sample __used, 298 struct perf_sample *sample __used,
294 struct perf_session *session __used) 299 struct machine *machine __used)
295{ 300{
296 pid_exit(event->fork.pid, event->fork.time); 301 pid_exit(event->fork.pid, event->fork.time);
297 return 0; 302 return 0;
@@ -486,14 +491,15 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
486} 491}
487 492
488 493
489static int process_sample_event(union perf_event *event __used, 494static int process_sample_event(struct perf_tool *tool __used,
495 union perf_event *event __used,
490 struct perf_sample *sample, 496 struct perf_sample *sample,
491 struct perf_evsel *evsel __used, 497 struct perf_evsel *evsel,
492 struct perf_session *session) 498 struct machine *machine __used)
493{ 499{
494 struct trace_entry *te; 500 struct trace_entry *te;
495 501
496 if (session->sample_type & PERF_SAMPLE_TIME) { 502 if (evsel->attr.sample_type & PERF_SAMPLE_TIME) {
497 if (!first_time || first_time > sample->time) 503 if (!first_time || first_time > sample->time)
498 first_time = sample->time; 504 first_time = sample->time;
499 if (last_time < sample->time) 505 if (last_time < sample->time)
@@ -501,7 +507,7 @@ static int process_sample_event(union perf_event *event __used,
501 } 507 }
502 508
503 te = (void *)sample->raw_data; 509 te = (void *)sample->raw_data;
504 if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) { 510 if ((evsel->attr.sample_type & PERF_SAMPLE_RAW) && sample->raw_size > 0) {
505 char *event_str; 511 char *event_str;
506#ifdef SUPPORT_OLD_POWER_EVENTS 512#ifdef SUPPORT_OLD_POWER_EVENTS
507 struct power_entry_old *peo; 513 struct power_entry_old *peo;
@@ -974,7 +980,7 @@ static void write_svg_file(const char *filename)
974 svg_close(); 980 svg_close();
975} 981}
976 982
977static struct perf_event_ops event_ops = { 983static struct perf_tool perf_timechart = {
978 .comm = process_comm_event, 984 .comm = process_comm_event,
979 .fork = process_fork_event, 985 .fork = process_fork_event,
980 .exit = process_exit_event, 986 .exit = process_exit_event,
@@ -985,7 +991,7 @@ static struct perf_event_ops event_ops = {
985static int __cmd_timechart(void) 991static int __cmd_timechart(void)
986{ 992{
987 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 993 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
988 0, false, &event_ops); 994 0, false, &perf_timechart);
989 int ret = -EINVAL; 995 int ret = -EINVAL;
990 996
991 if (session == NULL) 997 if (session == NULL)
@@ -994,7 +1000,7 @@ static int __cmd_timechart(void)
994 if (!perf_session__has_traces(session, "timechart record")) 1000 if (!perf_session__has_traces(session, "timechart record"))
995 goto out_delete; 1001 goto out_delete;
996 1002
997 ret = perf_session__process_events(session, &event_ops); 1003 ret = perf_session__process_events(session, &perf_timechart);
998 if (ret) 1004 if (ret)
999 goto out_delete; 1005 goto out_delete;
1000 1006
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c9cdedb58134..ecff31257eb3 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -64,44 +64,6 @@
64#include <linux/unistd.h> 64#include <linux/unistd.h>
65#include <linux/types.h> 65#include <linux/types.h>
66 66
67static struct perf_top top = {
68 .count_filter = 5,
69 .delay_secs = 2,
70 .target_pid = -1,
71 .target_tid = -1,
72 .freq = 1000, /* 1 KHz */
73};
74
75static bool system_wide = false;
76
77static bool use_tui, use_stdio;
78
79static bool sort_has_symbols;
80
81static bool dont_use_callchains;
82static char callchain_default_opt[] = "fractal,0.5,callee";
83
84
85static int default_interval = 0;
86
87static bool kptr_restrict_warned;
88static bool vmlinux_warned;
89static bool inherit = false;
90static int realtime_prio = 0;
91static bool group = false;
92static bool sample_id_all_avail = true;
93static unsigned int mmap_pages = 128;
94
95static bool dump_symtab = false;
96
97static struct winsize winsize;
98
99static const char *sym_filter = NULL;
100static int sym_pcnt_filter = 5;
101
102/*
103 * Source functions
104 */
105 67
106void get_term_dimensions(struct winsize *ws) 68void get_term_dimensions(struct winsize *ws)
107{ 69{
@@ -125,21 +87,28 @@ void get_term_dimensions(struct winsize *ws)
125 ws->ws_col = 80; 87 ws->ws_col = 80;
126} 88}
127 89
128static void update_print_entries(struct winsize *ws) 90static void perf_top__update_print_entries(struct perf_top *top)
129{ 91{
130 top.print_entries = ws->ws_row; 92 if (top->print_entries > 9)
131 93 top->print_entries -= 9;
132 if (top.print_entries > 9)
133 top.print_entries -= 9;
134} 94}
135 95
136static void sig_winch_handler(int sig __used) 96static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *arg)
137{ 97{
138 get_term_dimensions(&winsize); 98 struct perf_top *top = arg;
139 update_print_entries(&winsize); 99
100 get_term_dimensions(&top->winsize);
101 if (!top->print_entries
102 || (top->print_entries+4) > top->winsize.ws_row) {
103 top->print_entries = top->winsize.ws_row;
104 } else {
105 top->print_entries += 4;
106 top->winsize.ws_row = top->print_entries;
107 }
108 perf_top__update_print_entries(top);
140} 109}
141 110
142static int parse_source(struct hist_entry *he) 111static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
143{ 112{
144 struct symbol *sym; 113 struct symbol *sym;
145 struct annotation *notes; 114 struct annotation *notes;
@@ -170,7 +139,7 @@ static int parse_source(struct hist_entry *he)
170 139
171 pthread_mutex_lock(&notes->lock); 140 pthread_mutex_lock(&notes->lock);
172 141
173 if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) { 142 if (symbol__alloc_hist(sym) < 0) {
174 pthread_mutex_unlock(&notes->lock); 143 pthread_mutex_unlock(&notes->lock);
175 pr_err("Not enough memory for annotating '%s' symbol!\n", 144 pr_err("Not enough memory for annotating '%s' symbol!\n",
176 sym->name); 145 sym->name);
@@ -181,7 +150,7 @@ static int parse_source(struct hist_entry *he)
181 err = symbol__annotate(sym, map, 0); 150 err = symbol__annotate(sym, map, 0);
182 if (err == 0) { 151 if (err == 0) {
183out_assign: 152out_assign:
184 top.sym_filter_entry = he; 153 top->sym_filter_entry = he;
185 } 154 }
186 155
187 pthread_mutex_unlock(&notes->lock); 156 pthread_mutex_unlock(&notes->lock);
@@ -194,14 +163,16 @@ static void __zero_source_counters(struct hist_entry *he)
194 symbol__annotate_zero_histograms(sym); 163 symbol__annotate_zero_histograms(sym);
195} 164}
196 165
197static void record_precise_ip(struct hist_entry *he, int counter, u64 ip) 166static void perf_top__record_precise_ip(struct perf_top *top,
167 struct hist_entry *he,
168 int counter, u64 ip)
198{ 169{
199 struct annotation *notes; 170 struct annotation *notes;
200 struct symbol *sym; 171 struct symbol *sym;
201 172
202 if (he == NULL || he->ms.sym == NULL || 173 if (he == NULL || he->ms.sym == NULL ||
203 ((top.sym_filter_entry == NULL || 174 ((top->sym_filter_entry == NULL ||
204 top.sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1)) 175 top->sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1))
205 return; 176 return;
206 177
207 sym = he->ms.sym; 178 sym = he->ms.sym;
@@ -210,8 +181,7 @@ static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
210 if (pthread_mutex_trylock(&notes->lock)) 181 if (pthread_mutex_trylock(&notes->lock))
211 return; 182 return;
212 183
213 if (notes->src == NULL && 184 if (notes->src == NULL && symbol__alloc_hist(sym) < 0) {
214 symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
215 pthread_mutex_unlock(&notes->lock); 185 pthread_mutex_unlock(&notes->lock);
216 pr_err("Not enough memory for annotating '%s' symbol!\n", 186 pr_err("Not enough memory for annotating '%s' symbol!\n",
217 sym->name); 187 sym->name);
@@ -225,8 +195,9 @@ static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
225 pthread_mutex_unlock(&notes->lock); 195 pthread_mutex_unlock(&notes->lock);
226} 196}
227 197
228static void show_details(struct hist_entry *he) 198static void perf_top__show_details(struct perf_top *top)
229{ 199{
200 struct hist_entry *he = top->sym_filter_entry;
230 struct annotation *notes; 201 struct annotation *notes;
231 struct symbol *symbol; 202 struct symbol *symbol;
232 int more; 203 int more;
@@ -242,15 +213,15 @@ static void show_details(struct hist_entry *he)
242 if (notes->src == NULL) 213 if (notes->src == NULL)
243 goto out_unlock; 214 goto out_unlock;
244 215
245 printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name); 216 printf("Showing %s for %s\n", event_name(top->sym_evsel), symbol->name);
246 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 217 printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter);
247 218
248 more = symbol__annotate_printf(symbol, he->ms.map, top.sym_evsel->idx, 219 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx,
249 0, sym_pcnt_filter, top.print_entries, 4); 220 0, top->sym_pcnt_filter, top->print_entries, 4);
250 if (top.zero) 221 if (top->zero)
251 symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx); 222 symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx);
252 else 223 else
253 symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx); 224 symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx);
254 if (more != 0) 225 if (more != 0)
255 printf("%d lines not displayed, maybe increase display entries [e]\n", more); 226 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
256out_unlock: 227out_unlock:
@@ -259,11 +230,9 @@ out_unlock:
259 230
260static const char CONSOLE_CLEAR[] = ""; 231static const char CONSOLE_CLEAR[] = "";
261 232
262static struct hist_entry * 233static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
263 perf_session__add_hist_entry(struct perf_session *session, 234 struct addr_location *al,
264 struct addr_location *al, 235 struct perf_sample *sample)
265 struct perf_sample *sample,
266 struct perf_evsel *evsel)
267{ 236{
268 struct hist_entry *he; 237 struct hist_entry *he;
269 238
@@ -271,50 +240,50 @@ static struct hist_entry *
271 if (he == NULL) 240 if (he == NULL)
272 return NULL; 241 return NULL;
273 242
274 session->hists.stats.total_period += sample->period;
275 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 243 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
276 return he; 244 return he;
277} 245}
278 246
279static void print_sym_table(void) 247static void perf_top__print_sym_table(struct perf_top *top)
280{ 248{
281 char bf[160]; 249 char bf[160];
282 int printed = 0; 250 int printed = 0;
283 const int win_width = winsize.ws_col - 1; 251 const int win_width = top->winsize.ws_col - 1;
284 252
285 puts(CONSOLE_CLEAR); 253 puts(CONSOLE_CLEAR);
286 254
287 perf_top__header_snprintf(&top, bf, sizeof(bf)); 255 perf_top__header_snprintf(top, bf, sizeof(bf));
288 printf("%s\n", bf); 256 printf("%s\n", bf);
289 257
290 perf_top__reset_sample_counters(&top); 258 perf_top__reset_sample_counters(top);
291 259
292 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 260 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
293 261
294 if (top.sym_evsel->hists.stats.nr_lost_warned != 262 if (top->sym_evsel->hists.stats.nr_lost_warned !=
295 top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) { 263 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) {
296 top.sym_evsel->hists.stats.nr_lost_warned = 264 top->sym_evsel->hists.stats.nr_lost_warned =
297 top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]; 265 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST];
298 color_fprintf(stdout, PERF_COLOR_RED, 266 color_fprintf(stdout, PERF_COLOR_RED,
299 "WARNING: LOST %d chunks, Check IO/CPU overload", 267 "WARNING: LOST %d chunks, Check IO/CPU overload",
300 top.sym_evsel->hists.stats.nr_lost_warned); 268 top->sym_evsel->hists.stats.nr_lost_warned);
301 ++printed; 269 ++printed;
302 } 270 }
303 271
304 if (top.sym_filter_entry) { 272 if (top->sym_filter_entry) {
305 show_details(top.sym_filter_entry); 273 perf_top__show_details(top);
306 return; 274 return;
307 } 275 }
308 276
309 hists__collapse_resort_threaded(&top.sym_evsel->hists); 277 hists__collapse_resort_threaded(&top->sym_evsel->hists);
310 hists__output_resort_threaded(&top.sym_evsel->hists); 278 hists__output_resort_threaded(&top->sym_evsel->hists);
311 hists__decay_entries_threaded(&top.sym_evsel->hists, 279 hists__decay_entries_threaded(&top->sym_evsel->hists,
312 top.hide_user_symbols, 280 top->hide_user_symbols,
313 top.hide_kernel_symbols); 281 top->hide_kernel_symbols);
314 hists__output_recalc_col_len(&top.sym_evsel->hists, winsize.ws_row - 3); 282 hists__output_recalc_col_len(&top->sym_evsel->hists,
283 top->winsize.ws_row - 3);
315 putchar('\n'); 284 putchar('\n');
316 hists__fprintf(&top.sym_evsel->hists, NULL, false, false, 285 hists__fprintf(&top->sym_evsel->hists, NULL, false, false,
317 winsize.ws_row - 4 - printed, win_width, stdout); 286 top->winsize.ws_row - 4 - printed, win_width, stdout);
318} 287}
319 288
320static void prompt_integer(int *target, const char *msg) 289static void prompt_integer(int *target, const char *msg)
@@ -352,17 +321,17 @@ static void prompt_percent(int *target, const char *msg)
352 *target = tmp; 321 *target = tmp;
353} 322}
354 323
355static void prompt_symbol(struct hist_entry **target, const char *msg) 324static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
356{ 325{
357 char *buf = malloc(0), *p; 326 char *buf = malloc(0), *p;
358 struct hist_entry *syme = *target, *n, *found = NULL; 327 struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL;
359 struct rb_node *next; 328 struct rb_node *next;
360 size_t dummy = 0; 329 size_t dummy = 0;
361 330
362 /* zero counters of active symbol */ 331 /* zero counters of active symbol */
363 if (syme) { 332 if (syme) {
364 __zero_source_counters(syme); 333 __zero_source_counters(syme);
365 *target = NULL; 334 top->sym_filter_entry = NULL;
366 } 335 }
367 336
368 fprintf(stdout, "\n%s: ", msg); 337 fprintf(stdout, "\n%s: ", msg);
@@ -373,7 +342,7 @@ static void prompt_symbol(struct hist_entry **target, const char *msg)
373 if (p) 342 if (p)
374 *p = 0; 343 *p = 0;
375 344
376 next = rb_first(&top.sym_evsel->hists.entries); 345 next = rb_first(&top->sym_evsel->hists.entries);
377 while (next) { 346 while (next) {
378 n = rb_entry(next, struct hist_entry, rb_node); 347 n = rb_entry(next, struct hist_entry, rb_node);
379 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) { 348 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
@@ -386,47 +355,46 @@ static void prompt_symbol(struct hist_entry **target, const char *msg)
386 if (!found) { 355 if (!found) {
387 fprintf(stderr, "Sorry, %s is not active.\n", buf); 356 fprintf(stderr, "Sorry, %s is not active.\n", buf);
388 sleep(1); 357 sleep(1);
389 return;
390 } else 358 } else
391 parse_source(found); 359 perf_top__parse_source(top, found);
392 360
393out_free: 361out_free:
394 free(buf); 362 free(buf);
395} 363}
396 364
397static void print_mapped_keys(void) 365static void perf_top__print_mapped_keys(struct perf_top *top)
398{ 366{
399 char *name = NULL; 367 char *name = NULL;
400 368
401 if (top.sym_filter_entry) { 369 if (top->sym_filter_entry) {
402 struct symbol *sym = top.sym_filter_entry->ms.sym; 370 struct symbol *sym = top->sym_filter_entry->ms.sym;
403 name = sym->name; 371 name = sym->name;
404 } 372 }
405 373
406 fprintf(stdout, "\nMapped keys:\n"); 374 fprintf(stdout, "\nMapped keys:\n");
407 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top.delay_secs); 375 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top->delay_secs);
408 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top.print_entries); 376 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top->print_entries);
409 377
410 if (top.evlist->nr_entries > 1) 378 if (top->evlist->nr_entries > 1)
411 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top.sym_evsel)); 379 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top->sym_evsel));
412 380
413 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top.count_filter); 381 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter);
414 382
415 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 383 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", top->sym_pcnt_filter);
416 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 384 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
417 fprintf(stdout, "\t[S] stop annotation.\n"); 385 fprintf(stdout, "\t[S] stop annotation.\n");
418 386
419 fprintf(stdout, 387 fprintf(stdout,
420 "\t[K] hide kernel_symbols symbols. \t(%s)\n", 388 "\t[K] hide kernel_symbols symbols. \t(%s)\n",
421 top.hide_kernel_symbols ? "yes" : "no"); 389 top->hide_kernel_symbols ? "yes" : "no");
422 fprintf(stdout, 390 fprintf(stdout,
423 "\t[U] hide user symbols. \t(%s)\n", 391 "\t[U] hide user symbols. \t(%s)\n",
424 top.hide_user_symbols ? "yes" : "no"); 392 top->hide_user_symbols ? "yes" : "no");
425 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", top.zero ? 1 : 0); 393 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", top->zero ? 1 : 0);
426 fprintf(stdout, "\t[qQ] quit.\n"); 394 fprintf(stdout, "\t[qQ] quit.\n");
427} 395}
428 396
429static int key_mapped(int c) 397static int perf_top__key_mapped(struct perf_top *top, int c)
430{ 398{
431 switch (c) { 399 switch (c) {
432 case 'd': 400 case 'd':
@@ -442,7 +410,7 @@ static int key_mapped(int c)
442 case 'S': 410 case 'S':
443 return 1; 411 return 1;
444 case 'E': 412 case 'E':
445 return top.evlist->nr_entries > 1 ? 1 : 0; 413 return top->evlist->nr_entries > 1 ? 1 : 0;
446 default: 414 default:
447 break; 415 break;
448 } 416 }
@@ -450,13 +418,13 @@ static int key_mapped(int c)
450 return 0; 418 return 0;
451} 419}
452 420
453static void handle_keypress(int c) 421static void perf_top__handle_keypress(struct perf_top *top, int c)
454{ 422{
455 if (!key_mapped(c)) { 423 if (!perf_top__key_mapped(top, c)) {
456 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 424 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
457 struct termios tc, save; 425 struct termios tc, save;
458 426
459 print_mapped_keys(); 427 perf_top__print_mapped_keys(top);
460 fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 428 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
461 fflush(stdout); 429 fflush(stdout);
462 430
@@ -471,81 +439,88 @@ static void handle_keypress(int c)
471 c = getc(stdin); 439 c = getc(stdin);
472 440
473 tcsetattr(0, TCSAFLUSH, &save); 441 tcsetattr(0, TCSAFLUSH, &save);
474 if (!key_mapped(c)) 442 if (!perf_top__key_mapped(top, c))
475 return; 443 return;
476 } 444 }
477 445
478 switch (c) { 446 switch (c) {
479 case 'd': 447 case 'd':
480 prompt_integer(&top.delay_secs, "Enter display delay"); 448 prompt_integer(&top->delay_secs, "Enter display delay");
481 if (top.delay_secs < 1) 449 if (top->delay_secs < 1)
482 top.delay_secs = 1; 450 top->delay_secs = 1;
483 break; 451 break;
484 case 'e': 452 case 'e':
485 prompt_integer(&top.print_entries, "Enter display entries (lines)"); 453 prompt_integer(&top->print_entries, "Enter display entries (lines)");
486 if (top.print_entries == 0) { 454 if (top->print_entries == 0) {
487 sig_winch_handler(SIGWINCH); 455 struct sigaction act = {
488 signal(SIGWINCH, sig_winch_handler); 456 .sa_sigaction = perf_top__sig_winch,
489 } else 457 .sa_flags = SA_SIGINFO,
458 };
459 perf_top__sig_winch(SIGWINCH, NULL, top);
460 sigaction(SIGWINCH, &act, NULL);
461 } else {
462 perf_top__sig_winch(SIGWINCH, NULL, top);
490 signal(SIGWINCH, SIG_DFL); 463 signal(SIGWINCH, SIG_DFL);
464 }
491 break; 465 break;
492 case 'E': 466 case 'E':
493 if (top.evlist->nr_entries > 1) { 467 if (top->evlist->nr_entries > 1) {
494 /* Select 0 as the default event: */ 468 /* Select 0 as the default event: */
495 int counter = 0; 469 int counter = 0;
496 470
497 fprintf(stderr, "\nAvailable events:"); 471 fprintf(stderr, "\nAvailable events:");
498 472
499 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) 473 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
500 fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel)); 474 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, event_name(top->sym_evsel));
501 475
502 prompt_integer(&counter, "Enter details event counter"); 476 prompt_integer(&counter, "Enter details event counter");
503 477
504 if (counter >= top.evlist->nr_entries) { 478 if (counter >= top->evlist->nr_entries) {
505 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 479 top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
506 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel)); 480 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top->sym_evsel));
507 sleep(1); 481 sleep(1);
508 break; 482 break;
509 } 483 }
510 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) 484 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
511 if (top.sym_evsel->idx == counter) 485 if (top->sym_evsel->idx == counter)
512 break; 486 break;
513 } else 487 } else
514 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 488 top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
515 break; 489 break;
516 case 'f': 490 case 'f':
517 prompt_integer(&top.count_filter, "Enter display event count filter"); 491 prompt_integer(&top->count_filter, "Enter display event count filter");
518 break; 492 break;
519 case 'F': 493 case 'F':
520 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)"); 494 prompt_percent(&top->sym_pcnt_filter,
495 "Enter details display event filter (percent)");
521 break; 496 break;
522 case 'K': 497 case 'K':
523 top.hide_kernel_symbols = !top.hide_kernel_symbols; 498 top->hide_kernel_symbols = !top->hide_kernel_symbols;
524 break; 499 break;
525 case 'q': 500 case 'q':
526 case 'Q': 501 case 'Q':
527 printf("exiting.\n"); 502 printf("exiting.\n");
528 if (dump_symtab) 503 if (top->dump_symtab)
529 perf_session__fprintf_dsos(top.session, stderr); 504 perf_session__fprintf_dsos(top->session, stderr);
530 exit(0); 505 exit(0);
531 case 's': 506 case 's':
532 prompt_symbol(&top.sym_filter_entry, "Enter details symbol"); 507 perf_top__prompt_symbol(top, "Enter details symbol");
533 break; 508 break;
534 case 'S': 509 case 'S':
535 if (!top.sym_filter_entry) 510 if (!top->sym_filter_entry)
536 break; 511 break;
537 else { 512 else {
538 struct hist_entry *syme = top.sym_filter_entry; 513 struct hist_entry *syme = top->sym_filter_entry;
539 514
540 top.sym_filter_entry = NULL; 515 top->sym_filter_entry = NULL;
541 __zero_source_counters(syme); 516 __zero_source_counters(syme);
542 } 517 }
543 break; 518 break;
544 case 'U': 519 case 'U':
545 top.hide_user_symbols = !top.hide_user_symbols; 520 top->hide_user_symbols = !top->hide_user_symbols;
546 break; 521 break;
547 case 'z': 522 case 'z':
548 top.zero = !top.zero; 523 top->zero = !top->zero;
549 break; 524 break;
550 default: 525 default:
551 break; 526 break;
@@ -563,28 +538,30 @@ static void perf_top__sort_new_samples(void *arg)
563 hists__collapse_resort_threaded(&t->sym_evsel->hists); 538 hists__collapse_resort_threaded(&t->sym_evsel->hists);
564 hists__output_resort_threaded(&t->sym_evsel->hists); 539 hists__output_resort_threaded(&t->sym_evsel->hists);
565 hists__decay_entries_threaded(&t->sym_evsel->hists, 540 hists__decay_entries_threaded(&t->sym_evsel->hists,
566 top.hide_user_symbols, 541 t->hide_user_symbols,
567 top.hide_kernel_symbols); 542 t->hide_kernel_symbols);
568} 543}
569 544
570static void *display_thread_tui(void *arg __used) 545static void *display_thread_tui(void *arg)
571{ 546{
547 struct perf_top *top = arg;
572 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";
573 549
574 perf_top__sort_new_samples(&top); 550 perf_top__sort_new_samples(top);
575 perf_evlist__tui_browse_hists(top.evlist, help, 551 perf_evlist__tui_browse_hists(top->evlist, help,
576 perf_top__sort_new_samples, 552 perf_top__sort_new_samples,
577 &top, top.delay_secs); 553 top, top->delay_secs);
578 554
579 exit_browser(0); 555 exit_browser(0);
580 exit(0); 556 exit(0);
581 return NULL; 557 return NULL;
582} 558}
583 559
584static void *display_thread(void *arg __used) 560static void *display_thread(void *arg)
585{ 561{
586 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 562 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
587 struct termios tc, save; 563 struct termios tc, save;
564 struct perf_top *top = arg;
588 int delay_msecs, c; 565 int delay_msecs, c;
589 566
590 tcgetattr(0, &save); 567 tcgetattr(0, &save);
@@ -595,13 +572,13 @@ static void *display_thread(void *arg __used)
595 572
596 pthread__unblock_sigwinch(); 573 pthread__unblock_sigwinch();
597repeat: 574repeat:
598 delay_msecs = top.delay_secs * 1000; 575 delay_msecs = top->delay_secs * 1000;
599 tcsetattr(0, TCSANOW, &tc); 576 tcsetattr(0, TCSANOW, &tc);
600 /* trash return*/ 577 /* trash return*/
601 getc(stdin); 578 getc(stdin);
602 579
603 while (1) { 580 while (1) {
604 print_sym_table(); 581 perf_top__print_sym_table(top);
605 /* 582 /*
606 * Either timeout expired or we got an EINTR due to SIGWINCH, 583 * Either timeout expired or we got an EINTR due to SIGWINCH,
607 * refresh screen in both cases. 584 * refresh screen in both cases.
@@ -621,7 +598,7 @@ process_hotkey:
621 c = getc(stdin); 598 c = getc(stdin);
622 tcsetattr(0, TCSAFLUSH, &save); 599 tcsetattr(0, TCSAFLUSH, &save);
623 600
624 handle_keypress(c); 601 perf_top__handle_keypress(top, c);
625 goto repeat; 602 goto repeat;
626 603
627 return NULL; 604 return NULL;
@@ -673,47 +650,17 @@ static int symbol_filter(struct map *map __used, struct symbol *sym)
673 return 0; 650 return 0;
674} 651}
675 652
676static void perf_event__process_sample(const union perf_event *event, 653static void perf_event__process_sample(struct perf_tool *tool,
654 const union perf_event *event,
677 struct perf_evsel *evsel, 655 struct perf_evsel *evsel,
678 struct perf_sample *sample, 656 struct perf_sample *sample,
679 struct perf_session *session) 657 struct machine *machine)
680{ 658{
659 struct perf_top *top = container_of(tool, struct perf_top, tool);
681 struct symbol *parent = NULL; 660 struct symbol *parent = NULL;
682 u64 ip = event->ip.ip; 661 u64 ip = event->ip.ip;
683 struct addr_location al; 662 struct addr_location al;
684 struct machine *machine;
685 int err; 663 int err;
686 u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
687
688 ++top.samples;
689
690 switch (origin) {
691 case PERF_RECORD_MISC_USER:
692 ++top.us_samples;
693 if (top.hide_user_symbols)
694 return;
695 machine = perf_session__find_host_machine(session);
696 break;
697 case PERF_RECORD_MISC_KERNEL:
698 ++top.kernel_samples;
699 if (top.hide_kernel_symbols)
700 return;
701 machine = perf_session__find_host_machine(session);
702 break;
703 case PERF_RECORD_MISC_GUEST_KERNEL:
704 ++top.guest_kernel_samples;
705 machine = perf_session__find_machine(session, event->ip.pid);
706 break;
707 case PERF_RECORD_MISC_GUEST_USER:
708 ++top.guest_us_samples;
709 /*
710 * TODO: we don't process guest user from host side
711 * except simple counting.
712 */
713 return;
714 default:
715 return;
716 }
717 664
718 if (!machine && perf_guest) { 665 if (!machine && perf_guest) {
719 pr_err("Can't find guest [%d]'s kernel information\n", 666 pr_err("Can't find guest [%d]'s kernel information\n",
@@ -722,14 +669,14 @@ static void perf_event__process_sample(const union perf_event *event,
722 } 669 }
723 670
724 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) 671 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
725 top.exact_samples++; 672 top->exact_samples++;
726 673
727 if (perf_event__preprocess_sample(event, session, &al, sample, 674 if (perf_event__preprocess_sample(event, machine, &al, sample,
728 symbol_filter) < 0 || 675 symbol_filter) < 0 ||
729 al.filtered) 676 al.filtered)
730 return; 677 return;
731 678
732 if (!kptr_restrict_warned && 679 if (!top->kptr_restrict_warned &&
733 symbol_conf.kptr_restrict && 680 symbol_conf.kptr_restrict &&
734 al.cpumode == PERF_RECORD_MISC_KERNEL) { 681 al.cpumode == PERF_RECORD_MISC_KERNEL) {
735 ui__warning( 682 ui__warning(
@@ -740,7 +687,7 @@ static void perf_event__process_sample(const union perf_event *event,
740 " modules" : ""); 687 " modules" : "");
741 if (use_browser <= 0) 688 if (use_browser <= 0)
742 sleep(5); 689 sleep(5);
743 kptr_restrict_warned = true; 690 top->kptr_restrict_warned = true;
744 } 691 }
745 692
746 if (al.sym == NULL) { 693 if (al.sym == NULL) {
@@ -756,7 +703,7 @@ static void perf_event__process_sample(const union perf_event *event,
756 * --hide-kernel-symbols, even if the user specifies an 703 * --hide-kernel-symbols, even if the user specifies an
757 * invalid --vmlinux ;-) 704 * invalid --vmlinux ;-)
758 */ 705 */
759 if (!kptr_restrict_warned && !vmlinux_warned && 706 if (!top->kptr_restrict_warned && !top->vmlinux_warned &&
760 al.map == machine->vmlinux_maps[MAP__FUNCTION] && 707 al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
761 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 708 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
762 if (symbol_conf.vmlinux_name) { 709 if (symbol_conf.vmlinux_name) {
@@ -769,7 +716,7 @@ static void perf_event__process_sample(const union perf_event *event,
769 716
770 if (use_browser <= 0) 717 if (use_browser <= 0)
771 sleep(5); 718 sleep(5);
772 vmlinux_warned = true; 719 top->vmlinux_warned = true;
773 } 720 }
774 } 721 }
775 722
@@ -778,70 +725,109 @@ static void perf_event__process_sample(const union perf_event *event,
778 725
779 if ((sort__has_parent || symbol_conf.use_callchain) && 726 if ((sort__has_parent || symbol_conf.use_callchain) &&
780 sample->callchain) { 727 sample->callchain) {
781 err = perf_session__resolve_callchain(session, al.thread, 728 err = machine__resolve_callchain(machine, evsel, al.thread,
782 sample->callchain, &parent); 729 sample->callchain, &parent);
783 if (err) 730 if (err)
784 return; 731 return;
785 } 732 }
786 733
787 he = perf_session__add_hist_entry(session, &al, sample, evsel); 734 he = perf_evsel__add_hist_entry(evsel, &al, sample);
788 if (he == NULL) { 735 if (he == NULL) {
789 pr_err("Problem incrementing symbol period, skipping event\n"); 736 pr_err("Problem incrementing symbol period, skipping event\n");
790 return; 737 return;
791 } 738 }
792 739
793 if (symbol_conf.use_callchain) { 740 if (symbol_conf.use_callchain) {
794 err = callchain_append(he->callchain, &session->callchain_cursor, 741 err = callchain_append(he->callchain, &evsel->hists.callchain_cursor,
795 sample->period); 742 sample->period);
796 if (err) 743 if (err)
797 return; 744 return;
798 } 745 }
799 746
800 if (sort_has_symbols) 747 if (top->sort_has_symbols)
801 record_precise_ip(he, evsel->idx, ip); 748 perf_top__record_precise_ip(top, he, evsel->idx, ip);
802 } 749 }
803 750
804 return; 751 return;
805} 752}
806 753
807static void perf_session__mmap_read_idx(struct perf_session *self, int idx) 754static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
808{ 755{
809 struct perf_sample sample; 756 struct perf_sample sample;
810 struct perf_evsel *evsel; 757 struct perf_evsel *evsel;
758 struct perf_session *session = top->session;
811 union perf_event *event; 759 union perf_event *event;
760 struct machine *machine;
761 u8 origin;
812 int ret; 762 int ret;
813 763
814 while ((event = perf_evlist__mmap_read(top.evlist, idx)) != NULL) { 764 while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
815 ret = perf_session__parse_sample(self, event, &sample); 765 ret = perf_session__parse_sample(session, event, &sample);
816 if (ret) { 766 if (ret) {
817 pr_err("Can't parse sample, err = %d\n", ret); 767 pr_err("Can't parse sample, err = %d\n", ret);
818 continue; 768 continue;
819 } 769 }
820 770
821 evsel = perf_evlist__id2evsel(self->evlist, sample.id); 771 evsel = perf_evlist__id2evsel(session->evlist, sample.id);
822 assert(evsel != NULL); 772 assert(evsel != NULL);
823 773
774 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
775
824 if (event->header.type == PERF_RECORD_SAMPLE) 776 if (event->header.type == PERF_RECORD_SAMPLE)
825 perf_event__process_sample(event, evsel, &sample, self); 777 ++top->samples;
826 else if (event->header.type < PERF_RECORD_MAX) { 778
779 switch (origin) {
780 case PERF_RECORD_MISC_USER:
781 ++top->us_samples;
782 if (top->hide_user_symbols)
783 continue;
784 machine = perf_session__find_host_machine(session);
785 break;
786 case PERF_RECORD_MISC_KERNEL:
787 ++top->kernel_samples;
788 if (top->hide_kernel_symbols)
789 continue;
790 machine = perf_session__find_host_machine(session);
791 break;
792 case PERF_RECORD_MISC_GUEST_KERNEL:
793 ++top->guest_kernel_samples;
794 machine = perf_session__find_machine(session, event->ip.pid);
795 break;
796 case PERF_RECORD_MISC_GUEST_USER:
797 ++top->guest_us_samples;
798 /*
799 * TODO: we don't process guest user from host side
800 * except simple counting.
801 */
802 /* Fall thru */
803 default:
804 continue;
805 }
806
807
808 if (event->header.type == PERF_RECORD_SAMPLE) {
809 perf_event__process_sample(&top->tool, event, evsel,
810 &sample, machine);
811 } else if (event->header.type < PERF_RECORD_MAX) {
827 hists__inc_nr_events(&evsel->hists, event->header.type); 812 hists__inc_nr_events(&evsel->hists, event->header.type);
828 perf_event__process(event, &sample, self); 813 perf_event__process(&top->tool, event, &sample, machine);
829 } else 814 } else
830 ++self->hists.stats.nr_unknown_events; 815 ++session->hists.stats.nr_unknown_events;
831 } 816 }
832} 817}
833 818
834static void perf_session__mmap_read(struct perf_session *self) 819static void perf_top__mmap_read(struct perf_top *top)
835{ 820{
836 int i; 821 int i;
837 822
838 for (i = 0; i < top.evlist->nr_mmaps; i++) 823 for (i = 0; i < top->evlist->nr_mmaps; i++)
839 perf_session__mmap_read_idx(self, i); 824 perf_top__mmap_read_idx(top, i);
840} 825}
841 826
842static void start_counters(struct perf_evlist *evlist) 827static void perf_top__start_counters(struct perf_top *top)
843{ 828{
844 struct perf_evsel *counter, *first; 829 struct perf_evsel *counter, *first;
830 struct perf_evlist *evlist = top->evlist;
845 831
846 first = list_entry(evlist->entries.next, struct perf_evsel, node); 832 first = list_entry(evlist->entries.next, struct perf_evsel, node);
847 833
@@ -849,15 +835,15 @@ static void start_counters(struct perf_evlist *evlist)
849 struct perf_event_attr *attr = &counter->attr; 835 struct perf_event_attr *attr = &counter->attr;
850 struct xyarray *group_fd = NULL; 836 struct xyarray *group_fd = NULL;
851 837
852 if (group && counter != first) 838 if (top->group && counter != first)
853 group_fd = first->fd; 839 group_fd = first->fd;
854 840
855 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 841 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
856 842
857 if (top.freq) { 843 if (top->freq) {
858 attr->sample_type |= PERF_SAMPLE_PERIOD; 844 attr->sample_type |= PERF_SAMPLE_PERIOD;
859 attr->freq = 1; 845 attr->freq = 1;
860 attr->sample_freq = top.freq; 846 attr->sample_freq = top->freq;
861 } 847 }
862 848
863 if (evlist->nr_entries > 1) { 849 if (evlist->nr_entries > 1) {
@@ -870,24 +856,35 @@ static void start_counters(struct perf_evlist *evlist)
870 856
871 attr->mmap = 1; 857 attr->mmap = 1;
872 attr->comm = 1; 858 attr->comm = 1;
873 attr->inherit = inherit; 859 attr->inherit = top->inherit;
860fallback_missing_features:
861 if (top->exclude_guest_missing)
862 attr->exclude_guest = attr->exclude_host = 0;
874retry_sample_id: 863retry_sample_id:
875 attr->sample_id_all = sample_id_all_avail ? 1 : 0; 864 attr->sample_id_all = top->sample_id_all_avail ? 1 : 0;
876try_again: 865try_again:
877 if (perf_evsel__open(counter, top.evlist->cpus, 866 if (perf_evsel__open(counter, top->evlist->cpus,
878 top.evlist->threads, group, 867 top->evlist->threads, top->group,
879 group_fd) < 0) { 868 group_fd) < 0) {
880 int err = errno; 869 int err = errno;
881 870
882 if (err == EPERM || err == EACCES) { 871 if (err == EPERM || err == EACCES) {
883 ui__error_paranoid(); 872 ui__error_paranoid();
884 goto out_err; 873 goto out_err;
885 } else if (err == EINVAL && sample_id_all_avail) { 874 } else if (err == EINVAL) {
886 /* 875 if (!top->exclude_guest_missing &&
887 * Old kernel, no attr->sample_id_type_all field 876 (attr->exclude_guest || attr->exclude_host)) {
888 */ 877 pr_debug("Old kernel, cannot exclude "
889 sample_id_all_avail = false; 878 "guest or host samples.\n");
890 goto retry_sample_id; 879 top->exclude_guest_missing = true;
880 goto fallback_missing_features;
881 } else if (top->sample_id_all_avail) {
882 /*
883 * Old kernel, no attr->sample_id_type_all field
884 */
885 top->sample_id_all_avail = false;
886 goto retry_sample_id;
887 }
891 } 888 }
892 /* 889 /*
893 * If it's cycles then fall back to hrtimer 890 * If it's cycles then fall back to hrtimer
@@ -909,6 +906,10 @@ try_again:
909 ui__warning("The %s event is not supported.\n", 906 ui__warning("The %s event is not supported.\n",
910 event_name(counter)); 907 event_name(counter));
911 goto out_err; 908 goto out_err;
909 } else if (err == EMFILE) {
910 ui__warning("Too many events are opened.\n"
911 "Try again after reducing the number of events\n");
912 goto out_err;
912 } 913 }
913 914
914 ui__warning("The sys_perf_event_open() syscall " 915 ui__warning("The sys_perf_event_open() syscall "
@@ -920,7 +921,7 @@ try_again:
920 } 921 }
921 } 922 }
922 923
923 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) { 924 if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) {
924 ui__warning("Failed to mmap with %d (%s)\n", 925 ui__warning("Failed to mmap with %d (%s)\n",
925 errno, strerror(errno)); 926 errno, strerror(errno));
926 goto out_err; 927 goto out_err;
@@ -933,14 +934,14 @@ out_err:
933 exit(0); 934 exit(0);
934} 935}
935 936
936static int setup_sample_type(void) 937static int perf_top__setup_sample_type(struct perf_top *top)
937{ 938{
938 if (!sort_has_symbols) { 939 if (!top->sort_has_symbols) {
939 if (symbol_conf.use_callchain) { 940 if (symbol_conf.use_callchain) {
940 ui__warning("Selected -g but \"sym\" not present in --sort/-s."); 941 ui__warning("Selected -g but \"sym\" not present in --sort/-s.");
941 return -EINVAL; 942 return -EINVAL;
942 } 943 }
943 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE) { 944 } else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) {
944 if (callchain_register_param(&callchain_param) < 0) { 945 if (callchain_register_param(&callchain_param) < 0) {
945 ui__warning("Can't register callchain params.\n"); 946 ui__warning("Can't register callchain params.\n");
946 return -EINVAL; 947 return -EINVAL;
@@ -950,7 +951,7 @@ static int setup_sample_type(void)
950 return 0; 951 return 0;
951} 952}
952 953
953static int __cmd_top(void) 954static int __cmd_top(struct perf_top *top)
954{ 955{
955 pthread_t thread; 956 pthread_t thread;
956 int ret; 957 int ret;
@@ -958,39 +959,40 @@ static int __cmd_top(void)
958 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 959 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
959 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 960 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
960 */ 961 */
961 top.session = perf_session__new(NULL, O_WRONLY, false, false, NULL); 962 top->session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
962 if (top.session == NULL) 963 if (top->session == NULL)
963 return -ENOMEM; 964 return -ENOMEM;
964 965
965 ret = setup_sample_type(); 966 ret = perf_top__setup_sample_type(top);
966 if (ret) 967 if (ret)
967 goto out_delete; 968 goto out_delete;
968 969
969 if (top.target_tid != -1) 970 if (top->target_tid != -1)
970 perf_event__synthesize_thread_map(top.evlist->threads, 971 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
971 perf_event__process, top.session); 972 perf_event__process,
973 &top->session->host_machine);
972 else 974 else
973 perf_event__synthesize_threads(perf_event__process, top.session); 975 perf_event__synthesize_threads(&top->tool, perf_event__process,
974 976 &top->session->host_machine);
975 start_counters(top.evlist); 977 perf_top__start_counters(top);
976 top.session->evlist = top.evlist; 978 top->session->evlist = top->evlist;
977 perf_session__update_sample_type(top.session); 979 perf_session__update_sample_type(top->session);
978 980
979 /* Wait for a minimal set of events before starting the snapshot */ 981 /* Wait for a minimal set of events before starting the snapshot */
980 poll(top.evlist->pollfd, top.evlist->nr_fds, 100); 982 poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
981 983
982 perf_session__mmap_read(top.session); 984 perf_top__mmap_read(top);
983 985
984 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : 986 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
985 display_thread), NULL)) { 987 display_thread), top)) {
986 printf("Could not create display thread.\n"); 988 printf("Could not create display thread.\n");
987 exit(-1); 989 exit(-1);
988 } 990 }
989 991
990 if (realtime_prio) { 992 if (top->realtime_prio) {
991 struct sched_param param; 993 struct sched_param param;
992 994
993 param.sched_priority = realtime_prio; 995 param.sched_priority = top->realtime_prio;
994 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 996 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
995 printf("Could not set realtime priority.\n"); 997 printf("Could not set realtime priority.\n");
996 exit(-1); 998 exit(-1);
@@ -998,25 +1000,25 @@ static int __cmd_top(void)
998 } 1000 }
999 1001
1000 while (1) { 1002 while (1) {
1001 u64 hits = top.samples; 1003 u64 hits = top->samples;
1002 1004
1003 perf_session__mmap_read(top.session); 1005 perf_top__mmap_read(top);
1004 1006
1005 if (hits == top.samples) 1007 if (hits == top->samples)
1006 ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100); 1008 ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
1007 } 1009 }
1008 1010
1009out_delete: 1011out_delete:
1010 perf_session__delete(top.session); 1012 perf_session__delete(top->session);
1011 top.session = NULL; 1013 top->session = NULL;
1012 1014
1013 return 0; 1015 return 0;
1014} 1016}
1015 1017
1016static int 1018static int
1017parse_callchain_opt(const struct option *opt __used, const char *arg, 1019parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1018 int unset)
1019{ 1020{
1021 struct perf_top *top = (struct perf_top *)opt->value;
1020 char *tok, *tok2; 1022 char *tok, *tok2;
1021 char *endptr; 1023 char *endptr;
1022 1024
@@ -1024,7 +1026,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
1024 * --no-call-graph 1026 * --no-call-graph
1025 */ 1027 */
1026 if (unset) { 1028 if (unset) {
1027 dont_use_callchains = true; 1029 top->dont_use_callchains = true;
1028 return 0; 1030 return 0;
1029 } 1031 }
1030 1032
@@ -1052,9 +1054,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
1052 symbol_conf.use_callchain = false; 1054 symbol_conf.use_callchain = false;
1053 1055
1054 return 0; 1056 return 0;
1055 } 1057 } else
1056
1057 else
1058 return -1; 1058 return -1;
1059 1059
1060 /* get the min percentage */ 1060 /* get the min percentage */
@@ -1098,17 +1098,32 @@ static const char * const top_usage[] = {
1098 NULL 1098 NULL
1099}; 1099};
1100 1100
1101static const struct option options[] = { 1101int cmd_top(int argc, const char **argv, const char *prefix __used)
1102{
1103 struct perf_evsel *pos;
1104 int status = -ENOMEM;
1105 struct perf_top top = {
1106 .count_filter = 5,
1107 .delay_secs = 2,
1108 .target_pid = -1,
1109 .target_tid = -1,
1110 .freq = 1000, /* 1 KHz */
1111 .sample_id_all_avail = true,
1112 .mmap_pages = 128,
1113 .sym_pcnt_filter = 5,
1114 };
1115 char callchain_default_opt[] = "fractal,0.5,callee";
1116 const struct option options[] = {
1102 OPT_CALLBACK('e', "event", &top.evlist, "event", 1117 OPT_CALLBACK('e', "event", &top.evlist, "event",
1103 "event selector. use 'perf list' to list available events", 1118 "event selector. use 'perf list' to list available events",
1104 parse_events_option), 1119 parse_events_option),
1105 OPT_INTEGER('c', "count", &default_interval, 1120 OPT_INTEGER('c', "count", &top.default_interval,
1106 "event period to sample"), 1121 "event period to sample"),
1107 OPT_INTEGER('p', "pid", &top.target_pid, 1122 OPT_INTEGER('p', "pid", &top.target_pid,
1108 "profile events on existing process id"), 1123 "profile events on existing process id"),
1109 OPT_INTEGER('t', "tid", &top.target_tid, 1124 OPT_INTEGER('t', "tid", &top.target_tid,
1110 "profile events on existing thread id"), 1125 "profile events on existing thread id"),
1111 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1126 OPT_BOOLEAN('a', "all-cpus", &top.system_wide,
1112 "system-wide collection from all CPUs"), 1127 "system-wide collection from all CPUs"),
1113 OPT_STRING('C', "cpu", &top.cpu_list, "cpu", 1128 OPT_STRING('C', "cpu", &top.cpu_list, "cpu",
1114 "list of cpus to monitor"), 1129 "list of cpus to monitor"),
@@ -1116,20 +1131,20 @@ static const struct option options[] = {
1116 "file", "vmlinux pathname"), 1131 "file", "vmlinux pathname"),
1117 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 1132 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1118 "hide kernel symbols"), 1133 "hide kernel symbols"),
1119 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 1134 OPT_UINTEGER('m', "mmap-pages", &top.mmap_pages, "number of mmap data pages"),
1120 OPT_INTEGER('r', "realtime", &realtime_prio, 1135 OPT_INTEGER('r', "realtime", &top.realtime_prio,
1121 "collect data with this RT SCHED_FIFO priority"), 1136 "collect data with this RT SCHED_FIFO priority"),
1122 OPT_INTEGER('d', "delay", &top.delay_secs, 1137 OPT_INTEGER('d', "delay", &top.delay_secs,
1123 "number of seconds to delay between refreshes"), 1138 "number of seconds to delay between refreshes"),
1124 OPT_BOOLEAN('D', "dump-symtab", &dump_symtab, 1139 OPT_BOOLEAN('D', "dump-symtab", &top.dump_symtab,
1125 "dump the symbol table used for profiling"), 1140 "dump the symbol table used for profiling"),
1126 OPT_INTEGER('f', "count-filter", &top.count_filter, 1141 OPT_INTEGER('f', "count-filter", &top.count_filter,
1127 "only display functions with more events than this"), 1142 "only display functions with more events than this"),
1128 OPT_BOOLEAN('g', "group", &group, 1143 OPT_BOOLEAN('g', "group", &top.group,
1129 "put the counters into a counter group"), 1144 "put the counters into a counter group"),
1130 OPT_BOOLEAN('i', "inherit", &inherit, 1145 OPT_BOOLEAN('i', "inherit", &top.inherit,
1131 "child tasks inherit counters"), 1146 "child tasks inherit counters"),
1132 OPT_STRING(0, "sym-annotate", &sym_filter, "symbol name", 1147 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
1133 "symbol to annotate"), 1148 "symbol to annotate"),
1134 OPT_BOOLEAN('z', "zero", &top.zero, 1149 OPT_BOOLEAN('z', "zero", &top.zero,
1135 "zero history across updates"), 1150 "zero history across updates"),
@@ -1139,15 +1154,15 @@ static const struct option options[] = {
1139 "display this many functions"), 1154 "display this many functions"),
1140 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 1155 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
1141 "hide user symbols"), 1156 "hide user symbols"),
1142 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), 1157 OPT_BOOLEAN(0, "tui", &top.use_tui, "Use the TUI interface"),
1143 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 1158 OPT_BOOLEAN(0, "stdio", &top.use_stdio, "Use the stdio interface"),
1144 OPT_INCR('v', "verbose", &verbose, 1159 OPT_INCR('v', "verbose", &verbose,
1145 "be more verbose (show counter open errors, etc)"), 1160 "be more verbose (show counter open errors, etc)"),
1146 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1161 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1147 "sort by key(s): pid, comm, dso, symbol, parent"), 1162 "sort by key(s): pid, comm, dso, symbol, parent"),
1148 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1163 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1149 "Show a column with the number of samples"), 1164 "Show a column with the number of samples"),
1150 OPT_CALLBACK_DEFAULT('G', "call-graph", NULL, "output_type,min_percent, call_order", 1165 OPT_CALLBACK_DEFAULT('G', "call-graph", &top, "output_type,min_percent, call_order",
1151 "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. " 1166 "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. "
1152 "Default: fractal,0.5,callee", &parse_callchain_opt, 1167 "Default: fractal,0.5,callee", &parse_callchain_opt,
1153 callchain_default_opt), 1168 callchain_default_opt),
@@ -1166,12 +1181,7 @@ static const struct option options[] = {
1166 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1181 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1167 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1182 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1168 OPT_END() 1183 OPT_END()
1169}; 1184 };
1170
1171int cmd_top(int argc, const char **argv, const char *prefix __used)
1172{
1173 struct perf_evsel *pos;
1174 int status = -ENOMEM;
1175 1185
1176 top.evlist = perf_evlist__new(NULL, NULL); 1186 top.evlist = perf_evlist__new(NULL, NULL);
1177 if (top.evlist == NULL) 1187 if (top.evlist == NULL)
@@ -1188,9 +1198,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1188 1198
1189 setup_sorting(top_usage, options); 1199 setup_sorting(top_usage, options);
1190 1200
1191 if (use_stdio) 1201 if (top.use_stdio)
1192 use_browser = 0; 1202 use_browser = 0;
1193 else if (use_tui) 1203 else if (top.use_tui)
1194 use_browser = 1; 1204 use_browser = 1;
1195 1205
1196 setup_browser(false); 1206 setup_browser(false);
@@ -1215,38 +1225,31 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1215 return -ENOMEM; 1225 return -ENOMEM;
1216 } 1226 }
1217 1227
1228 symbol_conf.nr_events = top.evlist->nr_entries;
1229
1218 if (top.delay_secs < 1) 1230 if (top.delay_secs < 1)
1219 top.delay_secs = 1; 1231 top.delay_secs = 1;
1220 1232
1221 /* 1233 /*
1222 * User specified count overrides default frequency. 1234 * User specified count overrides default frequency.
1223 */ 1235 */
1224 if (default_interval) 1236 if (top.default_interval)
1225 top.freq = 0; 1237 top.freq = 0;
1226 else if (top.freq) { 1238 else if (top.freq) {
1227 default_interval = top.freq; 1239 top.default_interval = top.freq;
1228 } else { 1240 } else {
1229 fprintf(stderr, "frequency and count are zero, aborting\n"); 1241 fprintf(stderr, "frequency and count are zero, aborting\n");
1230 exit(EXIT_FAILURE); 1242 exit(EXIT_FAILURE);
1231 } 1243 }
1232 1244
1233 list_for_each_entry(pos, &top.evlist->entries, node) { 1245 list_for_each_entry(pos, &top.evlist->entries, node) {
1234 if (perf_evsel__alloc_fd(pos, top.evlist->cpus->nr,
1235 top.evlist->threads->nr) < 0)
1236 goto out_free_fd;
1237 /* 1246 /*
1238 * Fill in the ones not specifically initialized via -c: 1247 * Fill in the ones not specifically initialized via -c:
1239 */ 1248 */
1240 if (pos->attr.sample_period) 1249 if (!pos->attr.sample_period)
1241 continue; 1250 pos->attr.sample_period = top.default_interval;
1242
1243 pos->attr.sample_period = default_interval;
1244 } 1251 }
1245 1252
1246 if (perf_evlist__alloc_pollfd(top.evlist) < 0 ||
1247 perf_evlist__alloc_mmap(top.evlist) < 0)
1248 goto out_free_fd;
1249
1250 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 1253 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
1251 1254
1252 symbol_conf.priv_size = sizeof(struct annotation); 1255 symbol_conf.priv_size = sizeof(struct annotation);
@@ -1263,16 +1266,20 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1263 * Avoid annotation data structures overhead when symbols aren't on the 1266 * Avoid annotation data structures overhead when symbols aren't on the
1264 * sort list. 1267 * sort list.
1265 */ 1268 */
1266 sort_has_symbols = sort_sym.list.next != NULL; 1269 top.sort_has_symbols = sort_sym.list.next != NULL;
1267 1270
1268 get_term_dimensions(&winsize); 1271 get_term_dimensions(&top.winsize);
1269 if (top.print_entries == 0) { 1272 if (top.print_entries == 0) {
1270 update_print_entries(&winsize); 1273 struct sigaction act = {
1271 signal(SIGWINCH, sig_winch_handler); 1274 .sa_sigaction = perf_top__sig_winch,
1275 .sa_flags = SA_SIGINFO,
1276 };
1277 perf_top__update_print_entries(&top);
1278 sigaction(SIGWINCH, &act, NULL);
1272 } 1279 }
1273 1280
1274 status = __cmd_top(); 1281 status = __cmd_top(&top);
1275out_free_fd: 1282
1276 perf_evlist__delete(top.evlist); 1283 perf_evlist__delete(top.evlist);
1277 1284
1278 return status; 1285 return status;
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 73d0cac8b67e..2b2e225a4d4c 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -29,8 +29,6 @@ struct pager_config {
29 int val; 29 int val;
30}; 30};
31 31
32static char debugfs_mntpt[MAXPATHLEN];
33
34static int pager_command_config(const char *var, const char *value, void *data) 32static int pager_command_config(const char *var, const char *value, void *data)
35{ 33{
36 struct pager_config *c = data; 34 struct pager_config *c = data;
@@ -81,15 +79,6 @@ static void commit_pager_choice(void)
81 } 79 }
82} 80}
83 81
84static void set_debugfs_path(void)
85{
86 char *path;
87
88 path = getenv(PERF_DEBUGFS_ENVIRONMENT);
89 snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
90 "tracing/events");
91}
92
93static int handle_options(const char ***argv, int *argc, int *envchanged) 82static int handle_options(const char ***argv, int *argc, int *envchanged)
94{ 83{
95 int handled = 0; 84 int handled = 0;
@@ -161,15 +150,14 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
161 fprintf(stderr, "No directory given for --debugfs-dir.\n"); 150 fprintf(stderr, "No directory given for --debugfs-dir.\n");
162 usage(perf_usage_string); 151 usage(perf_usage_string);
163 } 152 }
164 strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN); 153 debugfs_set_path((*argv)[1]);
165 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
166 if (envchanged) 154 if (envchanged)
167 *envchanged = 1; 155 *envchanged = 1;
168 (*argv)++; 156 (*argv)++;
169 (*argc)--; 157 (*argc)--;
170 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { 158 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
171 strncpy(debugfs_mntpt, cmd + strlen(CMD_DEBUGFS_DIR), MAXPATHLEN); 159 debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR));
172 debugfs_mntpt[MAXPATHLEN - 1] = '\0'; 160 fprintf(stderr, "dir: %s\n", debugfs_mountpoint);
173 if (envchanged) 161 if (envchanged)
174 *envchanged = 1; 162 *envchanged = 1;
175 } else { 163 } else {
@@ -281,7 +269,6 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
281 if (use_pager == -1 && p->option & USE_PAGER) 269 if (use_pager == -1 && p->option & USE_PAGER)
282 use_pager = 1; 270 use_pager = 1;
283 commit_pager_choice(); 271 commit_pager_choice();
284 set_debugfs_path();
285 272
286 status = p->fn(argc, argv, prefix); 273 status = p->fn(argc, argv, prefix);
287 exit_browser(status); 274 exit_browser(status);
@@ -416,17 +403,6 @@ static int run_argv(int *argcp, const char ***argv)
416 return done_alias; 403 return done_alias;
417} 404}
418 405
419/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
420static void get_debugfs_mntpt(void)
421{
422 const char *path = debugfs_mount(NULL);
423
424 if (path)
425 strncpy(debugfs_mntpt, path, sizeof(debugfs_mntpt));
426 else
427 debugfs_mntpt[0] = '\0';
428}
429
430static void pthread__block_sigwinch(void) 406static void pthread__block_sigwinch(void)
431{ 407{
432 sigset_t set; 408 sigset_t set;
@@ -453,7 +429,7 @@ int main(int argc, const char **argv)
453 if (!cmd) 429 if (!cmd)
454 cmd = "perf-help"; 430 cmd = "perf-help";
455 /* get debugfs mount point from /proc/mounts */ 431 /* get debugfs mount point from /proc/mounts */
456 get_debugfs_mntpt(); 432 debugfs_mount(NULL);
457 /* 433 /*
458 * "perf-xxxx" is the same as "perf xxxx", but we obviously: 434 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
459 * 435 *
@@ -476,7 +452,6 @@ int main(int argc, const char **argv)
476 argc--; 452 argc--;
477 handle_options(&argv, &argc, NULL); 453 handle_options(&argv, &argc, NULL);
478 commit_pager_choice(); 454 commit_pager_choice();
479 set_debugfs_path();
480 set_buildid_dir(); 455 set_buildid_dir();
481 456
482 if (argc > 0) { 457 if (argc > 0) {
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 914c895510f7..3afa39ac1d40 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__
@@ -185,4 +191,29 @@ extern const char perf_version_string[];
185 191
186void pthread__unblock_sigwinch(void); 192void pthread__unblock_sigwinch(void);
187 193
194struct perf_record_opts {
195 pid_t target_pid;
196 pid_t target_tid;
197 bool call_graph;
198 bool group;
199 bool inherit_stat;
200 bool no_delay;
201 bool no_inherit;
202 bool no_samples;
203 bool pipe_output;
204 bool raw_samples;
205 bool sample_address;
206 bool sample_time;
207 bool sample_id_all_avail;
208 bool exclude_guest_missing;
209 bool system_wide;
210 bool period;
211 unsigned int freq;
212 unsigned int mmap_pages;
213 unsigned int user_freq;
214 u64 default_interval;
215 u64 user_interval;
216 const char *cpu_list;
217};
218
188#endif 219#endif
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 119e996035c8..011ed2676604 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -25,17 +25,17 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym)
25 return 0; 25 return 0;
26} 26}
27 27
28int symbol__alloc_hist(struct symbol *sym, int nevents) 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 size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
32 (sym->end - sym->start) * sizeof(u64)); 32 (sym->end - sym->start) * sizeof(u64));
33 33
34 notes->src = zalloc(sizeof(*notes->src) + nevents * 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)
36 return -1; 36 return -1;
37 notes->src->sizeof_sym_hist = sizeof_sym_hist; 37 notes->src->sizeof_sym_hist = sizeof_sym_hist;
38 notes->src->nr_histograms = nevents; 38 notes->src->nr_histograms = symbol_conf.nr_events;
39 INIT_LIST_HEAD(&notes->src->source); 39 INIT_LIST_HEAD(&notes->src->source);
40 return 0; 40 return 0;
41} 41}
@@ -334,7 +334,7 @@ fallback:
334 disassembler_style ? "-M " : "", 334 disassembler_style ? "-M " : "",
335 disassembler_style ? disassembler_style : "", 335 disassembler_style ? disassembler_style : "",
336 map__rip_2objdump(map, sym->start), 336 map__rip_2objdump(map, sym->start),
337 map__rip_2objdump(map, sym->end), 337 map__rip_2objdump(map, sym->end+1),
338 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", 338 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
339 symbol_conf.annotate_src ? "-S" : "", 339 symbol_conf.annotate_src ? "-S" : "",
340 symfs_filename, filename); 340 symfs_filename, filename);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index d9072523d342..efa5dc82bfae 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -72,7 +72,7 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
72 72
73int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 73int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
74 int evidx, u64 addr); 74 int evidx, u64 addr);
75int symbol__alloc_hist(struct symbol *sym, int nevents); 75int symbol__alloc_hist(struct symbol *sym);
76void symbol__annotate_zero_histograms(struct symbol *sym); 76void symbol__annotate_zero_histograms(struct symbol *sym);
77 77
78int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 78int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
@@ -99,8 +99,7 @@ static inline int symbol__tui_annotate(struct symbol *sym __used,
99} 99}
100#else 100#else
101int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 101int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
102 int nr_events, void(*timer)(void *arg), void *arg, 102 void(*timer)(void *arg), void *arg, int delay_secs);
103 int delay_secs);
104#endif 103#endif
105 104
106extern const char *disassembler_style; 105extern const char *disassembler_style;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index a91cd99f26ea..dff9c7a725f4 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -13,15 +13,18 @@
13#include "symbol.h" 13#include "symbol.h"
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include "debug.h" 15#include "debug.h"
16#include "session.h"
17#include "tool.h"
16 18
17static int build_id__mark_dso_hit(union perf_event *event, 19static int build_id__mark_dso_hit(struct perf_tool *tool __used,
20 union perf_event *event,
18 struct perf_sample *sample __used, 21 struct perf_sample *sample __used,
19 struct perf_evsel *evsel __used, 22 struct perf_evsel *evsel __used,
20 struct perf_session *session) 23 struct machine *machine)
21{ 24{
22 struct addr_location al; 25 struct addr_location al;
23 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 26 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
24 struct thread *thread = perf_session__findnew(session, event->ip.pid); 27 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
25 28
26 if (thread == NULL) { 29 if (thread == NULL) {
27 pr_err("problem processing %d event, skipping it.\n", 30 pr_err("problem processing %d event, skipping it.\n",
@@ -29,8 +32,8 @@ static int build_id__mark_dso_hit(union perf_event *event,
29 return -1; 32 return -1;
30 } 33 }
31 34
32 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 35 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
33 event->ip.pid, event->ip.ip, &al); 36 event->ip.ip, &al);
34 37
35 if (al.map != NULL) 38 if (al.map != NULL)
36 al.map->dso->hit = 1; 39 al.map->dso->hit = 1;
@@ -38,25 +41,26 @@ static int build_id__mark_dso_hit(union perf_event *event,
38 return 0; 41 return 0;
39} 42}
40 43
41static int perf_event__exit_del_thread(union perf_event *event, 44static int perf_event__exit_del_thread(struct perf_tool *tool __used,
45 union perf_event *event,
42 struct perf_sample *sample __used, 46 struct perf_sample *sample __used,
43 struct perf_session *session) 47 struct machine *machine)
44{ 48{
45 struct thread *thread = perf_session__findnew(session, event->fork.tid); 49 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
46 50
47 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 51 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
48 event->fork.ppid, event->fork.ptid); 52 event->fork.ppid, event->fork.ptid);
49 53
50 if (thread) { 54 if (thread) {
51 rb_erase(&thread->rb_node, &session->threads); 55 rb_erase(&thread->rb_node, &machine->threads);
52 session->last_match = NULL; 56 machine->last_match = NULL;
53 thread__delete(thread); 57 thread__delete(thread);
54 } 58 }
55 59
56 return 0; 60 return 0;
57} 61}
58 62
59struct perf_event_ops build_id__mark_dso_hit_ops = { 63struct perf_tool build_id__mark_dso_hit_ops = {
60 .sample = build_id__mark_dso_hit, 64 .sample = build_id__mark_dso_hit,
61 .mmap = perf_event__process_mmap, 65 .mmap = perf_event__process_mmap,
62 .fork = perf_event__process_task, 66 .fork = perf_event__process_task,
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 5dafb00eaa06..a993ba87d996 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -3,7 +3,7 @@
3 3
4#include "session.h" 4#include "session.h"
5 5
6extern struct perf_event_ops build_id__mark_dso_hit_ops; 6extern struct perf_tool build_id__mark_dso_hit_ops;
7 7
8char *dso__build_id_filename(struct dso *self, char *bf, size_t size); 8char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
9 9
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 9b4ff16cac96..7f9c0f1ae3a9 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -101,6 +101,9 @@ int callchain_append(struct callchain_root *root,
101int callchain_merge(struct callchain_cursor *cursor, 101int callchain_merge(struct callchain_cursor *cursor,
102 struct callchain_root *dst, struct callchain_root *src); 102 struct callchain_root *dst, struct callchain_root *src);
103 103
104struct ip_callchain;
105union perf_event;
106
104bool ip_callchain__valid(struct ip_callchain *chain, 107bool ip_callchain__valid(struct ip_callchain *chain,
105 const union perf_event *event); 108 const union perf_event *event);
106/* 109/*
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 96bee5c46008..dbe2f16b1a1a 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -3,7 +3,6 @@
3#include "parse-options.h" 3#include "parse-options.h"
4#include "evsel.h" 4#include "evsel.h"
5#include "cgroup.h" 5#include "cgroup.h"
6#include "debugfs.h" /* MAX_PATH, STR() */
7#include "evlist.h" 6#include "evlist.h"
8 7
9int nr_cgroups; 8int nr_cgroups;
@@ -12,7 +11,7 @@ static int
12cgroupfs_find_mountpoint(char *buf, size_t maxlen) 11cgroupfs_find_mountpoint(char *buf, size_t maxlen)
13{ 12{
14 FILE *fp; 13 FILE *fp;
15 char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1]; 14 char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1];
16 char *token, *saved_ptr = NULL; 15 char *token, *saved_ptr = NULL;
17 int found = 0; 16 int found = 0;
18 17
@@ -25,8 +24,8 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
25 * and inspect every cgroupfs mount point to find one that has 24 * and inspect every cgroupfs mount point to find one that has
26 * perf_event subsystem 25 * perf_event subsystem
27 */ 26 */
28 while (fscanf(fp, "%*s %"STR(MAX_PATH)"s %"STR(MAX_PATH)"s %" 27 while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %"
29 STR(MAX_PATH)"s %*d %*d\n", 28 STR(PATH_MAX)"s %*d %*d\n",
30 mountpoint, type, tokens) == 3) { 29 mountpoint, type, tokens) == 3) {
31 30
32 if (!strcmp(type, "cgroup")) { 31 if (!strcmp(type, "cgroup")) {
@@ -57,15 +56,15 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
57 56
58static int open_cgroup(char *name) 57static int open_cgroup(char *name)
59{ 58{
60 char path[MAX_PATH+1]; 59 char path[PATH_MAX + 1];
61 char mnt[MAX_PATH+1]; 60 char mnt[PATH_MAX + 1];
62 int fd; 61 int fd;
63 62
64 63
65 if (cgroupfs_find_mountpoint(mnt, MAX_PATH+1)) 64 if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
66 return -1; 65 return -1;
67 66
68 snprintf(path, MAX_PATH, "%s/%s", mnt, name); 67 snprintf(path, PATH_MAX, "%s/%s", mnt, name);
69 68
70 fd = open(path, O_RDONLY); 69 fd = open(path, O_RDONLY);
71 if (fd == -1) 70 if (fd == -1)
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/config.c b/tools/perf/util/config.c
index 80d9598db31a..0deac6a14b65 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -1,5 +1,8 @@
1/* 1/*
2 * GIT - The information manager from hell 2 * config.c
3 *
4 * Helper functions for parsing config items.
5 * Originally copied from GIT source.
3 * 6 *
4 * Copyright (C) Linus Torvalds, 2005 7 * Copyright (C) Linus Torvalds, 2005
5 * Copyright (C) Johannes Schindelin, 2005 8 * Copyright (C) Johannes Schindelin, 2005
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
index a88fefc0cc0a..ffc35e748e89 100644
--- a/tools/perf/util/debugfs.c
+++ b/tools/perf/util/debugfs.c
@@ -2,8 +2,12 @@
2#include "debugfs.h" 2#include "debugfs.h"
3#include "cache.h" 3#include "cache.h"
4 4
5#include <linux/kernel.h>
6#include <sys/mount.h>
7
5static int debugfs_premounted; 8static int debugfs_premounted;
6static char debugfs_mountpoint[MAX_PATH+1]; 9char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug";
10char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
7 11
8static const char *debugfs_known_mountpoints[] = { 12static const char *debugfs_known_mountpoints[] = {
9 "/sys/kernel/debug/", 13 "/sys/kernel/debug/",
@@ -62,11 +66,9 @@ const char *debugfs_find_mountpoint(void)
62 /* give up and parse /proc/mounts */ 66 /* give up and parse /proc/mounts */
63 fp = fopen("/proc/mounts", "r"); 67 fp = fopen("/proc/mounts", "r");
64 if (fp == NULL) 68 if (fp == NULL)
65 die("Can't open /proc/mounts for read"); 69 return NULL;
66 70
67 while (fscanf(fp, "%*s %" 71 while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
68 STR(MAX_PATH)
69 "s %99s %*s %*d %*d\n",
70 debugfs_mountpoint, type) == 2) { 72 debugfs_mountpoint, type) == 2) {
71 if (strcmp(type, "debugfs") == 0) 73 if (strcmp(type, "debugfs") == 0)
72 break; 74 break;
@@ -106,6 +108,12 @@ int debugfs_valid_entry(const char *path)
106 return 0; 108 return 0;
107} 109}
108 110
111static void debugfs_set_tracing_events_path(const char *mountpoint)
112{
113 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
114 mountpoint, "tracing/events");
115}
116
109/* mount the debugfs somewhere if it's not mounted */ 117/* mount the debugfs somewhere if it's not mounted */
110 118
111char *debugfs_mount(const char *mountpoint) 119char *debugfs_mount(const char *mountpoint)
@@ -113,7 +121,7 @@ char *debugfs_mount(const char *mountpoint)
113 /* see if it's already mounted */ 121 /* see if it's already mounted */
114 if (debugfs_find_mountpoint()) { 122 if (debugfs_find_mountpoint()) {
115 debugfs_premounted = 1; 123 debugfs_premounted = 1;
116 return debugfs_mountpoint; 124 goto out;
117 } 125 }
118 126
119 /* if not mounted and no argument */ 127 /* if not mounted and no argument */
@@ -129,12 +137,19 @@ char *debugfs_mount(const char *mountpoint)
129 return NULL; 137 return NULL;
130 138
131 /* save the mountpoint */ 139 /* save the mountpoint */
132 strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
133 debugfs_found = 1; 140 debugfs_found = 1;
134 141 strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
142out:
143 debugfs_set_tracing_events_path(debugfs_mountpoint);
135 return debugfs_mountpoint; 144 return debugfs_mountpoint;
136} 145}
137 146
147void debugfs_set_path(const char *mountpoint)
148{
149 snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint);
150 debugfs_set_tracing_events_path(mountpoint);
151}
152
138/* umount the debugfs */ 153/* umount the debugfs */
139 154
140int debugfs_umount(void) 155int debugfs_umount(void)
@@ -158,7 +173,7 @@ int debugfs_umount(void)
158 173
159int debugfs_write(const char *entry, const char *value) 174int debugfs_write(const char *entry, const char *value)
160{ 175{
161 char path[MAX_PATH+1]; 176 char path[PATH_MAX + 1];
162 int ret, count; 177 int ret, count;
163 int fd; 178 int fd;
164 179
@@ -203,7 +218,7 @@ int debugfs_write(const char *entry, const char *value)
203 */ 218 */
204int debugfs_read(const char *entry, char *buffer, size_t size) 219int debugfs_read(const char *entry, char *buffer, size_t size)
205{ 220{
206 char path[MAX_PATH+1]; 221 char path[PATH_MAX + 1];
207 int ret; 222 int ret;
208 int fd; 223 int fd;
209 224
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
index 83a02879745f..4a878f735eb0 100644
--- a/tools/perf/util/debugfs.h
+++ b/tools/perf/util/debugfs.h
@@ -1,25 +1,18 @@
1#ifndef __DEBUGFS_H__ 1#ifndef __DEBUGFS_H__
2#define __DEBUGFS_H__ 2#define __DEBUGFS_H__
3 3
4#include <sys/mount.h> 4const char *debugfs_find_mountpoint(void);
5int debugfs_valid_mountpoint(const char *debugfs);
6int debugfs_valid_entry(const char *path);
7char *debugfs_mount(const char *mountpoint);
8int debugfs_umount(void);
9void 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);
5 14
6#ifndef MAX_PATH 15extern char debugfs_mountpoint[];
7# define MAX_PATH 256 16extern char tracing_events_path[];
8#endif
9
10#ifndef STR
11# define _STR(x) #x
12# define STR(x) _STR(x)
13#endif
14
15extern const char *debugfs_find_mountpoint(void);
16extern int debugfs_valid_mountpoint(const char *debugfs);
17extern int debugfs_valid_entry(const char *path);
18extern char *debugfs_mount(const char *mountpoint);
19extern int debugfs_umount(void);
20extern int debugfs_write(const char *entry, const char *value);
21extern int debugfs_read(const char *entry, char *buffer, size_t size);
22extern void debugfs_force_cleanup(void);
23extern int debugfs_make_path(const char *element, char *buffer, int size);
24 17
25#endif /* __DEBUGFS_H__ */ 18#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 437f8ca679a0..2a6f33cd888c 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,7 +1,6 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include "event.h" 2#include "event.h"
3#include "debug.h" 3#include "debug.h"
4#include "session.h"
5#include "sort.h" 4#include "sort.h"
6#include "string.h" 5#include "string.h"
7#include "strlist.h" 6#include "strlist.h"
@@ -44,36 +43,27 @@ static struct perf_sample synth_sample = {
44 .period = 1, 43 .period = 1,
45}; 44};
46 45
47static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid, 46static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
48 int full, perf_event__handler_t process,
49 struct perf_session *session)
50{ 47{
51 char filename[PATH_MAX]; 48 char filename[PATH_MAX];
52 char bf[BUFSIZ]; 49 char bf[BUFSIZ];
53 FILE *fp; 50 FILE *fp;
54 size_t size = 0; 51 size_t size = 0;
55 DIR *tasks; 52 pid_t tgid = -1;
56 struct dirent dirent, *next;
57 pid_t tgid = 0;
58 53
59 snprintf(filename, sizeof(filename), "/proc/%d/status", pid); 54 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
60 55
61 fp = fopen(filename, "r"); 56 fp = fopen(filename, "r");
62 if (fp == NULL) { 57 if (fp == NULL) {
63out_race:
64 /*
65 * We raced with a task exiting - just return:
66 */
67 pr_debug("couldn't open %s\n", filename); 58 pr_debug("couldn't open %s\n", filename);
68 return 0; 59 return 0;
69 } 60 }
70 61
71 memset(&event->comm, 0, sizeof(event->comm)); 62 while (!comm[0] || (tgid < 0)) {
72
73 while (!event->comm.comm[0] || !event->comm.pid) {
74 if (fgets(bf, sizeof(bf), fp) == NULL) { 63 if (fgets(bf, sizeof(bf), fp) == NULL) {
75 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename); 64 pr_warning("couldn't get COMM and pgid, malformed %s\n",
76 goto out; 65 filename);
66 break;
77 } 67 }
78 68
79 if (memcmp(bf, "Name:", 5) == 0) { 69 if (memcmp(bf, "Name:", 5) == 0) {
@@ -81,33 +71,66 @@ out_race:
81 while (*name && isspace(*name)) 71 while (*name && isspace(*name))
82 ++name; 72 ++name;
83 size = strlen(name) - 1; 73 size = strlen(name) - 1;
84 memcpy(event->comm.comm, name, size++); 74 if (size >= len)
75 size = len - 1;
76 memcpy(comm, name, size);
77 comm[size] = '\0';
78
85 } else if (memcmp(bf, "Tgid:", 5) == 0) { 79 } else if (memcmp(bf, "Tgid:", 5) == 0) {
86 char *tgids = bf + 5; 80 char *tgids = bf + 5;
87 while (*tgids && isspace(*tgids)) 81 while (*tgids && isspace(*tgids))
88 ++tgids; 82 ++tgids;
89 tgid = event->comm.pid = atoi(tgids); 83 tgid = atoi(tgids);
90 } 84 }
91 } 85 }
92 86
87 fclose(fp);
88
89 return tgid;
90}
91
92static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
93 union perf_event *event, pid_t pid,
94 int full,
95 perf_event__handler_t process,
96 struct machine *machine)
97{
98 char filename[PATH_MAX];
99 size_t size;
100 DIR *tasks;
101 struct dirent dirent, *next;
102 pid_t tgid;
103
104 memset(&event->comm, 0, sizeof(event->comm));
105
106 tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
107 sizeof(event->comm.comm));
108 if (tgid < 0)
109 goto out;
110
111 event->comm.pid = tgid;
93 event->comm.header.type = PERF_RECORD_COMM; 112 event->comm.header.type = PERF_RECORD_COMM;
113
114 size = strlen(event->comm.comm) + 1;
94 size = ALIGN(size, sizeof(u64)); 115 size = ALIGN(size, sizeof(u64));
95 memset(event->comm.comm + size, 0, session->id_hdr_size); 116 memset(event->comm.comm + size, 0, machine->id_hdr_size);
96 event->comm.header.size = (sizeof(event->comm) - 117 event->comm.header.size = (sizeof(event->comm) -
97 (sizeof(event->comm.comm) - size) + 118 (sizeof(event->comm.comm) - size) +
98 session->id_hdr_size); 119 machine->id_hdr_size);
99 if (!full) { 120 if (!full) {
100 event->comm.tid = pid; 121 event->comm.tid = pid;
101 122
102 process(event, &synth_sample, session); 123 process(tool, event, &synth_sample, machine);
103 goto out; 124 goto out;
104 } 125 }
105 126
106 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 127 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
107 128
108 tasks = opendir(filename); 129 tasks = opendir(filename);
109 if (tasks == NULL) 130 if (tasks == NULL) {
110 goto out_race; 131 pr_debug("couldn't open %s\n", filename);
132 return 0;
133 }
111 134
112 while (!readdir_r(tasks, &dirent, &next) && next) { 135 while (!readdir_r(tasks, &dirent, &next) && next) {
113 char *end; 136 char *end;
@@ -115,22 +138,32 @@ out_race:
115 if (*end) 138 if (*end)
116 continue; 139 continue;
117 140
141 /* already have tgid; jut want to update the comm */
142 (void) perf_event__get_comm_tgid(pid, event->comm.comm,
143 sizeof(event->comm.comm));
144
145 size = strlen(event->comm.comm) + 1;
146 size = ALIGN(size, sizeof(u64));
147 memset(event->comm.comm + size, 0, machine->id_hdr_size);
148 event->comm.header.size = (sizeof(event->comm) -
149 (sizeof(event->comm.comm) - size) +
150 machine->id_hdr_size);
151
118 event->comm.tid = pid; 152 event->comm.tid = pid;
119 153
120 process(event, &synth_sample, session); 154 process(tool, event, &synth_sample, machine);
121 } 155 }
122 156
123 closedir(tasks); 157 closedir(tasks);
124out: 158out:
125 fclose(fp);
126
127 return tgid; 159 return tgid;
128} 160}
129 161
130static int perf_event__synthesize_mmap_events(union perf_event *event, 162static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
163 union perf_event *event,
131 pid_t pid, pid_t tgid, 164 pid_t pid, pid_t tgid,
132 perf_event__handler_t process, 165 perf_event__handler_t process,
133 struct perf_session *session) 166 struct machine *machine)
134{ 167{
135 char filename[PATH_MAX]; 168 char filename[PATH_MAX];
136 FILE *fp; 169 FILE *fp;
@@ -193,12 +226,12 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
193 event->mmap.len -= event->mmap.start; 226 event->mmap.len -= event->mmap.start;
194 event->mmap.header.size = (sizeof(event->mmap) - 227 event->mmap.header.size = (sizeof(event->mmap) -
195 (sizeof(event->mmap.filename) - size)); 228 (sizeof(event->mmap.filename) - size));
196 memset(event->mmap.filename + size, 0, session->id_hdr_size); 229 memset(event->mmap.filename + size, 0, machine->id_hdr_size);
197 event->mmap.header.size += session->id_hdr_size; 230 event->mmap.header.size += machine->id_hdr_size;
198 event->mmap.pid = tgid; 231 event->mmap.pid = tgid;
199 event->mmap.tid = pid; 232 event->mmap.tid = pid;
200 233
201 process(event, &synth_sample, session); 234 process(tool, event, &synth_sample, machine);
202 } 235 }
203 } 236 }
204 237
@@ -206,14 +239,14 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
206 return 0; 239 return 0;
207} 240}
208 241
209int perf_event__synthesize_modules(perf_event__handler_t process, 242int perf_event__synthesize_modules(struct perf_tool *tool,
210 struct perf_session *session, 243 perf_event__handler_t process,
211 struct machine *machine) 244 struct machine *machine)
212{ 245{
213 struct rb_node *nd; 246 struct rb_node *nd;
214 struct map_groups *kmaps = &machine->kmaps; 247 struct map_groups *kmaps = &machine->kmaps;
215 union perf_event *event = zalloc((sizeof(event->mmap) + 248 union perf_event *event = zalloc((sizeof(event->mmap) +
216 session->id_hdr_size)); 249 machine->id_hdr_size));
217 if (event == NULL) { 250 if (event == NULL) {
218 pr_debug("Not enough memory synthesizing mmap event " 251 pr_debug("Not enough memory synthesizing mmap event "
219 "for kernel modules\n"); 252 "for kernel modules\n");
@@ -243,15 +276,15 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
243 event->mmap.header.type = PERF_RECORD_MMAP; 276 event->mmap.header.type = PERF_RECORD_MMAP;
244 event->mmap.header.size = (sizeof(event->mmap) - 277 event->mmap.header.size = (sizeof(event->mmap) -
245 (sizeof(event->mmap.filename) - size)); 278 (sizeof(event->mmap.filename) - size));
246 memset(event->mmap.filename + size, 0, session->id_hdr_size); 279 memset(event->mmap.filename + size, 0, machine->id_hdr_size);
247 event->mmap.header.size += session->id_hdr_size; 280 event->mmap.header.size += machine->id_hdr_size;
248 event->mmap.start = pos->start; 281 event->mmap.start = pos->start;
249 event->mmap.len = pos->end - pos->start; 282 event->mmap.len = pos->end - pos->start;
250 event->mmap.pid = machine->pid; 283 event->mmap.pid = machine->pid;
251 284
252 memcpy(event->mmap.filename, pos->dso->long_name, 285 memcpy(event->mmap.filename, pos->dso->long_name,
253 pos->dso->long_name_len + 1); 286 pos->dso->long_name_len + 1);
254 process(event, &synth_sample, session); 287 process(tool, event, &synth_sample, machine);
255 } 288 }
256 289
257 free(event); 290 free(event);
@@ -260,40 +293,69 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
260 293
261static int __event__synthesize_thread(union perf_event *comm_event, 294static int __event__synthesize_thread(union perf_event *comm_event,
262 union perf_event *mmap_event, 295 union perf_event *mmap_event,
263 pid_t pid, perf_event__handler_t process, 296 pid_t pid, int full,
264 struct perf_session *session) 297 perf_event__handler_t process,
298 struct perf_tool *tool,
299 struct machine *machine)
265{ 300{
266 pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process, 301 pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full,
267 session); 302 process, machine);
268 if (tgid == -1) 303 if (tgid == -1)
269 return -1; 304 return -1;
270 return perf_event__synthesize_mmap_events(mmap_event, pid, tgid, 305 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
271 process, session); 306 process, machine);
272} 307}
273 308
274int perf_event__synthesize_thread_map(struct thread_map *threads, 309int perf_event__synthesize_thread_map(struct perf_tool *tool,
310 struct thread_map *threads,
275 perf_event__handler_t process, 311 perf_event__handler_t process,
276 struct perf_session *session) 312 struct machine *machine)
277{ 313{
278 union perf_event *comm_event, *mmap_event; 314 union perf_event *comm_event, *mmap_event;
279 int err = -1, thread; 315 int err = -1, thread, j;
280 316
281 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 317 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
282 if (comm_event == NULL) 318 if (comm_event == NULL)
283 goto out; 319 goto out;
284 320
285 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 321 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
286 if (mmap_event == NULL) 322 if (mmap_event == NULL)
287 goto out_free_comm; 323 goto out_free_comm;
288 324
289 err = 0; 325 err = 0;
290 for (thread = 0; thread < threads->nr; ++thread) { 326 for (thread = 0; thread < threads->nr; ++thread) {
291 if (__event__synthesize_thread(comm_event, mmap_event, 327 if (__event__synthesize_thread(comm_event, mmap_event,
292 threads->map[thread], 328 threads->map[thread], 0,
293 process, session)) { 329 process, tool, machine)) {
294 err = -1; 330 err = -1;
295 break; 331 break;
296 } 332 }
333
334 /*
335 * comm.pid is set to thread group id by
336 * perf_event__synthesize_comm
337 */
338 if ((int) comm_event->comm.pid != threads->map[thread]) {
339 bool need_leader = true;
340
341 /* is thread group leader in thread_map? */
342 for (j = 0; j < threads->nr; ++j) {
343 if ((int) comm_event->comm.pid == threads->map[j]) {
344 need_leader = false;
345 break;
346 }
347 }
348
349 /* if not, generate events for it */
350 if (need_leader &&
351 __event__synthesize_thread(comm_event,
352 mmap_event,
353 comm_event->comm.pid, 0,
354 process, tool, machine)) {
355 err = -1;
356 break;
357 }
358 }
297 } 359 }
298 free(mmap_event); 360 free(mmap_event);
299out_free_comm: 361out_free_comm:
@@ -302,19 +364,20 @@ out:
302 return err; 364 return err;
303} 365}
304 366
305int perf_event__synthesize_threads(perf_event__handler_t process, 367int perf_event__synthesize_threads(struct perf_tool *tool,
306 struct perf_session *session) 368 perf_event__handler_t process,
369 struct machine *machine)
307{ 370{
308 DIR *proc; 371 DIR *proc;
309 struct dirent dirent, *next; 372 struct dirent dirent, *next;
310 union perf_event *comm_event, *mmap_event; 373 union perf_event *comm_event, *mmap_event;
311 int err = -1; 374 int err = -1;
312 375
313 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 376 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
314 if (comm_event == NULL) 377 if (comm_event == NULL)
315 goto out; 378 goto out;
316 379
317 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 380 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
318 if (mmap_event == NULL) 381 if (mmap_event == NULL)
319 goto out_free_comm; 382 goto out_free_comm;
320 383
@@ -329,8 +392,8 @@ int perf_event__synthesize_threads(perf_event__handler_t process,
329 if (*end) /* only interested in proper numerical dirents */ 392 if (*end) /* only interested in proper numerical dirents */
330 continue; 393 continue;
331 394
332 __event__synthesize_thread(comm_event, mmap_event, pid, 395 __event__synthesize_thread(comm_event, mmap_event, pid, 1,
333 process, session); 396 process, tool, machine);
334 } 397 }
335 398
336 closedir(proc); 399 closedir(proc);
@@ -365,8 +428,8 @@ static int find_symbol_cb(void *arg, const char *name, char type,
365 return 1; 428 return 1;
366} 429}
367 430
368int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, 431int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
369 struct perf_session *session, 432 perf_event__handler_t process,
370 struct machine *machine, 433 struct machine *machine,
371 const char *symbol_name) 434 const char *symbol_name)
372{ 435{
@@ -383,7 +446,7 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
383 */ 446 */
384 struct process_symbol_args args = { .name = symbol_name, }; 447 struct process_symbol_args args = { .name = symbol_name, };
385 union perf_event *event = zalloc((sizeof(event->mmap) + 448 union perf_event *event = zalloc((sizeof(event->mmap) +
386 session->id_hdr_size)); 449 machine->id_hdr_size));
387 if (event == NULL) { 450 if (event == NULL) {
388 pr_debug("Not enough memory synthesizing mmap event " 451 pr_debug("Not enough memory synthesizing mmap event "
389 "for kernel modules\n"); 452 "for kernel modules\n");
@@ -417,25 +480,32 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
417 size = ALIGN(size, sizeof(u64)); 480 size = ALIGN(size, sizeof(u64));
418 event->mmap.header.type = PERF_RECORD_MMAP; 481 event->mmap.header.type = PERF_RECORD_MMAP;
419 event->mmap.header.size = (sizeof(event->mmap) - 482 event->mmap.header.size = (sizeof(event->mmap) -
420 (sizeof(event->mmap.filename) - size) + session->id_hdr_size); 483 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
421 event->mmap.pgoff = args.start; 484 event->mmap.pgoff = args.start;
422 event->mmap.start = map->start; 485 event->mmap.start = map->start;
423 event->mmap.len = map->end - event->mmap.start; 486 event->mmap.len = map->end - event->mmap.start;
424 event->mmap.pid = machine->pid; 487 event->mmap.pid = machine->pid;
425 488
426 err = process(event, &synth_sample, session); 489 err = process(tool, event, &synth_sample, machine);
427 free(event); 490 free(event);
428 491
429 return err; 492 return err;
430} 493}
431 494
432int perf_event__process_comm(union perf_event *event, 495size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
496{
497 return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid);
498}
499
500int perf_event__process_comm(struct perf_tool *tool __used,
501 union perf_event *event,
433 struct perf_sample *sample __used, 502 struct perf_sample *sample __used,
434 struct perf_session *session) 503 struct machine *machine)
435{ 504{
436 struct thread *thread = perf_session__findnew(session, event->comm.tid); 505 struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
437 506
438 dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid); 507 if (dump_trace)
508 perf_event__fprintf_comm(event, stdout);
439 509
440 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { 510 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
441 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 511 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
@@ -445,13 +515,13 @@ int perf_event__process_comm(union perf_event *event,
445 return 0; 515 return 0;
446} 516}
447 517
448int perf_event__process_lost(union perf_event *event, 518int perf_event__process_lost(struct perf_tool *tool __used,
519 union perf_event *event,
449 struct perf_sample *sample __used, 520 struct perf_sample *sample __used,
450 struct perf_session *session) 521 struct machine *machine __used)
451{ 522{
452 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 523 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
453 event->lost.id, event->lost.lost); 524 event->lost.id, event->lost.lost);
454 session->hists.stats.total_lost += event->lost.lost;
455 return 0; 525 return 0;
456} 526}
457 527
@@ -468,21 +538,15 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event,
468 maps[MAP__FUNCTION]->end = ~0ULL; 538 maps[MAP__FUNCTION]->end = ~0ULL;
469} 539}
470 540
471static int perf_event__process_kernel_mmap(union perf_event *event, 541static int perf_event__process_kernel_mmap(struct perf_tool *tool __used,
472 struct perf_session *session) 542 union perf_event *event,
543 struct machine *machine)
473{ 544{
474 struct map *map; 545 struct map *map;
475 char kmmap_prefix[PATH_MAX]; 546 char kmmap_prefix[PATH_MAX];
476 struct machine *machine;
477 enum dso_kernel_type kernel_type; 547 enum dso_kernel_type kernel_type;
478 bool is_kernel_mmap; 548 bool is_kernel_mmap;
479 549
480 machine = perf_session__findnew_machine(session, event->mmap.pid);
481 if (!machine) {
482 pr_err("Can't find id %d's machine\n", event->mmap.pid);
483 goto out_problem;
484 }
485
486 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); 550 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
487 if (machine__is_host(machine)) 551 if (machine__is_host(machine))
488 kernel_type = DSO_TYPE_KERNEL; 552 kernel_type = DSO_TYPE_KERNEL;
@@ -491,7 +555,7 @@ static int perf_event__process_kernel_mmap(union perf_event *event,
491 555
492 is_kernel_mmap = memcmp(event->mmap.filename, 556 is_kernel_mmap = memcmp(event->mmap.filename,
493 kmmap_prefix, 557 kmmap_prefix,
494 strlen(kmmap_prefix)) == 0; 558 strlen(kmmap_prefix) - 1) == 0;
495 if (event->mmap.filename[0] == '/' || 559 if (event->mmap.filename[0] == '/' ||
496 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 560 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
497 561
@@ -549,9 +613,9 @@ static int perf_event__process_kernel_mmap(union perf_event *event,
549 * time /proc/sys/kernel/kptr_restrict was non zero. 613 * time /proc/sys/kernel/kptr_restrict was non zero.
550 */ 614 */
551 if (event->mmap.pgoff != 0) { 615 if (event->mmap.pgoff != 0) {
552 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, 616 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
553 symbol_name, 617 symbol_name,
554 event->mmap.pgoff); 618 event->mmap.pgoff);
555 } 619 }
556 620
557 if (machine__is_default_guest(machine)) { 621 if (machine__is_default_guest(machine)) {
@@ -567,32 +631,35 @@ out_problem:
567 return -1; 631 return -1;
568} 632}
569 633
570int perf_event__process_mmap(union perf_event *event, 634size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
635{
636 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
637 event->mmap.pid, event->mmap.tid, event->mmap.start,
638 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
639}
640
641int perf_event__process_mmap(struct perf_tool *tool,
642 union perf_event *event,
571 struct perf_sample *sample __used, 643 struct perf_sample *sample __used,
572 struct perf_session *session) 644 struct machine *machine)
573{ 645{
574 struct machine *machine;
575 struct thread *thread; 646 struct thread *thread;
576 struct map *map; 647 struct map *map;
577 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 648 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
578 int ret = 0; 649 int ret = 0;
579 650
580 dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", 651 if (dump_trace)
581 event->mmap.pid, event->mmap.tid, event->mmap.start, 652 perf_event__fprintf_mmap(event, stdout);
582 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
583 653
584 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || 654 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
585 cpumode == PERF_RECORD_MISC_KERNEL) { 655 cpumode == PERF_RECORD_MISC_KERNEL) {
586 ret = perf_event__process_kernel_mmap(event, session); 656 ret = perf_event__process_kernel_mmap(tool, event, machine);
587 if (ret < 0) 657 if (ret < 0)
588 goto out_problem; 658 goto out_problem;
589 return 0; 659 return 0;
590 } 660 }
591 661
592 machine = perf_session__find_host_machine(session); 662 thread = machine__findnew_thread(machine, event->mmap.pid);
593 if (machine == NULL)
594 goto out_problem;
595 thread = perf_session__findnew(session, event->mmap.pid);
596 if (thread == NULL) 663 if (thread == NULL)
597 goto out_problem; 664 goto out_problem;
598 map = map__new(&machine->user_dsos, event->mmap.start, 665 map = map__new(&machine->user_dsos, event->mmap.start,
@@ -610,18 +677,26 @@ out_problem:
610 return 0; 677 return 0;
611} 678}
612 679
613int perf_event__process_task(union perf_event *event, 680size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
681{
682 return fprintf(fp, "(%d:%d):(%d:%d)\n",
683 event->fork.pid, event->fork.tid,
684 event->fork.ppid, event->fork.ptid);
685}
686
687int perf_event__process_task(struct perf_tool *tool __used,
688 union perf_event *event,
614 struct perf_sample *sample __used, 689 struct perf_sample *sample __used,
615 struct perf_session *session) 690 struct machine *machine)
616{ 691{
617 struct thread *thread = perf_session__findnew(session, event->fork.tid); 692 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
618 struct thread *parent = perf_session__findnew(session, event->fork.ptid); 693 struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
619 694
620 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 695 if (dump_trace)
621 event->fork.ppid, event->fork.ptid); 696 perf_event__fprintf_task(event, stdout);
622 697
623 if (event->header.type == PERF_RECORD_EXIT) { 698 if (event->header.type == PERF_RECORD_EXIT) {
624 perf_session__remove_thread(session, thread); 699 machine__remove_thread(machine, thread);
625 return 0; 700 return 0;
626 } 701 }
627 702
@@ -634,22 +709,45 @@ int perf_event__process_task(union perf_event *event,
634 return 0; 709 return 0;
635} 710}
636 711
637int perf_event__process(union perf_event *event, struct perf_sample *sample, 712size_t perf_event__fprintf(union perf_event *event, FILE *fp)
638 struct perf_session *session) 713{
714 size_t ret = fprintf(fp, "PERF_RECORD_%s",
715 perf_event__name(event->header.type));
716
717 switch (event->header.type) {
718 case PERF_RECORD_COMM:
719 ret += perf_event__fprintf_comm(event, fp);
720 break;
721 case PERF_RECORD_FORK:
722 case PERF_RECORD_EXIT:
723 ret += perf_event__fprintf_task(event, fp);
724 break;
725 case PERF_RECORD_MMAP:
726 ret += perf_event__fprintf_mmap(event, fp);
727 break;
728 default:
729 ret += fprintf(fp, "\n");
730 }
731
732 return ret;
733}
734
735int perf_event__process(struct perf_tool *tool, union perf_event *event,
736 struct perf_sample *sample, struct machine *machine)
639{ 737{
640 switch (event->header.type) { 738 switch (event->header.type) {
641 case PERF_RECORD_COMM: 739 case PERF_RECORD_COMM:
642 perf_event__process_comm(event, sample, session); 740 perf_event__process_comm(tool, event, sample, machine);
643 break; 741 break;
644 case PERF_RECORD_MMAP: 742 case PERF_RECORD_MMAP:
645 perf_event__process_mmap(event, sample, session); 743 perf_event__process_mmap(tool, event, sample, machine);
646 break; 744 break;
647 case PERF_RECORD_FORK: 745 case PERF_RECORD_FORK:
648 case PERF_RECORD_EXIT: 746 case PERF_RECORD_EXIT:
649 perf_event__process_task(event, sample, session); 747 perf_event__process_task(tool, event, sample, machine);
650 break; 748 break;
651 case PERF_RECORD_LOST: 749 case PERF_RECORD_LOST:
652 perf_event__process_lost(event, sample, session); 750 perf_event__process_lost(tool, event, sample, machine);
653 default: 751 default:
654 break; 752 break;
655 } 753 }
@@ -658,36 +756,29 @@ int perf_event__process(union perf_event *event, struct perf_sample *sample,
658} 756}
659 757
660void thread__find_addr_map(struct thread *self, 758void thread__find_addr_map(struct thread *self,
661 struct perf_session *session, u8 cpumode, 759 struct machine *machine, u8 cpumode,
662 enum map_type type, pid_t pid, u64 addr, 760 enum map_type type, u64 addr,
663 struct addr_location *al) 761 struct addr_location *al)
664{ 762{
665 struct map_groups *mg = &self->mg; 763 struct map_groups *mg = &self->mg;
666 struct machine *machine = NULL;
667 764
668 al->thread = self; 765 al->thread = self;
669 al->addr = addr; 766 al->addr = addr;
670 al->cpumode = cpumode; 767 al->cpumode = cpumode;
671 al->filtered = false; 768 al->filtered = false;
672 769
770 if (machine == NULL) {
771 al->map = NULL;
772 return;
773 }
774
673 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { 775 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
674 al->level = 'k'; 776 al->level = 'k';
675 machine = perf_session__find_host_machine(session);
676 if (machine == NULL) {
677 al->map = NULL;
678 return;
679 }
680 mg = &machine->kmaps; 777 mg = &machine->kmaps;
681 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { 778 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
682 al->level = '.'; 779 al->level = '.';
683 machine = perf_session__find_host_machine(session);
684 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 780 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
685 al->level = 'g'; 781 al->level = 'g';
686 machine = perf_session__find_machine(session, pid);
687 if (machine == NULL) {
688 al->map = NULL;
689 return;
690 }
691 mg = &machine->kmaps; 782 mg = &machine->kmaps;
692 } else { 783 } else {
693 /* 784 /*
@@ -733,13 +824,12 @@ try_again:
733 al->addr = al->map->map_ip(al->map, al->addr); 824 al->addr = al->map->map_ip(al->map, al->addr);
734} 825}
735 826
736void thread__find_addr_location(struct thread *self, 827void thread__find_addr_location(struct thread *thread, struct machine *machine,
737 struct perf_session *session, u8 cpumode, 828 u8 cpumode, enum map_type type, u64 addr,
738 enum map_type type, pid_t pid, u64 addr,
739 struct addr_location *al, 829 struct addr_location *al,
740 symbol_filter_t filter) 830 symbol_filter_t filter)
741{ 831{
742 thread__find_addr_map(self, session, cpumode, type, pid, addr, al); 832 thread__find_addr_map(thread, machine, cpumode, type, addr, al);
743 if (al->map != NULL) 833 if (al->map != NULL)
744 al->sym = map__find_symbol(al->map, al->addr, filter); 834 al->sym = map__find_symbol(al->map, al->addr, filter);
745 else 835 else
@@ -747,13 +837,13 @@ void thread__find_addr_location(struct thread *self,
747} 837}
748 838
749int perf_event__preprocess_sample(const union perf_event *event, 839int perf_event__preprocess_sample(const union perf_event *event,
750 struct perf_session *session, 840 struct machine *machine,
751 struct addr_location *al, 841 struct addr_location *al,
752 struct perf_sample *sample, 842 struct perf_sample *sample,
753 symbol_filter_t filter) 843 symbol_filter_t filter)
754{ 844{
755 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 845 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
756 struct thread *thread = perf_session__findnew(session, event->ip.pid); 846 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
757 847
758 if (thread == NULL) 848 if (thread == NULL)
759 return -1; 849 return -1;
@@ -764,18 +854,18 @@ int perf_event__preprocess_sample(const union perf_event *event,
764 854
765 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 855 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
766 /* 856 /*
767 * Have we already created the kernel maps for the host machine? 857 * Have we already created the kernel maps for this machine?
768 * 858 *
769 * This should have happened earlier, when we processed the kernel MMAP 859 * This should have happened earlier, when we processed the kernel MMAP
770 * events, but for older perf.data files there was no such thing, so do 860 * events, but for older perf.data files there was no such thing, so do
771 * it now. 861 * it now.
772 */ 862 */
773 if (cpumode == PERF_RECORD_MISC_KERNEL && 863 if (cpumode == PERF_RECORD_MISC_KERNEL &&
774 session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL) 864 machine->vmlinux_maps[MAP__FUNCTION] == NULL)
775 machine__create_kernel_maps(&session->host_machine); 865 machine__create_kernel_maps(machine);
776 866
777 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 867 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
778 event->ip.pid, event->ip.ip, al); 868 event->ip.ip, al);
779 dump_printf(" ...... dso: %s\n", 869 dump_printf(" ...... dso: %s\n",
780 al->map ? al->map->dso->long_name : 870 al->map ? al->map->dso->long_name :
781 al->level == 'H' ? "[hypervisor]" : "<not found>"); 871 al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -783,13 +873,14 @@ int perf_event__preprocess_sample(const union perf_event *event,
783 al->cpu = sample->cpu; 873 al->cpu = sample->cpu;
784 874
785 if (al->map) { 875 if (al->map) {
876 struct dso *dso = al->map->dso;
877
786 if (symbol_conf.dso_list && 878 if (symbol_conf.dso_list &&
787 (!al->map || !al->map->dso || 879 (!dso || !(strlist__has_entry(symbol_conf.dso_list,
788 !(strlist__has_entry(symbol_conf.dso_list, 880 dso->short_name) ||
789 al->map->dso->short_name) || 881 (dso->short_name != dso->long_name &&
790 (al->map->dso->short_name != al->map->dso->long_name && 882 strlist__has_entry(symbol_conf.dso_list,
791 strlist__has_entry(symbol_conf.dso_list, 883 dso->long_name)))))
792 al->map->dso->long_name)))))
793 goto out_filtered; 884 goto out_filtered;
794 885
795 al->sym = map__find_symbol(al->map, al->addr, filter); 886 al->sym = map__find_symbol(al->map, al->addr, filter);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 357a85b85248..cbdeaad9c5e5 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -2,6 +2,7 @@
2#define __PERF_RECORD_H 2#define __PERF_RECORD_H
3 3
4#include <limits.h> 4#include <limits.h>
5#include <stdio.h>
5 6
6#include "../perf.h" 7#include "../perf.h"
7#include "map.h" 8#include "map.h"
@@ -141,43 +142,54 @@ union perf_event {
141 142
142void perf_event__print_totals(void); 143void perf_event__print_totals(void);
143 144
144struct perf_session; 145struct perf_tool;
145struct thread_map; 146struct thread_map;
146 147
147typedef int (*perf_event__handler_synth_t)(union perf_event *event, 148typedef int (*perf_event__handler_t)(struct perf_tool *tool,
148 struct perf_session *session); 149 union perf_event *event,
149typedef int (*perf_event__handler_t)(union perf_event *event,
150 struct perf_sample *sample, 150 struct perf_sample *sample,
151 struct perf_session *session); 151 struct machine *machine);
152 152
153int perf_event__synthesize_thread_map(struct thread_map *threads, 153int perf_event__synthesize_thread_map(struct perf_tool *tool,
154 struct thread_map *threads,
154 perf_event__handler_t process, 155 perf_event__handler_t process,
155 struct perf_session *session); 156 struct machine *machine);
156int perf_event__synthesize_threads(perf_event__handler_t process, 157int perf_event__synthesize_threads(struct perf_tool *tool,
157 struct perf_session *session); 158 perf_event__handler_t process,
158int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, 159 struct machine *machine);
159 struct perf_session *session, 160int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
161 perf_event__handler_t process,
160 struct machine *machine, 162 struct machine *machine,
161 const char *symbol_name); 163 const char *symbol_name);
162 164
163int perf_event__synthesize_modules(perf_event__handler_t process, 165int perf_event__synthesize_modules(struct perf_tool *tool,
164 struct perf_session *session, 166 perf_event__handler_t process,
165 struct machine *machine); 167 struct machine *machine);
166 168
167int perf_event__process_comm(union perf_event *event, struct perf_sample *sample, 169int perf_event__process_comm(struct perf_tool *tool,
168 struct perf_session *session); 170 union perf_event *event,
169int perf_event__process_lost(union perf_event *event, struct perf_sample *sample, 171 struct perf_sample *sample,
170 struct perf_session *session); 172 struct machine *machine);
171int perf_event__process_mmap(union perf_event *event, struct perf_sample *sample, 173int perf_event__process_lost(struct perf_tool *tool,
172 struct perf_session *session); 174 union perf_event *event,
173int perf_event__process_task(union perf_event *event, struct perf_sample *sample, 175 struct perf_sample *sample,
174 struct perf_session *session); 176 struct machine *machine);
175int perf_event__process(union perf_event *event, struct perf_sample *sample, 177int perf_event__process_mmap(struct perf_tool *tool,
176 struct perf_session *session); 178 union perf_event *event,
179 struct perf_sample *sample,
180 struct machine *machine);
181int perf_event__process_task(struct perf_tool *tool,
182 union perf_event *event,
183 struct perf_sample *sample,
184 struct machine *machine);
185int perf_event__process(struct perf_tool *tool,
186 union perf_event *event,
187 struct perf_sample *sample,
188 struct machine *machine);
177 189
178struct addr_location; 190struct addr_location;
179int perf_event__preprocess_sample(const union perf_event *self, 191int perf_event__preprocess_sample(const union perf_event *self,
180 struct perf_session *session, 192 struct machine *machine,
181 struct addr_location *al, 193 struct addr_location *al,
182 struct perf_sample *sample, 194 struct perf_sample *sample,
183 symbol_filter_t filter); 195 symbol_filter_t filter);
@@ -187,5 +199,13 @@ const char *perf_event__name(unsigned int id);
187int perf_event__parse_sample(const union perf_event *event, u64 type, 199int perf_event__parse_sample(const union perf_event *event, u64 type,
188 int sample_size, bool sample_id_all, 200 int sample_size, bool sample_id_all,
189 struct perf_sample *sample, bool swapped); 201 struct perf_sample *sample, bool swapped);
202int perf_event__synthesize_sample(union perf_event *event, u64 type,
203 const struct perf_sample *sample,
204 bool swapped);
205
206size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
207size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
208size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
209size_t perf_event__fprintf(union perf_event *event, FILE *fp);
190 210
191#endif /* __PERF_RECORD_H */ 211#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index fbb4b4ab9cc6..ea32a061f1c8 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -6,12 +6,16 @@
6 * 6 *
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9#include "util.h"
10#include "debugfs.h"
9#include <poll.h> 11#include <poll.h>
10#include "cpumap.h" 12#include "cpumap.h"
11#include "thread_map.h" 13#include "thread_map.h"
12#include "evlist.h" 14#include "evlist.h"
13#include "evsel.h" 15#include "evsel.h"
14#include "util.h" 16#include <unistd.h>
17
18#include "parse-events.h"
15 19
16#include <sys/mman.h> 20#include <sys/mman.h>
17 21
@@ -30,6 +34,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
30 INIT_HLIST_HEAD(&evlist->heads[i]); 34 INIT_HLIST_HEAD(&evlist->heads[i]);
31 INIT_LIST_HEAD(&evlist->entries); 35 INIT_LIST_HEAD(&evlist->entries);
32 perf_evlist__set_maps(evlist, cpus, threads); 36 perf_evlist__set_maps(evlist, cpus, threads);
37 evlist->workload.pid = -1;
33} 38}
34 39
35struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 40struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
@@ -43,6 +48,22 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
43 return evlist; 48 return evlist;
44} 49}
45 50
51void perf_evlist__config_attrs(struct perf_evlist *evlist,
52 struct perf_record_opts *opts)
53{
54 struct perf_evsel *evsel;
55
56 if (evlist->cpus->map[0] < 0)
57 opts->no_inherit = true;
58
59 list_for_each_entry(evsel, &evlist->entries, node) {
60 perf_evsel__config(evsel, opts);
61
62 if (evlist->nr_entries > 1)
63 evsel->attr.sample_type |= PERF_SAMPLE_ID;
64 }
65}
66
46static void perf_evlist__purge(struct perf_evlist *evlist) 67static void perf_evlist__purge(struct perf_evlist *evlist)
47{ 68{
48 struct perf_evsel *pos, *n; 69 struct perf_evsel *pos, *n;
@@ -76,14 +97,25 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
76 ++evlist->nr_entries; 97 ++evlist->nr_entries;
77} 98}
78 99
100static void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
101 struct list_head *list,
102 int nr_entries)
103{
104 list_splice_tail(list, &evlist->entries);
105 evlist->nr_entries += nr_entries;
106}
107
79int perf_evlist__add_default(struct perf_evlist *evlist) 108int perf_evlist__add_default(struct perf_evlist *evlist)
80{ 109{
81 struct perf_event_attr attr = { 110 struct perf_event_attr attr = {
82 .type = PERF_TYPE_HARDWARE, 111 .type = PERF_TYPE_HARDWARE,
83 .config = PERF_COUNT_HW_CPU_CYCLES, 112 .config = PERF_COUNT_HW_CPU_CYCLES,
84 }; 113 };
85 struct perf_evsel *evsel = perf_evsel__new(&attr, 0); 114 struct perf_evsel *evsel;
86 115
116 event_attr_init(&attr);
117
118 evsel = perf_evsel__new(&attr, 0);
87 if (evsel == NULL) 119 if (evsel == NULL)
88 goto error; 120 goto error;
89 121
@@ -100,6 +132,126 @@ error:
100 return -ENOMEM; 132 return -ENOMEM;
101} 133}
102 134
135int perf_evlist__add_attrs(struct perf_evlist *evlist,
136 struct perf_event_attr *attrs, size_t nr_attrs)
137{
138 struct perf_evsel *evsel, *n;
139 LIST_HEAD(head);
140 size_t i;
141
142 for (i = 0; i < nr_attrs; i++) {
143 evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i);
144 if (evsel == NULL)
145 goto out_delete_partial_list;
146 list_add_tail(&evsel->node, &head);
147 }
148
149 perf_evlist__splice_list_tail(evlist, &head, nr_attrs);
150
151 return 0;
152
153out_delete_partial_list:
154 list_for_each_entry_safe(evsel, n, &head, node)
155 perf_evsel__delete(evsel);
156 return -1;
157}
158
159static int trace_event__id(const char *evname)
160{
161 char *filename, *colon;
162 int err = -1, fd;
163
164 if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
165 return -1;
166
167 colon = strrchr(filename, ':');
168 if (colon != NULL)
169 *colon = '/';
170
171 fd = open(filename, O_RDONLY);
172 if (fd >= 0) {
173 char id[16];
174 if (read(fd, id, sizeof(id)) > 0)
175 err = atoi(id);
176 close(fd);
177 }
178
179 free(filename);
180 return err;
181}
182
183int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
184 const char *tracepoints[],
185 size_t nr_tracepoints)
186{
187 int err;
188 size_t i;
189 struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
190
191 if (attrs == NULL)
192 return -1;
193
194 for (i = 0; i < nr_tracepoints; i++) {
195 err = trace_event__id(tracepoints[i]);
196
197 if (err < 0)
198 goto out_free_attrs;
199
200 attrs[i].type = PERF_TYPE_TRACEPOINT;
201 attrs[i].config = err;
202 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
203 PERF_SAMPLE_CPU);
204 attrs[i].sample_period = 1;
205 }
206
207 err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
208out_free_attrs:
209 free(attrs);
210 return err;
211}
212
213static struct perf_evsel *
214 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
215{
216 struct perf_evsel *evsel;
217
218 list_for_each_entry(evsel, &evlist->entries, node) {
219 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
220 (int)evsel->attr.config == id)
221 return evsel;
222 }
223
224 return NULL;
225}
226
227int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
228 const struct perf_evsel_str_handler *assocs,
229 size_t nr_assocs)
230{
231 struct perf_evsel *evsel;
232 int err;
233 size_t i;
234
235 for (i = 0; i < nr_assocs; i++) {
236 err = trace_event__id(assocs[i].name);
237 if (err < 0)
238 goto out;
239
240 evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
241 if (evsel == NULL)
242 continue;
243
244 err = -EEXIST;
245 if (evsel->handler.func != NULL)
246 goto out;
247 evsel->handler.func = assocs[i].handler;
248 }
249
250 err = 0;
251out:
252 return err;
253}
254
103void perf_evlist__disable(struct perf_evlist *evlist) 255void perf_evlist__disable(struct perf_evlist *evlist)
104{ 256{
105 int cpu, thread; 257 int cpu, thread;
@@ -126,7 +278,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
126 } 278 }
127} 279}
128 280
129int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 281static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
130{ 282{
131 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; 283 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
132 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 284 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
@@ -197,6 +349,10 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
197 hlist_for_each_entry(sid, pos, head, node) 349 hlist_for_each_entry(sid, pos, head, node)
198 if (sid->id == id) 350 if (sid->id == id)
199 return sid->evsel; 351 return sid->evsel;
352
353 if (!perf_evlist__sample_id_all(evlist))
354 return list_entry(evlist->entries.next, struct perf_evsel, node);
355
200 return NULL; 356 return NULL;
201} 357}
202 358
@@ -282,7 +438,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
282 evlist->mmap = NULL; 438 evlist->mmap = NULL;
283} 439}
284 440
285int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 441static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
286{ 442{
287 evlist->nr_mmaps = evlist->cpus->nr; 443 evlist->nr_mmaps = evlist->cpus->nr;
288 if (evlist->cpus->map[0] == -1) 444 if (evlist->cpus->map[0] == -1)
@@ -298,8 +454,10 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
298 evlist->mmap[idx].mask = mask; 454 evlist->mmap[idx].mask = mask;
299 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 455 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
300 MAP_SHARED, fd, 0); 456 MAP_SHARED, fd, 0);
301 if (evlist->mmap[idx].base == MAP_FAILED) 457 if (evlist->mmap[idx].base == MAP_FAILED) {
458 evlist->mmap[idx].base = NULL;
302 return -1; 459 return -1;
460 }
303 461
304 perf_evlist__add_pollfd(evlist, fd); 462 perf_evlist__add_pollfd(evlist, fd);
305 return 0; 463 return 0;
@@ -400,14 +558,22 @@ out_unmap:
400 * 558 *
401 * Using perf_evlist__read_on_cpu does this automatically. 559 * Using perf_evlist__read_on_cpu does this automatically.
402 */ 560 */
403int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) 561int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
562 bool overwrite)
404{ 563{
405 unsigned int page_size = sysconf(_SC_PAGE_SIZE); 564 unsigned int page_size = sysconf(_SC_PAGE_SIZE);
406 int mask = pages * page_size - 1;
407 struct perf_evsel *evsel; 565 struct perf_evsel *evsel;
408 const struct cpu_map *cpus = evlist->cpus; 566 const struct cpu_map *cpus = evlist->cpus;
409 const struct thread_map *threads = evlist->threads; 567 const struct thread_map *threads = evlist->threads;
410 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE); 568 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
569
570 /* 512 kiB: default amount of unprivileged mlocked memory */
571 if (pages == UINT_MAX)
572 pages = (512 * 1024) / page_size;
573 else if (!is_power_of_2(pages))
574 return -EINVAL;
575
576 mask = pages * page_size - 1;
411 577
412 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 578 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
413 return -ENOMEM; 579 return -ENOMEM;
@@ -512,6 +678,38 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
512 return first->attr.sample_type; 678 return first->attr.sample_type;
513} 679}
514 680
681u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist)
682{
683 struct perf_evsel *first;
684 struct perf_sample *data;
685 u64 sample_type;
686 u16 size = 0;
687
688 first = list_entry(evlist->entries.next, struct perf_evsel, node);
689
690 if (!first->attr.sample_id_all)
691 goto out;
692
693 sample_type = first->attr.sample_type;
694
695 if (sample_type & PERF_SAMPLE_TID)
696 size += sizeof(data->tid) * 2;
697
698 if (sample_type & PERF_SAMPLE_TIME)
699 size += sizeof(data->time);
700
701 if (sample_type & PERF_SAMPLE_ID)
702 size += sizeof(data->id);
703
704 if (sample_type & PERF_SAMPLE_STREAM_ID)
705 size += sizeof(data->stream_id);
706
707 if (sample_type & PERF_SAMPLE_CPU)
708 size += sizeof(data->cpu) * 2;
709out:
710 return size;
711}
712
515bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) 713bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
516{ 714{
517 struct perf_evsel *pos, *first; 715 struct perf_evsel *pos, *first;
@@ -569,3 +767,97 @@ out_err:
569 767
570 return err; 768 return err;
571} 769}
770
771int perf_evlist__prepare_workload(struct perf_evlist *evlist,
772 struct perf_record_opts *opts,
773 const char *argv[])
774{
775 int child_ready_pipe[2], go_pipe[2];
776 char bf;
777
778 if (pipe(child_ready_pipe) < 0) {
779 perror("failed to create 'ready' pipe");
780 return -1;
781 }
782
783 if (pipe(go_pipe) < 0) {
784 perror("failed to create 'go' pipe");
785 goto out_close_ready_pipe;
786 }
787
788 evlist->workload.pid = fork();
789 if (evlist->workload.pid < 0) {
790 perror("failed to fork");
791 goto out_close_pipes;
792 }
793
794 if (!evlist->workload.pid) {
795 if (opts->pipe_output)
796 dup2(2, 1);
797
798 close(child_ready_pipe[0]);
799 close(go_pipe[1]);
800 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
801
802 /*
803 * Do a dummy execvp to get the PLT entry resolved,
804 * so we avoid the resolver overhead on the real
805 * execvp call.
806 */
807 execvp("", (char **)argv);
808
809 /*
810 * Tell the parent we're ready to go
811 */
812 close(child_ready_pipe[1]);
813
814 /*
815 * Wait until the parent tells us to go.
816 */
817 if (read(go_pipe[0], &bf, 1) == -1)
818 perror("unable to read pipe");
819
820 execvp(argv[0], (char **)argv);
821
822 perror(argv[0]);
823 kill(getppid(), SIGUSR1);
824 exit(-1);
825 }
826
827 if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1)
828 evlist->threads->map[0] = evlist->workload.pid;
829
830 close(child_ready_pipe[1]);
831 close(go_pipe[0]);
832 /*
833 * wait for child to settle
834 */
835 if (read(child_ready_pipe[0], &bf, 1) == -1) {
836 perror("unable to read pipe");
837 goto out_close_pipes;
838 }
839
840 evlist->workload.cork_fd = go_pipe[1];
841 close(child_ready_pipe[0]);
842 return 0;
843
844out_close_pipes:
845 close(go_pipe[0]);
846 close(go_pipe[1]);
847out_close_ready_pipe:
848 close(child_ready_pipe[0]);
849 close(child_ready_pipe[1]);
850 return -1;
851}
852
853int perf_evlist__start_workload(struct perf_evlist *evlist)
854{
855 if (evlist->workload.cork_fd > 0) {
856 /*
857 * Remove the cork, let it rip!
858 */
859 return close(evlist->workload.cork_fd);
860 }
861
862 return 0;
863}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 1779ffef7828..8922aeed0467 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,12 +2,16 @@
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <stdio.h>
5#include "../perf.h" 6#include "../perf.h"
6#include "event.h" 7#include "event.h"
8#include "util.h"
9#include <unistd.h>
7 10
8struct pollfd; 11struct pollfd;
9struct thread_map; 12struct thread_map;
10struct cpu_map; 13struct cpu_map;
14struct perf_record_opts;
11 15
12#define PERF_EVLIST__HLIST_BITS 8 16#define PERF_EVLIST__HLIST_BITS 8
13#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 17#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
@@ -19,6 +23,10 @@ struct perf_evlist {
19 int nr_fds; 23 int nr_fds;
20 int nr_mmaps; 24 int nr_mmaps;
21 int mmap_len; 25 int mmap_len;
26 struct {
27 int cork_fd;
28 pid_t pid;
29 } workload;
22 bool overwrite; 30 bool overwrite;
23 union perf_event event_copy; 31 union perf_event event_copy;
24 struct perf_mmap *mmap; 32 struct perf_mmap *mmap;
@@ -28,6 +36,11 @@ struct perf_evlist {
28 struct perf_evsel *selected; 36 struct perf_evsel *selected;
29}; 37};
30 38
39struct perf_evsel_str_handler {
40 const char *name;
41 void *handler;
42};
43
31struct perf_evsel; 44struct perf_evsel;
32 45
33struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 46struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
@@ -39,11 +52,26 @@ void perf_evlist__delete(struct perf_evlist *evlist);
39 52
40void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 53void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
41int perf_evlist__add_default(struct perf_evlist *evlist); 54int perf_evlist__add_default(struct perf_evlist *evlist);
55int perf_evlist__add_attrs(struct perf_evlist *evlist,
56 struct perf_event_attr *attrs, size_t nr_attrs);
57int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
58 const char *tracepoints[], size_t nr_tracepoints);
59int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
60 const struct perf_evsel_str_handler *assocs,
61 size_t nr_assocs);
62
63#define perf_evlist__add_attrs_array(evlist, array) \
64 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
65
66#define perf_evlist__add_tracepoints_array(evlist, array) \
67 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
68
69#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
70 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
42 71
43void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 72void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
44 int cpu, int thread, u64 id); 73 int cpu, int thread, u64 id);
45 74
46int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
47void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 75void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
48 76
49struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 77struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
@@ -52,8 +80,16 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
52 80
53int perf_evlist__open(struct perf_evlist *evlist, bool group); 81int perf_evlist__open(struct perf_evlist *evlist, bool group);
54 82
55int perf_evlist__alloc_mmap(struct perf_evlist *evlist); 83void perf_evlist__config_attrs(struct perf_evlist *evlist,
56int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); 84 struct perf_record_opts *opts);
85
86int perf_evlist__prepare_workload(struct perf_evlist *evlist,
87 struct perf_record_opts *opts,
88 const char *argv[]);
89int perf_evlist__start_workload(struct perf_evlist *evlist);
90
91int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
92 bool overwrite);
57void perf_evlist__munmap(struct perf_evlist *evlist); 93void perf_evlist__munmap(struct perf_evlist *evlist);
58 94
59void perf_evlist__disable(struct perf_evlist *evlist); 95void perf_evlist__disable(struct perf_evlist *evlist);
@@ -77,6 +113,7 @@ int perf_evlist__set_filters(struct perf_evlist *evlist);
77 113
78u64 perf_evlist__sample_type(const struct perf_evlist *evlist); 114u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
79bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); 115bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
116u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
80 117
81bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); 118bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
82bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); 119bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d7915d4e77cb..7132ee834e0e 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -63,6 +63,79 @@ 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)
67{
68 struct perf_event_attr *attr = &evsel->attr;
69 int track = !evsel->idx; /* only the first counter needs these */
70
71 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
72 attr->inherit = !opts->no_inherit;
73 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
74 PERF_FORMAT_TOTAL_TIME_RUNNING |
75 PERF_FORMAT_ID;
76
77 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
78
79 /*
80 * We default some events to a 1 default interval. But keep
81 * it a weak assumption overridable by the user.
82 */
83 if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
84 opts->user_interval != ULLONG_MAX)) {
85 if (opts->freq) {
86 attr->sample_type |= PERF_SAMPLE_PERIOD;
87 attr->freq = 1;
88 attr->sample_freq = opts->freq;
89 } else {
90 attr->sample_period = opts->default_interval;
91 }
92 }
93
94 if (opts->no_samples)
95 attr->sample_freq = 0;
96
97 if (opts->inherit_stat)
98 attr->inherit_stat = 1;
99
100 if (opts->sample_address) {
101 attr->sample_type |= PERF_SAMPLE_ADDR;
102 attr->mmap_data = track;
103 }
104
105 if (opts->call_graph)
106 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
107
108 if (opts->system_wide)
109 attr->sample_type |= PERF_SAMPLE_CPU;
110
111 if (opts->period)
112 attr->sample_type |= PERF_SAMPLE_PERIOD;
113
114 if (opts->sample_id_all_avail &&
115 (opts->sample_time || opts->system_wide ||
116 !opts->no_inherit || opts->cpu_list))
117 attr->sample_type |= PERF_SAMPLE_TIME;
118
119 if (opts->raw_samples) {
120 attr->sample_type |= PERF_SAMPLE_TIME;
121 attr->sample_type |= PERF_SAMPLE_RAW;
122 attr->sample_type |= PERF_SAMPLE_CPU;
123 }
124
125 if (opts->no_delay) {
126 attr->watermark = 0;
127 attr->wakeup_events = 1;
128 }
129
130 attr->mmap = track;
131 attr->comm = track;
132
133 if (opts->target_pid == -1 && opts->target_tid == -1 && !opts->system_wide) {
134 attr->disabled = 1;
135 attr->enable_on_exec = 1;
136 }
137}
138
66int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 139int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
67{ 140{
68 int cpu, thread; 141 int cpu, thread;
@@ -387,9 +460,10 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
387 u32 val32[2]; 460 u32 val32[2];
388 } u; 461 } u;
389 462
390 463 memset(data, 0, sizeof(*data));
391 data->cpu = data->pid = data->tid = -1; 464 data->cpu = data->pid = data->tid = -1;
392 data->stream_id = data->id = data->time = -1ULL; 465 data->stream_id = data->id = data->time = -1ULL;
466 data->period = 1;
393 467
394 if (event->header.type != PERF_RECORD_SAMPLE) { 468 if (event->header.type != PERF_RECORD_SAMPLE) {
395 if (!sample_id_all) 469 if (!sample_id_all)
@@ -504,3 +578,82 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
504 578
505 return 0; 579 return 0;
506} 580}
581
582int perf_event__synthesize_sample(union perf_event *event, u64 type,
583 const struct perf_sample *sample,
584 bool swapped)
585{
586 u64 *array;
587
588 /*
589 * used for cross-endian analysis. See git commit 65014ab3
590 * for why this goofiness is needed.
591 */
592 union {
593 u64 val64;
594 u32 val32[2];
595 } u;
596
597 array = event->sample.array;
598
599 if (type & PERF_SAMPLE_IP) {
600 event->ip.ip = sample->ip;
601 array++;
602 }
603
604 if (type & PERF_SAMPLE_TID) {
605 u.val32[0] = sample->pid;
606 u.val32[1] = sample->tid;
607 if (swapped) {
608 /*
609 * Inverse of what is done in perf_event__parse_sample
610 */
611 u.val32[0] = bswap_32(u.val32[0]);
612 u.val32[1] = bswap_32(u.val32[1]);
613 u.val64 = bswap_64(u.val64);
614 }
615
616 *array = u.val64;
617 array++;
618 }
619
620 if (type & PERF_SAMPLE_TIME) {
621 *array = sample->time;
622 array++;
623 }
624
625 if (type & PERF_SAMPLE_ADDR) {
626 *array = sample->addr;
627 array++;
628 }
629
630 if (type & PERF_SAMPLE_ID) {
631 *array = sample->id;
632 array++;
633 }
634
635 if (type & PERF_SAMPLE_STREAM_ID) {
636 *array = sample->stream_id;
637 array++;
638 }
639
640 if (type & PERF_SAMPLE_CPU) {
641 u.val32[0] = sample->cpu;
642 if (swapped) {
643 /*
644 * Inverse of what is done in perf_event__parse_sample
645 */
646 u.val32[0] = bswap_32(u.val32[0]);
647 u.val64 = bswap_64(u.val64);
648 }
649 *array = u.val64;
650 array++;
651 }
652
653 if (type & PERF_SAMPLE_PERIOD) {
654 *array = sample->period;
655 array++;
656 }
657
658 return 0;
659}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b1d15e6f7ae3..326b8e4d5035 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -61,12 +61,17 @@ struct perf_evsel {
61 off_t id_offset; 61 off_t id_offset;
62 }; 62 };
63 struct cgroup_sel *cgrp; 63 struct cgroup_sel *cgrp;
64 struct {
65 void *func;
66 void *data;
67 } handler;
64 bool supported; 68 bool supported;
65}; 69};
66 70
67struct cpu_map; 71struct cpu_map;
68struct thread_map; 72struct thread_map;
69struct perf_evlist; 73struct perf_evlist;
74struct perf_record_opts;
70 75
71struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); 76struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
72void perf_evsel__init(struct perf_evsel *evsel, 77void perf_evsel__init(struct perf_evsel *evsel,
@@ -74,6 +79,9 @@ void perf_evsel__init(struct perf_evsel *evsel,
74void perf_evsel__exit(struct perf_evsel *evsel); 79void perf_evsel__exit(struct perf_evsel *evsel);
75void perf_evsel__delete(struct perf_evsel *evsel); 80void perf_evsel__delete(struct perf_evsel *evsel);
76 81
82void perf_evsel__config(struct perf_evsel *evsel,
83 struct perf_record_opts *opts);
84
77int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 85int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
78int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 86int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
79int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); 87int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 33c17a2b2a81..14bb035c5fd9 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,6 +8,7 @@
8#include <stdlib.h> 8#include <stdlib.h>
9#include <linux/list.h> 9#include <linux/list.h>
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/bitops.h>
11#include <sys/utsname.h> 12#include <sys/utsname.h>
12 13
13#include "evlist.h" 14#include "evlist.h"
@@ -28,9 +29,6 @@ static struct perf_trace_event_type *events;
28static u32 header_argc; 29static u32 header_argc;
29static const char **header_argv; 30static const char **header_argv;
30 31
31static int dsos__write_buildid_table(struct perf_header *header, int fd);
32static int perf_session__cache_build_ids(struct perf_session *session);
33
34int perf_header__push_event(u64 id, const char *name) 32int perf_header__push_event(u64 id, const char *name)
35{ 33{
36 if (strlen(name) > MAX_EVENT_NAME) 34 if (strlen(name) > MAX_EVENT_NAME)
@@ -187,6 +185,252 @@ perf_header__set_cmdline(int argc, const char **argv)
187 return 0; 185 return 0;
188} 186}
189 187
188#define dsos__for_each_with_build_id(pos, head) \
189 list_for_each_entry(pos, head, node) \
190 if (!pos->has_build_id) \
191 continue; \
192 else
193
194static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
195 u16 misc, int fd)
196{
197 struct dso *pos;
198
199 dsos__for_each_with_build_id(pos, head) {
200 int err;
201 struct build_id_event b;
202 size_t len;
203
204 if (!pos->hit)
205 continue;
206 len = pos->long_name_len + 1;
207 len = ALIGN(len, NAME_ALIGN);
208 memset(&b, 0, sizeof(b));
209 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
210 b.pid = pid;
211 b.header.misc = misc;
212 b.header.size = sizeof(b) + len;
213 err = do_write(fd, &b, sizeof(b));
214 if (err < 0)
215 return err;
216 err = write_padded(fd, pos->long_name,
217 pos->long_name_len + 1, len);
218 if (err < 0)
219 return err;
220 }
221
222 return 0;
223}
224
225static int machine__write_buildid_table(struct machine *machine, int fd)
226{
227 int err;
228 u16 kmisc = PERF_RECORD_MISC_KERNEL,
229 umisc = PERF_RECORD_MISC_USER;
230
231 if (!machine__is_host(machine)) {
232 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
233 umisc = PERF_RECORD_MISC_GUEST_USER;
234 }
235
236 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
237 kmisc, fd);
238 if (err == 0)
239 err = __dsos__write_buildid_table(&machine->user_dsos,
240 machine->pid, umisc, fd);
241 return err;
242}
243
244static int dsos__write_buildid_table(struct perf_header *header, int fd)
245{
246 struct perf_session *session = container_of(header,
247 struct perf_session, header);
248 struct rb_node *nd;
249 int err = machine__write_buildid_table(&session->host_machine, fd);
250
251 if (err)
252 return err;
253
254 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
255 struct machine *pos = rb_entry(nd, struct machine, rb_node);
256 err = machine__write_buildid_table(pos, fd);
257 if (err)
258 break;
259 }
260 return err;
261}
262
263int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
264 const char *name, bool is_kallsyms)
265{
266 const size_t size = PATH_MAX;
267 char *realname, *filename = zalloc(size),
268 *linkname = zalloc(size), *targetname;
269 int len, err = -1;
270
271 if (is_kallsyms) {
272 if (symbol_conf.kptr_restrict) {
273 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
274 return 0;
275 }
276 realname = (char *)name;
277 } else
278 realname = realpath(name, NULL);
279
280 if (realname == NULL || filename == NULL || linkname == NULL)
281 goto out_free;
282
283 len = scnprintf(filename, size, "%s%s%s",
284 debugdir, is_kallsyms ? "/" : "", realname);
285 if (mkdir_p(filename, 0755))
286 goto out_free;
287
288 snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
289
290 if (access(filename, F_OK)) {
291 if (is_kallsyms) {
292 if (copyfile("/proc/kallsyms", filename))
293 goto out_free;
294 } else if (link(realname, filename) && copyfile(name, filename))
295 goto out_free;
296 }
297
298 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
299 debugdir, sbuild_id);
300
301 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
302 goto out_free;
303
304 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
305 targetname = filename + strlen(debugdir) - 5;
306 memcpy(targetname, "../..", 5);
307
308 if (symlink(targetname, linkname) == 0)
309 err = 0;
310out_free:
311 if (!is_kallsyms)
312 free(realname);
313 free(filename);
314 free(linkname);
315 return err;
316}
317
318static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
319 const char *name, const char *debugdir,
320 bool is_kallsyms)
321{
322 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
323
324 build_id__sprintf(build_id, build_id_size, sbuild_id);
325
326 return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
327}
328
329int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
330{
331 const size_t size = PATH_MAX;
332 char *filename = zalloc(size),
333 *linkname = zalloc(size);
334 int err = -1;
335
336 if (filename == NULL || linkname == NULL)
337 goto out_free;
338
339 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
340 debugdir, sbuild_id, sbuild_id + 2);
341
342 if (access(linkname, F_OK))
343 goto out_free;
344
345 if (readlink(linkname, filename, size - 1) < 0)
346 goto out_free;
347
348 if (unlink(linkname))
349 goto out_free;
350
351 /*
352 * Since the link is relative, we must make it absolute:
353 */
354 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
355 debugdir, sbuild_id, filename);
356
357 if (unlink(linkname))
358 goto out_free;
359
360 err = 0;
361out_free:
362 free(filename);
363 free(linkname);
364 return err;
365}
366
367static int dso__cache_build_id(struct dso *dso, const char *debugdir)
368{
369 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
370
371 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
372 dso->long_name, debugdir, is_kallsyms);
373}
374
375static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
376{
377 struct dso *pos;
378 int err = 0;
379
380 dsos__for_each_with_build_id(pos, head)
381 if (dso__cache_build_id(pos, debugdir))
382 err = -1;
383
384 return err;
385}
386
387static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
388{
389 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
390 ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
391 return ret;
392}
393
394static int perf_session__cache_build_ids(struct perf_session *session)
395{
396 struct rb_node *nd;
397 int ret;
398 char debugdir[PATH_MAX];
399
400 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
401
402 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
403 return -1;
404
405 ret = machine__cache_build_ids(&session->host_machine, debugdir);
406
407 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
408 struct machine *pos = rb_entry(nd, struct machine, rb_node);
409 ret |= machine__cache_build_ids(pos, debugdir);
410 }
411 return ret ? -1 : 0;
412}
413
414static bool machine__read_build_ids(struct machine *machine, bool with_hits)
415{
416 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
417 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
418 return ret;
419}
420
421static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
422{
423 struct rb_node *nd;
424 bool ret = machine__read_build_ids(&session->host_machine, with_hits);
425
426 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
427 struct machine *pos = rb_entry(nd, struct machine, rb_node);
428 ret |= machine__read_build_ids(pos, with_hits);
429 }
430
431 return ret;
432}
433
190static int write_trace_info(int fd, struct perf_header *h __used, 434static int write_trace_info(int fd, struct perf_header *h __used,
191 struct perf_evlist *evlist) 435 struct perf_evlist *evlist)
192{ 436{
@@ -202,6 +446,9 @@ static int write_build_id(int fd, struct perf_header *h,
202 446
203 session = container_of(h, struct perf_session, header); 447 session = container_of(h, struct perf_session, header);
204 448
449 if (!perf_session__read_build_ids(session, true))
450 return -1;
451
205 err = dsos__write_buildid_table(h, fd); 452 err = dsos__write_buildid_table(h, fd);
206 if (err < 0) { 453 if (err < 0) {
207 pr_debug("failed to write buildid table\n"); 454 pr_debug("failed to write buildid table\n");
@@ -1065,26 +1312,30 @@ struct feature_ops {
1065 bool full_only; 1312 bool full_only;
1066}; 1313};
1067 1314
1068#define FEAT_OPA(n, w, p) \ 1315#define FEAT_OPA(n, func) \
1069 [n] = { .name = #n, .write = w, .print = p } 1316 [n] = { .name = #n, .write = write_##func, .print = print_##func }
1070#define FEAT_OPF(n, w, p) \ 1317#define FEAT_OPF(n, func) \
1071 [n] = { .name = #n, .write = w, .print = p, .full_only = true } 1318 [n] = { .name = #n, .write = write_##func, .print = print_##func, .full_only = true }
1319
1320/* feature_ops not implemented: */
1321#define print_trace_info NULL
1322#define print_build_id NULL
1072 1323
1073static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { 1324static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1074 FEAT_OPA(HEADER_TRACE_INFO, write_trace_info, NULL), 1325 FEAT_OPA(HEADER_TRACE_INFO, trace_info),
1075 FEAT_OPA(HEADER_BUILD_ID, write_build_id, NULL), 1326 FEAT_OPA(HEADER_BUILD_ID, build_id),
1076 FEAT_OPA(HEADER_HOSTNAME, write_hostname, print_hostname), 1327 FEAT_OPA(HEADER_HOSTNAME, hostname),
1077 FEAT_OPA(HEADER_OSRELEASE, write_osrelease, print_osrelease), 1328 FEAT_OPA(HEADER_OSRELEASE, osrelease),
1078 FEAT_OPA(HEADER_VERSION, write_version, print_version), 1329 FEAT_OPA(HEADER_VERSION, version),
1079 FEAT_OPA(HEADER_ARCH, write_arch, print_arch), 1330 FEAT_OPA(HEADER_ARCH, arch),
1080 FEAT_OPA(HEADER_NRCPUS, write_nrcpus, print_nrcpus), 1331 FEAT_OPA(HEADER_NRCPUS, nrcpus),
1081 FEAT_OPA(HEADER_CPUDESC, write_cpudesc, print_cpudesc), 1332 FEAT_OPA(HEADER_CPUDESC, cpudesc),
1082 FEAT_OPA(HEADER_CPUID, write_cpuid, print_cpuid), 1333 FEAT_OPA(HEADER_CPUID, cpuid),
1083 FEAT_OPA(HEADER_TOTAL_MEM, write_total_mem, print_total_mem), 1334 FEAT_OPA(HEADER_TOTAL_MEM, total_mem),
1084 FEAT_OPA(HEADER_EVENT_DESC, write_event_desc, print_event_desc), 1335 FEAT_OPA(HEADER_EVENT_DESC, event_desc),
1085 FEAT_OPA(HEADER_CMDLINE, write_cmdline, print_cmdline), 1336 FEAT_OPA(HEADER_CMDLINE, cmdline),
1086 FEAT_OPF(HEADER_CPU_TOPOLOGY, write_cpu_topology, print_cpu_topology), 1337 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
1087 FEAT_OPF(HEADER_NUMA_TOPOLOGY, write_numa_topology, print_numa_topology), 1338 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
1088}; 1339};
1089 1340
1090struct header_print_data { 1341struct header_print_data {
@@ -1103,9 +1354,9 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,
1103 "%d, continuing...\n", section->offset, feat); 1354 "%d, continuing...\n", section->offset, feat);
1104 return 0; 1355 return 0;
1105 } 1356 }
1106 if (feat < HEADER_TRACE_INFO || feat >= HEADER_LAST_FEATURE) { 1357 if (feat >= HEADER_LAST_FEATURE) {
1107 pr_warning("unknown feature %d\n", feat); 1358 pr_warning("unknown feature %d\n", feat);
1108 return -1; 1359 return 0;
1109 } 1360 }
1110 if (!feat_ops[feat].print) 1361 if (!feat_ops[feat].print)
1111 return 0; 1362 return 0;
@@ -1132,252 +1383,6 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
1132 return 0; 1383 return 0;
1133} 1384}
1134 1385
1135#define dsos__for_each_with_build_id(pos, head) \
1136 list_for_each_entry(pos, head, node) \
1137 if (!pos->has_build_id) \
1138 continue; \
1139 else
1140
1141static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
1142 u16 misc, int fd)
1143{
1144 struct dso *pos;
1145
1146 dsos__for_each_with_build_id(pos, head) {
1147 int err;
1148 struct build_id_event b;
1149 size_t len;
1150
1151 if (!pos->hit)
1152 continue;
1153 len = pos->long_name_len + 1;
1154 len = ALIGN(len, NAME_ALIGN);
1155 memset(&b, 0, sizeof(b));
1156 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
1157 b.pid = pid;
1158 b.header.misc = misc;
1159 b.header.size = sizeof(b) + len;
1160 err = do_write(fd, &b, sizeof(b));
1161 if (err < 0)
1162 return err;
1163 err = write_padded(fd, pos->long_name,
1164 pos->long_name_len + 1, len);
1165 if (err < 0)
1166 return err;
1167 }
1168
1169 return 0;
1170}
1171
1172static int machine__write_buildid_table(struct machine *machine, int fd)
1173{
1174 int err;
1175 u16 kmisc = PERF_RECORD_MISC_KERNEL,
1176 umisc = PERF_RECORD_MISC_USER;
1177
1178 if (!machine__is_host(machine)) {
1179 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
1180 umisc = PERF_RECORD_MISC_GUEST_USER;
1181 }
1182
1183 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
1184 kmisc, fd);
1185 if (err == 0)
1186 err = __dsos__write_buildid_table(&machine->user_dsos,
1187 machine->pid, umisc, fd);
1188 return err;
1189}
1190
1191static int dsos__write_buildid_table(struct perf_header *header, int fd)
1192{
1193 struct perf_session *session = container_of(header,
1194 struct perf_session, header);
1195 struct rb_node *nd;
1196 int err = machine__write_buildid_table(&session->host_machine, fd);
1197
1198 if (err)
1199 return err;
1200
1201 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
1202 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1203 err = machine__write_buildid_table(pos, fd);
1204 if (err)
1205 break;
1206 }
1207 return err;
1208}
1209
1210int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
1211 const char *name, bool is_kallsyms)
1212{
1213 const size_t size = PATH_MAX;
1214 char *realname, *filename = zalloc(size),
1215 *linkname = zalloc(size), *targetname;
1216 int len, err = -1;
1217
1218 if (is_kallsyms) {
1219 if (symbol_conf.kptr_restrict) {
1220 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
1221 return 0;
1222 }
1223 realname = (char *)name;
1224 } else
1225 realname = realpath(name, NULL);
1226
1227 if (realname == NULL || filename == NULL || linkname == NULL)
1228 goto out_free;
1229
1230 len = snprintf(filename, size, "%s%s%s",
1231 debugdir, is_kallsyms ? "/" : "", realname);
1232 if (mkdir_p(filename, 0755))
1233 goto out_free;
1234
1235 snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
1236
1237 if (access(filename, F_OK)) {
1238 if (is_kallsyms) {
1239 if (copyfile("/proc/kallsyms", filename))
1240 goto out_free;
1241 } else if (link(realname, filename) && copyfile(name, filename))
1242 goto out_free;
1243 }
1244
1245 len = snprintf(linkname, size, "%s/.build-id/%.2s",
1246 debugdir, sbuild_id);
1247
1248 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
1249 goto out_free;
1250
1251 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
1252 targetname = filename + strlen(debugdir) - 5;
1253 memcpy(targetname, "../..", 5);
1254
1255 if (symlink(targetname, linkname) == 0)
1256 err = 0;
1257out_free:
1258 if (!is_kallsyms)
1259 free(realname);
1260 free(filename);
1261 free(linkname);
1262 return err;
1263}
1264
1265static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
1266 const char *name, const char *debugdir,
1267 bool is_kallsyms)
1268{
1269 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1270
1271 build_id__sprintf(build_id, build_id_size, sbuild_id);
1272
1273 return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
1274}
1275
1276int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
1277{
1278 const size_t size = PATH_MAX;
1279 char *filename = zalloc(size),
1280 *linkname = zalloc(size);
1281 int err = -1;
1282
1283 if (filename == NULL || linkname == NULL)
1284 goto out_free;
1285
1286 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
1287 debugdir, sbuild_id, sbuild_id + 2);
1288
1289 if (access(linkname, F_OK))
1290 goto out_free;
1291
1292 if (readlink(linkname, filename, size - 1) < 0)
1293 goto out_free;
1294
1295 if (unlink(linkname))
1296 goto out_free;
1297
1298 /*
1299 * Since the link is relative, we must make it absolute:
1300 */
1301 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
1302 debugdir, sbuild_id, filename);
1303
1304 if (unlink(linkname))
1305 goto out_free;
1306
1307 err = 0;
1308out_free:
1309 free(filename);
1310 free(linkname);
1311 return err;
1312}
1313
1314static int dso__cache_build_id(struct dso *dso, const char *debugdir)
1315{
1316 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
1317
1318 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
1319 dso->long_name, debugdir, is_kallsyms);
1320}
1321
1322static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
1323{
1324 struct dso *pos;
1325 int err = 0;
1326
1327 dsos__for_each_with_build_id(pos, head)
1328 if (dso__cache_build_id(pos, debugdir))
1329 err = -1;
1330
1331 return err;
1332}
1333
1334static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
1335{
1336 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
1337 ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
1338 return ret;
1339}
1340
1341static int perf_session__cache_build_ids(struct perf_session *session)
1342{
1343 struct rb_node *nd;
1344 int ret;
1345 char debugdir[PATH_MAX];
1346
1347 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
1348
1349 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
1350 return -1;
1351
1352 ret = machine__cache_build_ids(&session->host_machine, debugdir);
1353
1354 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
1355 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1356 ret |= machine__cache_build_ids(pos, debugdir);
1357 }
1358 return ret ? -1 : 0;
1359}
1360
1361static bool machine__read_build_ids(struct machine *machine, bool with_hits)
1362{
1363 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
1364 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
1365 return ret;
1366}
1367
1368static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
1369{
1370 struct rb_node *nd;
1371 bool ret = machine__read_build_ids(&session->host_machine, with_hits);
1372
1373 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
1374 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1375 ret |= machine__read_build_ids(pos, with_hits);
1376 }
1377
1378 return ret;
1379}
1380
1381static int do_write_feat(int fd, struct perf_header *h, int type, 1386static int do_write_feat(int fd, struct perf_header *h, int type,
1382 struct perf_file_section **p, 1387 struct perf_file_section **p,
1383 struct perf_evlist *evlist) 1388 struct perf_evlist *evlist)
@@ -1386,6 +1391,8 @@ static int do_write_feat(int fd, struct perf_header *h, int type,
1386 int ret = 0; 1391 int ret = 0;
1387 1392
1388 if (perf_header__has_feat(h, type)) { 1393 if (perf_header__has_feat(h, type)) {
1394 if (!feat_ops[type].write)
1395 return -1;
1389 1396
1390 (*p)->offset = lseek(fd, 0, SEEK_CUR); 1397 (*p)->offset = lseek(fd, 0, SEEK_CUR);
1391 1398
@@ -1408,18 +1415,12 @@ static int perf_header__adds_write(struct perf_header *header,
1408 struct perf_evlist *evlist, int fd) 1415 struct perf_evlist *evlist, int fd)
1409{ 1416{
1410 int nr_sections; 1417 int nr_sections;
1411 struct perf_session *session;
1412 struct perf_file_section *feat_sec, *p; 1418 struct perf_file_section *feat_sec, *p;
1413 int sec_size; 1419 int sec_size;
1414 u64 sec_start; 1420 u64 sec_start;
1421 int feat;
1415 int err; 1422 int err;
1416 1423
1417 session = container_of(header, struct perf_session, header);
1418
1419 if (perf_header__has_feat(header, HEADER_BUILD_ID &&
1420 !perf_session__read_build_ids(session, true)))
1421 perf_header__clear_feat(header, HEADER_BUILD_ID);
1422
1423 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); 1424 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
1424 if (!nr_sections) 1425 if (!nr_sections)
1425 return 0; 1426 return 0;
@@ -1433,64 +1434,11 @@ static int perf_header__adds_write(struct perf_header *header,
1433 sec_start = header->data_offset + header->data_size; 1434 sec_start = header->data_offset + header->data_size;
1434 lseek(fd, sec_start + sec_size, SEEK_SET); 1435 lseek(fd, sec_start + sec_size, SEEK_SET);
1435 1436
1436 err = do_write_feat(fd, header, HEADER_TRACE_INFO, &p, evlist); 1437 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
1437 if (err) 1438 if (do_write_feat(fd, header, feat, &p, evlist))
1438 goto out_free; 1439 perf_header__clear_feat(header, feat);
1439
1440 err = do_write_feat(fd, header, HEADER_BUILD_ID, &p, evlist);
1441 if (err) {
1442 perf_header__clear_feat(header, HEADER_BUILD_ID);
1443 goto out_free;
1444 } 1440 }
1445 1441
1446 err = do_write_feat(fd, header, HEADER_HOSTNAME, &p, evlist);
1447 if (err)
1448 perf_header__clear_feat(header, HEADER_HOSTNAME);
1449
1450 err = do_write_feat(fd, header, HEADER_OSRELEASE, &p, evlist);
1451 if (err)
1452 perf_header__clear_feat(header, HEADER_OSRELEASE);
1453
1454 err = do_write_feat(fd, header, HEADER_VERSION, &p, evlist);
1455 if (err)
1456 perf_header__clear_feat(header, HEADER_VERSION);
1457
1458 err = do_write_feat(fd, header, HEADER_ARCH, &p, evlist);
1459 if (err)
1460 perf_header__clear_feat(header, HEADER_ARCH);
1461
1462 err = do_write_feat(fd, header, HEADER_NRCPUS, &p, evlist);
1463 if (err)
1464 perf_header__clear_feat(header, HEADER_NRCPUS);
1465
1466 err = do_write_feat(fd, header, HEADER_CPUDESC, &p, evlist);
1467 if (err)
1468 perf_header__clear_feat(header, HEADER_CPUDESC);
1469
1470 err = do_write_feat(fd, header, HEADER_CPUID, &p, evlist);
1471 if (err)
1472 perf_header__clear_feat(header, HEADER_CPUID);
1473
1474 err = do_write_feat(fd, header, HEADER_TOTAL_MEM, &p, evlist);
1475 if (err)
1476 perf_header__clear_feat(header, HEADER_TOTAL_MEM);
1477
1478 err = do_write_feat(fd, header, HEADER_CMDLINE, &p, evlist);
1479 if (err)
1480 perf_header__clear_feat(header, HEADER_CMDLINE);
1481
1482 err = do_write_feat(fd, header, HEADER_EVENT_DESC, &p, evlist);
1483 if (err)
1484 perf_header__clear_feat(header, HEADER_EVENT_DESC);
1485
1486 err = do_write_feat(fd, header, HEADER_CPU_TOPOLOGY, &p, evlist);
1487 if (err)
1488 perf_header__clear_feat(header, HEADER_CPU_TOPOLOGY);
1489
1490 err = do_write_feat(fd, header, HEADER_NUMA_TOPOLOGY, &p, evlist);
1491 if (err)
1492 perf_header__clear_feat(header, HEADER_NUMA_TOPOLOGY);
1493
1494 lseek(fd, sec_start, SEEK_SET); 1442 lseek(fd, sec_start, SEEK_SET);
1495 /* 1443 /*
1496 * may write more than needed due to dropped feature, but 1444 * may write more than needed due to dropped feature, but
@@ -1499,7 +1447,6 @@ static int perf_header__adds_write(struct perf_header *header,
1499 err = do_write(fd, feat_sec, sec_size); 1447 err = do_write(fd, feat_sec, sec_size);
1500 if (err < 0) 1448 if (err < 0)
1501 pr_debug("failed to write feature section\n"); 1449 pr_debug("failed to write feature section\n");
1502out_free:
1503 free(feat_sec); 1450 free(feat_sec);
1504 return err; 1451 return err;
1505} 1452}
@@ -1637,20 +1584,20 @@ static int perf_header__getbuffer64(struct perf_header *header,
1637int perf_header__process_sections(struct perf_header *header, int fd, 1584int perf_header__process_sections(struct perf_header *header, int fd,
1638 void *data, 1585 void *data,
1639 int (*process)(struct perf_file_section *section, 1586 int (*process)(struct perf_file_section *section,
1640 struct perf_header *ph, 1587 struct perf_header *ph,
1641 int feat, int fd, void *data)) 1588 int feat, int fd, void *data))
1642{ 1589{
1643 struct perf_file_section *feat_sec; 1590 struct perf_file_section *feat_sec, *sec;
1644 int nr_sections; 1591 int nr_sections;
1645 int sec_size; 1592 int sec_size;
1646 int idx = 0; 1593 int feat;
1647 int err = -1, feat = 1; 1594 int err;
1648 1595
1649 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); 1596 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
1650 if (!nr_sections) 1597 if (!nr_sections)
1651 return 0; 1598 return 0;
1652 1599
1653 feat_sec = calloc(sizeof(*feat_sec), nr_sections); 1600 feat_sec = sec = calloc(sizeof(*feat_sec), nr_sections);
1654 if (!feat_sec) 1601 if (!feat_sec)
1655 return -1; 1602 return -1;
1656 1603
@@ -1658,20 +1605,16 @@ int perf_header__process_sections(struct perf_header *header, int fd,
1658 1605
1659 lseek(fd, header->data_offset + header->data_size, SEEK_SET); 1606 lseek(fd, header->data_offset + header->data_size, SEEK_SET);
1660 1607
1661 if (perf_header__getbuffer64(header, fd, feat_sec, sec_size)) 1608 err = perf_header__getbuffer64(header, fd, feat_sec, sec_size);
1609 if (err < 0)
1662 goto out_free; 1610 goto out_free;
1663 1611
1664 err = 0; 1612 for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) {
1665 while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { 1613 err = process(sec++, header, feat, fd, data);
1666 if (perf_header__has_feat(header, feat)) { 1614 if (err < 0)
1667 struct perf_file_section *sec = &feat_sec[idx++]; 1615 goto out_free;
1668
1669 err = process(sec, header, feat, fd, data);
1670 if (err < 0)
1671 break;
1672 }
1673 ++feat;
1674 } 1616 }
1617 err = 0;
1675out_free: 1618out_free:
1676 free(feat_sec); 1619 free(feat_sec);
1677 return err; 1620 return err;
@@ -1906,32 +1849,21 @@ static int perf_file_section__process(struct perf_file_section *section,
1906 return 0; 1849 return 0;
1907 } 1850 }
1908 1851
1852 if (feat >= HEADER_LAST_FEATURE) {
1853 pr_debug("unknown feature %d, continuing...\n", feat);
1854 return 0;
1855 }
1856
1909 switch (feat) { 1857 switch (feat) {
1910 case HEADER_TRACE_INFO: 1858 case HEADER_TRACE_INFO:
1911 trace_report(fd, false); 1859 trace_report(fd, false);
1912 break; 1860 break;
1913
1914 case HEADER_BUILD_ID: 1861 case HEADER_BUILD_ID:
1915 if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) 1862 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1916 pr_debug("Failed to read buildids, continuing...\n"); 1863 pr_debug("Failed to read buildids, continuing...\n");
1917 break; 1864 break;
1918
1919 case HEADER_HOSTNAME:
1920 case HEADER_OSRELEASE:
1921 case HEADER_VERSION:
1922 case HEADER_ARCH:
1923 case HEADER_NRCPUS:
1924 case HEADER_CPUDESC:
1925 case HEADER_CPUID:
1926 case HEADER_TOTAL_MEM:
1927 case HEADER_CMDLINE:
1928 case HEADER_EVENT_DESC:
1929 case HEADER_CPU_TOPOLOGY:
1930 case HEADER_NUMA_TOPOLOGY:
1931 break;
1932
1933 default: 1865 default:
1934 pr_debug("unknown feature %d, continuing...\n", feat); 1866 break;
1935 } 1867 }
1936 1868
1937 return 0; 1869 return 0;
@@ -2041,6 +1973,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
2041 lseek(fd, tmp, SEEK_SET); 1973 lseek(fd, tmp, SEEK_SET);
2042 } 1974 }
2043 1975
1976 symbol_conf.nr_events = nr_attrs;
1977
2044 if (f_header.event_types.size) { 1978 if (f_header.event_types.size) {
2045 lseek(fd, f_header.event_types.offset, SEEK_SET); 1979 lseek(fd, f_header.event_types.offset, SEEK_SET);
2046 events = malloc(f_header.event_types.size); 1980 events = malloc(f_header.event_types.size);
@@ -2068,9 +2002,9 @@ out_delete_evlist:
2068 return -ENOMEM; 2002 return -ENOMEM;
2069} 2003}
2070 2004
2071int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 2005int perf_event__synthesize_attr(struct perf_tool *tool,
2072 perf_event__handler_t process, 2006 struct perf_event_attr *attr, u16 ids, u64 *id,
2073 struct perf_session *session) 2007 perf_event__handler_t process)
2074{ 2008{
2075 union perf_event *ev; 2009 union perf_event *ev;
2076 size_t size; 2010 size_t size;
@@ -2092,22 +2026,23 @@ int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
2092 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 2026 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
2093 ev->attr.header.size = size; 2027 ev->attr.header.size = size;
2094 2028
2095 err = process(ev, NULL, session); 2029 err = process(tool, ev, NULL, NULL);
2096 2030
2097 free(ev); 2031 free(ev);
2098 2032
2099 return err; 2033 return err;
2100} 2034}
2101 2035
2102int perf_session__synthesize_attrs(struct perf_session *session, 2036int perf_event__synthesize_attrs(struct perf_tool *tool,
2037 struct perf_session *session,
2103 perf_event__handler_t process) 2038 perf_event__handler_t process)
2104{ 2039{
2105 struct perf_evsel *attr; 2040 struct perf_evsel *attr;
2106 int err = 0; 2041 int err = 0;
2107 2042
2108 list_for_each_entry(attr, &session->evlist->entries, node) { 2043 list_for_each_entry(attr, &session->evlist->entries, node) {
2109 err = perf_event__synthesize_attr(&attr->attr, attr->ids, 2044 err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids,
2110 attr->id, process, session); 2045 attr->id, process);
2111 if (err) { 2046 if (err) {
2112 pr_debug("failed to create perf header attribute\n"); 2047 pr_debug("failed to create perf header attribute\n");
2113 return err; 2048 return err;
@@ -2118,23 +2053,23 @@ int perf_session__synthesize_attrs(struct perf_session *session,
2118} 2053}
2119 2054
2120int perf_event__process_attr(union perf_event *event, 2055int perf_event__process_attr(union perf_event *event,
2121 struct perf_session *session) 2056 struct perf_evlist **pevlist)
2122{ 2057{
2123 unsigned int i, ids, n_ids; 2058 unsigned int i, ids, n_ids;
2124 struct perf_evsel *evsel; 2059 struct perf_evsel *evsel;
2060 struct perf_evlist *evlist = *pevlist;
2125 2061
2126 if (session->evlist == NULL) { 2062 if (evlist == NULL) {
2127 session->evlist = perf_evlist__new(NULL, NULL); 2063 *pevlist = evlist = perf_evlist__new(NULL, NULL);
2128 if (session->evlist == NULL) 2064 if (evlist == NULL)
2129 return -ENOMEM; 2065 return -ENOMEM;
2130 } 2066 }
2131 2067
2132 evsel = perf_evsel__new(&event->attr.attr, 2068 evsel = perf_evsel__new(&event->attr.attr, evlist->nr_entries);
2133 session->evlist->nr_entries);
2134 if (evsel == NULL) 2069 if (evsel == NULL)
2135 return -ENOMEM; 2070 return -ENOMEM;
2136 2071
2137 perf_evlist__add(session->evlist, evsel); 2072 perf_evlist__add(evlist, evsel);
2138 2073
2139 ids = event->header.size; 2074 ids = event->header.size;
2140 ids -= (void *)&event->attr.id - (void *)event; 2075 ids -= (void *)&event->attr.id - (void *)event;
@@ -2148,18 +2083,16 @@ int perf_event__process_attr(union perf_event *event,
2148 return -ENOMEM; 2083 return -ENOMEM;
2149 2084
2150 for (i = 0; i < n_ids; i++) { 2085 for (i = 0; i < n_ids; i++) {
2151 perf_evlist__id_add(session->evlist, evsel, 0, i, 2086 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
2152 event->attr.id[i]);
2153 } 2087 }
2154 2088
2155 perf_session__update_sample_type(session);
2156
2157 return 0; 2089 return 0;
2158} 2090}
2159 2091
2160int perf_event__synthesize_event_type(u64 event_id, char *name, 2092int perf_event__synthesize_event_type(struct perf_tool *tool,
2093 u64 event_id, char *name,
2161 perf_event__handler_t process, 2094 perf_event__handler_t process,
2162 struct perf_session *session) 2095 struct machine *machine)
2163{ 2096{
2164 union perf_event ev; 2097 union perf_event ev;
2165 size_t size = 0; 2098 size_t size = 0;
@@ -2172,18 +2105,19 @@ int perf_event__synthesize_event_type(u64 event_id, char *name,
2172 strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); 2105 strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
2173 2106
2174 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; 2107 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
2175 size = strlen(name); 2108 size = strlen(ev.event_type.event_type.name);
2176 size = ALIGN(size, sizeof(u64)); 2109 size = ALIGN(size, sizeof(u64));
2177 ev.event_type.header.size = sizeof(ev.event_type) - 2110 ev.event_type.header.size = sizeof(ev.event_type) -
2178 (sizeof(ev.event_type.event_type.name) - size); 2111 (sizeof(ev.event_type.event_type.name) - size);
2179 2112
2180 err = process(&ev, NULL, session); 2113 err = process(tool, &ev, NULL, machine);
2181 2114
2182 return err; 2115 return err;
2183} 2116}
2184 2117
2185int perf_event__synthesize_event_types(perf_event__handler_t process, 2118int perf_event__synthesize_event_types(struct perf_tool *tool,
2186 struct perf_session *session) 2119 perf_event__handler_t process,
2120 struct machine *machine)
2187{ 2121{
2188 struct perf_trace_event_type *type; 2122 struct perf_trace_event_type *type;
2189 int i, err = 0; 2123 int i, err = 0;
@@ -2191,9 +2125,9 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
2191 for (i = 0; i < event_count; i++) { 2125 for (i = 0; i < event_count; i++) {
2192 type = &events[i]; 2126 type = &events[i];
2193 2127
2194 err = perf_event__synthesize_event_type(type->event_id, 2128 err = perf_event__synthesize_event_type(tool, type->event_id,
2195 type->name, process, 2129 type->name, process,
2196 session); 2130 machine);
2197 if (err) { 2131 if (err) {
2198 pr_debug("failed to create perf header event type\n"); 2132 pr_debug("failed to create perf header event type\n");
2199 return err; 2133 return err;
@@ -2203,8 +2137,8 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
2203 return err; 2137 return err;
2204} 2138}
2205 2139
2206int perf_event__process_event_type(union perf_event *event, 2140int perf_event__process_event_type(struct perf_tool *tool __unused,
2207 struct perf_session *session __unused) 2141 union perf_event *event)
2208{ 2142{
2209 if (perf_header__push_event(event->event_type.event_type.event_id, 2143 if (perf_header__push_event(event->event_type.event_type.event_id,
2210 event->event_type.event_type.name) < 0) 2144 event->event_type.event_type.name) < 0)
@@ -2213,9 +2147,9 @@ int perf_event__process_event_type(union perf_event *event,
2213 return 0; 2147 return 0;
2214} 2148}
2215 2149
2216int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, 2150int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
2217 perf_event__handler_t process, 2151 struct perf_evlist *evlist,
2218 struct perf_session *session __unused) 2152 perf_event__handler_t process)
2219{ 2153{
2220 union perf_event ev; 2154 union perf_event ev;
2221 struct tracing_data *tdata; 2155 struct tracing_data *tdata;
@@ -2246,7 +2180,7 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
2246 ev.tracing_data.header.size = sizeof(ev.tracing_data); 2180 ev.tracing_data.header.size = sizeof(ev.tracing_data);
2247 ev.tracing_data.size = aligned_size; 2181 ev.tracing_data.size = aligned_size;
2248 2182
2249 process(&ev, NULL, session); 2183 process(tool, &ev, NULL, NULL);
2250 2184
2251 /* 2185 /*
2252 * The put function will copy all the tracing data 2186 * The put function will copy all the tracing data
@@ -2288,10 +2222,10 @@ int perf_event__process_tracing_data(union perf_event *event,
2288 return size_read + padding; 2222 return size_read + padding;
2289} 2223}
2290 2224
2291int perf_event__synthesize_build_id(struct dso *pos, u16 misc, 2225int perf_event__synthesize_build_id(struct perf_tool *tool,
2226 struct dso *pos, u16 misc,
2292 perf_event__handler_t process, 2227 perf_event__handler_t process,
2293 struct machine *machine, 2228 struct machine *machine)
2294 struct perf_session *session)
2295{ 2229{
2296 union perf_event ev; 2230 union perf_event ev;
2297 size_t len; 2231 size_t len;
@@ -2311,12 +2245,13 @@ int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
2311 ev.build_id.header.size = sizeof(ev.build_id) + len; 2245 ev.build_id.header.size = sizeof(ev.build_id) + len;
2312 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); 2246 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
2313 2247
2314 err = process(&ev, NULL, session); 2248 err = process(tool, &ev, NULL, machine);
2315 2249
2316 return err; 2250 return err;
2317} 2251}
2318 2252
2319int perf_event__process_build_id(union perf_event *event, 2253int perf_event__process_build_id(struct perf_tool *tool __used,
2254 union perf_event *event,
2320 struct perf_session *session) 2255 struct perf_session *session)
2321{ 2256{
2322 __event_process_build_id(&event->build_id, 2257 __event_process_build_id(&event->build_id,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 3d5a742f4a2a..ac4ec956024e 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -10,7 +10,8 @@
10#include <linux/bitmap.h> 10#include <linux/bitmap.h>
11 11
12enum { 12enum {
13 HEADER_TRACE_INFO = 1, 13 HEADER_RESERVED = 0, /* always cleared */
14 HEADER_TRACE_INFO = 1,
14 HEADER_BUILD_ID, 15 HEADER_BUILD_ID,
15 16
16 HEADER_HOSTNAME, 17 HEADER_HOSTNAME,
@@ -27,10 +28,9 @@ enum {
27 HEADER_NUMA_TOPOLOGY, 28 HEADER_NUMA_TOPOLOGY,
28 29
29 HEADER_LAST_FEATURE, 30 HEADER_LAST_FEATURE,
31 HEADER_FEAT_BITS = 256,
30}; 32};
31 33
32#define HEADER_FEAT_BITS 256
33
34struct perf_file_section { 34struct perf_file_section {
35 u64 offset; 35 u64 offset;
36 u64 size; 36 u64 size;
@@ -68,6 +68,7 @@ struct perf_header {
68}; 68};
69 69
70struct perf_evlist; 70struct perf_evlist;
71struct perf_session;
71 72
72int perf_session__read_header(struct perf_session *session, int fd); 73int perf_session__read_header(struct perf_session *session, int fd);
73int perf_session__write_header(struct perf_session *session, 74int perf_session__write_header(struct perf_session *session,
@@ -96,32 +97,36 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
96 const char *name, bool is_kallsyms); 97 const char *name, bool is_kallsyms);
97int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); 98int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
98 99
99int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 100int perf_event__synthesize_attr(struct perf_tool *tool,
100 perf_event__handler_t process, 101 struct perf_event_attr *attr, u16 ids, u64 *id,
101 struct perf_session *session); 102 perf_event__handler_t process);
102int perf_session__synthesize_attrs(struct perf_session *session, 103int perf_event__synthesize_attrs(struct perf_tool *tool,
103 perf_event__handler_t process); 104 struct perf_session *session,
104int perf_event__process_attr(union perf_event *event, struct perf_session *session); 105 perf_event__handler_t process);
106int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevlist);
105 107
106int perf_event__synthesize_event_type(u64 event_id, char *name, 108int perf_event__synthesize_event_type(struct perf_tool *tool,
109 u64 event_id, char *name,
107 perf_event__handler_t process, 110 perf_event__handler_t process,
108 struct perf_session *session); 111 struct machine *machine);
109int perf_event__synthesize_event_types(perf_event__handler_t process, 112int perf_event__synthesize_event_types(struct perf_tool *tool,
110 struct perf_session *session); 113 perf_event__handler_t process,
111int perf_event__process_event_type(union perf_event *event, 114 struct machine *machine);
112 struct perf_session *session); 115int perf_event__process_event_type(struct perf_tool *tool,
113 116 union perf_event *event);
114int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, 117
115 perf_event__handler_t process, 118int perf_event__synthesize_tracing_data(struct perf_tool *tool,
116 struct perf_session *session); 119 int fd, struct perf_evlist *evlist,
120 perf_event__handler_t process);
117int perf_event__process_tracing_data(union perf_event *event, 121int perf_event__process_tracing_data(union perf_event *event,
118 struct perf_session *session); 122 struct perf_session *session);
119 123
120int perf_event__synthesize_build_id(struct dso *pos, u16 misc, 124int perf_event__synthesize_build_id(struct perf_tool *tool,
125 struct dso *pos, u16 misc,
121 perf_event__handler_t process, 126 perf_event__handler_t process,
122 struct machine *machine, 127 struct machine *machine);
123 struct perf_session *session); 128int perf_event__process_build_id(struct perf_tool *tool,
124int perf_event__process_build_id(union perf_event *event, 129 union perf_event *event,
125 struct perf_session *session); 130 struct perf_session *session);
126 131
127/* 132/*
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index abef2703cd24..e11e482bd185 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -76,21 +76,21 @@ static void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
76 } 76 }
77} 77}
78 78
79static void hist_entry__add_cpumode_period(struct hist_entry *self, 79static void hist_entry__add_cpumode_period(struct hist_entry *he,
80 unsigned int cpumode, u64 period) 80 unsigned int cpumode, u64 period)
81{ 81{
82 switch (cpumode) { 82 switch (cpumode) {
83 case PERF_RECORD_MISC_KERNEL: 83 case PERF_RECORD_MISC_KERNEL:
84 self->period_sys += period; 84 he->period_sys += period;
85 break; 85 break;
86 case PERF_RECORD_MISC_USER: 86 case PERF_RECORD_MISC_USER:
87 self->period_us += period; 87 he->period_us += period;
88 break; 88 break;
89 case PERF_RECORD_MISC_GUEST_KERNEL: 89 case PERF_RECORD_MISC_GUEST_KERNEL:
90 self->period_guest_sys += period; 90 he->period_guest_sys += period;
91 break; 91 break;
92 case PERF_RECORD_MISC_GUEST_USER: 92 case PERF_RECORD_MISC_GUEST_USER:
93 self->period_guest_us += period; 93 he->period_guest_us += period;
94 break; 94 break;
95 default: 95 default:
96 break; 96 break;
@@ -165,18 +165,18 @@ void hists__decay_entries_threaded(struct hists *hists,
165static struct hist_entry *hist_entry__new(struct hist_entry *template) 165static struct hist_entry *hist_entry__new(struct hist_entry *template)
166{ 166{
167 size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0; 167 size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
168 struct hist_entry *self = malloc(sizeof(*self) + callchain_size); 168 struct hist_entry *he = malloc(sizeof(*he) + callchain_size);
169 169
170 if (self != NULL) { 170 if (he != NULL) {
171 *self = *template; 171 *he = *template;
172 self->nr_events = 1; 172 he->nr_events = 1;
173 if (self->ms.map) 173 if (he->ms.map)
174 self->ms.map->referenced = true; 174 he->ms.map->referenced = true;
175 if (symbol_conf.use_callchain) 175 if (symbol_conf.use_callchain)
176 callchain_init(self->callchain); 176 callchain_init(he->callchain);
177 } 177 }
178 178
179 return self; 179 return he;
180} 180}
181 181
182static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h) 182static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
@@ -677,15 +677,16 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
677 return ret; 677 return ret;
678} 678}
679 679
680static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, 680static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
681 u64 total_samples, int left_margin) 681 u64 total_samples, int left_margin,
682 FILE *fp)
682{ 683{
683 struct rb_node *rb_node; 684 struct rb_node *rb_node;
684 struct callchain_node *chain; 685 struct callchain_node *chain;
685 size_t ret = 0; 686 size_t ret = 0;
686 u32 entries_printed = 0; 687 u32 entries_printed = 0;
687 688
688 rb_node = rb_first(&self->sorted_chain); 689 rb_node = rb_first(&he->sorted_chain);
689 while (rb_node) { 690 while (rb_node) {
690 double percent; 691 double percent;
691 692
@@ -730,35 +731,35 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows)
730 } 731 }
731} 732}
732 733
733static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s, 734static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s,
734 size_t size, struct hists *pair_hists, 735 size_t size, struct hists *pair_hists,
735 bool show_displacement, long displacement, 736 bool show_displacement, long displacement,
736 bool color, u64 session_total) 737 bool color, u64 total_period)
737{ 738{
738 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; 739 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
739 u64 nr_events; 740 u64 nr_events;
740 const char *sep = symbol_conf.field_sep; 741 const char *sep = symbol_conf.field_sep;
741 int ret; 742 int ret;
742 743
743 if (symbol_conf.exclude_other && !self->parent) 744 if (symbol_conf.exclude_other && !he->parent)
744 return 0; 745 return 0;
745 746
746 if (pair_hists) { 747 if (pair_hists) {
747 period = self->pair ? self->pair->period : 0; 748 period = he->pair ? he->pair->period : 0;
748 nr_events = self->pair ? self->pair->nr_events : 0; 749 nr_events = he->pair ? he->pair->nr_events : 0;
749 total = pair_hists->stats.total_period; 750 total = pair_hists->stats.total_period;
750 period_sys = self->pair ? self->pair->period_sys : 0; 751 period_sys = he->pair ? he->pair->period_sys : 0;
751 period_us = self->pair ? self->pair->period_us : 0; 752 period_us = he->pair ? he->pair->period_us : 0;
752 period_guest_sys = self->pair ? self->pair->period_guest_sys : 0; 753 period_guest_sys = he->pair ? he->pair->period_guest_sys : 0;
753 period_guest_us = self->pair ? self->pair->period_guest_us : 0; 754 period_guest_us = he->pair ? he->pair->period_guest_us : 0;
754 } else { 755 } else {
755 period = self->period; 756 period = he->period;
756 nr_events = self->nr_events; 757 nr_events = he->nr_events;
757 total = session_total; 758 total = total_period;
758 period_sys = self->period_sys; 759 period_sys = he->period_sys;
759 period_us = self->period_us; 760 period_us = he->period_us;
760 period_guest_sys = self->period_guest_sys; 761 period_guest_sys = he->period_guest_sys;
761 period_guest_us = self->period_guest_us; 762 period_guest_us = he->period_guest_us;
762 } 763 }
763 764
764 if (total) { 765 if (total) {
@@ -767,7 +768,7 @@ static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s,
767 sep ? "%.2f" : " %6.2f%%", 768 sep ? "%.2f" : " %6.2f%%",
768 (period * 100.0) / total); 769 (period * 100.0) / total);
769 else 770 else
770 ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%", 771 ret = scnprintf(s, size, sep ? "%.2f" : " %6.2f%%",
771 (period * 100.0) / total); 772 (period * 100.0) / total);
772 if (symbol_conf.show_cpu_utilization) { 773 if (symbol_conf.show_cpu_utilization) {
773 ret += percent_color_snprintf(s + ret, size - ret, 774 ret += percent_color_snprintf(s + ret, size - ret,
@@ -790,20 +791,20 @@ static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s,
790 } 791 }
791 } 792 }
792 } else 793 } else
793 ret = snprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period); 794 ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period);
794 795
795 if (symbol_conf.show_nr_samples) { 796 if (symbol_conf.show_nr_samples) {
796 if (sep) 797 if (sep)
797 ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events); 798 ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events);
798 else 799 else
799 ret += snprintf(s + ret, size - ret, "%11" PRIu64, nr_events); 800 ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
800 } 801 }
801 802
802 if (symbol_conf.show_total_period) { 803 if (symbol_conf.show_total_period) {
803 if (sep) 804 if (sep)
804 ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period); 805 ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
805 else 806 else
806 ret += snprintf(s + ret, size - ret, " %12" PRIu64, period); 807 ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period);
807 } 808 }
808 809
809 if (pair_hists) { 810 if (pair_hists) {
@@ -812,31 +813,31 @@ static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s,
812 813
813 if (total > 0) 814 if (total > 0)
814 old_percent = (period * 100.0) / total; 815 old_percent = (period * 100.0) / total;
815 if (session_total > 0) 816 if (total_period > 0)
816 new_percent = (self->period * 100.0) / session_total; 817 new_percent = (he->period * 100.0) / total_period;
817 818
818 diff = new_percent - old_percent; 819 diff = new_percent - old_percent;
819 820
820 if (fabs(diff) >= 0.01) 821 if (fabs(diff) >= 0.01)
821 snprintf(bf, sizeof(bf), "%+4.2F%%", diff); 822 ret += scnprintf(bf, sizeof(bf), "%+4.2F%%", diff);
822 else 823 else
823 snprintf(bf, sizeof(bf), " "); 824 ret += scnprintf(bf, sizeof(bf), " ");
824 825
825 if (sep) 826 if (sep)
826 ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf); 827 ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
827 else 828 else
828 ret += snprintf(s + ret, size - ret, "%11.11s", bf); 829 ret += scnprintf(s + ret, size - ret, "%11.11s", bf);
829 830
830 if (show_displacement) { 831 if (show_displacement) {
831 if (displacement) 832 if (displacement)
832 snprintf(bf, sizeof(bf), "%+4ld", displacement); 833 ret += scnprintf(bf, sizeof(bf), "%+4ld", displacement);
833 else 834 else
834 snprintf(bf, sizeof(bf), " "); 835 ret += scnprintf(bf, sizeof(bf), " ");
835 836
836 if (sep) 837 if (sep)
837 ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf); 838 ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
838 else 839 else
839 ret += snprintf(s + ret, size - ret, "%6.6s", bf); 840 ret += scnprintf(s + ret, size - ret, "%6.6s", bf);
840 } 841 }
841 } 842 }
842 843
@@ -854,7 +855,7 @@ int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
854 if (se->elide) 855 if (se->elide)
855 continue; 856 continue;
856 857
857 ret += snprintf(s + ret, size - ret, "%s", sep ?: " "); 858 ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
858 ret += se->se_snprintf(he, s + ret, size - ret, 859 ret += se->se_snprintf(he, s + ret, size - ret,
859 hists__col_len(hists, se->se_width_idx)); 860 hists__col_len(hists, se->se_width_idx));
860 } 861 }
@@ -862,9 +863,10 @@ int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
862 return ret; 863 return ret;
863} 864}
864 865
865int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists, 866static int hist_entry__fprintf(struct hist_entry *he, size_t size,
866 struct hists *pair_hists, bool show_displacement, 867 struct hists *hists, struct hists *pair_hists,
867 long displacement, FILE *fp, u64 session_total) 868 bool show_displacement, long displacement,
869 u64 total_period, FILE *fp)
868{ 870{
869 char bf[512]; 871 char bf[512];
870 int ret; 872 int ret;
@@ -874,14 +876,14 @@ int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists,
874 876
875 ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists, 877 ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists,
876 show_displacement, displacement, 878 show_displacement, displacement,
877 true, session_total); 879 true, total_period);
878 hist_entry__snprintf(he, bf + ret, size - ret, hists); 880 hist_entry__snprintf(he, bf + ret, size - ret, hists);
879 return fprintf(fp, "%s\n", bf); 881 return fprintf(fp, "%s\n", bf);
880} 882}
881 883
882static size_t hist_entry__fprintf_callchain(struct hist_entry *self, 884static size_t hist_entry__fprintf_callchain(struct hist_entry *he,
883 struct hists *hists, FILE *fp, 885 struct hists *hists,
884 u64 session_total) 886 u64 total_period, FILE *fp)
885{ 887{
886 int left_margin = 0; 888 int left_margin = 0;
887 889
@@ -889,11 +891,10 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self,
889 struct sort_entry *se = list_first_entry(&hist_entry__sort_list, 891 struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
890 typeof(*se), list); 892 typeof(*se), list);
891 left_margin = hists__col_len(hists, se->se_width_idx); 893 left_margin = hists__col_len(hists, se->se_width_idx);
892 left_margin -= thread__comm_len(self->thread); 894 left_margin -= thread__comm_len(he->thread);
893 } 895 }
894 896
895 return hist_entry_callchain__fprintf(fp, self, session_total, 897 return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
896 left_margin);
897} 898}
898 899
899size_t hists__fprintf(struct hists *hists, struct hists *pair, 900size_t hists__fprintf(struct hists *hists, struct hists *pair,
@@ -903,6 +904,7 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
903 struct sort_entry *se; 904 struct sort_entry *se;
904 struct rb_node *nd; 905 struct rb_node *nd;
905 size_t ret = 0; 906 size_t ret = 0;
907 u64 total_period;
906 unsigned long position = 1; 908 unsigned long position = 1;
907 long displacement = 0; 909 long displacement = 0;
908 unsigned int width; 910 unsigned int width;
@@ -917,20 +919,6 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
917 919
918 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead"); 920 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
919 921
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) { 922 if (symbol_conf.show_cpu_utilization) {
935 if (sep) { 923 if (sep) {
936 ret += fprintf(fp, "%csys", *sep); 924 ret += fprintf(fp, "%csys", *sep);
@@ -940,8 +928,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
940 ret += fprintf(fp, "%cguest us", *sep); 928 ret += fprintf(fp, "%cguest us", *sep);
941 } 929 }
942 } else { 930 } else {
943 ret += fprintf(fp, " sys "); 931 ret += fprintf(fp, " sys ");
944 ret += fprintf(fp, " us "); 932 ret += fprintf(fp, " us ");
945 if (perf_guest) { 933 if (perf_guest) {
946 ret += fprintf(fp, " guest sys "); 934 ret += fprintf(fp, " guest sys ");
947 ret += fprintf(fp, " guest us "); 935 ret += fprintf(fp, " guest us ");
@@ -949,6 +937,20 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
949 } 937 }
950 } 938 }
951 939
940 if (symbol_conf.show_nr_samples) {
941 if (sep)
942 fprintf(fp, "%cSamples", *sep);
943 else
944 fputs(" Samples ", fp);
945 }
946
947 if (symbol_conf.show_total_period) {
948 if (sep)
949 ret += fprintf(fp, "%cPeriod", *sep);
950 else
951 ret += fprintf(fp, " Period ");
952 }
953
952 if (pair) { 954 if (pair) {
953 if (sep) 955 if (sep)
954 ret += fprintf(fp, "%cDelta", *sep); 956 ret += fprintf(fp, "%cDelta", *sep);
@@ -993,6 +995,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
993 goto print_entries; 995 goto print_entries;
994 996
995 fprintf(fp, "# ........"); 997 fprintf(fp, "# ........");
998 if (symbol_conf.show_cpu_utilization)
999 fprintf(fp, " ....... .......");
996 if (symbol_conf.show_nr_samples) 1000 if (symbol_conf.show_nr_samples)
997 fprintf(fp, " .........."); 1001 fprintf(fp, " ..........");
998 if (symbol_conf.show_total_period) 1002 if (symbol_conf.show_total_period)
@@ -1025,6 +1029,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
1025 goto out; 1029 goto out;
1026 1030
1027print_entries: 1031print_entries:
1032 total_period = hists->stats.total_period;
1033
1028 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 1034 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
1029 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 1035 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
1030 1036
@@ -1040,11 +1046,10 @@ print_entries:
1040 ++position; 1046 ++position;
1041 } 1047 }
1042 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement, 1048 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement,
1043 displacement, fp, hists->stats.total_period); 1049 displacement, total_period, fp);
1044 1050
1045 if (symbol_conf.use_callchain) 1051 if (symbol_conf.use_callchain)
1046 ret += hist_entry__fprintf_callchain(h, hists, fp, 1052 ret += hist_entry__fprintf_callchain(h, hists, total_period, fp);
1047 hists->stats.total_period);
1048 if (max_rows && ++nr_rows >= max_rows) 1053 if (max_rows && ++nr_rows >= max_rows)
1049 goto out; 1054 goto out;
1050 1055
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 89289c8e935e..f55f0a8d1f81 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -66,11 +66,8 @@ struct hists {
66struct hist_entry *__hists__add_entry(struct hists *self, 66struct hist_entry *__hists__add_entry(struct hists *self,
67 struct addr_location *al, 67 struct addr_location *al,
68 struct symbol *parent, u64 period); 68 struct symbol *parent, u64 period);
69extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); 69int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
70extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); 70int64_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, 71int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size,
75 struct hists *hists); 72 struct hists *hists);
76void hist_entry__free(struct hist_entry *); 73void hist_entry__free(struct hist_entry *);
@@ -117,7 +114,6 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
117 114
118static inline int hist_entry__tui_annotate(struct hist_entry *self __used, 115static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
119 int evidx __used, 116 int evidx __used,
120 int nr_events __used,
121 void(*timer)(void *arg) __used, 117 void(*timer)(void *arg) __used,
122 void *arg __used, 118 void *arg __used,
123 int delay_secs __used) 119 int delay_secs __used)
@@ -128,7 +124,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
128#define K_RIGHT -2 124#define K_RIGHT -2
129#else 125#else
130#include "ui/keysyms.h" 126#include "ui/keysyms.h"
131int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, 127int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
132 void(*timer)(void *arg), void *arg, int delay_secs); 128 void(*timer)(void *arg), void *arg, int delay_secs);
133 129
134int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 130int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
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/bitops.h b/tools/perf/util/include/linux/bitops.h
index 305c8484f200..62cdee78db7b 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -9,6 +9,17 @@
9#define BITS_PER_BYTE 8 9#define BITS_PER_BYTE 8
10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
11 11
12#define for_each_set_bit(bit, addr, size) \
13 for ((bit) = find_first_bit((addr), (size)); \
14 (bit) < (size); \
15 (bit) = find_next_bit((addr), (size), (bit) + 1))
16
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) \
19 for ((bit) = find_next_bit((addr), (size), (bit)); \
20 (bit) < (size); \
21 (bit) = find_next_bit((addr), (size), (bit) + 1))
22
12static inline void set_bit(int nr, unsigned long *addr) 23static inline void set_bit(int nr, unsigned long *addr)
13{ 24{
14 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); 25 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
@@ -30,4 +41,111 @@ static inline unsigned long hweight_long(unsigned long w)
30 return sizeof(w) == 4 ? hweight32(w) : hweight64(w); 41 return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
31} 42}
32 43
44#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
45
46/**
47 * __ffs - find first bit in word.
48 * @word: The word to search
49 *
50 * Undefined if no bit exists, so code should check against 0 first.
51 */
52static __always_inline unsigned long __ffs(unsigned long word)
53{
54 int num = 0;
55
56#if BITS_PER_LONG == 64
57 if ((word & 0xffffffff) == 0) {
58 num += 32;
59 word >>= 32;
60 }
61#endif
62 if ((word & 0xffff) == 0) {
63 num += 16;
64 word >>= 16;
65 }
66 if ((word & 0xff) == 0) {
67 num += 8;
68 word >>= 8;
69 }
70 if ((word & 0xf) == 0) {
71 num += 4;
72 word >>= 4;
73 }
74 if ((word & 0x3) == 0) {
75 num += 2;
76 word >>= 2;
77 }
78 if ((word & 0x1) == 0)
79 num += 1;
80 return num;
81}
82
83/*
84 * Find the first set bit in a memory region.
85 */
86static inline unsigned long
87find_first_bit(const unsigned long *addr, unsigned long size)
88{
89 const unsigned long *p = addr;
90 unsigned long result = 0;
91 unsigned long tmp;
92
93 while (size & ~(BITS_PER_LONG-1)) {
94 if ((tmp = *(p++)))
95 goto found;
96 result += BITS_PER_LONG;
97 size -= BITS_PER_LONG;
98 }
99 if (!size)
100 return result;
101
102 tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
103 if (tmp == 0UL) /* Are any bits set? */
104 return result + size; /* Nope. */
105found:
106 return result + __ffs(tmp);
107}
108
109/*
110 * Find the next set bit in a memory region.
111 */
112static inline unsigned long
113find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
114{
115 const unsigned long *p = addr + BITOP_WORD(offset);
116 unsigned long result = offset & ~(BITS_PER_LONG-1);
117 unsigned long tmp;
118
119 if (offset >= size)
120 return size;
121 size -= result;
122 offset %= BITS_PER_LONG;
123 if (offset) {
124 tmp = *(p++);
125 tmp &= (~0UL << offset);
126 if (size < BITS_PER_LONG)
127 goto found_first;
128 if (tmp)
129 goto found_middle;
130 size -= BITS_PER_LONG;
131 result += BITS_PER_LONG;
132 }
133 while (size & ~(BITS_PER_LONG-1)) {
134 if ((tmp = *(p++)))
135 goto found_middle;
136 result += BITS_PER_LONG;
137 size -= BITS_PER_LONG;
138 }
139 if (!size)
140 return result;
141 tmp = *p;
142
143found_first:
144 tmp &= (~0UL >> (BITS_PER_LONG - size));
145 if (tmp == 0UL) /* Are any bits set? */
146 return result + size; /* Nope. */
147found_middle:
148 return result + __ffs(tmp);
149}
150
33#endif 151#endif
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 78284b13e808..316aa0ab7122 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -562,6 +562,10 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid)
562 INIT_LIST_HEAD(&self->user_dsos); 562 INIT_LIST_HEAD(&self->user_dsos);
563 INIT_LIST_HEAD(&self->kernel_dsos); 563 INIT_LIST_HEAD(&self->kernel_dsos);
564 564
565 self->threads = RB_ROOT;
566 INIT_LIST_HEAD(&self->dead_threads);
567 self->last_match = NULL;
568
565 self->kmaps.machine = self; 569 self->kmaps.machine = self;
566 self->pid = pid; 570 self->pid = pid;
567 self->root_dir = strdup(root_dir); 571 self->root_dir = strdup(root_dir);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 890d85545d0f..2b8017f8a930 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -18,9 +18,11 @@ enum map_type {
18extern const char *map_type__name[MAP__NR_TYPES]; 18extern const char *map_type__name[MAP__NR_TYPES];
19 19
20struct dso; 20struct dso;
21struct ip_callchain;
21struct ref_reloc_sym; 22struct ref_reloc_sym;
22struct map_groups; 23struct map_groups;
23struct machine; 24struct machine;
25struct perf_evsel;
24 26
25struct map { 27struct map {
26 union { 28 union {
@@ -61,7 +63,11 @@ struct map_groups {
61struct machine { 63struct machine {
62 struct rb_node rb_node; 64 struct rb_node rb_node;
63 pid_t pid; 65 pid_t pid;
66 u16 id_hdr_size;
64 char *root_dir; 67 char *root_dir;
68 struct rb_root threads;
69 struct list_head dead_threads;
70 struct thread *last_match;
65 struct list_head user_dsos; 71 struct list_head user_dsos;
66 struct list_head kernel_dsos; 72 struct list_head kernel_dsos;
67 struct map_groups kmaps; 73 struct map_groups kmaps;
@@ -148,6 +154,13 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid);
148void machine__exit(struct machine *self); 154void machine__exit(struct machine *self);
149void machine__delete(struct machine *self); 155void machine__delete(struct machine *self);
150 156
157int machine__resolve_callchain(struct machine *machine,
158 struct perf_evsel *evsel, struct thread *thread,
159 struct ip_callchain *chain,
160 struct symbol **parent);
161int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
162 u64 addr);
163
151/* 164/*
152 * Default guest kernel is defined by parameter --guestkallsyms 165 * Default guest kernel is defined by parameter --guestkallsyms
153 * and --guestmodules 166 * and --guestmodules
@@ -190,6 +203,12 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
190 struct map **mapp, 203 struct map **mapp,
191 symbol_filter_t filter); 204 symbol_filter_t filter);
192 205
206
207struct thread *machine__findnew_thread(struct machine *machine, pid_t pid);
208void machine__remove_thread(struct machine *machine, struct thread *th);
209
210size_t machine__fprintf(struct machine *machine, FILE *fp);
211
193static inline 212static inline
194struct symbol *machine__find_kernel_symbol(struct machine *self, 213struct symbol *machine__find_kernel_symbol(struct machine *self,
195 enum map_type type, u64 addr, 214 enum map_type type, u64 addr,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 928918b796b2..c7a6f6faf91e 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -25,8 +25,6 @@ enum event_result {
25 EVT_HANDLED_ALL 25 EVT_HANDLED_ALL
26}; 26};
27 27
28char debugfs_path[MAXPATHLEN];
29
30#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 28#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
31#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 29#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
32 30
@@ -40,6 +38,7 @@ static struct event_symbol event_symbols[] = {
40 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 38 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
41 { CHW(BRANCH_MISSES), "branch-misses", "" }, 39 { CHW(BRANCH_MISSES), "branch-misses", "" },
42 { CHW(BUS_CYCLES), "bus-cycles", "" }, 40 { CHW(BUS_CYCLES), "bus-cycles", "" },
41 { CHW(REF_CPU_CYCLES), "ref-cycles", "" },
43 42
44 { CSW(CPU_CLOCK), "cpu-clock", "" }, 43 { CSW(CPU_CLOCK), "cpu-clock", "" },
45 { CSW(TASK_CLOCK), "task-clock", "" }, 44 { CSW(TASK_CLOCK), "task-clock", "" },
@@ -70,6 +69,7 @@ static const char *hw_event_names[PERF_COUNT_HW_MAX] = {
70 "bus-cycles", 69 "bus-cycles",
71 "stalled-cycles-frontend", 70 "stalled-cycles-frontend",
72 "stalled-cycles-backend", 71 "stalled-cycles-backend",
72 "ref-cycles",
73}; 73};
74 74
75static const char *sw_event_names[PERF_COUNT_SW_MAX] = { 75static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
@@ -140,7 +140,7 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
140 char evt_path[MAXPATHLEN]; 140 char evt_path[MAXPATHLEN];
141 int fd; 141 int fd;
142 142
143 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 143 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
144 sys_dir->d_name, evt_dir->d_name); 144 sys_dir->d_name, evt_dir->d_name);
145 fd = open(evt_path, O_RDONLY); 145 fd = open(evt_path, O_RDONLY);
146 if (fd < 0) 146 if (fd < 0)
@@ -165,22 +165,22 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
165 struct tracepoint_path *path = NULL; 165 struct tracepoint_path *path = NULL;
166 DIR *sys_dir, *evt_dir; 166 DIR *sys_dir, *evt_dir;
167 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 167 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
168 char id_buf[4]; 168 char id_buf[24];
169 int fd; 169 int fd;
170 u64 id; 170 u64 id;
171 char evt_path[MAXPATHLEN]; 171 char evt_path[MAXPATHLEN];
172 char dir_path[MAXPATHLEN]; 172 char dir_path[MAXPATHLEN];
173 173
174 if (debugfs_valid_mountpoint(debugfs_path)) 174 if (debugfs_valid_mountpoint(tracing_events_path))
175 return NULL; 175 return NULL;
176 176
177 sys_dir = opendir(debugfs_path); 177 sys_dir = opendir(tracing_events_path);
178 if (!sys_dir) 178 if (!sys_dir)
179 return NULL; 179 return NULL;
180 180
181 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 181 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
182 182
183 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 183 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
184 sys_dirent.d_name); 184 sys_dirent.d_name);
185 evt_dir = opendir(dir_path); 185 evt_dir = opendir(dir_path);
186 if (!evt_dir) 186 if (!evt_dir)
@@ -447,7 +447,7 @@ parse_single_tracepoint_event(char *sys_name,
447 u64 id; 447 u64 id;
448 int fd; 448 int fd;
449 449
450 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 450 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
451 sys_name, evt_name); 451 sys_name, evt_name);
452 452
453 fd = open(evt_path, O_RDONLY); 453 fd = open(evt_path, O_RDONLY);
@@ -485,7 +485,7 @@ parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name,
485 struct dirent *evt_ent; 485 struct dirent *evt_ent;
486 DIR *evt_dir; 486 DIR *evt_dir;
487 487
488 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name); 488 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
489 evt_dir = opendir(evt_path); 489 evt_dir = opendir(evt_path);
490 490
491 if (!evt_dir) { 491 if (!evt_dir) {
@@ -528,7 +528,7 @@ parse_tracepoint_event(struct perf_evlist *evlist, const char **strp,
528 char sys_name[MAX_EVENT_LENGTH]; 528 char sys_name[MAX_EVENT_LENGTH];
529 unsigned int sys_length, evt_length; 529 unsigned int sys_length, evt_length;
530 530
531 if (debugfs_valid_mountpoint(debugfs_path)) 531 if (debugfs_valid_mountpoint(tracing_events_path))
532 return 0; 532 return 0;
533 533
534 evt_name = strchr(*strp, ':'); 534 evt_name = strchr(*strp, ':');
@@ -735,8 +735,8 @@ static int
735parse_event_modifier(const char **strp, struct perf_event_attr *attr) 735parse_event_modifier(const char **strp, struct perf_event_attr *attr)
736{ 736{
737 const char *str = *strp; 737 const char *str = *strp;
738 int exclude = 0; 738 int exclude = 0, exclude_GH = 0;
739 int eu = 0, ek = 0, eh = 0, precise = 0; 739 int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0;
740 740
741 if (!*str) 741 if (!*str)
742 return 0; 742 return 0;
@@ -760,6 +760,14 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
760 if (!exclude) 760 if (!exclude)
761 exclude = eu = ek = eh = 1; 761 exclude = eu = ek = eh = 1;
762 eh = 0; 762 eh = 0;
763 } else if (*str == 'G') {
764 if (!exclude_GH)
765 exclude_GH = eG = eH = 1;
766 eG = 0;
767 } else if (*str == 'H') {
768 if (!exclude_GH)
769 exclude_GH = eG = eH = 1;
770 eH = 0;
763 } else if (*str == 'p') { 771 } else if (*str == 'p') {
764 precise++; 772 precise++;
765 } else 773 } else
@@ -776,6 +784,8 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
776 attr->exclude_kernel = ek; 784 attr->exclude_kernel = ek;
777 attr->exclude_hv = eh; 785 attr->exclude_hv = eh;
778 attr->precise_ip = precise; 786 attr->precise_ip = precise;
787 attr->exclude_host = eH;
788 attr->exclude_guest = eG;
779 789
780 return 0; 790 return 0;
781} 791}
@@ -838,6 +848,7 @@ int parse_events(struct perf_evlist *evlist , const char *str, int unset __used)
838 for (;;) { 848 for (;;) {
839 ostr = str; 849 ostr = str;
840 memset(&attr, 0, sizeof(attr)); 850 memset(&attr, 0, sizeof(attr));
851 event_attr_init(&attr);
841 ret = parse_event_symbols(evlist, &str, &attr); 852 ret = parse_event_symbols(evlist, &str, &attr);
842 if (ret == EVT_FAILED) 853 if (ret == EVT_FAILED)
843 return -1; 854 return -1;
@@ -920,10 +931,10 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
920 char evt_path[MAXPATHLEN]; 931 char evt_path[MAXPATHLEN];
921 char dir_path[MAXPATHLEN]; 932 char dir_path[MAXPATHLEN];
922 933
923 if (debugfs_valid_mountpoint(debugfs_path)) 934 if (debugfs_valid_mountpoint(tracing_events_path))
924 return; 935 return;
925 936
926 sys_dir = opendir(debugfs_path); 937 sys_dir = opendir(tracing_events_path);
927 if (!sys_dir) 938 if (!sys_dir)
928 return; 939 return;
929 940
@@ -932,7 +943,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
932 !strglobmatch(sys_dirent.d_name, subsys_glob)) 943 !strglobmatch(sys_dirent.d_name, subsys_glob))
933 continue; 944 continue;
934 945
935 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 946 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
936 sys_dirent.d_name); 947 sys_dirent.d_name);
937 evt_dir = opendir(dir_path); 948 evt_dir = opendir(dir_path);
938 if (!evt_dir) 949 if (!evt_dir)
@@ -964,16 +975,16 @@ int is_valid_tracepoint(const char *event_string)
964 char evt_path[MAXPATHLEN]; 975 char evt_path[MAXPATHLEN];
965 char dir_path[MAXPATHLEN]; 976 char dir_path[MAXPATHLEN];
966 977
967 if (debugfs_valid_mountpoint(debugfs_path)) 978 if (debugfs_valid_mountpoint(tracing_events_path))
968 return 0; 979 return 0;
969 980
970 sys_dir = opendir(debugfs_path); 981 sys_dir = opendir(tracing_events_path);
971 if (!sys_dir) 982 if (!sys_dir)
972 return 0; 983 return 0;
973 984
974 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 985 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
975 986
976 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 987 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
977 sys_dirent.d_name); 988 sys_dirent.d_name);
978 evt_dir = opendir(dir_path); 989 evt_dir = opendir(dir_path);
979 if (!evt_dir) 990 if (!evt_dir)
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 2f8e375e038d..7e0cbe75d5f1 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -39,7 +39,6 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
39int print_hwcache_events(const char *event_glob); 39int print_hwcache_events(const char *event_glob);
40extern int is_valid_tracepoint(const char *event_string); 40extern int is_valid_tracepoint(const char *event_string);
41 41
42extern char debugfs_path[];
43extern int valid_debugfs_mount(const char *debugfs); 42extern int valid_debugfs_mount(const char *debugfs);
44 43
45#endif /* __PERF_PARSE_EVENTS_H */ 44#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index eb25900e2211..e33554a562b3 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,7 +32,6 @@
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" 37#include "string.h"
@@ -1869,6 +1867,12 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1869 tev->point.symbol); 1867 tev->point.symbol);
1870 ret = -ENOENT; 1868 ret = -ENOENT;
1871 goto error; 1869 goto error;
1870 } else if (tev->point.offset > sym->end - sym->start) {
1871 pr_warning("Offset specified is greater than size of %s\n",
1872 tev->point.symbol);
1873 ret = -ENOENT;
1874 goto error;
1875
1872 } 1876 }
1873 1877
1874 return 1; 1878 return 1;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 5d732621a462..74bd2e63c4b4 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -672,7 +672,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, 672static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
673 bool retprobe, struct probe_trace_point *tp) 673 bool retprobe, struct probe_trace_point *tp)
674{ 674{
675 Dwarf_Addr eaddr; 675 Dwarf_Addr eaddr, highaddr;
676 const char *name; 676 const char *name;
677 677
678 /* Copy the name of probe point */ 678 /* Copy the name of probe point */
@@ -683,6 +683,16 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
683 dwarf_diename(sp_die)); 683 dwarf_diename(sp_die));
684 return -ENOENT; 684 return -ENOENT;
685 } 685 }
686 if (dwarf_highpc(sp_die, &highaddr) != 0) {
687 pr_warning("Failed to get end address of %s\n",
688 dwarf_diename(sp_die));
689 return -ENOENT;
690 }
691 if (paddr > highaddr) {
692 pr_warning("Offset specified is greater than size of %s\n",
693 dwarf_diename(sp_die));
694 return -EINVAL;
695 }
686 tp->symbol = strdup(name); 696 tp->symbol = strdup(name);
687 if (tp->symbol == NULL) 697 if (tp->symbol == NULL)
688 return -ENOMEM; 698 return -ENOMEM;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 1132c8f0ce89..17e94d0c36f9 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -5,7 +5,6 @@
5#include "util.h" 5#include "util.h"
6#include "probe-event.h" 6#include "probe-event.h"
7 7
8#define MAX_PATH_LEN 256
9#define MAX_PROBE_BUFFER 1024 8#define MAX_PROBE_BUFFER 1024
10#define MAX_PROBES 128 9#define MAX_PROBES 128
11 10
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 74350ffb57fe..e30749e38a9b 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -27,7 +27,10 @@
27 27
28#include "../../perf.h" 28#include "../../perf.h"
29#include "../util.h" 29#include "../util.h"
30#include "../thread.h"
31#include "../event.h"
30#include "../trace-event.h" 32#include "../trace-event.h"
33#include "../evsel.h"
31 34
32#include <EXTERN.h> 35#include <EXTERN.h>
33#include <perl.h> 36#include <perl.h>
@@ -245,11 +248,11 @@ static inline struct event *find_cache_event(int type)
245 return event; 248 return event;
246} 249}
247 250
248static void perl_process_event(union perf_event *pevent __unused, 251static void perl_process_tracepoint(union perf_event *pevent __unused,
249 struct perf_sample *sample, 252 struct perf_sample *sample,
250 struct perf_evsel *evsel, 253 struct perf_evsel *evsel,
251 struct perf_session *session __unused, 254 struct machine *machine __unused,
252 struct thread *thread) 255 struct thread *thread)
253{ 256{
254 struct format_field *field; 257 struct format_field *field;
255 static char handler[256]; 258 static char handler[256];
@@ -265,6 +268,9 @@ static void perl_process_event(union perf_event *pevent __unused,
265 268
266 dSP; 269 dSP;
267 270
271 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
272 return;
273
268 type = trace_parse_common_type(data); 274 type = trace_parse_common_type(data);
269 275
270 event = find_cache_event(type); 276 event = find_cache_event(type);
@@ -332,6 +338,42 @@ static void perl_process_event(union perf_event *pevent __unused,
332 LEAVE; 338 LEAVE;
333} 339}
334 340
341static void perl_process_event_generic(union perf_event *pevent __unused,
342 struct perf_sample *sample,
343 struct perf_evsel *evsel __unused,
344 struct machine *machine __unused,
345 struct thread *thread __unused)
346{
347 dSP;
348
349 if (!get_cv("process_event", 0))
350 return;
351
352 ENTER;
353 SAVETMPS;
354 PUSHMARK(SP);
355 XPUSHs(sv_2mortal(newSVpvn((const char *)pevent, pevent->header.size)));
356 XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr))));
357 XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample))));
358 XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size)));
359 PUTBACK;
360 call_pv("process_event", G_SCALAR);
361 SPAGAIN;
362 PUTBACK;
363 FREETMPS;
364 LEAVE;
365}
366
367static void perl_process_event(union perf_event *pevent,
368 struct perf_sample *sample,
369 struct perf_evsel *evsel,
370 struct machine *machine,
371 struct thread *thread)
372{
373 perl_process_tracepoint(pevent, sample, evsel, machine, thread);
374 perl_process_event_generic(pevent, sample, evsel, machine, thread);
375}
376
335static void run_start_sub(void) 377static void run_start_sub(void)
336{ 378{
337 dSP; /* access to Perl stack */ 379 dSP; /* access to Perl stack */
@@ -553,7 +595,28 @@ static int perl_generate_script(const char *outfile)
553 fprintf(ofp, "sub print_header\n{\n" 595 fprintf(ofp, "sub print_header\n{\n"
554 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n" 596 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
555 "\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t " 597 "\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t "
556 "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}"); 598 "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}\n");
599
600 fprintf(ofp,
601 "\n# Packed byte string args of process_event():\n"
602 "#\n"
603 "# $event:\tunion perf_event\tutil/event.h\n"
604 "# $attr:\tstruct perf_event_attr\tlinux/perf_event.h\n"
605 "# $sample:\tstruct perf_sample\tutil/event.h\n"
606 "# $raw_data:\tperf_sample->raw_data\tutil/event.h\n"
607 "\n"
608 "sub process_event\n"
609 "{\n"
610 "\tmy ($event, $attr, $sample, $raw_data) = @_;\n"
611 "\n"
612 "\tmy @event\t= unpack(\"LSS\", $event);\n"
613 "\tmy @attr\t= unpack(\"LLQQQQQLLQQ\", $attr);\n"
614 "\tmy @sample\t= unpack(\"QLLQQQQQLL\", $sample);\n"
615 "\tmy @raw_data\t= unpack(\"C*\", $raw_data);\n"
616 "\n"
617 "\tuse Data::Dumper;\n"
618 "\tprint Dumper \\@event, \\@attr, \\@sample, \\@raw_data;\n"
619 "}\n");
557 620
558 fclose(ofp); 621 fclose(ofp);
559 622
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 6ccf70e8d8f2..0b2a48783172 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -29,6 +29,8 @@
29 29
30#include "../../perf.h" 30#include "../../perf.h"
31#include "../util.h" 31#include "../util.h"
32#include "../event.h"
33#include "../thread.h"
32#include "../trace-event.h" 34#include "../trace-event.h"
33 35
34PyMODINIT_FUNC initperf_trace_context(void); 36PyMODINIT_FUNC initperf_trace_context(void);
@@ -207,7 +209,7 @@ static inline struct event *find_cache_event(int type)
207static void python_process_event(union perf_event *pevent __unused, 209static void python_process_event(union perf_event *pevent __unused,
208 struct perf_sample *sample, 210 struct perf_sample *sample,
209 struct perf_evsel *evsel __unused, 211 struct perf_evsel *evsel __unused,
210 struct perf_session *session __unused, 212 struct machine *machine __unused,
211 struct thread *thread) 213 struct thread *thread)
212{ 214{
213 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 215 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0f4555ce9063..b5ca2558c7bb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -10,6 +10,7 @@
10#include "evlist.h" 10#include "evlist.h"
11#include "evsel.h" 11#include "evsel.h"
12#include "session.h" 12#include "session.h"
13#include "tool.h"
13#include "sort.h" 14#include "sort.h"
14#include "util.h" 15#include "util.h"
15#include "cpumap.h" 16#include "cpumap.h"
@@ -78,39 +79,13 @@ out_close:
78 return -1; 79 return -1;
79} 80}
80 81
81static void perf_session__id_header_size(struct perf_session *session)
82{
83 struct perf_sample *data;
84 u64 sample_type = session->sample_type;
85 u16 size = 0;
86
87 if (!session->sample_id_all)
88 goto out;
89
90 if (sample_type & PERF_SAMPLE_TID)
91 size += sizeof(data->tid) * 2;
92
93 if (sample_type & PERF_SAMPLE_TIME)
94 size += sizeof(data->time);
95
96 if (sample_type & PERF_SAMPLE_ID)
97 size += sizeof(data->id);
98
99 if (sample_type & PERF_SAMPLE_STREAM_ID)
100 size += sizeof(data->stream_id);
101
102 if (sample_type & PERF_SAMPLE_CPU)
103 size += sizeof(data->cpu) * 2;
104out:
105 session->id_hdr_size = size;
106}
107
108void perf_session__update_sample_type(struct perf_session *self) 82void perf_session__update_sample_type(struct perf_session *self)
109{ 83{
110 self->sample_type = perf_evlist__sample_type(self->evlist); 84 self->sample_type = perf_evlist__sample_type(self->evlist);
111 self->sample_size = __perf_evsel__sample_size(self->sample_type); 85 self->sample_size = __perf_evsel__sample_size(self->sample_type);
112 self->sample_id_all = perf_evlist__sample_id_all(self->evlist); 86 self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
113 perf_session__id_header_size(self); 87 self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
88 self->host_machine.id_hdr_size = self->id_hdr_size;
114} 89}
115 90
116int perf_session__create_kernel_maps(struct perf_session *self) 91int perf_session__create_kernel_maps(struct perf_session *self)
@@ -130,18 +105,26 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self)
130 105
131struct perf_session *perf_session__new(const char *filename, int mode, 106struct perf_session *perf_session__new(const char *filename, int mode,
132 bool force, bool repipe, 107 bool force, bool repipe,
133 struct perf_event_ops *ops) 108 struct perf_tool *tool)
134{ 109{
135 size_t len = filename ? strlen(filename) + 1 : 0; 110 struct perf_session *self;
136 struct perf_session *self = zalloc(sizeof(*self) + len); 111 struct stat st;
112 size_t len;
113
114 if (!filename || !strlen(filename)) {
115 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
116 filename = "-";
117 else
118 filename = "perf.data";
119 }
120
121 len = strlen(filename);
122 self = zalloc(sizeof(*self) + len);
137 123
138 if (self == NULL) 124 if (self == NULL)
139 goto out; 125 goto out;
140 126
141 memcpy(self->filename, filename, len); 127 memcpy(self->filename, filename, len);
142 self->threads = RB_ROOT;
143 INIT_LIST_HEAD(&self->dead_threads);
144 self->last_match = NULL;
145 /* 128 /*
146 * On 64bit we can mmap the data file in one go. No need for tiny mmap 129 * On 64bit we can mmap the data file in one go. No need for tiny mmap
147 * slices. On 32bit we use 32MB. 130 * slices. On 32bit we use 32MB.
@@ -171,10 +154,10 @@ struct perf_session *perf_session__new(const char *filename, int mode,
171 goto out_delete; 154 goto out_delete;
172 } 155 }
173 156
174 if (ops && ops->ordering_requires_timestamps && 157 if (tool && tool->ordering_requires_timestamps &&
175 ops->ordered_samples && !self->sample_id_all) { 158 tool->ordered_samples && !self->sample_id_all) {
176 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 159 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
177 ops->ordered_samples = false; 160 tool->ordered_samples = false;
178 } 161 }
179 162
180out: 163out:
@@ -184,17 +167,22 @@ out_delete:
184 return NULL; 167 return NULL;
185} 168}
186 169
187static void perf_session__delete_dead_threads(struct perf_session *self) 170static void machine__delete_dead_threads(struct machine *machine)
188{ 171{
189 struct thread *n, *t; 172 struct thread *n, *t;
190 173
191 list_for_each_entry_safe(t, n, &self->dead_threads, node) { 174 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
192 list_del(&t->node); 175 list_del(&t->node);
193 thread__delete(t); 176 thread__delete(t);
194 } 177 }
195} 178}
196 179
197static void perf_session__delete_threads(struct perf_session *self) 180static void perf_session__delete_dead_threads(struct perf_session *session)
181{
182 machine__delete_dead_threads(&session->host_machine);
183}
184
185static void machine__delete_threads(struct machine *self)
198{ 186{
199 struct rb_node *nd = rb_first(&self->threads); 187 struct rb_node *nd = rb_first(&self->threads);
200 188
@@ -207,6 +195,11 @@ static void perf_session__delete_threads(struct perf_session *self)
207 } 195 }
208} 196}
209 197
198static void perf_session__delete_threads(struct perf_session *session)
199{
200 machine__delete_threads(&session->host_machine);
201}
202
210void perf_session__delete(struct perf_session *self) 203void perf_session__delete(struct perf_session *self)
211{ 204{
212 perf_session__destroy_kernel_maps(self); 205 perf_session__destroy_kernel_maps(self);
@@ -217,7 +210,7 @@ void perf_session__delete(struct perf_session *self)
217 free(self); 210 free(self);
218} 211}
219 212
220void perf_session__remove_thread(struct perf_session *self, struct thread *th) 213void machine__remove_thread(struct machine *self, struct thread *th)
221{ 214{
222 self->last_match = NULL; 215 self->last_match = NULL;
223 rb_erase(&th->rb_node, &self->threads); 216 rb_erase(&th->rb_node, &self->threads);
@@ -236,16 +229,16 @@ static bool symbol__match_parent_regex(struct symbol *sym)
236 return 0; 229 return 0;
237} 230}
238 231
239int perf_session__resolve_callchain(struct perf_session *self, 232int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
240 struct thread *thread, 233 struct thread *thread,
241 struct ip_callchain *chain, 234 struct ip_callchain *chain,
242 struct symbol **parent) 235 struct symbol **parent)
243{ 236{
244 u8 cpumode = PERF_RECORD_MISC_USER; 237 u8 cpumode = PERF_RECORD_MISC_USER;
245 unsigned int i; 238 unsigned int i;
246 int err; 239 int err;
247 240
248 callchain_cursor_reset(&self->callchain_cursor); 241 callchain_cursor_reset(&evsel->hists.callchain_cursor);
249 242
250 for (i = 0; i < chain->nr; i++) { 243 for (i = 0; i < chain->nr; i++) {
251 u64 ip; 244 u64 ip;
@@ -272,7 +265,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
272 265
273 al.filtered = false; 266 al.filtered = false;
274 thread__find_addr_location(thread, self, cpumode, 267 thread__find_addr_location(thread, self, cpumode,
275 MAP__FUNCTION, thread->pid, ip, &al, NULL); 268 MAP__FUNCTION, ip, &al, NULL);
276 if (al.sym != NULL) { 269 if (al.sym != NULL) {
277 if (sort__has_parent && !*parent && 270 if (sort__has_parent && !*parent &&
278 symbol__match_parent_regex(al.sym)) 271 symbol__match_parent_regex(al.sym))
@@ -281,7 +274,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
281 break; 274 break;
282 } 275 }
283 276
284 err = callchain_cursor_append(&self->callchain_cursor, 277 err = callchain_cursor_append(&evsel->hists.callchain_cursor,
285 ip, al.map, al.sym); 278 ip, al.map, al.sym);
286 if (err) 279 if (err)
287 return err; 280 return err;
@@ -290,75 +283,91 @@ int perf_session__resolve_callchain(struct perf_session *self,
290 return 0; 283 return 0;
291} 284}
292 285
293static int process_event_synth_stub(union perf_event *event __used, 286static int process_event_synth_tracing_data_stub(union perf_event *event __used,
294 struct perf_session *session __used) 287 struct perf_session *session __used)
288{
289 dump_printf(": unhandled!\n");
290 return 0;
291}
292
293static int process_event_synth_attr_stub(union perf_event *event __used,
294 struct perf_evlist **pevlist __used)
295{ 295{
296 dump_printf(": unhandled!\n"); 296 dump_printf(": unhandled!\n");
297 return 0; 297 return 0;
298} 298}
299 299
300static int process_event_sample_stub(union perf_event *event __used, 300static int process_event_sample_stub(struct perf_tool *tool __used,
301 union perf_event *event __used,
301 struct perf_sample *sample __used, 302 struct perf_sample *sample __used,
302 struct perf_evsel *evsel __used, 303 struct perf_evsel *evsel __used,
303 struct perf_session *session __used) 304 struct machine *machine __used)
304{ 305{
305 dump_printf(": unhandled!\n"); 306 dump_printf(": unhandled!\n");
306 return 0; 307 return 0;
307} 308}
308 309
309static int process_event_stub(union perf_event *event __used, 310static int process_event_stub(struct perf_tool *tool __used,
311 union perf_event *event __used,
310 struct perf_sample *sample __used, 312 struct perf_sample *sample __used,
311 struct perf_session *session __used) 313 struct machine *machine __used)
312{ 314{
313 dump_printf(": unhandled!\n"); 315 dump_printf(": unhandled!\n");
314 return 0; 316 return 0;
315} 317}
316 318
317static int process_finished_round_stub(union perf_event *event __used, 319static int process_finished_round_stub(struct perf_tool *tool __used,
318 struct perf_session *session __used, 320 union perf_event *event __used,
319 struct perf_event_ops *ops __used) 321 struct perf_session *perf_session __used)
320{ 322{
321 dump_printf(": unhandled!\n"); 323 dump_printf(": unhandled!\n");
322 return 0; 324 return 0;
323} 325}
324 326
325static int process_finished_round(union perf_event *event, 327static int process_event_type_stub(struct perf_tool *tool __used,
326 struct perf_session *session, 328 union perf_event *event __used)
327 struct perf_event_ops *ops); 329{
330 dump_printf(": unhandled!\n");
331 return 0;
332}
328 333
329static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) 334static int process_finished_round(struct perf_tool *tool,
335 union perf_event *event,
336 struct perf_session *session);
337
338static void perf_tool__fill_defaults(struct perf_tool *tool)
330{ 339{
331 if (handler->sample == NULL) 340 if (tool->sample == NULL)
332 handler->sample = process_event_sample_stub; 341 tool->sample = process_event_sample_stub;
333 if (handler->mmap == NULL) 342 if (tool->mmap == NULL)
334 handler->mmap = process_event_stub; 343 tool->mmap = process_event_stub;
335 if (handler->comm == NULL) 344 if (tool->comm == NULL)
336 handler->comm = process_event_stub; 345 tool->comm = process_event_stub;
337 if (handler->fork == NULL) 346 if (tool->fork == NULL)
338 handler->fork = process_event_stub; 347 tool->fork = process_event_stub;
339 if (handler->exit == NULL) 348 if (tool->exit == NULL)
340 handler->exit = process_event_stub; 349 tool->exit = process_event_stub;
341 if (handler->lost == NULL) 350 if (tool->lost == NULL)
342 handler->lost = perf_event__process_lost; 351 tool->lost = perf_event__process_lost;
343 if (handler->read == NULL) 352 if (tool->read == NULL)
344 handler->read = process_event_stub; 353 tool->read = process_event_sample_stub;
345 if (handler->throttle == NULL) 354 if (tool->throttle == NULL)
346 handler->throttle = process_event_stub; 355 tool->throttle = process_event_stub;
347 if (handler->unthrottle == NULL) 356 if (tool->unthrottle == NULL)
348 handler->unthrottle = process_event_stub; 357 tool->unthrottle = process_event_stub;
349 if (handler->attr == NULL) 358 if (tool->attr == NULL)
350 handler->attr = process_event_synth_stub; 359 tool->attr = process_event_synth_attr_stub;
351 if (handler->event_type == NULL) 360 if (tool->event_type == NULL)
352 handler->event_type = process_event_synth_stub; 361 tool->event_type = process_event_type_stub;
353 if (handler->tracing_data == NULL) 362 if (tool->tracing_data == NULL)
354 handler->tracing_data = process_event_synth_stub; 363 tool->tracing_data = process_event_synth_tracing_data_stub;
355 if (handler->build_id == NULL) 364 if (tool->build_id == NULL)
356 handler->build_id = process_event_synth_stub; 365 tool->build_id = process_finished_round_stub;
357 if (handler->finished_round == NULL) { 366 if (tool->finished_round == NULL) {
358 if (handler->ordered_samples) 367 if (tool->ordered_samples)
359 handler->finished_round = process_finished_round; 368 tool->finished_round = process_finished_round;
360 else 369 else
361 handler->finished_round = process_finished_round_stub; 370 tool->finished_round = process_finished_round_stub;
362 } 371 }
363} 372}
364 373
@@ -490,11 +499,11 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
490static int perf_session_deliver_event(struct perf_session *session, 499static int perf_session_deliver_event(struct perf_session *session,
491 union perf_event *event, 500 union perf_event *event,
492 struct perf_sample *sample, 501 struct perf_sample *sample,
493 struct perf_event_ops *ops, 502 struct perf_tool *tool,
494 u64 file_offset); 503 u64 file_offset);
495 504
496static void flush_sample_queue(struct perf_session *s, 505static void flush_sample_queue(struct perf_session *s,
497 struct perf_event_ops *ops) 506 struct perf_tool *tool)
498{ 507{
499 struct ordered_samples *os = &s->ordered_samples; 508 struct ordered_samples *os = &s->ordered_samples;
500 struct list_head *head = &os->samples; 509 struct list_head *head = &os->samples;
@@ -505,7 +514,7 @@ static void flush_sample_queue(struct perf_session *s,
505 unsigned idx = 0, progress_next = os->nr_samples / 16; 514 unsigned idx = 0, progress_next = os->nr_samples / 16;
506 int ret; 515 int ret;
507 516
508 if (!ops->ordered_samples || !limit) 517 if (!tool->ordered_samples || !limit)
509 return; 518 return;
510 519
511 list_for_each_entry_safe(iter, tmp, head, list) { 520 list_for_each_entry_safe(iter, tmp, head, list) {
@@ -516,7 +525,7 @@ static void flush_sample_queue(struct perf_session *s,
516 if (ret) 525 if (ret)
517 pr_err("Can't parse sample, err = %d\n", ret); 526 pr_err("Can't parse sample, err = %d\n", ret);
518 else 527 else
519 perf_session_deliver_event(s, iter->event, &sample, ops, 528 perf_session_deliver_event(s, iter->event, &sample, tool,
520 iter->file_offset); 529 iter->file_offset);
521 530
522 os->last_flush = iter->timestamp; 531 os->last_flush = iter->timestamp;
@@ -578,11 +587,11 @@ static void flush_sample_queue(struct perf_session *s,
578 * Flush every events below timestamp 7 587 * Flush every events below timestamp 7
579 * etc... 588 * etc...
580 */ 589 */
581static int process_finished_round(union perf_event *event __used, 590static int process_finished_round(struct perf_tool *tool,
582 struct perf_session *session, 591 union perf_event *event __used,
583 struct perf_event_ops *ops) 592 struct perf_session *session)
584{ 593{
585 flush_sample_queue(session, ops); 594 flush_sample_queue(session, tool);
586 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; 595 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
587 596
588 return 0; 597 return 0;
@@ -737,13 +746,26 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
737 callchain__printf(sample); 746 callchain__printf(sample);
738} 747}
739 748
749static struct machine *
750 perf_session__find_machine_for_cpumode(struct perf_session *session,
751 union perf_event *event)
752{
753 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
754
755 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)
756 return perf_session__find_machine(session, event->ip.pid);
757
758 return perf_session__find_host_machine(session);
759}
760
740static int perf_session_deliver_event(struct perf_session *session, 761static int perf_session_deliver_event(struct perf_session *session,
741 union perf_event *event, 762 union perf_event *event,
742 struct perf_sample *sample, 763 struct perf_sample *sample,
743 struct perf_event_ops *ops, 764 struct perf_tool *tool,
744 u64 file_offset) 765 u64 file_offset)
745{ 766{
746 struct perf_evsel *evsel; 767 struct perf_evsel *evsel;
768 struct machine *machine;
747 769
748 dump_event(session, event, file_offset, sample); 770 dump_event(session, event, file_offset, sample);
749 771
@@ -765,6 +787,8 @@ static int perf_session_deliver_event(struct perf_session *session,
765 hists__inc_nr_events(&evsel->hists, event->header.type); 787 hists__inc_nr_events(&evsel->hists, event->header.type);
766 } 788 }
767 789
790 machine = perf_session__find_machine_for_cpumode(session, event);
791
768 switch (event->header.type) { 792 switch (event->header.type) {
769 case PERF_RECORD_SAMPLE: 793 case PERF_RECORD_SAMPLE:
770 dump_sample(session, event, sample); 794 dump_sample(session, event, sample);
@@ -772,23 +796,25 @@ static int perf_session_deliver_event(struct perf_session *session,
772 ++session->hists.stats.nr_unknown_id; 796 ++session->hists.stats.nr_unknown_id;
773 return -1; 797 return -1;
774 } 798 }
775 return ops->sample(event, sample, evsel, session); 799 return tool->sample(tool, event, sample, evsel, machine);
776 case PERF_RECORD_MMAP: 800 case PERF_RECORD_MMAP:
777 return ops->mmap(event, sample, session); 801 return tool->mmap(tool, event, sample, machine);
778 case PERF_RECORD_COMM: 802 case PERF_RECORD_COMM:
779 return ops->comm(event, sample, session); 803 return tool->comm(tool, event, sample, machine);
780 case PERF_RECORD_FORK: 804 case PERF_RECORD_FORK:
781 return ops->fork(event, sample, session); 805 return tool->fork(tool, event, sample, machine);
782 case PERF_RECORD_EXIT: 806 case PERF_RECORD_EXIT:
783 return ops->exit(event, sample, session); 807 return tool->exit(tool, event, sample, machine);
784 case PERF_RECORD_LOST: 808 case PERF_RECORD_LOST:
785 return ops->lost(event, sample, session); 809 if (tool->lost == perf_event__process_lost)
810 session->hists.stats.total_lost += event->lost.lost;
811 return tool->lost(tool, event, sample, machine);
786 case PERF_RECORD_READ: 812 case PERF_RECORD_READ:
787 return ops->read(event, sample, session); 813 return tool->read(tool, event, sample, evsel, machine);
788 case PERF_RECORD_THROTTLE: 814 case PERF_RECORD_THROTTLE:
789 return ops->throttle(event, sample, session); 815 return tool->throttle(tool, event, sample, machine);
790 case PERF_RECORD_UNTHROTTLE: 816 case PERF_RECORD_UNTHROTTLE:
791 return ops->unthrottle(event, sample, session); 817 return tool->unthrottle(tool, event, sample, machine);
792 default: 818 default:
793 ++session->hists.stats.nr_unknown_events; 819 ++session->hists.stats.nr_unknown_events;
794 return -1; 820 return -1;
@@ -812,24 +838,29 @@ static int perf_session__preprocess_sample(struct perf_session *session,
812} 838}
813 839
814static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, 840static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
815 struct perf_event_ops *ops, u64 file_offset) 841 struct perf_tool *tool, u64 file_offset)
816{ 842{
843 int err;
844
817 dump_event(session, event, file_offset, NULL); 845 dump_event(session, event, file_offset, NULL);
818 846
819 /* These events are processed right away */ 847 /* These events are processed right away */
820 switch (event->header.type) { 848 switch (event->header.type) {
821 case PERF_RECORD_HEADER_ATTR: 849 case PERF_RECORD_HEADER_ATTR:
822 return ops->attr(event, session); 850 err = tool->attr(event, &session->evlist);
851 if (err == 0)
852 perf_session__update_sample_type(session);
853 return err;
823 case PERF_RECORD_HEADER_EVENT_TYPE: 854 case PERF_RECORD_HEADER_EVENT_TYPE:
824 return ops->event_type(event, session); 855 return tool->event_type(tool, event);
825 case PERF_RECORD_HEADER_TRACING_DATA: 856 case PERF_RECORD_HEADER_TRACING_DATA:
826 /* setup for reading amidst mmap */ 857 /* setup for reading amidst mmap */
827 lseek(session->fd, file_offset, SEEK_SET); 858 lseek(session->fd, file_offset, SEEK_SET);
828 return ops->tracing_data(event, session); 859 return tool->tracing_data(event, session);
829 case PERF_RECORD_HEADER_BUILD_ID: 860 case PERF_RECORD_HEADER_BUILD_ID:
830 return ops->build_id(event, session); 861 return tool->build_id(tool, event, session);
831 case PERF_RECORD_FINISHED_ROUND: 862 case PERF_RECORD_FINISHED_ROUND:
832 return ops->finished_round(event, session, ops); 863 return tool->finished_round(tool, event, session);
833 default: 864 default:
834 return -EINVAL; 865 return -EINVAL;
835 } 866 }
@@ -837,7 +868,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
837 868
838static int perf_session__process_event(struct perf_session *session, 869static int perf_session__process_event(struct perf_session *session,
839 union perf_event *event, 870 union perf_event *event,
840 struct perf_event_ops *ops, 871 struct perf_tool *tool,
841 u64 file_offset) 872 u64 file_offset)
842{ 873{
843 struct perf_sample sample; 874 struct perf_sample sample;
@@ -853,7 +884,7 @@ static int perf_session__process_event(struct perf_session *session,
853 hists__inc_nr_events(&session->hists, event->header.type); 884 hists__inc_nr_events(&session->hists, event->header.type);
854 885
855 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 886 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
856 return perf_session__process_user_event(session, event, ops, file_offset); 887 return perf_session__process_user_event(session, event, tool, file_offset);
857 888
858 /* 889 /*
859 * For all kernel events we get the sample data 890 * For all kernel events we get the sample data
@@ -866,14 +897,14 @@ static int perf_session__process_event(struct perf_session *session,
866 if (perf_session__preprocess_sample(session, event, &sample)) 897 if (perf_session__preprocess_sample(session, event, &sample))
867 return 0; 898 return 0;
868 899
869 if (ops->ordered_samples) { 900 if (tool->ordered_samples) {
870 ret = perf_session_queue_event(session, event, &sample, 901 ret = perf_session_queue_event(session, event, &sample,
871 file_offset); 902 file_offset);
872 if (ret != -ETIME) 903 if (ret != -ETIME)
873 return ret; 904 return ret;
874 } 905 }
875 906
876 return perf_session_deliver_event(session, event, &sample, ops, 907 return perf_session_deliver_event(session, event, &sample, tool,
877 file_offset); 908 file_offset);
878} 909}
879 910
@@ -884,6 +915,11 @@ void perf_event_header__bswap(struct perf_event_header *self)
884 self->size = bswap_16(self->size); 915 self->size = bswap_16(self->size);
885} 916}
886 917
918struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
919{
920 return machine__findnew_thread(&session->host_machine, pid);
921}
922
887static struct thread *perf_session__register_idle_thread(struct perf_session *self) 923static struct thread *perf_session__register_idle_thread(struct perf_session *self)
888{ 924{
889 struct thread *thread = perf_session__findnew(self, 0); 925 struct thread *thread = perf_session__findnew(self, 0);
@@ -897,9 +933,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
897} 933}
898 934
899static void perf_session__warn_about_errors(const struct perf_session *session, 935static void perf_session__warn_about_errors(const struct perf_session *session,
900 const struct perf_event_ops *ops) 936 const struct perf_tool *tool)
901{ 937{
902 if (ops->lost == perf_event__process_lost && 938 if (tool->lost == perf_event__process_lost &&
903 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) { 939 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
904 ui__warning("Processed %d events and lost %d chunks!\n\n" 940 ui__warning("Processed %d events and lost %d chunks!\n\n"
905 "Check IO/CPU overload!\n\n", 941 "Check IO/CPU overload!\n\n",
@@ -934,7 +970,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
934volatile int session_done; 970volatile int session_done;
935 971
936static int __perf_session__process_pipe_events(struct perf_session *self, 972static int __perf_session__process_pipe_events(struct perf_session *self,
937 struct perf_event_ops *ops) 973 struct perf_tool *tool)
938{ 974{
939 union perf_event event; 975 union perf_event event;
940 uint32_t size; 976 uint32_t size;
@@ -943,7 +979,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
943 int err; 979 int err;
944 void *p; 980 void *p;
945 981
946 perf_event_ops__fill_defaults(ops); 982 perf_tool__fill_defaults(tool);
947 983
948 head = 0; 984 head = 0;
949more: 985more:
@@ -979,8 +1015,7 @@ more:
979 } 1015 }
980 } 1016 }
981 1017
982 if (size == 0 || 1018 if ((skip = perf_session__process_event(self, &event, tool, head)) < 0) {
983 (skip = perf_session__process_event(self, &event, ops, head)) < 0) {
984 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1019 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
985 head, event.header.size, event.header.type); 1020 head, event.header.size, event.header.type);
986 /* 1021 /*
@@ -1003,7 +1038,7 @@ more:
1003done: 1038done:
1004 err = 0; 1039 err = 0;
1005out_err: 1040out_err:
1006 perf_session__warn_about_errors(self, ops); 1041 perf_session__warn_about_errors(self, tool);
1007 perf_session_free_sample_buffers(self); 1042 perf_session_free_sample_buffers(self);
1008 return err; 1043 return err;
1009} 1044}
@@ -1034,7 +1069,7 @@ fetch_mmaped_event(struct perf_session *session,
1034 1069
1035int __perf_session__process_events(struct perf_session *session, 1070int __perf_session__process_events(struct perf_session *session,
1036 u64 data_offset, u64 data_size, 1071 u64 data_offset, u64 data_size,
1037 u64 file_size, struct perf_event_ops *ops) 1072 u64 file_size, struct perf_tool *tool)
1038{ 1073{
1039 u64 head, page_offset, file_offset, file_pos, progress_next; 1074 u64 head, page_offset, file_offset, file_pos, progress_next;
1040 int err, mmap_prot, mmap_flags, map_idx = 0; 1075 int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1043,7 +1078,7 @@ int __perf_session__process_events(struct perf_session *session,
1043 union perf_event *event; 1078 union perf_event *event;
1044 uint32_t size; 1079 uint32_t size;
1045 1080
1046 perf_event_ops__fill_defaults(ops); 1081 perf_tool__fill_defaults(tool);
1047 1082
1048 page_size = sysconf(_SC_PAGESIZE); 1083 page_size = sysconf(_SC_PAGESIZE);
1049 1084
@@ -1098,7 +1133,7 @@ more:
1098 size = event->header.size; 1133 size = event->header.size;
1099 1134
1100 if (size == 0 || 1135 if (size == 0 ||
1101 perf_session__process_event(session, event, ops, file_pos) < 0) { 1136 perf_session__process_event(session, event, tool, file_pos) < 0) {
1102 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1137 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
1103 file_offset + head, event->header.size, 1138 file_offset + head, event->header.size,
1104 event->header.type); 1139 event->header.type);
@@ -1127,15 +1162,15 @@ more:
1127 err = 0; 1162 err = 0;
1128 /* do the final flush for ordered samples */ 1163 /* do the final flush for ordered samples */
1129 session->ordered_samples.next_flush = ULLONG_MAX; 1164 session->ordered_samples.next_flush = ULLONG_MAX;
1130 flush_sample_queue(session, ops); 1165 flush_sample_queue(session, tool);
1131out_err: 1166out_err:
1132 perf_session__warn_about_errors(session, ops); 1167 perf_session__warn_about_errors(session, tool);
1133 perf_session_free_sample_buffers(session); 1168 perf_session_free_sample_buffers(session);
1134 return err; 1169 return err;
1135} 1170}
1136 1171
1137int perf_session__process_events(struct perf_session *self, 1172int perf_session__process_events(struct perf_session *self,
1138 struct perf_event_ops *ops) 1173 struct perf_tool *tool)
1139{ 1174{
1140 int err; 1175 int err;
1141 1176
@@ -1146,9 +1181,9 @@ int perf_session__process_events(struct perf_session *self,
1146 err = __perf_session__process_events(self, 1181 err = __perf_session__process_events(self,
1147 self->header.data_offset, 1182 self->header.data_offset,
1148 self->header.data_size, 1183 self->header.data_size,
1149 self->size, ops); 1184 self->size, tool);
1150 else 1185 else
1151 err = __perf_session__process_pipe_events(self, ops); 1186 err = __perf_session__process_pipe_events(self, tool);
1152 1187
1153 return err; 1188 return err;
1154} 1189}
@@ -1163,9 +1198,8 @@ bool perf_session__has_traces(struct perf_session *self, const char *msg)
1163 return true; 1198 return true;
1164} 1199}
1165 1200
1166int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps, 1201int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1167 const char *symbol_name, 1202 const char *symbol_name, u64 addr)
1168 u64 addr)
1169{ 1203{
1170 char *bracket; 1204 char *bracket;
1171 enum map_type i; 1205 enum map_type i;
@@ -1224,6 +1258,27 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1224 return ret; 1258 return ret;
1225} 1259}
1226 1260
1261size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
1262{
1263 /*
1264 * FIXME: Here we have to actually print all the machines in this
1265 * session, not just the host...
1266 */
1267 return machine__fprintf(&session->host_machine, fp);
1268}
1269
1270void perf_session__remove_thread(struct perf_session *session,
1271 struct thread *th)
1272{
1273 /*
1274 * FIXME: This one makes no sense, we need to remove the thread from
1275 * the machine it belongs to, perf_session can have many machines, so
1276 * doing it always on ->host_machine is wrong. Fix when auditing all
1277 * the 'perf kvm' code.
1278 */
1279 machine__remove_thread(&session->host_machine, th);
1280}
1281
1227struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 1282struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1228 unsigned int type) 1283 unsigned int type)
1229{ 1284{
@@ -1236,17 +1291,16 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1236 return NULL; 1291 return NULL;
1237} 1292}
1238 1293
1239void perf_session__print_ip(union perf_event *event, 1294void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1240 struct perf_sample *sample, 1295 struct machine *machine, struct perf_evsel *evsel,
1241 struct perf_session *session, 1296 int print_sym, int print_dso)
1242 int print_sym, int print_dso)
1243{ 1297{
1244 struct addr_location al; 1298 struct addr_location al;
1245 const char *symname, *dsoname; 1299 const char *symname, *dsoname;
1246 struct callchain_cursor *cursor = &session->callchain_cursor; 1300 struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
1247 struct callchain_cursor_node *node; 1301 struct callchain_cursor_node *node;
1248 1302
1249 if (perf_event__preprocess_sample(event, session, &al, sample, 1303 if (perf_event__preprocess_sample(event, machine, &al, sample,
1250 NULL) < 0) { 1304 NULL) < 0) {
1251 error("problem processing %d event, skipping it.\n", 1305 error("problem processing %d event, skipping it.\n",
1252 event->header.type); 1306 event->header.type);
@@ -1255,7 +1309,7 @@ void perf_session__print_ip(union perf_event *event,
1255 1309
1256 if (symbol_conf.use_callchain && sample->callchain) { 1310 if (symbol_conf.use_callchain && sample->callchain) {
1257 1311
1258 if (perf_session__resolve_callchain(session, al.thread, 1312 if (machine__resolve_callchain(machine, evsel, al.thread,
1259 sample->callchain, NULL) != 0) { 1313 sample->callchain, NULL) != 0) {
1260 if (verbose) 1314 if (verbose)
1261 error("Failed to resolve callchain. Skipping\n"); 1315 error("Failed to resolve callchain. Skipping\n");
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6e393c98eb34..37bc38381fb6 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -30,9 +30,6 @@ struct perf_session {
30 struct perf_header header; 30 struct perf_header header;
31 unsigned long size; 31 unsigned long size;
32 unsigned long mmap_window; 32 unsigned long mmap_window;
33 struct rb_root threads;
34 struct list_head dead_threads;
35 struct thread *last_match;
36 struct machine host_machine; 33 struct machine host_machine;
37 struct rb_root machines; 34 struct rb_root machines;
38 struct perf_evlist *evlist; 35 struct perf_evlist *evlist;
@@ -53,65 +50,31 @@ struct perf_session {
53 int cwdlen; 50 int cwdlen;
54 char *cwd; 51 char *cwd;
55 struct ordered_samples ordered_samples; 52 struct ordered_samples ordered_samples;
56 struct callchain_cursor callchain_cursor; 53 char filename[1];
57 char filename[0];
58}; 54};
59 55
60struct perf_evsel; 56struct perf_tool;
61struct perf_event_ops;
62
63typedef int (*event_sample)(union perf_event *event, struct perf_sample *sample,
64 struct perf_evsel *evsel, struct perf_session *session);
65typedef int (*event_op)(union perf_event *self, struct perf_sample *sample,
66 struct perf_session *session);
67typedef int (*event_synth_op)(union perf_event *self,
68 struct perf_session *session);
69typedef int (*event_op2)(union perf_event *self, struct perf_session *session,
70 struct perf_event_ops *ops);
71
72struct perf_event_ops {
73 event_sample sample;
74 event_op mmap,
75 comm,
76 fork,
77 exit,
78 lost,
79 read,
80 throttle,
81 unthrottle;
82 event_synth_op attr,
83 event_type,
84 tracing_data,
85 build_id;
86 event_op2 finished_round;
87 bool ordered_samples;
88 bool ordering_requires_timestamps;
89};
90 57
91struct perf_session *perf_session__new(const char *filename, int mode, 58struct perf_session *perf_session__new(const char *filename, int mode,
92 bool force, bool repipe, 59 bool force, bool repipe,
93 struct perf_event_ops *ops); 60 struct perf_tool *tool);
94void perf_session__delete(struct perf_session *self); 61void perf_session__delete(struct perf_session *self);
95 62
96void perf_event_header__bswap(struct perf_event_header *self); 63void perf_event_header__bswap(struct perf_event_header *self);
97 64
98int __perf_session__process_events(struct perf_session *self, 65int __perf_session__process_events(struct perf_session *self,
99 u64 data_offset, u64 data_size, u64 size, 66 u64 data_offset, u64 data_size, u64 size,
100 struct perf_event_ops *ops); 67 struct perf_tool *tool);
101int perf_session__process_events(struct perf_session *self, 68int perf_session__process_events(struct perf_session *self,
102 struct perf_event_ops *event_ops); 69 struct perf_tool *tool);
103 70
104int perf_session__resolve_callchain(struct perf_session *self, 71int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
105 struct thread *thread, 72 struct thread *thread,
106 struct ip_callchain *chain, 73 struct ip_callchain *chain,
107 struct symbol **parent); 74 struct symbol **parent);
108 75
109bool perf_session__has_traces(struct perf_session *self, const char *msg); 76bool perf_session__has_traces(struct perf_session *self, const char *msg);
110 77
111int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
112 const char *symbol_name,
113 u64 addr);
114
115void mem_bswap_64(void *src, int byte_size); 78void mem_bswap_64(void *src, int byte_size);
116void perf_event__attr_swap(struct perf_event_attr *attr); 79void perf_event__attr_swap(struct perf_event_attr *attr);
117 80
@@ -144,12 +107,16 @@ struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t p
144 107
145static inline 108static inline
146void perf_session__process_machines(struct perf_session *self, 109void perf_session__process_machines(struct perf_session *self,
110 struct perf_tool *tool,
147 machine__process_t process) 111 machine__process_t process)
148{ 112{
149 process(&self->host_machine, self); 113 process(&self->host_machine, tool);
150 return machines__process(&self->machines, process, self); 114 return machines__process(&self->machines, process, tool);
151} 115}
152 116
117struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
118size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
119
153size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); 120size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
154 121
155size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, 122size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
@@ -167,13 +134,20 @@ static inline int perf_session__parse_sample(struct perf_session *session,
167 session->header.needs_swap); 134 session->header.needs_swap);
168} 135}
169 136
137static inline int perf_session__synthesize_sample(struct perf_session *session,
138 union perf_event *event,
139 const struct perf_sample *sample)
140{
141 return perf_event__synthesize_sample(event, session->sample_type,
142 sample, session->header.needs_swap);
143}
144
170struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 145struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
171 unsigned int type); 146 unsigned int type);
172 147
173void perf_session__print_ip(union perf_event *event, 148void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
174 struct perf_sample *sample, 149 struct machine *machine, struct perf_evsel *evsel,
175 struct perf_session *session, 150 int print_sym, int print_dso);
176 int print_sym, int print_dso);
177 151
178int perf_session__cpu_bitmap(struct perf_session *session, 152int perf_session__cpu_bitmap(struct perf_session *session,
179 const char *cpu_list, unsigned long *cpu_bitmap); 153 const char *cpu_list, unsigned long *cpu_bitmap);
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 95d370074928..36d4c5619575 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -27,7 +27,8 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP')
27perf = Extension('perf', 27perf = Extension('perf',
28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', 29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
30 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'], 30 'util/util.c', 'util/xyarray.c', 'util/cgroup.c',
31 'util/debugfs.c'],
31 include_dirs = ['util/include'], 32 include_dirs = ['util/include'],
32 extra_compile_args = cflags, 33 extra_compile_args = cflags,
33 ) 34 )
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 16da30d8d765..076c9d4e1ea4 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -33,6 +33,9 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
33 } 33 }
34 } 34 }
35 va_end(ap); 35 va_end(ap);
36
37 if (n >= (int)size)
38 return size - 1;
36 return n; 39 return n;
37} 40}
38 41
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 632b50c7bc26..0975438c3e72 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,4 +1,3 @@
1#define _GNU_SOURCE
2#include <ctype.h> 1#include <ctype.h>
3#include <dirent.h> 2#include <dirent.h>
4#include <errno.h> 3#include <errno.h>
@@ -1757,7 +1756,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
1757 struct stat st; 1756 struct stat st;
1758 1757
1759 /*sshfs might return bad dent->d_type, so we have to stat*/ 1758 /*sshfs might return bad dent->d_type, so we have to stat*/
1760 sprintf(path, "%s/%s", dir_name, dent->d_name); 1759 snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
1761 if (stat(path, &st)) 1760 if (stat(path, &st))
1762 continue; 1761 continue;
1763 1762
@@ -1766,8 +1765,6 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
1766 !strcmp(dent->d_name, "..")) 1765 !strcmp(dent->d_name, ".."))
1767 continue; 1766 continue;
1768 1767
1769 snprintf(path, sizeof(path), "%s/%s",
1770 dir_name, dent->d_name);
1771 ret = map_groups__set_modules_path_dir(mg, path); 1768 ret = map_groups__set_modules_path_dir(mg, path);
1772 if (ret < 0) 1769 if (ret < 0)
1773 goto out; 1770 goto out;
@@ -1788,9 +1785,6 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
1788 if (map == NULL) 1785 if (map == NULL)
1789 continue; 1786 continue;
1790 1787
1791 snprintf(path, sizeof(path), "%s/%s",
1792 dir_name, dent->d_name);
1793
1794 long_name = strdup(path); 1788 long_name = strdup(path);
1795 if (long_name == NULL) { 1789 if (long_name == NULL) {
1796 ret = -1; 1790 ret = -1;
@@ -2609,10 +2603,10 @@ int symbol__init(void)
2609 symbol_conf.initialized = true; 2603 symbol_conf.initialized = true;
2610 return 0; 2604 return 0;
2611 2605
2612out_free_dso_list:
2613 strlist__delete(symbol_conf.dso_list);
2614out_free_comm_list: 2606out_free_comm_list:
2615 strlist__delete(symbol_conf.comm_list); 2607 strlist__delete(symbol_conf.comm_list);
2608out_free_dso_list:
2609 strlist__delete(symbol_conf.dso_list);
2616 return -1; 2610 return -1;
2617} 2611}
2618 2612
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 29f8d742e92f..123c2e14353e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -68,6 +68,7 @@ struct strlist;
68 68
69struct symbol_conf { 69struct symbol_conf {
70 unsigned short priv_size; 70 unsigned short priv_size;
71 unsigned short nr_events;
71 bool try_vmlinux_path, 72 bool try_vmlinux_path,
72 use_modules, 73 use_modules,
73 sort_by_name, 74 sort_by_name,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index d5d3b22250f3..fb4b7ea6752f 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -61,7 +61,7 @@ static size_t thread__fprintf(struct thread *self, FILE *fp)
61 map_groups__fprintf(&self->mg, verbose, fp); 61 map_groups__fprintf(&self->mg, verbose, fp);
62} 62}
63 63
64struct thread *perf_session__findnew(struct perf_session *self, pid_t pid) 64struct thread *machine__findnew_thread(struct machine *self, pid_t pid)
65{ 65{
66 struct rb_node **p = &self->threads.rb_node; 66 struct rb_node **p = &self->threads.rb_node;
67 struct rb_node *parent = NULL; 67 struct rb_node *parent = NULL;
@@ -125,12 +125,12 @@ int thread__fork(struct thread *self, struct thread *parent)
125 return 0; 125 return 0;
126} 126}
127 127
128size_t perf_session__fprintf(struct perf_session *self, FILE *fp) 128size_t machine__fprintf(struct machine *machine, FILE *fp)
129{ 129{
130 size_t ret = 0; 130 size_t ret = 0;
131 struct rb_node *nd; 131 struct rb_node *nd;
132 132
133 for (nd = rb_first(&self->threads); nd; nd = rb_next(nd)) { 133 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
134 struct thread *pos = rb_entry(nd, struct thread, rb_node); 134 struct thread *pos = rb_entry(nd, struct thread, rb_node);
135 135
136 ret += thread__fprintf(pos, fp); 136 ret += thread__fprintf(pos, fp);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index e5f2401c1b5e..70c2c13ff679 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -18,16 +18,14 @@ struct thread {
18 int comm_len; 18 int comm_len;
19}; 19};
20 20
21struct perf_session; 21struct machine;
22 22
23void thread__delete(struct thread *self); 23void thread__delete(struct thread *self);
24 24
25int thread__set_comm(struct thread *self, const char *comm); 25int thread__set_comm(struct thread *self, const char *comm);
26int thread__comm_len(struct thread *self); 26int thread__comm_len(struct thread *self);
27struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
28void thread__insert_map(struct thread *self, struct map *map); 27void thread__insert_map(struct thread *self, struct map *map);
29int thread__fork(struct thread *self, struct thread *parent); 28int thread__fork(struct thread *self, struct thread *parent);
30size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
31 29
32static inline struct map *thread__find_map(struct thread *self, 30static inline struct map *thread__find_map(struct thread *self,
33 enum map_type type, u64 addr) 31 enum map_type type, u64 addr)
@@ -35,14 +33,12 @@ static inline struct map *thread__find_map(struct thread *self,
35 return self ? map_groups__find(&self->mg, type, addr) : NULL; 33 return self ? map_groups__find(&self->mg, type, addr) : NULL;
36} 34}
37 35
38void thread__find_addr_map(struct thread *self, 36void thread__find_addr_map(struct thread *thread, struct machine *machine,
39 struct perf_session *session, u8 cpumode, 37 u8 cpumode, enum map_type type, u64 addr,
40 enum map_type type, pid_t pid, u64 addr,
41 struct addr_location *al); 38 struct addr_location *al);
42 39
43void thread__find_addr_location(struct thread *self, 40void thread__find_addr_location(struct thread *thread, struct machine *machine,
44 struct perf_session *session, u8 cpumode, 41 u8 cpumode, enum map_type type, u64 addr,
45 enum map_type type, pid_t pid, u64 addr,
46 struct addr_location *al, 42 struct addr_location *al,
47 symbol_filter_t filter); 43 symbol_filter_t filter);
48#endif /* __PERF_THREAD_H */ 44#endif /* __PERF_THREAD_H */
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
new file mode 100644
index 000000000000..b0e1aadba8d5
--- /dev/null
+++ b/tools/perf/util/tool.h
@@ -0,0 +1,50 @@
1#ifndef __PERF_TOOL_H
2#define __PERF_TOOL_H
3
4#include <stdbool.h>
5
6struct perf_session;
7union perf_event;
8struct perf_evlist;
9struct perf_evsel;
10struct perf_sample;
11struct perf_tool;
12struct machine;
13
14typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
15 struct perf_sample *sample,
16 struct perf_evsel *evsel, struct machine *machine);
17
18typedef int (*event_op)(struct perf_tool *tool, union perf_event *event,
19 struct perf_sample *sample, struct machine *machine);
20
21typedef int (*event_attr_op)(union perf_event *event,
22 struct perf_evlist **pevlist);
23typedef int (*event_simple_op)(struct perf_tool *tool, union perf_event *event);
24
25typedef int (*event_synth_op)(union perf_event *event,
26 struct perf_session *session);
27
28typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
29 struct perf_session *session);
30
31struct perf_tool {
32 event_sample sample,
33 read;
34 event_op mmap,
35 comm,
36 fork,
37 exit,
38 lost,
39 throttle,
40 unthrottle;
41 event_attr_op attr;
42 event_synth_op tracing_data;
43 event_simple_op event_type;
44 event_op2 finished_round,
45 build_id;
46 bool ordered_samples;
47 bool ordering_requires_timestamps;
48};
49
50#endif /* __PERF_TOOL_H */
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 399650967958..f2eab81435ae 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -1,15 +1,17 @@
1#ifndef __PERF_TOP_H 1#ifndef __PERF_TOP_H
2#define __PERF_TOP_H 1 2#define __PERF_TOP_H 1
3 3
4#include "tool.h"
4#include "types.h" 5#include "types.h"
5#include "../perf.h"
6#include <stddef.h> 6#include <stddef.h>
7#include <stdbool.h>
7 8
8struct perf_evlist; 9struct perf_evlist;
9struct perf_evsel; 10struct perf_evsel;
10struct perf_session; 11struct perf_session;
11 12
12struct perf_top { 13struct perf_top {
14 struct perf_tool tool;
13 struct perf_evlist *evlist; 15 struct perf_evlist *evlist;
14 /* 16 /*
15 * Symbols will be added here in perf_event__process_sample and will 17 * Symbols will be added here in perf_event__process_sample and will
@@ -23,10 +25,27 @@ struct perf_top {
23 int freq; 25 int freq;
24 pid_t target_pid, target_tid; 26 pid_t target_pid, target_tid;
25 bool hide_kernel_symbols, hide_user_symbols, zero; 27 bool hide_kernel_symbols, hide_user_symbols, zero;
28 bool system_wide;
29 bool use_tui, use_stdio;
30 bool sort_has_symbols;
31 bool dont_use_callchains;
32 bool kptr_restrict_warned;
33 bool vmlinux_warned;
34 bool inherit;
35 bool group;
36 bool sample_id_all_avail;
37 bool exclude_guest_missing;
38 bool dump_symtab;
26 const char *cpu_list; 39 const char *cpu_list;
27 struct hist_entry *sym_filter_entry; 40 struct hist_entry *sym_filter_entry;
28 struct perf_evsel *sym_evsel; 41 struct perf_evsel *sym_evsel;
29 struct perf_session *session; 42 struct perf_session *session;
43 struct winsize winsize;
44 unsigned int mmap_pages;
45 int default_interval;
46 int realtime_prio;
47 int sym_pcnt_filter;
48 const char *sym_filter;
30}; 49};
31 50
32size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 51size_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 d2655f08bcc0..fc22cf5c605f 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -18,7 +18,7 @@
18 * 18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */ 20 */
21#define _GNU_SOURCE 21#include "util.h"
22#include <dirent.h> 22#include <dirent.h>
23#include <mntent.h> 23#include <mntent.h>
24#include <stdio.h> 24#include <stdio.h>
@@ -31,7 +31,6 @@
31#include <pthread.h> 31#include <pthread.h>
32#include <fcntl.h> 32#include <fcntl.h>
33#include <unistd.h> 33#include <unistd.h>
34#include <ctype.h>
35#include <errno.h> 34#include <errno.h>
36#include <stdbool.h> 35#include <stdbool.h>
37#include <linux/list.h> 36#include <linux/list.h>
@@ -44,10 +43,6 @@
44 43
45#define VERSION "0.5" 44#define VERSION "0.5"
46 45
47#define _STR(x) #x
48#define STR(x) _STR(x)
49#define MAX_PATH 256
50
51#define TRACE_CTRL "tracing_on" 46#define TRACE_CTRL "tracing_on"
52#define TRACE "trace" 47#define TRACE "trace"
53#define AVAILABLE "available_tracers" 48#define AVAILABLE "available_tracers"
@@ -73,26 +68,6 @@ struct events {
73}; 68};
74 69
75 70
76
77static void die(const char *fmt, ...)
78{
79 va_list ap;
80 int ret = errno;
81
82 if (errno)
83 perror("perf");
84 else
85 ret = -1;
86
87 va_start(ap, fmt);
88 fprintf(stderr, " ");
89 vfprintf(stderr, fmt, ap);
90 va_end(ap);
91
92 fprintf(stderr, "\n");
93 exit(ret);
94}
95
96void *malloc_or_die(unsigned int size) 71void *malloc_or_die(unsigned int size)
97{ 72{
98 void *data; 73 void *data;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 6c164dc9ee95..1a8d4dc4f386 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -21,14 +21,13 @@
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> 28#include <ctype.h>
29#include <errno.h> 29#include <errno.h>
30 30
31#undef _GNU_SOURCE
32#include "../perf.h" 31#include "../perf.h"
33#include "util.h" 32#include "util.h"
34#include "trace-event.h" 33#include "trace-event.h"
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index c9dcbec7d800..a3fdf55f317b 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -39,7 +39,7 @@ static int stop_script_unsupported(void)
39static void process_event_unsupported(union perf_event *event __unused, 39static void process_event_unsupported(union perf_event *event __unused,
40 struct perf_sample *sample __unused, 40 struct perf_sample *sample __unused,
41 struct perf_evsel *evsel __unused, 41 struct perf_evsel *evsel __unused,
42 struct perf_session *session __unused, 42 struct machine *machine __unused,
43 struct thread *thread __unused) 43 struct thread *thread __unused)
44{ 44{
45} 45}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index a84100817649..58ae14c5baac 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,7 +3,11 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "parse-events.h" 5#include "parse-events.h"
6#include "session.h" 6
7struct machine;
8struct perf_sample;
9union perf_event;
10struct thread;
7 11
8#define __unused __attribute__((unused)) 12#define __unused __attribute__((unused))
9 13
@@ -292,7 +296,7 @@ struct scripting_ops {
292 void (*process_event) (union perf_event *event, 296 void (*process_event) (union perf_event *event,
293 struct perf_sample *sample, 297 struct perf_sample *sample,
294 struct perf_evsel *evsel, 298 struct perf_evsel *evsel,
295 struct perf_session *session, 299 struct machine *machine,
296 struct thread *thread); 300 struct thread *thread);
297 int (*generate_script) (const char *outfile); 301 int (*generate_script) (const char *outfile);
298}; 302};
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 0575905d1205..295a9c93f945 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -224,7 +224,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)
224} 224}
225 225
226static int annotate_browser__run(struct annotate_browser *self, int evidx, 226static int annotate_browser__run(struct annotate_browser *self, int evidx,
227 int nr_events, void(*timer)(void *arg), 227 void(*timer)(void *arg),
228 void *arg, int delay_secs) 228 void *arg, int delay_secs)
229{ 229{
230 struct rb_node *nd = NULL; 230 struct rb_node *nd = NULL;
@@ -328,8 +328,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
328 notes = symbol__annotation(target); 328 notes = symbol__annotation(target);
329 pthread_mutex_lock(&notes->lock); 329 pthread_mutex_lock(&notes->lock);
330 330
331 if (notes->src == NULL && 331 if (notes->src == NULL && symbol__alloc_hist(target) < 0) {
332 symbol__alloc_hist(target, nr_events) < 0) {
333 pthread_mutex_unlock(&notes->lock); 332 pthread_mutex_unlock(&notes->lock);
334 ui__warning("Not enough memory for annotating '%s' symbol!\n", 333 ui__warning("Not enough memory for annotating '%s' symbol!\n",
335 target->name); 334 target->name);
@@ -337,7 +336,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
337 } 336 }
338 337
339 pthread_mutex_unlock(&notes->lock); 338 pthread_mutex_unlock(&notes->lock);
340 symbol__tui_annotate(target, ms->map, evidx, nr_events, 339 symbol__tui_annotate(target, ms->map, evidx,
341 timer, arg, delay_secs); 340 timer, arg, delay_secs);
342 } 341 }
343 continue; 342 continue;
@@ -358,15 +357,15 @@ out:
358 return key; 357 return key;
359} 358}
360 359
361int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, 360int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
362 void(*timer)(void *arg), void *arg, int delay_secs) 361 void(*timer)(void *arg), void *arg, int delay_secs)
363{ 362{
364 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, nr_events, 363 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx,
365 timer, arg, delay_secs); 364 timer, arg, delay_secs);
366} 365}
367 366
368int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 367int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
369 int nr_events, void(*timer)(void *arg), void *arg, 368 void(*timer)(void *arg), void *arg,
370 int delay_secs) 369 int delay_secs)
371{ 370{
372 struct objdump_line *pos, *n; 371 struct objdump_line *pos, *n;
@@ -419,8 +418,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
419 browser.b.nr_entries = browser.nr_entries; 418 browser.b.nr_entries = browser.nr_entries;
420 browser.b.entries = &notes->src->source, 419 browser.b.entries = &notes->src->source,
421 browser.b.width += 18; /* Percentage */ 420 browser.b.width += 18; /* Percentage */
422 ret = annotate_browser__run(&browser, evidx, nr_events, 421 ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs);
423 timer, arg, delay_secs);
424 list_for_each_entry_safe(pos, n, &notes->src->source, node) { 422 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
425 list_del(&pos->node); 423 list_del(&pos->node);
426 objdump_line__free(pos); 424 objdump_line__free(pos);
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index d0c94b459685..bb9197c9c4a4 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>
@@ -839,15 +837,15 @@ 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]; 837 unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];
840 838
841 nr_events = convert_unit(nr_events, &unit); 839 nr_events = convert_unit(nr_events, &unit);
842 printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name); 840 printed = scnprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name);
843 841
844 if (thread) 842 if (thread)
845 printed += snprintf(bf + printed, size - printed, 843 printed += scnprintf(bf + printed, size - printed,
846 ", Thread: %s(%d)", 844 ", Thread: %s(%d)",
847 (thread->comm_set ? thread->comm : ""), 845 (thread->comm_set ? thread->comm : ""),
848 thread->pid); 846 thread->pid);
849 if (dso) 847 if (dso)
850 printed += snprintf(bf + printed, size - printed, 848 printed += scnprintf(bf + printed, size - printed,
851 ", DSO: %s", dso->short_name); 849 ", DSO: %s", dso->short_name);
852 return printed; 850 return printed;
853} 851}
@@ -1020,7 +1018,7 @@ do_annotate:
1020 * Don't let this be freed, say, by hists__decay_entry. 1018 * Don't let this be freed, say, by hists__decay_entry.
1021 */ 1019 */
1022 he->used = true; 1020 he->used = true;
1023 err = hist_entry__tui_annotate(he, evsel->idx, nr_events, 1021 err = hist_entry__tui_annotate(he, evsel->idx,
1024 timer, arg, delay_secs); 1022 timer, arg, delay_secs);
1025 he->used = false; 1023 he->used = false;
1026 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); 1024 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
@@ -1097,7 +1095,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1097 HE_COLORSET_NORMAL); 1095 HE_COLORSET_NORMAL);
1098 1096
1099 nr_events = convert_unit(nr_events, &unit); 1097 nr_events = convert_unit(nr_events, &unit);
1100 printed = snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events, 1098 printed = scnprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
1101 unit, unit == ' ' ? "" : " ", ev_name); 1099 unit, unit == ' ' ? "" : " ", ev_name);
1102 slsmg_printf("%s", bf); 1100 slsmg_printf("%s", bf);
1103 1101
@@ -1107,8 +1105,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1107 if (!current_entry) 1105 if (!current_entry)
1108 ui_browser__set_color(browser, HE_COLORSET_TOP); 1106 ui_browser__set_color(browser, HE_COLORSET_TOP);
1109 nr_events = convert_unit(nr_events, &unit); 1107 nr_events = convert_unit(nr_events, &unit);
1110 snprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!", nr_events, 1108 printed += scnprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!",
1111 unit, unit == ' ' ? "" : " "); 1109 nr_events, unit, unit == ' ' ? "" : " ");
1112 warn = bf; 1110 warn = bf;
1113 } 1111 }
1114 1112
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/progress.c b/tools/perf/util/ui/progress.c
index 295e366b6311..13aa64e50e11 100644
--- a/tools/perf/util/ui/progress.c
+++ b/tools/perf/util/ui/progress.c
@@ -14,6 +14,9 @@ void ui_progress__update(u64 curr, u64 total, const char *title)
14 if (use_browser <= 0) 14 if (use_browser <= 0)
15 return; 15 return;
16 16
17 if (total == 0)
18 return;
19
17 ui__refresh_dimensions(true); 20 ui__refresh_dimensions(true);
18 pthread_mutex_lock(&ui__lock); 21 pthread_mutex_lock(&ui__lock);
19 y = SLtt_Screen_Rows / 2 - 2; 22 y = SLtt_Screen_Rows / 2 - 2;
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index e16bf9a707e8..d76d1c0ff98f 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -1,5 +1,8 @@
1/* 1/*
2 * GIT - The information manager from hell 2 * usage.c
3 *
4 * Various reporting routines.
5 * Originally copied from GIT source.
3 * 6 *
4 * Copyright (C) Linus Torvalds, 2005 7 * Copyright (C) Linus Torvalds, 2005
5 */ 8 */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 5b3ea49aa63e..fb25d1329218 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,6 +1,21 @@
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}
18
4int mkdir_p(char *path, mode_t mode) 19int mkdir_p(char *path, mode_t mode)
5{ 20{
6 struct stat st; 21 struct stat st;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 0128906bac88..ecf9898169c8 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
@@ -242,7 +241,22 @@ int strtailcmp(const char *s1, const char *s2);
242unsigned long convert_unit(unsigned long value, char *unit); 241unsigned long convert_unit(unsigned long value, char *unit);
243int readn(int fd, void *buf, size_t size); 242int readn(int fd, void *buf, size_t size);
244 243
244struct perf_event_attr;
245
246void event_attr_init(struct perf_event_attr *attr);
247
245#define _STR(x) #x 248#define _STR(x) #x
246#define STR(x) _STR(x) 249#define STR(x) _STR(x)
247 250
251/*
252 * Determine whether some value is a power of two, where zero is
253 * *not* considered a power of two.
254 */
255
256static inline __attribute__((const))
257bool is_power_of_2(unsigned long n)
258{
259 return (n != 0 && ((n & (n - 1)) == 0));
260}
261
248#endif 262#endif
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index bdd33470b235..697c8b4e59cc 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -32,6 +32,7 @@ void perf_read_values_destroy(struct perf_read_values *values)
32 32
33 for (i = 0; i < values->threads; i++) 33 for (i = 0; i < values->threads; i++)
34 free(values->value[i]); 34 free(values->value[i]);
35 free(values->value);
35 free(values->pid); 36 free(values->pid);
36 free(values->tid); 37 free(values->tid);
37 free(values->counterrawid); 38 free(values->counterrawid);
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index ff75125deed0..555c69a5592a 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -38,8 +38,8 @@ displays the statistics gathered since it was forked.
38.PP 38.PP
39.SH FIELD DESCRIPTIONS 39.SH FIELD DESCRIPTIONS
40.nf 40.nf
41\fBpkg\fP processor package number. 41\fBpk\fP processor package number.
42\fBcore\fP processor core number. 42\fBcr\fP processor core number.
43\fBCPU\fP Linux CPU (logical processor) number. 43\fBCPU\fP Linux CPU (logical processor) number.
44\fB%c0\fP percent of the interval that the CPU retired instructions. 44\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. 45\fBGHz\fP average clock rate while the CPU was in c0 state.
@@ -58,7 +58,7 @@ Subsequent rows show per-CPU statistics.
58 58
59.nf 59.nf
60[root@x980]# ./turbostat 60[root@x980]# ./turbostat
61core CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 61cr 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 62 0.04 1.62 3.38 0.11 0.00 99.85 0.00 95.07
63 0 0 0.04 1.62 3.38 0.06 0.00 99.90 0.00 95.07 63 0 0 0.04 1.62 3.38 0.06 0.00 99.90 0.00 95.07
64 0 6 0.02 1.62 3.38 0.08 0.00 99.90 0.00 95.07 64 0 6 0.02 1.62 3.38 0.08 0.00 99.90 0.00 95.07
@@ -102,7 +102,7 @@ until ^C while the other CPUs are mostly idle:
102.nf 102.nf
103[root@x980 lenb]# ./turbostat cat /dev/zero > /dev/null 103[root@x980 lenb]# ./turbostat cat /dev/zero > /dev/null
104 104
105^Ccore CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 105^Ccr 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 106 8.49 3.63 3.38 16.23 0.66 74.63 0.00 0.00
107 0 0 1.22 3.62 3.38 32.18 0.00 66.60 0.00 0.00 107 0 0 1.22 3.62 3.38 32.18 0.00 66.60 0.00 0.00
108 0 6 0.40 3.61 3.38 33.00 0.00 66.60 0.00 0.00 108 0 6 0.40 3.61 3.38 33.00 0.00 66.60 0.00 0.00
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 3c6f7808efae..310d3dd5e547 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -811,6 +811,8 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
811 case 0x2C: /* Westmere EP - Gulftown */ 811 case 0x2C: /* Westmere EP - Gulftown */
812 case 0x2A: /* SNB */ 812 case 0x2A: /* SNB */
813 case 0x2D: /* SNB Xeon */ 813 case 0x2D: /* SNB Xeon */
814 case 0x3A: /* IVB */
815 case 0x3D: /* IVB Xeon */
814 return 1; 816 return 1;
815 case 0x2E: /* Nehalem-EX Xeon - Beckton */ 817 case 0x2E: /* Nehalem-EX Xeon - Beckton */
816 case 0x2F: /* Westmere-EX Xeon - Eagleton */ 818 case 0x2F: /* Westmere-EX Xeon - Eagleton */
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..9507c4b251a8 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -18,40 +18,50 @@ $| = 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 "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot",
51$default{"STOP_AFTER_SUCCESS"} = 10; 50 "STOP_AFTER_SUCCESS" => 10,
52$default{"STOP_AFTER_FAILURE"} = 60; 51 "STOP_AFTER_FAILURE" => 60,
53$default{"STOP_TEST_AFTER"} = 600; 52 "STOP_TEST_AFTER" => 600,
54$default{"LOCALVERSION"} = "-test"; 53
54# required, and we will ask users if they don't have them but we keep the default
55# value something that is common.
56 "REBOOT_TYPE" => "grub",
57 "LOCALVERSION" => "-test",
58 "SSH_USER" => "root",
59 "BUILD_TARGET" => "arch/x86/boot/bzImage",
60 "TARGET_IMAGE" => "/boot/vmlinuz-test",
61
62 "LOG_FILE" => undef,
63 "IGNORE_UNUSED" => 0,
64);
55 65
56my $ktest_config; 66my $ktest_config;
57my $version; 67my $version;
@@ -73,6 +83,8 @@ my $reboot_script;
73my $power_cycle; 83my $power_cycle;
74my $reboot; 84my $reboot;
75my $reboot_on_error; 85my $reboot_on_error;
86my $switch_to_good;
87my $switch_to_test;
76my $poweroff_on_error; 88my $poweroff_on_error;
77my $die_on_failure; 89my $die_on_failure;
78my $powercycle_after_reboot; 90my $powercycle_after_reboot;
@@ -92,17 +104,24 @@ my $start_minconfig;
92my $start_minconfig_defined; 104my $start_minconfig_defined;
93my $output_minconfig; 105my $output_minconfig;
94my $ignore_config; 106my $ignore_config;
107my $ignore_errors;
95my $addconfig; 108my $addconfig;
96my $in_bisect = 0; 109my $in_bisect = 0;
97my $bisect_bad = ""; 110my $bisect_bad_commit = "";
98my $reverse_bisect; 111my $reverse_bisect;
99my $bisect_manual; 112my $bisect_manual;
100my $bisect_skip; 113my $bisect_skip;
101my $config_bisect_good; 114my $config_bisect_good;
115my $bisect_ret_good;
116my $bisect_ret_bad;
117my $bisect_ret_skip;
118my $bisect_ret_abort;
119my $bisect_ret_default;
102my $in_patchcheck = 0; 120my $in_patchcheck = 0;
103my $run_test; 121my $run_test;
104my $redirect; 122my $redirect;
105my $buildlog; 123my $buildlog;
124my $testlog;
106my $dmesg; 125my $dmesg;
107my $monitor_fp; 126my $monitor_fp;
108my $monitor_pid; 127my $monitor_pid;
@@ -112,6 +131,7 @@ my $bisect_sleep_time;
112my $patchcheck_sleep_time; 131my $patchcheck_sleep_time;
113my $ignore_warnings; 132my $ignore_warnings;
114my $store_failures; 133my $store_failures;
134my $store_successes;
115my $test_name; 135my $test_name;
116my $timeout; 136my $timeout;
117my $booted_timeout; 137my $booted_timeout;
@@ -124,10 +144,34 @@ my $stop_after_failure;
124my $stop_test_after; 144my $stop_test_after;
125my $build_target; 145my $build_target;
126my $target_image; 146my $target_image;
147my $checkout;
127my $localversion; 148my $localversion;
128my $iteration = 0; 149my $iteration = 0;
129my $successes = 0; 150my $successes = 0;
130 151
152my $bisect_good;
153my $bisect_bad;
154my $bisect_type;
155my $bisect_start;
156my $bisect_replay;
157my $bisect_files;
158my $bisect_reverse;
159my $bisect_check;
160
161my $config_bisect;
162my $config_bisect_type;
163
164my $patchcheck_type;
165my $patchcheck_start;
166my $patchcheck_end;
167
168# set when a test is something other that just building or install
169# which would require more options.
170my $buildonly = 1;
171
172# set when creating a new config
173my $newconfig = 0;
174
131my %entered_configs; 175my %entered_configs;
132my %config_help; 176my %config_help;
133my %variable; 177my %variable;
@@ -136,11 +180,99 @@ my %force_config;
136# do not force reboots on config problems 180# do not force reboots on config problems
137my $no_reboot = 1; 181my $no_reboot = 1;
138 182
183my %option_map = (
184 "MACHINE" => \$machine,
185 "SSH_USER" => \$ssh_user,
186 "TMP_DIR" => \$tmpdir,
187 "OUTPUT_DIR" => \$outputdir,
188 "BUILD_DIR" => \$builddir,
189 "TEST_TYPE" => \$test_type,
190 "BUILD_TYPE" => \$build_type,
191 "BUILD_OPTIONS" => \$build_options,
192 "PRE_BUILD" => \$pre_build,
193 "POST_BUILD" => \$post_build,
194 "PRE_BUILD_DIE" => \$pre_build_die,
195 "POST_BUILD_DIE" => \$post_build_die,
196 "POWER_CYCLE" => \$power_cycle,
197 "REBOOT" => \$reboot,
198 "BUILD_NOCLEAN" => \$noclean,
199 "MIN_CONFIG" => \$minconfig,
200 "OUTPUT_MIN_CONFIG" => \$output_minconfig,
201 "START_MIN_CONFIG" => \$start_minconfig,
202 "IGNORE_CONFIG" => \$ignore_config,
203 "TEST" => \$run_test,
204 "ADD_CONFIG" => \$addconfig,
205 "REBOOT_TYPE" => \$reboot_type,
206 "GRUB_MENU" => \$grub_menu,
207 "POST_INSTALL" => \$post_install,
208 "NO_INSTALL" => \$no_install,
209 "REBOOT_SCRIPT" => \$reboot_script,
210 "REBOOT_ON_ERROR" => \$reboot_on_error,
211 "SWITCH_TO_GOOD" => \$switch_to_good,
212 "SWITCH_TO_TEST" => \$switch_to_test,
213 "POWEROFF_ON_ERROR" => \$poweroff_on_error,
214 "DIE_ON_FAILURE" => \$die_on_failure,
215 "POWER_OFF" => \$power_off,
216 "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot,
217 "POWEROFF_AFTER_HALT" => \$poweroff_after_halt,
218 "SLEEP_TIME" => \$sleep_time,
219 "BISECT_SLEEP_TIME" => \$bisect_sleep_time,
220 "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time,
221 "IGNORE_WARNINGS" => \$ignore_warnings,
222 "IGNORE_ERRORS" => \$ignore_errors,
223 "BISECT_MANUAL" => \$bisect_manual,
224 "BISECT_SKIP" => \$bisect_skip,
225 "CONFIG_BISECT_GOOD" => \$config_bisect_good,
226 "BISECT_RET_GOOD" => \$bisect_ret_good,
227 "BISECT_RET_BAD" => \$bisect_ret_bad,
228 "BISECT_RET_SKIP" => \$bisect_ret_skip,
229 "BISECT_RET_ABORT" => \$bisect_ret_abort,
230 "BISECT_RET_DEFAULT" => \$bisect_ret_default,
231 "STORE_FAILURES" => \$store_failures,
232 "STORE_SUCCESSES" => \$store_successes,
233 "TEST_NAME" => \$test_name,
234 "TIMEOUT" => \$timeout,
235 "BOOTED_TIMEOUT" => \$booted_timeout,
236 "CONSOLE" => \$console,
237 "DETECT_TRIPLE_FAULT" => \$detect_triplefault,
238 "SUCCESS_LINE" => \$success_line,
239 "REBOOT_SUCCESS_LINE" => \$reboot_success_line,
240 "STOP_AFTER_SUCCESS" => \$stop_after_success,
241 "STOP_AFTER_FAILURE" => \$stop_after_failure,
242 "STOP_TEST_AFTER" => \$stop_test_after,
243 "BUILD_TARGET" => \$build_target,
244 "SSH_EXEC" => \$ssh_exec,
245 "SCP_TO_TARGET" => \$scp_to_target,
246 "CHECKOUT" => \$checkout,
247 "TARGET_IMAGE" => \$target_image,
248 "LOCALVERSION" => \$localversion,
249
250 "BISECT_GOOD" => \$bisect_good,
251 "BISECT_BAD" => \$bisect_bad,
252 "BISECT_TYPE" => \$bisect_type,
253 "BISECT_START" => \$bisect_start,
254 "BISECT_REPLAY" => \$bisect_replay,
255 "BISECT_FILES" => \$bisect_files,
256 "BISECT_REVERSE" => \$bisect_reverse,
257 "BISECT_CHECK" => \$bisect_check,
258
259 "CONFIG_BISECT" => \$config_bisect,
260 "CONFIG_BISECT_TYPE" => \$config_bisect_type,
261
262 "PATCHCHECK_TYPE" => \$patchcheck_type,
263 "PATCHCHECK_START" => \$patchcheck_start,
264 "PATCHCHECK_END" => \$patchcheck_end,
265);
266
267# Options may be used by other options, record them.
268my %used_options;
269
139# default variables that can be used 270# default variables that can be used
140chomp ($variable{"PWD"} = `pwd`); 271chomp ($variable{"PWD"} = `pwd`);
141 272
142$config_help{"MACHINE"} = << "EOF" 273$config_help{"MACHINE"} = << "EOF"
143 The machine hostname that you will test. 274 The machine hostname that you will test.
275 For build only tests, it is still needed to differentiate log files.
144EOF 276EOF
145 ; 277 ;
146$config_help{"SSH_USER"} = << "EOF" 278$config_help{"SSH_USER"} = << "EOF"
@@ -150,11 +282,15 @@ EOF
150 ; 282 ;
151$config_help{"BUILD_DIR"} = << "EOF" 283$config_help{"BUILD_DIR"} = << "EOF"
152 The directory that contains the Linux source code (full path). 284 The directory that contains the Linux source code (full path).
285 You can use \${PWD} that will be the path where ktest.pl is run, or use
286 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
153EOF 287EOF
154 ; 288 ;
155$config_help{"OUTPUT_DIR"} = << "EOF" 289$config_help{"OUTPUT_DIR"} = << "EOF"
156 The directory that the objects will be built (full path). 290 The directory that the objects will be built (full path).
157 (can not be same as BUILD_DIR) 291 (can not be same as BUILD_DIR)
292 You can use \${PWD} that will be the path where ktest.pl is run, or use
293 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
158EOF 294EOF
159 ; 295 ;
160$config_help{"BUILD_TARGET"} = << "EOF" 296$config_help{"BUILD_TARGET"} = << "EOF"
@@ -162,6 +298,11 @@ $config_help{"BUILD_TARGET"} = << "EOF"
162 (relative to OUTPUT_DIR) 298 (relative to OUTPUT_DIR)
163EOF 299EOF
164 ; 300 ;
301$config_help{"BUILD_OPTIONS"} = << "EOF"
302 Options to add to \"make\" when building.
303 i.e. -j20
304EOF
305 ;
165$config_help{"TARGET_IMAGE"} = << "EOF" 306$config_help{"TARGET_IMAGE"} = << "EOF"
166 The place to put your image on the test machine. 307 The place to put your image on the test machine.
167EOF 308EOF
@@ -227,20 +368,36 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF"
227EOF 368EOF
228 ; 369 ;
229 370
230sub read_yn { 371sub read_prompt {
231 my ($prompt) = @_; 372 my ($cancel, $prompt) = @_;
232 373
233 my $ans; 374 my $ans;
234 375
235 for (;;) { 376 for (;;) {
236 print "$prompt [Y/n] "; 377 if ($cancel) {
378 print "$prompt [y/n/C] ";
379 } else {
380 print "$prompt [Y/n] ";
381 }
237 $ans = <STDIN>; 382 $ans = <STDIN>;
238 chomp $ans; 383 chomp $ans;
239 if ($ans =~ /^\s*$/) { 384 if ($ans =~ /^\s*$/) {
240 $ans = "y"; 385 if ($cancel) {
386 $ans = "c";
387 } else {
388 $ans = "y";
389 }
241 } 390 }
242 last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 391 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
243 print "Please answer either 'y' or 'n'.\n"; 392 if ($cancel) {
393 last if ($ans =~ /^c$/i);
394 print "Please answer either 'y', 'n' or 'c'.\n";
395 } else {
396 print "Please answer either 'y' or 'n'.\n";
397 }
398 }
399 if ($ans =~ /^c/i) {
400 exit;
244 } 401 }
245 if ($ans !~ /^y$/i) { 402 if ($ans !~ /^y$/i) {
246 return 0; 403 return 0;
@@ -248,6 +405,18 @@ sub read_yn {
248 return 1; 405 return 1;
249} 406}
250 407
408sub read_yn {
409 my ($prompt) = @_;
410
411 return read_prompt 0, $prompt;
412}
413
414sub read_ync {
415 my ($prompt) = @_;
416
417 return read_prompt 1, $prompt;
418}
419
251sub get_ktest_config { 420sub get_ktest_config {
252 my ($config) = @_; 421 my ($config) = @_;
253 my $ans; 422 my $ans;
@@ -261,7 +430,7 @@ sub get_ktest_config {
261 430
262 for (;;) { 431 for (;;) {
263 print "$config = "; 432 print "$config = ";
264 if (defined($default{$config})) { 433 if (defined($default{$config}) && length($default{$config})) {
265 print "\[$default{$config}\] "; 434 print "\[$default{$config}\] ";
266 } 435 }
267 $ans = <STDIN>; 436 $ans = <STDIN>;
@@ -274,22 +443,37 @@ sub get_ktest_config {
274 next; 443 next;
275 } 444 }
276 } 445 }
277 $entered_configs{$config} = process_variables($ans); 446 $entered_configs{$config} = ${ans};
278 last; 447 last;
279 } 448 }
280} 449}
281 450
282sub get_ktest_configs { 451sub get_ktest_configs {
283 get_ktest_config("MACHINE"); 452 get_ktest_config("MACHINE");
284 get_ktest_config("SSH_USER");
285 get_ktest_config("BUILD_DIR"); 453 get_ktest_config("BUILD_DIR");
286 get_ktest_config("OUTPUT_DIR"); 454 get_ktest_config("OUTPUT_DIR");
287 get_ktest_config("BUILD_TARGET"); 455
288 get_ktest_config("TARGET_IMAGE"); 456 if ($newconfig) {
289 get_ktest_config("POWER_CYCLE"); 457 get_ktest_config("BUILD_OPTIONS");
290 get_ktest_config("CONSOLE"); 458 }
459
460 # options required for other than just building a kernel
461 if (!$buildonly) {
462 get_ktest_config("POWER_CYCLE");
463 get_ktest_config("CONSOLE");
464 }
465
466 # options required for install and more
467 if ($buildonly != 1) {
468 get_ktest_config("SSH_USER");
469 get_ktest_config("BUILD_TARGET");
470 get_ktest_config("TARGET_IMAGE");
471 }
472
291 get_ktest_config("LOCALVERSION"); 473 get_ktest_config("LOCALVERSION");
292 474
475 return if ($buildonly);
476
293 my $rtype = $opt{"REBOOT_TYPE"}; 477 my $rtype = $opt{"REBOOT_TYPE"};
294 478
295 if (!defined($rtype)) { 479 if (!defined($rtype)) {
@@ -303,8 +487,6 @@ sub get_ktest_configs {
303 487
304 if ($rtype eq "grub") { 488 if ($rtype eq "grub") {
305 get_ktest_config("GRUB_MENU"); 489 get_ktest_config("GRUB_MENU");
306 } else {
307 get_ktest_config("REBOOT_SCRIPT");
308 } 490 }
309} 491}
310 492
@@ -334,6 +516,10 @@ sub process_variables {
334 } else { 516 } else {
335 # put back the origin piece. 517 # put back the origin piece.
336 $retval = "$retval\$\{$var\}"; 518 $retval = "$retval\$\{$var\}";
519 # This could be an option that is used later, save
520 # it so we don't warn if this option is not one of
521 # ktests options.
522 $used_options{$var} = 1;
337 } 523 }
338 $value = $end; 524 $value = $end;
339 } 525 }
@@ -348,6 +534,19 @@ sub process_variables {
348sub set_value { 534sub set_value {
349 my ($lvalue, $rvalue, $override, $overrides, $name) = @_; 535 my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
350 536
537 my $prvalue = process_variables($rvalue);
538
539 if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
540 # Note if a test is something other than build, then we
541 # will need other manditory options.
542 if ($prvalue ne "install") {
543 $buildonly = 0;
544 } else {
545 # install still limits some manditory options.
546 $buildonly = 2;
547 }
548 }
549
351 if (defined($opt{$lvalue})) { 550 if (defined($opt{$lvalue})) {
352 if (!$override || defined(${$overrides}{$lvalue})) { 551 if (!$override || defined(${$overrides}{$lvalue})) {
353 my $extra = ""; 552 my $extra = "";
@@ -356,13 +555,12 @@ sub set_value {
356 } 555 }
357 die "$name: $.: Option $lvalue defined more than once!\n$extra"; 556 die "$name: $.: Option $lvalue defined more than once!\n$extra";
358 } 557 }
359 ${$overrides}{$lvalue} = $rvalue; 558 ${$overrides}{$lvalue} = $prvalue;
360 } 559 }
361 if ($rvalue =~ /^\s*$/) { 560 if ($rvalue =~ /^\s*$/) {
362 delete $opt{$lvalue}; 561 delete $opt{$lvalue};
363 } else { 562 } else {
364 $rvalue = process_variables($rvalue); 563 $opt{$lvalue} = $prvalue;
365 $opt{$lvalue} = $rvalue;
366 } 564 }
367} 565}
368 566
@@ -712,6 +910,15 @@ sub __read_config {
712 return $test_case; 910 return $test_case;
713} 911}
714 912
913sub get_test_case {
914 print "What test case would you like to run?\n";
915 print " (build, install or boot)\n";
916 print " Other tests are available but require editing the config file\n";
917 my $ans = <STDIN>;
918 chomp $ans;
919 $default{"TEST_TYPE"} = $ans;
920}
921
715sub read_config { 922sub read_config {
716 my ($config) = @_; 923 my ($config) = @_;
717 924
@@ -726,10 +933,7 @@ sub read_config {
726 # was a test specified? 933 # was a test specified?
727 if (!$test_case) { 934 if (!$test_case) {
728 print "No test case specified.\n"; 935 print "No test case specified.\n";
729 print "What test case would you like to run?\n"; 936 get_test_case;
730 my $ans = <STDIN>;
731 chomp $ans;
732 $default{"TEST_TYPE"} = $ans;
733 } 937 }
734 938
735 # set any defaults 939 # set any defaults
@@ -739,6 +943,37 @@ sub read_config {
739 $opt{$default} = $default{$default}; 943 $opt{$default} = $default{$default};
740 } 944 }
741 } 945 }
946
947 if ($opt{"IGNORE_UNUSED"} == 1) {
948 return;
949 }
950
951 my %not_used;
952
953 # check if there are any stragglers (typos?)
954 foreach my $option (keys %opt) {
955 my $op = $option;
956 # remove per test labels.
957 $op =~ s/\[.*\]//;
958 if (!exists($option_map{$op}) &&
959 !exists($default{$op}) &&
960 !exists($used_options{$op})) {
961 $not_used{$op} = 1;
962 }
963 }
964
965 if (%not_used) {
966 my $s = "s are";
967 $s = " is" if (keys %not_used == 1);
968 print "The following option$s not used; could be a typo:\n";
969 foreach my $option (keys %not_used) {
970 print "$option\n";
971 }
972 print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
973 if (!read_yn "Do you want to continue?") {
974 exit -1;
975 }
976 }
742} 977}
743 978
744sub __eval_option { 979sub __eval_option {
@@ -873,6 +1108,17 @@ sub reboot {
873 } 1108 }
874} 1109}
875 1110
1111sub reboot_to_good {
1112 my ($time) = @_;
1113
1114 if (defined($switch_to_good)) {
1115 run_command $switch_to_good;
1116 return;
1117 }
1118
1119 reboot $time;
1120}
1121
876sub do_not_reboot { 1122sub do_not_reboot {
877 my $i = $iteration; 1123 my $i = $iteration;
878 1124
@@ -889,7 +1135,7 @@ sub dodie {
889 if ($reboot_on_error && !do_not_reboot) { 1135 if ($reboot_on_error && !do_not_reboot) {
890 1136
891 doprint "REBOOTING\n"; 1137 doprint "REBOOTING\n";
892 reboot; 1138 reboot_to_good;
893 1139
894 } elsif ($poweroff_on_error && defined($power_off)) { 1140 } elsif ($poweroff_on_error && defined($power_off)) {
895 doprint "POWERING OFF\n"; 1141 doprint "POWERING OFF\n";
@@ -975,6 +1221,43 @@ sub wait_for_monitor {
975 print "** Monitor flushed **\n"; 1221 print "** Monitor flushed **\n";
976} 1222}
977 1223
1224sub save_logs {
1225 my ($result, $basedir) = @_;
1226 my @t = localtime;
1227 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1228 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1229
1230 my $type = $build_type;
1231 if ($type =~ /useconfig/) {
1232 $type = "useconfig";
1233 }
1234
1235 my $dir = "$machine-$test_type-$type-$result-$date";
1236
1237 $dir = "$basedir/$dir";
1238
1239 if (!-d $dir) {
1240 mkpath($dir) or
1241 die "can't create $dir";
1242 }
1243
1244 my %files = (
1245 "config" => $output_config,
1246 "buildlog" => $buildlog,
1247 "dmesg" => $dmesg,
1248 "testlog" => $testlog,
1249 );
1250
1251 while (my ($name, $source) = each(%files)) {
1252 if (-f "$source") {
1253 cp "$source", "$dir/$name" or
1254 die "failed to copy $source";
1255 }
1256 }
1257
1258 doprint "*** Saved info to $dir ***\n";
1259}
1260
978sub fail { 1261sub fail {
979 1262
980 if ($die_on_failure) { 1263 if ($die_on_failure) {
@@ -988,7 +1271,7 @@ sub fail {
988 # no need to reboot for just building. 1271 # no need to reboot for just building.
989 if (!do_not_reboot) { 1272 if (!do_not_reboot) {
990 doprint "REBOOTING\n"; 1273 doprint "REBOOTING\n";
991 reboot $sleep_time; 1274 reboot_to_good $sleep_time;
992 } 1275 }
993 1276
994 my $name = ""; 1277 my $name = "";
@@ -1003,38 +1286,9 @@ sub fail {
1003 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1286 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1004 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1287 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1005 1288
1006 return 1 if (!defined($store_failures)); 1289 if (defined($store_failures)) {
1007 1290 save_logs "fail", $store_failures;
1008 my @t = localtime; 1291 }
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 1292
1039 return 1; 1293 return 1;
1040} 1294}
@@ -1170,13 +1424,16 @@ sub wait_for_input
1170} 1424}
1171 1425
1172sub reboot_to { 1426sub reboot_to {
1427 if (defined($switch_to_test)) {
1428 run_command $switch_to_test;
1429 }
1430
1173 if ($reboot_type eq "grub") { 1431 if ($reboot_type eq "grub") {
1174 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 1432 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1175 reboot; 1433 } elsif (defined $reboot_script) {
1176 return; 1434 run_command "$reboot_script";
1177 } 1435 }
1178 1436 reboot;
1179 run_command "$reboot_script";
1180} 1437}
1181 1438
1182sub get_sha1 { 1439sub get_sha1 {
@@ -1274,7 +1531,7 @@ sub monitor {
1274 } 1531 }
1275 1532
1276 if ($full_line =~ /call trace:/i) { 1533 if ($full_line =~ /call trace:/i) {
1277 if (!$bug && !$skip_call_trace) { 1534 if (!$ignore_errors && !$bug && !$skip_call_trace) {
1278 $bug = 1; 1535 $bug = 1;
1279 $failure_start = time; 1536 $failure_start = time;
1280 } 1537 }
@@ -1341,12 +1598,19 @@ sub monitor {
1341 return 1; 1598 return 1;
1342} 1599}
1343 1600
1601sub eval_kernel_version {
1602 my ($option) = @_;
1603
1604 $option =~ s/\$KERNEL_VERSION/$version/g;
1605
1606 return $option;
1607}
1608
1344sub do_post_install { 1609sub do_post_install {
1345 1610
1346 return if (!defined($post_install)); 1611 return if (!defined($post_install));
1347 1612
1348 my $cp_post_install = $post_install; 1613 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 1614 run_command "$cp_post_install" or
1351 dodie "Failed to run post install"; 1615 dodie "Failed to run post install";
1352} 1616}
@@ -1355,7 +1619,9 @@ sub install {
1355 1619
1356 return if ($no_install); 1620 return if ($no_install);
1357 1621
1358 run_scp "$outputdir/$build_target", "$target_image" or 1622 my $cp_target = eval_kernel_version $target_image;
1623
1624 run_scp "$outputdir/$build_target", "$cp_target" or
1359 dodie "failed to copy image"; 1625 dodie "failed to copy image";
1360 1626
1361 my $install_mods = 0; 1627 my $install_mods = 0;
@@ -1640,9 +1906,13 @@ sub success {
1640 doprint "*******************************************\n"; 1906 doprint "*******************************************\n";
1641 doprint "*******************************************\n"; 1907 doprint "*******************************************\n";
1642 1908
1909 if (defined($store_successes)) {
1910 save_logs "success", $store_successes;
1911 }
1912
1643 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1913 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1644 doprint "Reboot and wait $sleep_time seconds\n"; 1914 doprint "Reboot and wait $sleep_time seconds\n";
1645 reboot $sleep_time; 1915 reboot_to_good $sleep_time;
1646 } 1916 }
1647} 1917}
1648 1918
@@ -1669,7 +1939,10 @@ sub child_run_test {
1669 $poweroff_on_error = 0; 1939 $poweroff_on_error = 0;
1670 $die_on_failure = 1; 1940 $die_on_failure = 1;
1671 1941
1942 $redirect = "$testlog";
1672 run_command $run_test or $failed = 1; 1943 run_command $run_test or $failed = 1;
1944 undef $redirect;
1945
1673 exit $failed; 1946 exit $failed;
1674} 1947}
1675 1948
@@ -1744,6 +2017,43 @@ sub do_run_test {
1744 waitpid $child_pid, 0; 2017 waitpid $child_pid, 0;
1745 $child_exit = $?; 2018 $child_exit = $?;
1746 2019
2020 if (!$bug && $in_bisect) {
2021 if (defined($bisect_ret_good)) {
2022 if ($child_exit == $bisect_ret_good) {
2023 return 1;
2024 }
2025 }
2026 if (defined($bisect_ret_skip)) {
2027 if ($child_exit == $bisect_ret_skip) {
2028 return -1;
2029 }
2030 }
2031 if (defined($bisect_ret_abort)) {
2032 if ($child_exit == $bisect_ret_abort) {
2033 fail "test abort" and return -2;
2034 }
2035 }
2036 if (defined($bisect_ret_bad)) {
2037 if ($child_exit == $bisect_ret_skip) {
2038 return 0;
2039 }
2040 }
2041 if (defined($bisect_ret_default)) {
2042 if ($bisect_ret_default eq "good") {
2043 return 1;
2044 } elsif ($bisect_ret_default eq "bad") {
2045 return 0;
2046 } elsif ($bisect_ret_default eq "skip") {
2047 return -1;
2048 } elsif ($bisect_ret_default eq "abort") {
2049 return -2;
2050 } else {
2051 fail "unknown default action: $bisect_ret_default"
2052 and return -2;
2053 }
2054 }
2055 }
2056
1747 if ($bug || $child_exit) { 2057 if ($bug || $child_exit) {
1748 return 0 if $in_bisect; 2058 return 0 if $in_bisect;
1749 fail "test failed" and return 0; 2059 fail "test failed" and return 0;
@@ -1770,7 +2080,7 @@ sub run_git_bisect {
1770 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 2080 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1771 doprint "$1 [$2]\n"; 2081 doprint "$1 [$2]\n";
1772 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 2082 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1773 $bisect_bad = $1; 2083 $bisect_bad_commit = $1;
1774 doprint "Found bad commit... $1\n"; 2084 doprint "Found bad commit... $1\n";
1775 return 0; 2085 return 0;
1776 } else { 2086 } else {
@@ -1783,7 +2093,7 @@ sub run_git_bisect {
1783 2093
1784sub bisect_reboot { 2094sub bisect_reboot {
1785 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 2095 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
1786 reboot $bisect_sleep_time; 2096 reboot_to_good $bisect_sleep_time;
1787} 2097}
1788 2098
1789# returns 1 on success, 0 on failure, -1 on skip 2099# returns 1 on success, 0 on failure, -1 on skip
@@ -1868,21 +2178,28 @@ sub run_bisect {
1868 } 2178 }
1869} 2179}
1870 2180
2181sub update_bisect_replay {
2182 my $tmp_log = "$tmpdir/ktest_bisect_log";
2183 run_command "git bisect log > $tmp_log" or
2184 die "can't create bisect log";
2185 return $tmp_log;
2186}
2187
1871sub bisect { 2188sub bisect {
1872 my ($i) = @_; 2189 my ($i) = @_;
1873 2190
1874 my $result; 2191 my $result;
1875 2192
1876 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 2193 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]"})); 2194 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]"})); 2195 die "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type));
1879 2196
1880 my $good = $opt{"BISECT_GOOD[$i]"}; 2197 my $good = $bisect_good;
1881 my $bad = $opt{"BISECT_BAD[$i]"}; 2198 my $bad = $bisect_bad;
1882 my $type = $opt{"BISECT_TYPE[$i]"}; 2199 my $type = $bisect_type;
1883 my $start = $opt{"BISECT_START[$i]"}; 2200 my $start = $bisect_start;
1884 my $replay = $opt{"BISECT_REPLAY[$i]"}; 2201 my $replay = $bisect_replay;
1885 my $start_files = $opt{"BISECT_FILES[$i]"}; 2202 my $start_files = $bisect_files;
1886 2203
1887 if (defined($start_files)) { 2204 if (defined($start_files)) {
1888 $start_files = " -- " . $start_files; 2205 $start_files = " -- " . $start_files;
@@ -1894,8 +2211,7 @@ sub bisect {
1894 $good = get_sha1($good); 2211 $good = get_sha1($good);
1895 $bad = get_sha1($bad); 2212 $bad = get_sha1($bad);
1896 2213
1897 if (defined($opt{"BISECT_REVERSE[$i]"}) && 2214 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"; 2215 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1900 $reverse_bisect = 1; 2216 $reverse_bisect = 1;
1901 } else { 2217 } else {
@@ -1907,8 +2223,31 @@ sub bisect {
1907 $type = "boot"; 2223 $type = "boot";
1908 } 2224 }
1909 2225
1910 my $check = $opt{"BISECT_CHECK[$i]"}; 2226 # Check if a bisect was running
1911 if (defined($check) && $check ne "0") { 2227 my $bisect_start_file = "$builddir/.git/BISECT_START";
2228
2229 my $check = $bisect_check;
2230 my $do_check = defined($check) && $check ne "0";
2231
2232 if ( -f $bisect_start_file ) {
2233 print "Bisect in progress found\n";
2234 if ($do_check) {
2235 print " If you say yes, then no checks of good or bad will be done\n";
2236 }
2237 if (defined($replay)) {
2238 print "** BISECT_REPLAY is defined in config file **";
2239 print " Ignore config option and perform new git bisect log?\n";
2240 if (read_ync " (yes, no, or cancel) ") {
2241 $replay = update_bisect_replay;
2242 $do_check = 0;
2243 }
2244 } elsif (read_yn "read git log and continue?") {
2245 $replay = update_bisect_replay;
2246 $do_check = 0;
2247 }
2248 }
2249
2250 if ($do_check) {
1912 2251
1913 # get current HEAD 2252 # get current HEAD
1914 my $head = get_sha1("HEAD"); 2253 my $head = get_sha1("HEAD");
@@ -1973,7 +2312,7 @@ sub bisect {
1973 run_command "git bisect reset" or 2312 run_command "git bisect reset" or
1974 dodie "could not reset git bisect"; 2313 dodie "could not reset git bisect";
1975 2314
1976 doprint "Bad commit was [$bisect_bad]\n"; 2315 doprint "Bad commit was [$bisect_bad_commit]\n";
1977 2316
1978 success $i; 2317 success $i;
1979} 2318}
@@ -2129,7 +2468,7 @@ sub run_config_bisect {
2129 } 2468 }
2130 2469
2131 doprint "***** RUN TEST ***\n"; 2470 doprint "***** RUN TEST ***\n";
2132 my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 2471 my $type = $config_bisect_type;
2133 my $ret; 2472 my $ret;
2134 my %current_config; 2473 my %current_config;
2135 2474
@@ -2233,7 +2572,7 @@ sub run_config_bisect {
2233sub config_bisect { 2572sub config_bisect {
2234 my ($i) = @_; 2573 my ($i) = @_;
2235 2574
2236 my $start_config = $opt{"CONFIG_BISECT[$i]"}; 2575 my $start_config = $config_bisect;
2237 2576
2238 my $tmpconfig = "$tmpdir/use_config"; 2577 my $tmpconfig = "$tmpdir/use_config";
2239 2578
@@ -2346,29 +2685,29 @@ sub config_bisect {
2346 2685
2347sub patchcheck_reboot { 2686sub patchcheck_reboot {
2348 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 2687 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
2349 reboot $patchcheck_sleep_time; 2688 reboot_to_good $patchcheck_sleep_time;
2350} 2689}
2351 2690
2352sub patchcheck { 2691sub patchcheck {
2353 my ($i) = @_; 2692 my ($i) = @_;
2354 2693
2355 die "PATCHCHECK_START[$i] not defined\n" 2694 die "PATCHCHECK_START[$i] not defined\n"
2356 if (!defined($opt{"PATCHCHECK_START[$i]"})); 2695 if (!defined($patchcheck_start));
2357 die "PATCHCHECK_TYPE[$i] not defined\n" 2696 die "PATCHCHECK_TYPE[$i] not defined\n"
2358 if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 2697 if (!defined($patchcheck_type));
2359 2698
2360 my $start = $opt{"PATCHCHECK_START[$i]"}; 2699 my $start = $patchcheck_start;
2361 2700
2362 my $end = "HEAD"; 2701 my $end = "HEAD";
2363 if (defined($opt{"PATCHCHECK_END[$i]"})) { 2702 if (defined($patchcheck_end)) {
2364 $end = $opt{"PATCHCHECK_END[$i]"}; 2703 $end = $patchcheck_end;
2365 } 2704 }
2366 2705
2367 # Get the true sha1's since we can use things like HEAD~3 2706 # Get the true sha1's since we can use things like HEAD~3
2368 $start = get_sha1($start); 2707 $start = get_sha1($start);
2369 $end = get_sha1($end); 2708 $end = get_sha1($end);
2370 2709
2371 my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 2710 my $type = $patchcheck_type;
2372 2711
2373 # Can't have a test without having a test to run 2712 # Can't have a test without having a test to run
2374 if ($type eq "test" && !defined($run_test)) { 2713 if ($type eq "test" && !defined($run_test)) {
@@ -2905,9 +3244,11 @@ sub make_min_config {
2905 $in_bisect = 1; 3244 $in_bisect = 1;
2906 3245
2907 my $failed = 0; 3246 my $failed = 0;
2908 build "oldconfig"; 3247 build "oldconfig" or $failed = 1;
2909 start_monitor_and_boot or $failed = 1; 3248 if (!$failed) {
2910 end_monitor; 3249 start_monitor_and_boot or $failed = 1;
3250 end_monitor;
3251 }
2911 3252
2912 $in_bisect = 0; 3253 $in_bisect = 0;
2913 3254
@@ -2963,7 +3304,7 @@ sub make_min_config {
2963 } 3304 }
2964 3305
2965 doprint "Reboot and wait $sleep_time seconds\n"; 3306 doprint "Reboot and wait $sleep_time seconds\n";
2966 reboot $sleep_time; 3307 reboot_to_good $sleep_time;
2967 } 3308 }
2968 3309
2969 success $i; 3310 success $i;
@@ -2985,13 +3326,27 @@ if ($#ARGV == 0) {
2985} 3326}
2986 3327
2987if (! -f $ktest_config) { 3328if (! -f $ktest_config) {
3329 $newconfig = 1;
3330 get_test_case;
2988 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 3331 open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
2989 print OUT << "EOF" 3332 print OUT << "EOF"
2990# Generated by ktest.pl 3333# Generated by ktest.pl
2991# 3334#
3335
3336# PWD is a ktest.pl variable that will result in the process working
3337# directory that ktest.pl is executed in.
3338
3339# THIS_DIR is automatically assigned the PWD of the path that generated
3340# the config file. It is best to use this variable when assigning other
3341# directory paths within this directory. This allows you to easily
3342# move the test cases to other locations or to other machines.
3343#
3344THIS_DIR := $variable{"PWD"}
3345
2992# Define each test with TEST_START 3346# Define each test with TEST_START
2993# The config options below it will override the defaults 3347# The config options below it will override the defaults
2994TEST_START 3348TEST_START
3349TEST_TYPE = $default{"TEST_TYPE"}
2995 3350
2996DEFAULTS 3351DEFAULTS
2997EOF 3352EOF
@@ -3011,7 +3366,7 @@ if ($#new_configs >= 0) {
3011 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 3366 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
3012 foreach my $config (@new_configs) { 3367 foreach my $config (@new_configs) {
3013 print OUT "$config = $entered_configs{$config}\n"; 3368 print OUT "$config = $entered_configs{$config}\n";
3014 $opt{$config} = $entered_configs{$config}; 3369 $opt{$config} = process_variables($entered_configs{$config});
3015 } 3370 }
3016} 3371}
3017 3372
@@ -3091,61 +3446,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3091 3446
3092 my $makecmd = set_test_option("MAKE_CMD", $i); 3447 my $makecmd = set_test_option("MAKE_CMD", $i);
3093 3448
3094 $machine = set_test_option("MACHINE", $i); 3449 # Load all the options into their mapped variable names
3095 $ssh_user = set_test_option("SSH_USER", $i); 3450 foreach my $opt (keys %option_map) {
3096 $tmpdir = set_test_option("TMP_DIR", $i); 3451 ${$option_map{$opt}} = set_test_option($opt, $i);
3097 $outputdir = set_test_option("OUTPUT_DIR", $i); 3452 }
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 3453
3150 $start_minconfig_defined = 1; 3454 $start_minconfig_defined = 1;
3151 3455
@@ -3166,26 +3470,26 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3166 $ENV{"SSH_USER"} = $ssh_user; 3470 $ENV{"SSH_USER"} = $ssh_user;
3167 $ENV{"MACHINE"} = $machine; 3471 $ENV{"MACHINE"} = $machine;
3168 3472
3169 $target = "$ssh_user\@$machine";
3170
3171 $buildlog = "$tmpdir/buildlog-$machine"; 3473 $buildlog = "$tmpdir/buildlog-$machine";
3474 $testlog = "$tmpdir/testlog-$machine";
3172 $dmesg = "$tmpdir/dmesg-$machine"; 3475 $dmesg = "$tmpdir/dmesg-$machine";
3173 $make = "$makecmd O=$outputdir"; 3476 $make = "$makecmd O=$outputdir";
3174 $output_config = "$outputdir/.config"; 3477 $output_config = "$outputdir/.config";
3175 3478
3176 if ($reboot_type eq "grub") { 3479 if (!$buildonly) {
3177 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 3480 $target = "$ssh_user\@$machine";
3178 } elsif (!defined($reboot_script)) { 3481 if ($reboot_type eq "grub") {
3179 dodie "REBOOT_SCRIPT not defined" 3482 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3483 }
3180 } 3484 }
3181 3485
3182 my $run_type = $build_type; 3486 my $run_type = $build_type;
3183 if ($test_type eq "patchcheck") { 3487 if ($test_type eq "patchcheck") {
3184 $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 3488 $run_type = $patchcheck_type;
3185 } elsif ($test_type eq "bisect") { 3489 } elsif ($test_type eq "bisect") {
3186 $run_type = $opt{"BISECT_TYPE[$i]"}; 3490 $run_type = $bisect_type;
3187 } elsif ($test_type eq "config_bisect") { 3491 } elsif ($test_type eq "config_bisect") {
3188 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 3492 $run_type = $config_bisect_type;
3189 } 3493 }
3190 3494
3191 if ($test_type eq "make_min_config") { 3495 if ($test_type eq "make_min_config") {
@@ -3205,6 +3509,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3205 3509
3206 unlink $dmesg; 3510 unlink $dmesg;
3207 unlink $buildlog; 3511 unlink $buildlog;
3512 unlink $testlog;
3208 3513
3209 if (defined($addconfig)) { 3514 if (defined($addconfig)) {
3210 my $min = $minconfig; 3515 my $min = $minconfig;
@@ -3216,7 +3521,6 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3216 $minconfig = "$tmpdir/add_config"; 3521 $minconfig = "$tmpdir/add_config";
3217 } 3522 }
3218 3523
3219 my $checkout = $opt{"CHECKOUT[$i]"};
3220 if (defined($checkout)) { 3524 if (defined($checkout)) {
3221 run_command "git checkout $checkout" or 3525 run_command "git checkout $checkout" or
3222 die "failed to checkout $checkout"; 3526 die "failed to checkout $checkout";
@@ -3267,7 +3571,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3267if ($opt{"POWEROFF_ON_SUCCESS"}) { 3571if ($opt{"POWEROFF_ON_SUCCESS"}) {
3268 halt; 3572 halt;
3269} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 3573} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
3270 reboot; 3574 reboot_to_good;
3271} 3575}
3272 3576
3273doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 3577doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n";
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index dbedfa196727..5ea04c6a71bf 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
@@ -700,6 +730,25 @@
700# (default 1) 730# (default 1)
701#DETECT_TRIPLE_FAULT = 0 731#DETECT_TRIPLE_FAULT = 0
702 732
733# All options in the config file should be either used by ktest
734# or could be used within a value of another option. If an option
735# in the config file is not used, ktest will warn about it and ask
736# if you want to continue.
737#
738# If you don't care if there are non-used options, enable this
739# option. Be careful though, a non-used option is usually a sign
740# of an option name being typed incorrectly.
741# (default 0)
742#IGNORE_UNUSED = 1
743
744# When testing a kernel that happens to have WARNINGs, and call
745# traces, ktest.pl will detect these and fail a boot or test run
746# due to warnings. By setting this option, ktest will ignore
747# call traces, and will not fail a test if the kernel produces
748# an oops. Use this option with care.
749# (default 0)
750#IGNORE_ERRORS = 1
751
703#### Per test run options #### 752#### Per test run options ####
704# The following options are only allowed in TEST_START sections. 753# The following options are only allowed in TEST_START sections.
705# They are ignored in the DEFAULTS sections. 754# They are ignored in the DEFAULTS sections.
@@ -862,6 +911,42 @@
862# BISECT_BAD with BISECT_CHECK = good or 911# BISECT_BAD with BISECT_CHECK = good or
863# BISECT_CHECK = bad, respectively. 912# BISECT_CHECK = bad, respectively.
864# 913#
914# BISECT_RET_GOOD = 0 (optional, default undefined)
915#
916# In case the specificed test returns something other than just
917# 0 for good, and non-zero for bad, you can override 0 being
918# good by defining BISECT_RET_GOOD.
919#
920# BISECT_RET_BAD = 1 (optional, default undefined)
921#
922# In case the specificed test returns something other than just
923# 0 for good, and non-zero for bad, you can override non-zero being
924# bad by defining BISECT_RET_BAD.
925#
926# BISECT_RET_ABORT = 255 (optional, default undefined)
927#
928# If you need to abort the bisect if the test discovers something
929# that was wrong, you can define BISECT_RET_ABORT to be the error
930# code returned by the test in order to abort the bisect.
931#
932# BISECT_RET_SKIP = 2 (optional, default undefined)
933#
934# If the test detects that the current commit is neither good
935# nor bad, but something else happened (another bug detected)
936# you can specify BISECT_RET_SKIP to an error code that the
937# test returns when it should skip the current commit.
938#
939# BISECT_RET_DEFAULT = good (optional, default undefined)
940#
941# You can override the default of what to do when the above
942# options are not hit. This may be one of, "good", "bad",
943# "abort" or "skip" (without the quotes).
944#
945# Note, if you do not define any of the previous BISECT_RET_*
946# and define BISECT_RET_DEFAULT, all bisects results will do
947# what the BISECT_RET_DEFAULT has.
948#
949#
865# Example: 950# Example:
866# TEST_START 951# TEST_START
867# TEST_TYPE = bisect 952# TEST_TYPE = bisect
@@ -950,7 +1035,7 @@
950# TEST_START 1035# TEST_START
951# TEST_TYPE = config_bisect 1036# TEST_TYPE = config_bisect
952# CONFIG_BISECT_TYPE = build 1037# CONFIG_BISECT_TYPE = build
953# CONFIG_BISECT = /home/test/¢onfig-bad 1038# CONFIG_BISECT = /home/test/config-bad
954# MIN_CONFIG = /home/test/config-min 1039# MIN_CONFIG = /home/test/config-min
955# BISECT_MANUAL = 1 1040# BISECT_MANUAL = 1
956# 1041#
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
new file mode 100644
index 000000000000..4ec84018cc13
--- /dev/null
+++ b/tools/testing/selftests/Makefile
@@ -0,0 +1,11 @@
1TARGETS = breakpoints
2
3all:
4 for TARGET in $(TARGETS); do \
5 make -C $$TARGET; \
6 done;
7
8clean:
9 for TARGET in $(TARGETS); do \
10 make -C $$TARGET clean; \
11 done;
diff --git a/tools/testing/selftests/breakpoints/Makefile b/tools/testing/selftests/breakpoints/Makefile
new file mode 100644
index 000000000000..f362722cdce7
--- /dev/null
+++ b/tools/testing/selftests/breakpoints/Makefile
@@ -0,0 +1,20 @@
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 run_test
15else
16 echo "Not an x86 target, can't build breakpoints selftests"
17endif
18
19clean:
20 rm -fr run_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/run_tests b/tools/testing/selftests/run_tests
new file mode 100644
index 000000000000..320718a4e6bf
--- /dev/null
+++ b/tools/testing/selftests/run_tests
@@ -0,0 +1,8 @@
1#!/bin/bash
2
3TARGETS=breakpoints
4
5for TARGET in $TARGETS
6do
7 $TARGET/run_test
8done
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index 669bcdd45805..b4fbc91c41b4 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -186,21 +186,12 @@ struct virtqueue {
186#endif 186#endif
187 187
188/* Interfaces exported by virtio_ring. */ 188/* Interfaces exported by virtio_ring. */
189int virtqueue_add_buf_gfp(struct virtqueue *vq, 189int virtqueue_add_buf(struct virtqueue *vq,
190 struct scatterlist sg[], 190 struct scatterlist sg[],
191 unsigned int out_num, 191 unsigned int out_num,
192 unsigned int in_num, 192 unsigned int in_num,
193 void *data, 193 void *data,
194 gfp_t gfp); 194 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 195
205void virtqueue_kick(struct virtqueue *vq); 196void virtqueue_kick(struct virtqueue *vq);
206 197
@@ -214,6 +205,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *vq);
214struct virtqueue *vring_new_virtqueue(unsigned int num, 205struct virtqueue *vring_new_virtqueue(unsigned int num,
215 unsigned int vring_align, 206 unsigned int vring_align,
216 struct virtio_device *vdev, 207 struct virtio_device *vdev,
208 bool weak_barriers,
217 void *pages, 209 void *pages,
218 void (*notify)(struct virtqueue *vq), 210 void (*notify)(struct virtqueue *vq),
219 void (*callback)(struct virtqueue *vq), 211 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);